Page:
Home
Pages
Accordion
AccordionItem
Alert
Avatar
Badge
BarChart
Button
ButtonGroup
Card
Changelog
ChartLegend
Checkbox
CodeEditor
Collapsible
Combobox
CommandPalette
ContextMenu
CopyButton
DatePicker
Dialog
DonutChart
Drawer
Field
FileInput
FileList
Forms
Gauge
Getting started
Heatmap
Home
Image
InlineEdit
Input
Kbd
Label
LineChart
Menu
MultiSelect
NumberInput
Overlays
Pagination
Popover
Progress
RadioGroup
Scroller
Select
Separator
ShareBar
Sheet
Skeleton
Slider
Sparkline
Spinner
StatCard
Switch
Table
Tabs
TagsInput
Textarea
Theming
Toaster
Toggle
Tooltip
Tree
No results
19
Home
L4stIdi0t edited this page 2026-10-09 22:01:06 +02:00
Table of contents
driftwood
A hand-written Svelte 5 + Tailwind v4 component kit — 58 components, zero UI dependencies. No shadcn, no Melt, no Bits: every interactive component implements its own ARIA roles, states and keyboard handling, and everything is themed by CSS custom properties, so one token block re-themes the whole app.
Currently v0.24.0. Changelog · Getting started · Theming · Forms · Overlays
pnpm add @l4st/driftwood @lucide/svelte tw-animate-css
<script lang="ts">
import { Button, Card, toast } from '@l4st/driftwood';
</script>
Which one do I want?
| I need… | Use | Because |
|---|---|---|
| A value from a short list | Select | Up to a few dozen options. No text entry, so nothing can be mistyped. |
| A value from a long list | Combobox | Filters as you type. Past ~30 options, arrow-scanning stops being usable. |
| Several values at once | MultiSelect | Stays open after each pick, and summarises the count on the trigger. |
| Several free-form values, or picks plus new ones | TagsInput | Enter turns typed text into a tag. Give it options and it suggests from them too. |
| A date | DatePicker | A calendar under the field, a bottom sheet on a phone. The value is a YYYY-MM-DD string. |
| Two to five visible options | RadioGroup | One tab stop; arrows move and select. No hidden state. |
| A yes/no that applies immediately | Switch | A setting that takes effect on the spot. |
| A yes/no in a form | Checkbox | Submitted with the form, and can be indeterminate. |
| A blocking question | Dialog | Modal: focus trapped, page inert, Escape closes. |
| A panel of work off to one side | Sheet | The same modal contract, anchored to an edge. Room for a form a Dialog would crowd. |
| A panel that comes up from the bottom | Drawer | Snap points, dragged or keyed between. What a phone map does over its map. |
| A panel of content near a control | Popover | Anchored, dismissible, focus moves in. Not modal. |
| A list of commands | Menu | Roving focus, activates on Enter. You open it and say where. |
| One field that finds anything and runs it | CommandPalette | The ⌘K box: grouped rows, results from the server as you type, and it runs an action instead of setting a value. |
| Commands on right-click | ContextMenu | Wraps a region; opens a Menu on right-click, Shift+F10 or a long-press. |
| A hint about a control | Tooltip | Text only, on hover and focus. Never put a control inside one. |
| A message that stays on the page | Alert | Part of the layout, and still there after a reload. |
| A message about what just happened | Toaster | Transient, bottom-right, announced. Use toast(). |
| Progress with a known end | Progress | A value between 0 and 100. |
| Work of unknown length | Spinner | Or <Progress value={null} /> for a bar. |
| Content arriving | Skeleton | In the shape of what is coming, not a centred spinner. |
| A figure usually read, sometimes set exactly | InlineEdit | Plain text that becomes a field when clicked. No permanent input, no dialog. |
| A labelled control with an error | Field | Wires the label, hint, error, aria-describedby and aria-invalid. |
| Source code the user edits | CodeEditor | Highlighted, foldable, with its own undo stack. Bring your own grammar. |
| Files from the user | FileInput | Drag, drop, browse or paste. variant="line" is Input-sized; the default is a drop area. |
| Text the user will paste elsewhere | CopyButton | Copies on click, shows a check or a cross, and announces the result. |
| Files already chosen | FileList | Name, size, progress and a remove button. FileInput renders one for you. |
| A value over time | LineChart | Two or more series compared at one x, with a crosshair. |
| Magnitude across categories | BarChart | Grouped or stacked, vertical or horizontal. |
| Parts of a whole | DonutChart | Up to five parts, with the total in the middle. |
| Many parts of a whole, with names | ShareBar | One bar and a list under it; hover links the two, a row can pick its part. |
| A number against its range | Gauge | One figure, optionally banded good-to-bad. |
| Two axes and one number | Heatmap | A sequential ramp; the shape of a pattern, not exact values. |
| More content than fits | Scroller | Scrolls either way with a button at each end, hidden scrollbar, and a load-more channel. |
| A trend beside a number | Sparkline | Glyph-sized, no axes. Or trend on a StatCard. |
All 58 components
Layout
![]() Card Surface for a block of related content: an optional title and description header, then whatever you render inside |
![]() StatCard A single number worth looking at — the unit of a dashboard's top row |
![]() Accordion A set of disclosure sections |
![]() AccordionItem One section of an Accordion: a native <button aria-expanded aria-controls> disclosing a labelled region |
![]() Collapsible Fully self-contained accessible disclosure — no UI dependency |
![]() Separator A rule between things |
![]() Table A styled <table>, not a data grid |
![]() Scroller A strip of content that scrolls, with a button at each end |
Actions
![]() Button The kit's primary action |
![]() ButtonGroup Visually joins a row of <Button>s into a segmented group |
![]() CopyButton Copies text to the clipboard and says whether it worked: the copy icon turns away, a check springs in and draws its own stroke (a cross draws and shakes), a tint blooms across the button, and after resetAfter it all settles back |
![]() Toggle Accessible toggle button (aria-pressed) — for on/off controls like a formatting button or a favourite |
![]() Menu Accessible floating menu (APG menu): roving focus, ↑/↓/Home/End, Enter/ Space activate, Escape/Tab/click-outside close, focus returns to the opener |
![]() ContextMenu Replaces the browser's context menu over a region with a Menu |
Forms
![]() Field Label, control, hint and error as one unit, with the ids wired up |
![]() Input Accessible text input |
![]() FileInput Picking files, in the two shapes a form actually wants: svelte <FileInput bind:files variant="line" accept=".csv" /> a control the size of an Input, for a field that sits in a column with other fields <FileInput bind:files multiple /> a drop area, for when choosing files IS the screen Both take a drop, both open the picker on click, and both are one real <input type="file"> underneath — so Enter and Space open the picker, the file dialog is the operating system's, and a name submits with the form |
![]() FileList The rows under a file picker: an icon for the kind, the name, the size, and a remove button |
![]() Textarea Multi-line input |
![]() CodeEditor A code editor: a highlighted layer behind a transparent textarea |
![]() Combobox Accessible combobox with list autocomplete (APG "combobox with list autocomplete, none selected"): a real <input> that filters the list as you type, with DOM focus staying in the field and the active option tracked through aria-activedescendant |
![]() RadioGroup Accessible radio group (APG radio group): one tab stop for the whole group, arrows move and select, and the checked radio is the tabbable one — which is what makes a keyboard user land back where they left |
![]() NumberInput Numeric field with a unit suffix and real clamping — the thing a plain <input type="number"> does not give you |
![]() InlineEdit A value shown as plain text that becomes a field when you click it — for a figure that is read far more often than it is set: a dimension in a readout, a layer's name |
![]() Label A form label |
![]() Select Custom accessible select (APG "select-only combobox"): DOM focus stays on the trigger, the highlighted option is tracked via aria-activedescendant |
![]() MultiSelect Multi-selectable variant of this library's Select (APG "select-only combobox"): DOM focus stays on the trigger, the active option is tracked with aria-activedescendant |
![]() DatePicker A date field: a trigger showing the chosen date, and a calendar to pick one from |
![]() TagsInput A field that collects several short values as tags: type, press Enter (or the delimiter), and what you typed becomes a removable chip |
![]() Checkbox Accessible checkbox: role="checkbox" with aria-checked (true |
false | "mixed" for indeterminate) |
Feedback
![]() Badge Semantic variants — all colors resolve to theme tokens (see layout.css), so this is the single place any badge color is decided |
![]() Alert A persistent message about the surrounding content — a warning above a form, an explanation of an empty state |
![]() Progress role="progressbar" with aria-value* |
![]() Spinner A small indeterminate spinner that inherits the current text colour |
![]() Skeleton Loading placeholder |
![]() Toaster Melt/sonner-style toaster: toasts collapse into a peeking stack at the bottom-right and fan out on hover/focus |
Avatar A person or a thing, as a round image with a fallback |
![]() Image An <img> that holds its space, shows a ThumbHash while it loads, fades in when decoded, never shows the browser's broken-image glyph, and swaps to a dark variant with the theme |
Charts
![]() LineChart A value over an ordered sequence — time, almost always |
![]() BarChart Magnitude across a handful of named things |
![]() DonutChart Parts of a whole, when the whole is worth naming and the parts are few |
![]() ShareBar Parts of a whole as one bar, with the parts listed under it |
![]() Heatmap A matrix of magnitudes — hour against weekday, endpoint against day, anything with two labelled axes and one number in each cell |
![]() Gauge One number against the range it lives in — a disk that is x% full, a load average, a score |
![]() Sparkline A trend at glyph size: no axes, no grid, no labels — just the shape of a series, meant to sit inside a table cell or beside a number |
![]() ChartLegend The identity key for a chart: a swatch and a name per series |
Overlays
![]() Dialog Accessible modal dialog that doubles as a bottom drawer on mobile |
![]() Sheet A modal panel anchored to an edge of the viewport, for the work that is too wide for a Dialog and too tied to the page to be a route: filters, a detail pane, a settings drawer |
![]() Drawer A bottom sheet that settles at more than one height — the pattern a phone map uses: a peek showing the headline, a half height for the list, and a full height for the detail, moved between by dragging the grabber or by the keyboard |
![]() Tooltip Accessible tooltip, melt-inspired: the trigger snippet receives a props object to spread onto YOUR interactive element, so aria-describedby lands on the real trigger |
![]() Popover A floating panel anchored to its trigger — the generic surface Menu and Select are specialisations of |
Navigation
![]() Tree Accessible tree view (APG tree pattern): role=tree/treeitem/group, roving tabindex (one item tabbable), aria-expanded/selected |
![]() Tabs Accessible tabs (APG tabs): role=tablist/tab/tabpanel, roving tabindex — one tab in the tab order, arrows move between them — and automatic activation, which is the APG default for cheap panels |
![]() Pagination Page navigation |
![]() CommandPalette The ⌘K box: one field that finds anything and runs it |
![]() Kbd Renders a keyboard shortcut with OS-appropriate glyphs: ⌘⇧⌥ on macOS and Ctrl/Shift/Alt everywhere else |
These pages are generated from the source by pnpm wiki in the
repository — a fix belongs in the component, not here.
driftwood
Layout
Actions
Forms
- Field
- Input
- FileInput
- FileList
- Textarea
- CodeEditor
- Combobox
- RadioGroup
- NumberInput
- InlineEdit
- Label
- Select
- MultiSelect
- DatePicker
- TagsInput
- Checkbox
- Switch
- Slider
Feedback
Charts
Overlays
Navigation
Generated from the source by pnpm wiki · repository · v0.24.0























































