@dorsk/tsumikit

Svelte 5 · pure CSS · zero deps
AppShell demo →
One token contract, themeable atoms & molecules. Current theme: Dark. Try the pickers top-right — every section below re-themes live and scales with the text control. Showcase Plum is not built in: this page calls theme.register() and ships its own [data-theme] block.

Foundations

Typography

Heading level 1

Heading level 2

Heading level 3

Heading level 4


Body — the default reading text. Label — form labels & field captions. Caption — small meta text. Code — monospace inline.
default muted faint accent success warn danger
normal medium semibold bold
numeric 1234.50% default 1234.50%
eyebrow italic nowrap text uppercase leading none scale=false 13px
Font-scale slider vs a pinned run — only the first line follows the picker:
size="lg" scales with --fs-scale size="lg" scale=false stays pinned
measure="40ch" — a paragraph capped at forty characters wide so long lines stay readable.

Truncated heading that runs past its container

Theme tokens

--bg
--bg-elevated
--bg-elevated-2
--surface
--border
--border-strong
--text
--text-muted
--text-faint
--accent
--link
--ok
--warn
--danger
--info

Text scaling opt-in

Optional in-app text-size control (drives --fs-scale, text tokens only). Most apps should rely on browser zoom and the user's OS/browser font-size instead — the kit is rem-based and never resets the root size, so both are respected out of the box. Reach for this only in reading-dense apps (chat, docs) that want to grow body text while keeping chrome compact.

Layout

Layout: Stack · Cluster · AutoGrid

Cluster — wraps, never overflows:
alpha beta gamma delta epsilon zeta
Cluster stackAt="md" — buttons stack full-width when the cluster is under 40rem:
AutoGrid — columns adapt to available width (resize the window):
Cell 1
Cell 2
Cell 3
Cell 4
Cell 5
Cell 6
AutoGrid — capped column width (max), left-packed instead of stretching:
Fixed 1
Fixed 2
Fixed 3

Card

Static card

An elevated surface with token-driven padding, border and radius.

Stacked card

Looks like a pile — two layers peek out bottom-right.

Stacked (info)

Back layers tinted with the info/blue hue.
tone info
tone ok
tone warn
tone danger
tone attention

Interactive card

Enter/Space activate; the nested button stays independent.

maxWidth 22rem

Fills its row up to the cap.

MasterDetail

Two columns above its own 48rem breakpoint; below it one pane at a time with a sticky back header. Drive selected from the URL to make each pane a route.
Alice

Alice

Detail pane for Alice.
Same component boxed at 22rem — the mobile regime on desktop:
Nothing selected
Pick someone on the left.

Actions

Button

Polymorphic roots — as="a" / as="button" keep the same chrome and focus ring:
Button as="a" Card as="a"
Hit area — hitArea="compact" drops the 44px touch slab (outlined box shows the real hit box on touch):
Variant × tone matrix (primary keeps a readable on-accent label):
npm i @dorsk/tsumikit

Icon & IconButton

Shared box scale (xs/sm/md/lg) across IconButton, SelectButton, Popover and Button square — 44px hit slab on touch:

All registry glyphs (sized at 1em — they scale with text):
back
arrow-right
arrow-up
arrow-down
chevron-up
chevron-down
chevron-left
chevron-right
menu
more
external
log-out
plus
minus
check
x
search
filter
copy
edit
trash
save
download
upload
send
share
retry
settings
play
pause
stop
music
tv
film
disc
file
file-text
folder
archive
image
markdown
list
grid
link
unlink
text-cursor
tag
bookmark
star
heart
fork
live
eye
eye-off
lock
unlock
bell
mail
calendar
clock
home
user
users
sun
moon
loader
info
warning
help
check-circle
x-circle
alert-circle
Custom (open) icon via children snippet:
Spinner (halts under prefers-reduced-motion):

Toggle · OptionButton · SelectButton



SelectButton (native select over a glyph button): selected: a

SegmentedControl

selected: all
view: grid
scope: album

Forms

Form atoms & Field

Helper text below the control.
This field is required.
Press Ctrl to submit.
Ctrl K Ctrl Alt Esc
On
40%
50

Checkbox & RadioGroup

Fieldset

Drag a card between pools (HTML5 DnD); buttons are the keyboard path.
Pool A
Ledger
Wallet
Pool B
Exchange

FileButton & Dropzone

native picker, keyboard-focusable
Drop files here or click to browse
overlay mode — wraps content, drop UI shows only while dragging a file over it

Navigation

Tabs

Overview panel — arrow keys move between tabs.

Pagination

Page mode — bind:page + pageCount: Offset mode, small, with range — bind:offset + limit + total: Compact collapse under 24rem of container width:

Accordion

What is it?
Built on native <details> — zero JS, full keyboard support.
Single-open mode
With multiple=false it uses the platform's exclusive-accordion (one open at a time).
Styling
The chevron rotates via a CSS transition on [open].

Data display

Badge · Link · Dot

