Skip to content
CroStreamUI kit

Data

Tables that sort, select and collapse to cards on phones, plus pagination, key/value lists, highlighted code and a full code editor.

01Table

Table

Sorts, selects (shift-click for ranges), keeps its header while you scroll, and turns into labelled cards when there's no room for columns.

Triggers Sortable, selectable, sticky header with a shade that only appears once rows pass under it, row actions.
  • --cs-control-h-md
  • --cs-state-selected
  • --cs-edge-shade
2 selected
Triggers
StatusActions
New follower confetti Follow8,410Active
Hydrate !hydrateChannel points1,284Active
Discord link !discordChat1,733Active
Lurk mode !lurkChat3,920Active
Socials reminder every thirty minutes while live !socialsChat2,051Active
Clown nose on the model !honkChannel points612Cooling down
Pet the cat cam !catChannel points947Cooling down
Bits rain Bits158Active
Raid welcome Raid74Active
BRB screen Hotkey512Active
Hype train horn Bits19Active
Scene: Just Chatting Hotkey233Active
Spooky scare flash Channel points41Paused
Song request !srChatNever0Paused
Leaderboard Numeric columns sort high-to-low first and line up on tabular figures; long names truncate with the full name kept.
Viewer points leaderboard
#
1 pixel_mage Sub184,220412.0 hjust now
2 Haliebug13 135,186340.5 h2 hours ago
3 NightOwlNoodle Sub106,412290.1 h3 hours ago
4 quietcartographer Sub87,665252.8 h5 hours ago
5 Il1ya_l1ght 74,458223.9 h6 hours ago
6 mossy_tea Sub65,534201.0 h8 hours ago
7 TurboGranny Sub57,925182.3 h10 hours ago
8 sleepyshrimp 51,848166.8 h11 hours ago
9 captain_crumpet Sub46,872153.7 h13 hours ago
10 ZeroO0zone Sub42,716142.6 h15 hours ago
Loading Skeleton rows hold the layout; the table is aria-busy and says so politely.
Recent triggers
TriggerSourceLast firedRuns
Loading Recent triggers
Empty A default empty state, or your own snippet with a way out.
Search results
TriggerSourceLast firedRuns
No triggers match “lurkmode2” Check the spelling, or search by command instead of name.
Cards under 600px A container query, not the viewport: the same table in a narrow panel. The header becomes a sort bar; each value keeps its label.
Triggers (narrow)
StatusActions
Hydrate !hydrateChannel points1,284Active
Lurk mode !lurkChat3,920Active
Clown nose on the model !honkChannel points612Cooling down
Raid welcome Raid74Active
Row focus and reordering rowFocus makes rows one roving tab stop: ↑/↓ move, Shift extends, Space toggles, Enter opens, Esc clears. Drag a grip, or Alt+↑/↓ on a row (↑/↓ on a grip) to move it; the move is announced. Narrow the panel and Source, then Last fired, step aside before the cards take over.
Alert queue order
Order TriggerSourceLast firedRuns
Hydrate !hydrateChannel points4 minutes ago1,284
Lurk mode !lurkChat11 minutes ago3,920
Raid welcome Raid3 hours ago74
Clown nose on the model !honkChannel points38 minutes ago612
New follower confetti Follow2 minutes ago8,410
Scene: Just Chatting Hotkeyyesterday233
Alt+Up or Alt+Down on a row moves it.
Alert queue order (narrow)
OrderTriggerSourceLast firedRuns
Hydrate !hydrateChannel points4 minutes ago1,284
Lurk mode !lurkChat11 minutes ago3,920
Raid welcome Raid3 hours ago74
Clown nose on the model !honkChannel points38 minutes ago612
New follower confetti Follow2 minutes ago8,410
Scene: Just Chatting Hotkeyyesterday233
Up and Down arrow keys move the row.
Index rows onrowclick makes the whole row a click target (never from its buttons or links); rowHref turns the title into a real link, so middle-click and Ctrl/⌘-click open a new tab (rowNewTab extends that to the whole row where the host can open tabs). rowTone dims rows that are off or edges a problem (visual only, so a cell says it too); groups add heading rows with counts (sorting applies inside each group). Under 600px, cardActions='bottom' ends each card with its actions and card: 'aside' keeps the status on the title line.
Click a row, or middle-click its name
Triggers by source
CommandStatusActions
Chat ,4
Lurk mode!lurk11 minutes ago3,920 Active
Socials reminder every thirty minutes while live!socials29 minutes ago2,051 Active
Song request!srNever0 Paused
Discord link!discord8 minutes ago1,733 Active
Channel points ,4
Hydrate!hydrate4 minutes ago1,284 Active
Clown nose on the model!honk38 minutes ago612 Cooling down
Spooky scare flash—3 days ago41 Paused
Pet the cat cam!cat52 minutes ago947 Cooling down
Follows ,1
New follower confetti—2 minutes ago8,410 Active
Raids ,1
Raid welcome—3 hours ago74 Active
Bits ,2
Bits rain—2 hours ago158 Active
Hype train horn—10 hours ago19 Active
Hotkeys ,2
Scene: Just Chatting—yesterday233 Active
BRB screen—5 hours ago512 Active
Triggers by source (narrow)
CommandStatusActions
Hydrate!hydrate4 minutes ago1,284 Active
Lurk mode!lurk11 minutes ago3,920 Active
Raid welcome—3 hours ago74 Active
Clown nose on the model!honk38 minutes ago612 Cooling down
New follower confetti—2 minutes ago8,410 Active
Density Row height follows the control height, so compact tightens tables with everything else.
comfortable
Triggers (comfortable)
TriggerSourceLast firedRuns
HydrateChannel points4 minutes ago1,284
Lurk modeChat11 minutes ago3,920
Raid welcomeRaid3 hours ago74
Clown nose on the modelChannel points38 minutes ago612
compact
Triggers (compact)
TriggerSourceLast firedRuns
HydrateChannel points4 minutes ago1,284
Lurk modeChat11 minutes ago3,920
Raid welcomeRaid3 hours ago74
Clown nose on the modelChannel points38 minutes ago612