neutral ok warn danger info
~/path/to/file removable typescript
uppercase stable
soft ok warn danger 3
accent muted violet color dot icon text · 12:34
xs 8 128 a very long account name that clips
Anchor link View all →
active stale dead hibernated custom ring

Metric · StatTile

Tracks
1284
Size
42.7 GB
Quality
FLAC
lossless · 16-bit
Added
37 this week
+12% vs last week

Surface variants — tiles (via Metric) and panels (via Card) opt into the same theme-aware shade by prop, no :global override:
Base
base
Raised
raised
Sunken
sunken
surface base
surface raised
surface sunken

SectionHeader · KeyValue · LoadMore

Recent sessions

12 last 24h
Group rows render here while open.

Failed

2
live

sakura

7

Host

sakura
Running
3
Queued
0
Image
cctui-worker:0.7.3
pulled 2h ago
Load
1.42
Tokens
128000
Cost
$0.42
Failed to load
No more items

DataTable generic <T>

NameRoleStatus
api-gatewayservice ok
worker-02worker warn
cache-01cache danger
layout="fixed" + truncate, hideBelow on the role column, rowTone accent bar, hover-revealed rowActions, size="sm".
RoleStatusActions
api-gatewayservice ok
worker-02worker warn
cache-01cache danger
responsive="stack" in a 22rem-wide box: rows become cards via Column.role (title / detail / meta / hidden), actions stay on the title line.
NameRoleStatusIdActions
api-gatewayservice ok 1
worker-02worker warn 2
cache-01cache danger 3
Same table with stackBelow="30rem": it stays tabular in this 34rem box and stacks once the box drops under 30rem.
NameRoleStatusId
api-gatewayservice ok 1
worker-02worker warn 2
cache-01cache danger 3

Timestamp subdued · click for UTC / epoch / zone

Renders an instant in one of six modes (date, time, datetime, relative, iso, short-iso), subdued by default. The date/time/datetime modes follow the viewer's zone unless you pass utc. Click it for a read-only popover with the same instant as UTC, relative, your time zone and the unix epoch. Opt into selectable to let viewers switch the inline mode.
datetime: date: date (utc): iso: short-iso: time: relative: mono: selectable: no popover:

GitRef branch · PR · ±diff

Branch chip, pull-request link and +/− diff stats in one inline row; every part is optional. The PR state picks its tone (open ok, merged accent, closed danger, draft muted). collapse="auto" keeps only the glyphs when the nearest .cq container is narrower than 18rem; glyph forces it.
branch: feat/wave-1-new-components-with-a-long-name pr: DorskFR/tsumikit#77 all three: fix/resizable-panel #78 +128 −42 glyph: fix/resizable-panel DorskFR/tsumikit#79 +3 −1

WorkingDir fish-style · degrades with width

Drag the handle: ancestors abbreviate one at a time left to right, then only the leaf stays, then the leaf ellipsises down to minLeaf chars. The full path is always in the tooltip.
/home/dorsk/Documents/tsumikit

Truncate char-count · hover reveal

Character-count truncation (the counterpart to <Text truncate>'s CSS ellipsis). Hover or focus a truncated value to reveal the full text.
middle: 0x71C765…6d8976F end: a-very-long-resourc… start: …/14/request-trace.log fits (no tooltip): short

CodeBlock BYO highlighter

typescript
// install and use
import { Button, theme } from '@dorsk/tsumikit';

function greet(name) {
  return `Hello, ${name}!`;
}
Plain (no highlighter, no line numbers):
setup.sh
git clone …
npm install
npm run dev

Feedback

EmptyState

No results

No albums match your filters. Try broadening the search or clearing filters.

Your library is empty

Add an artist or album to start building your collection.

Nothing here yet

This section hasn't been set up.

Loading sessions…

No results

Try a different query.

Skeleton:

Callout

Auto-search runs in the background and links matches as it goes.

Linked

12 releases matched and were linked to this collection.

Some matches need review

3 releases had several candidates and were left unlinked.
Searching MusicBrainz for 48 releases…

Narrow container

Wraps its body and actions instead of overflowing.

Toasts

Progress

  • conforming 412
  • nonconforming 12
  • blocked 0
  • done 300
  • skipped 120

Gauge

🍃

CapBar

Anthropic
62% · resets 3h
▲ using 62% · cap 80%
OpenAI
81% · resets 12h
Locked
95% · over cap

Overlays

Popover & Menu native top layer

Open a menu and navigate with ↑/↓, Enter to select.

Tooltip

ConfirmModal

Drawer

Side panel on the native <dialog>: Escape, scrim click and the close button close it; focus is trapped; body scroll is locked. A nav snippet becomes a 150px page column beside the content on wide viewports and a horizontal strip above it under 48rem, where the panel goes full-screen.
Edit src/lib/styles/variables.css to retheme everything · add a [data-theme] block for a new theme · components never hard-code a color or pixel.
Delete library?
This removes the library and all of its items. This cannot be undone.
Provider General
2 changes