02Pagination

Pagination

Numbered pages with ellipses for long lists, or a compact range readout for toolbars. Arrow keys move between pages.

Full The current page is raised, bold and underlined: never colour alone.
  • --cs-control-h-sm
Compact “1–25 of 340”, announced as the page changes.
Narrow Below 480px the words go and the arrows stay.
Flex item The nav is a size container, so it asks for the width it has (100% of its parent) instead of collapsing to nothing beside a sibling.
Page

03DescriptionList

DescriptionList

Key/value details as a real description list. Terms share one column; copyable values carry their own copy button.

Horizontal Terms line up in one column (subgrid); stacks itself under 28rem.
Name
Stream deck relay
Endpoint
https://hooks.example.com/crostream/9f2c4e1a
Signing secret
whsec_••••••••••••3Fq9 Copied in full; shown masked.
Events
channel.points.redeemed, channel.raid, stream.online
Last delivery
200 OK · 4 minutes ago · 182 ms
Created
Oct 5, 2026, 8:30 PM
Stacked Label over value, for narrow sidebars and cards.
Login
pixel_mage
Points
184,220
Watch time
412.0 hours
First seen
March 2, 2025

04CodeBlock

CodeBlock

Payloads, commands and config. Known languages are highlighted on the server with the editor's own colours, so a read-only block costs no JavaScript. Line numbers never come along when you copy; long lines scroll with an edge shade, or wrap on request.

With a title bar Filename, language tag, wrap toggle and copy.
  • --cs-syntax-*
channel.points.redeemed.json JSON
{
  "id": "evt_01JA7W3T8M5Q2K",
  "type": "channel.points.redeemed",
  "created_at": "2026-10-14T20:26:11Z",
  "channel": { "id": "41245072", "login": "haliebug13" },
  "data": {
    "reward": { "id": "c0ffee42", "title": "Hydrate", "cost": 500 },
    "user": { "id": "88123004", "login": "pixel_mage", "display_name": "pixel_mage" },
    "input": "",

    "trigger": { "id": "t1", "macro": "hydrate-sip", "queued": false }
  }
}
JavaScript Same token classes as CodeEditor: a block and an editor holding the same code look identical.
widget.js JavaScript
// Hydrate reminder: counts up drinks and celebrates every fifth.
const goal = sl.fields.goal ?? 8;
let drinks = 0;

sl.on('trigger', ({ user }) => {
  drinks += 1;
  sl.set('count', `${drinks} / ${goal}`);
  if (drinks % 5 === 0) {
    sl.play('cheer', { volume: 0.6 });
    sl.flash(`Thanks, ${user.name}!`);
  }
});

/* Reset at the start of every stream */
sl.on('stream.online', () => (drinks = 0));
Templates {placeholders} and {{#if}} blocks are tinted and underlined, not just coloured.
widget.html HTML
<div class="card">
  <img class="drop" src="{{asset 'drop.png'}}" alt="" />
  <p class="count">{{count}}</p>
  {{#if user}}
    <p class="thanks">Thanks, {{user.name}}!</p>
  {{else}}
    <p class="thanks">Stay hydrated</p>
  {{/if}}
</div>
body.json JSON template
{
  "content": "{user.name} redeemed {reward.title}",
  "username": "CroStream",
  "embeds": [
    {
      "title": "{reward.title}",
      "description": "{reward.input}",
      "color": 3999487,
      "fields": [
        { "name": "Cost", "value": "{reward.cost} points", "inline": true },
        { "name": "Viewers", "value": {stream.viewers}, "inline": true }
      ]
    }
  ]
}
Bare No bar: the copy button floats; the shade shows there's more to the right.
curl -X POST https://hooks.example.com/crostream/9f2c4e1a -H "Content-Type: application/json" -H "X-CroStream-Signature: sha256=5d41402abc4b2a76b9719d911017c592" --data @payload.json
Wrapped, numbered Wrapped lines hang under their own number. Unknown languages stay plain.
deliver.sh sh
curl -X POST https://hooks.example.com/crostream/9f2c4e1a -H "Content-Type: application/json" -H "X-CroStream-Signature: sha256=5d41402abc4b2a76b9719d911017c592" --data @payload.json
Shell bash, sh, zsh and shell: comments, strings, variables, flags and keywords.
deploy.sh Shell
#!/usr/bin/env bash
# Deliver a test event to the local listener.
set -euo pipefail

URL="${CROSTREAM_URL:-http://127.0.0.1:8080}"
for kind in follow cheer raid; do
  if curl -fsS -X POST "$URL/hooks/test" -H 'Content-Type: application/json' \
    -d "{"type": "$kind", "amount": 100}"; then
    echo "sent $kind"
  fi
done
PowerShell Cmdlets, parameters, variables and block comments.
deploy.ps1 PowerShell
<# Deliver a test event to the local listener. #>
param([string]$Url = 'http://127.0.0.1:8080')

foreach ($kind in 'follow', 'cheer', 'raid') {
  $body = @{ type = $kind; amount = 100 } | ConvertTo-Json
  Invoke-RestMethod -Method Post -Uri "$Url/hooks/test" -Body $body -ContentType 'application/json'
  Write-Host "sent $kind" -ForegroundColor Green # done
}

05CodeEditor

CodeEditor

The full editor the app uses for widgets and webhooks: highlighting shared with CodeBlock, folding, brackets, multiple cursors, find and replace, checks as you type, and hooks for product smarts.

Widget script An error from the preview is marked in the gutter, underlined, and listed below; click it to jump there.
  • --cs-syntax-*
JavaScript Ln 1, Col 1

Code editor. Tab indents; press Escape, then Tab, to move focus out.

Webhook body (JSON template) Placeholders are tinted and underlined. Type { for completion (a hook), hover one for docs (a hook). The missing comma on line 3 is caught as you type.
JSON template Ln 1, Col 1

Code editor. Tab indents; press Escape, then Tab, to move focus out.

JSON with {placeholders}; they're filled in when the webhook fires.

Styles CSS, including bare declarations.
CSS Ln 1, Col 1

Code editor. Tab indents; press Escape, then Tab, to move focus out.

Read-only template Selectable and searchable, not editable. {{#if}} keywords stand out.
HTML Ln 1, Col 1

Code editor. Tab indents; press Escape, then Tab, to move focus out.

Format hook Shift+Alt+F (or the button) runs the format hook. The app plugs Prettier in here.
JSON 148 / 4,000 Ln 1, Col 1

Code editor. Tab indents; press Escape, then Tab, to move focus out.Shift+Alt+F formats.

Keyboard Everything a code editor should do, and a way out.
Tab
Indent (Shift+Tab outdents)
Esc then Tab
Leave the editor; announced and shown in the status bar
Ctrl+F
Find and replace
Ctrl+/
Toggle comment
Alt+click, Ctrl+D
Add a cursor; select the next match
Ctrl+Space
Show completions
Ctrl+Shift+M
Problems panel
Shift+Alt+F
Format (when a format hook is set)

06CopyButton

CopyButton

Copies, then says so twice: the icon pops to a check, and a polite live region announces it.

Icon only Labelled for screen readers by what it copies.
With a label The width is set by the longest label, so nothing jumps.
Failure If the clipboard refuses, it says how to copy by hand instead of failing silently.

07JsonTree

JsonTree

A document's shape as an outline: every key with its type and a sample value; pick a value to map it to a variable. Branches fold, lists offer “each item” and “first item”, and values already in use show what they feed.

Picking Plain nested lists with buttons, so every row is an ordinary tab stop. The path being edited is highlighted.
Nothing picked yet
Collapsed, disabled openDepth 1 opens only the first level; disabled draws the values as not pickable.
Empty document A root with no children reads as a single value.
  • Nothing in it.