components

components.

copy-paste, dark-only, no abstractions you don't own. install via the cli — the component lives in your codebase, not behind a package boundary.

all components
accordion
collapsible rows on native <details>/<summary> with a rotating chevron. share a name across items for one-open-at-a-time behavior. zero javascript state.
view
add-to-calendar
"add to calendar" for a confirmed booking: google, outlook, office 365 and yahoo as links, plus a generated .ics for everything else. the ics is built in-component (rfc 5545 folding and escaping included) so it works with no backend; icsHref overrides it when the server owns the canonical file. exports buildIcs and calendarUrl.
view
album-art
square cover tile with a real fallback state — expired cdn links and art-less tracks are the norm in music apis, so onError swaps to a disc glyph without changing the tile's footprint. pass an array of urls for a playlist mosaic (halves, half-plus-quarters, or a grid), and bleed to throw the cover's colour onto the page behind it.
view
article
article reading layout — back link, banner, title, date + tags, then a body slot with staggered fade-ins. pair with prose for the markdown body.
view
article-list
searchable, tag-filterable grid of article cards. animated banners stay frozen in grayscale until hover, then play in full color. cards stagger their entrance fade.
view
ascii
seamless ascii-art renderer — point src at a .txt file (or pass a string child) and it renders on a fixed character grid, no ligatures, no spacing drift. wrap it in chrome to foil every glyph.
view
ascii-shader
ascii fragment shader — supply (x, y, t) => luminance and it paints a character grid. the general form of what donut does for one fixed torus. one string assigned to textContent per frame, capped fps, paused off-screen by an IntersectionObserver, and static under reduced motion. ships plasma, ripple and tunnel presets.
view
asset-sidebar
scrollable image/asset sidebar. drag a row into a textarea or click insert; optional drop zone for uploads.
view
availability-grid
the weekly "when am i free" editor: a switch per day plus any number of time windows, with copy-to-open-days. inverted and overlapping windows are flagged inline and never silently corrected — rewriting what someone typed is how you ship a schedule they didn't ask for. exports isAvailabilityValid for the save button.
view
avatar-stack
overlapping square tiles for "who else is here" — initials when there's no image, a name pill on hover, and an overflow counter as the last tile rather than a line of text. pass total when people is a fetched slice and it counts the ones you never loaded. pfp is the single 3d-tilt portrait; this is the crowd.
view
badge
small chip. static label by default; pass onClick to make it a toggle/filter chip, with active swapping to the solid look.
view
bar-list
ranked horizontal bar list — each row's proportional bar is the row's own background, with the label on the left and the value right-aligned. rows can link out or fire a click handler; per-item colors are opt-in and tinted back so labels stay legible.
view
blueprint
engineering graph-paper substrate — minor/major grid, corner registration marks, edge fade, and an optional pointer crosshair with a live coordinate readout. four stacked linear-gradients rather than a tiled image, so it stays crisp at any zoom and costs no request.
view
breadcrumb
breadcrumb trail from caller-supplied items; the last crumb is the muted current page. framework-agnostic links via linkComponent. ships a crumbsFromPath helper.
view
break-overlay
full-screen rest overlay with a large live countdown and resume / extend / skip actions. traps focus, locks scroll, and only escapes when you let it.
view
button
polymorphic button with five variants, optional icons, hover tooltip, and click-to-clipboard. renders as an anchor when given href.
view
calendar
month date grid with selectable days, today ring, and prev/next header. pass renderDay to layer dots or counts onto cells, or renderCell + cellClassName to take over cells for agenda-style month views.
view
calendar-nav
period-navigation header: a day/month/year switcher plus prev / today / next controls. fully controlled, no router coupling.
view
callout
inline notice attached to the thing it's about — the counterpart to toast, which interrupts from a corner and leaves. aria role follows severity: danger asserts, warn and success announce politely, a plain note stays silent.
view
card
compositional bordered card: Card shell plus CardHeader / CardTitle / CardMeta / CardBody / CardActions slots.
view
chat-composer
the line you type into, under a chat-log. split from the log rather than bundled with it because the two have different reasons to re-render — the log repaints on every arriving message, the composer only on your own keystrokes — and because a read-only room is a real state: render the log without this and there is nothing to disable or explain. owns the draft and nothing else; onSend may be async, and a rejected send hands the sentence back rather than losing it, because losing a typed sentence to a dropped request is the one failure a chat box must not have.
view
chat-log
an append-only stream of messages that follows the newest one — unless the reader has scrolled up to read something, in which case it holds still and offers a jump back. track-list and article-list render a collection that happens to be ordered; this is a *stream*, and its whole contract is what happens when content arrives while you're looking at it, which is a behaviour neither of those has and neither should grow. groups consecutive messages from one sender, marks the viewer's own, and announces additions via role=log.
view
checkbox
square checkbox with a check-on-fill. wraps a native checkbox so it works in forms; thin border, no corners, fills white with a black check when checked.
view
chrome
wrapper that renders every text glyph inside it as shimmering chrome foil.
view
clock
live clock — thin-stroke analog face, tabular-nums digital readout, or both. any iana time zone via intl, optional sweep second hand. ssr-safe: renders a stable midnight form until mounted.
view
code-block
syntax-highlighted code box with a built-in copy button. monochrome prism theme tuned for a black background.
view
collapsible-prose
splits markdown into collapsible sections on each ## heading. bring your own renderer via renderMarkdown — typically prose.
view
color-swatch
a fixed-palette color chip plus a controlled palette picker, with a muted default palette and a next-unused-color helper.
view
combobox
searchable select with optional color swatches, inline create, and clear. behavior split into a headless useCombobox hook. generalized from the calendar category picker.
view
command-palette
spotlight-style command palette: cmd+k opens a centered search overlay with grouped, keyboard-navigable results.
view
copy-button
copy-to-clipboard button with copied/error feedback states.
view
count-up
animated number that tweens to its target with an easeout curve, starting when scrolled into view. dependency-free requestanimationframe, respects prefers-reduced-motion.
view
date-strip
horizontal run of days — the linear counterpart to calendar's month grid, for when the next opening matters more than which week it's in. availability is a dot, not a number; a known count of zero disables the day while an absent count leaves it alone, so a loading strip never claims the week is empty.
view
desk
the full markdown workbench: toolbar, image sidebar, split editor with a two-way synced preview, and floating drawing windows. bring your own markdown renderer; backend ops are callbacks.
view
detail-list
label/value metadata as a real <dl>, in row, two-column grid or stacked layouts. for the handful of unrelated facts about one thing — the case stat-tile (one number) and manager-table (many identical rows) both miss. server-renderable.
view
dialog
promise-based confirm and alert dialogs.
view
dimension
architect's dimension line — witness lines, arrow / tick / dot caps, and the measurement sitting in a break in the rule. every part inherits currentColor, so recolouring the whole annotation is one prop. horizontal or vertical.
view
docket
work order / docket — mono header with a reference, label-value rows, a slot for a stamp, and an optional tear-off stub below a perforation. detail-list renders the same pairs, but a docket is the document around them: numbered, marked, and torn. the notches are opaque circles in the page colour rather than a mask, because masking the card to cut real holes also masks the border.
view
donut
spinning ascii torus baked off-thread in a shared web worker and replayed as a seamless loop. multiple donuts share one bake.
view
drawing-window
floating, draggable, resizable paint window: brush/eraser, colors, undo/redo, zoom + pan, and canvas-size presets. save emits png(s) via onSave, or downloads.
view
dropzone
standalone drag-and-drop upload zone — validates a drop against accept/maxSize/maxFiles and hands you File[], with optional rows showing size, upload progress and errors. stateless by design: upload transport is yours. drag depth is counted rather than flagged, so the highlight doesn't strobe when the pointer crosses a child, and the zone is a real button so click, enter and space all open the picker.
view
editor
split-pane markdown editor whose live preview scrolls and highlights in sync, both ways. bring your own markdown renderer (e.g. prose).
view
editor-toolbar
the bar above a markdown editor: edit/preview/split toggle, format buttons, and an action cluster. with enableDrawing it owns the floating numbered drawing windows.
view
empty-state
the "nothing here" panel — icon, title, reason, and the action that would fix it. dashed border by default, matching the library's existing signal for a slot that could hold something but doesn't. server-renderable.
view
fade-in
fade + translate a node in on mount. pure css keyframe with per-instance delay/offset; stagger a list via the staggerDelay helper. honors prefers-reduced-motion.
view
field
label, control, hint and error as one accessible unit. the render-prop form hands the control its id, aria-describedby, aria-invalid and required already computed, so a field is announced correctly without matching ids by hand. an error replaces the hint rather than stacking under it.
view
file-card
animated stacked-paper download card — papers fan out on hover, still under reduced motion. renders as a link or button. composes stack.
view
file-grid
asset-browser grid of stacked-paper file cards with press-and-drag-to-trash delete (pointer-driven, so it never triggers native link-drag; the trash zone only appears while dragging) and a type-the-name-to-confirm dialog. composes file-card, input, and button.
view
gallery
searchable, filterable, sortable project card grid with chrome-foiled pinned markers, tech chips, and repo/live links. composes card, badge, menu, and chrome.
view
grain
paper / film texture overlay — speckle, fibrous paper stock, or a dot screen. the texture is an inline feTurbulence data uri rather than a bundled png, so it is a few hundred bytes and resolution-independent. pointer-events-none and aria-hidden, so it can sit over live ui at any z-index.
view
hazard
diagonal caution-stripe tape — a band that reads as a boundary rather than a border, plus a HazardFrame that tapes the edges of any block. hard-stop repeating gradients stay knife-sharp at any pitch, and the optional march animates by exactly one pitch so the loop is seamless.
view
heatmap
year activity grid — 12 mini month grids of day cells tinted by value (contribution-graph style), with a less-to-more legend. generalized from the justin06lee.dev year view.
view
image-cropper
drag-to-reposition, scroll/slider-to-zoom image cropper. pan and zoom are clamped so the image always covers the frame. emits { url, scale, x, y }.
view
inline-edit
blur-to-save editable field. holds a local draft, commits onblur and enter, shows a pending state, rolls back on error, escape cancels. behavior split into a headless useInlineEdit hook.
view
input
minimal text input. thin border, no corners.
view
interval-picker
duration picker for "every n minutes" settings — quick presets in a roving-tabindex radiogroup plus a stepper for anything in between. always emits a plain minute count.
view
intro
full-screen intro overlay: a hero holds on top while lines take turns in a fixed slot beneath it, then the whole scene fades out. skippable, with a play-once localStorage gate.
view
kbd
a macos-style keycap: mono glyph on a faint raised cap with a heavier bottom edge. compose combos by placing several side by side.
view
lane-bar
multi-lane sibling of now-playing-bar: several activities running in parallel, each with a live elapsed timer and its own action slot, all driven by one shared tick.
view
live-badge
"happening right now" — a pulsing dot, a word, and an optional detail. badge says what a thing is; this says what it is doing at this second, across four fixed states, with role=status so going live is announced. the pulse is an expanding ring rather than a blinking dot, and drops out under reduced motion.
view
login-form
styled credential form with loading / error / rate-limited states and enter-to-submit. transport-agnostic via an injected onSubmit; behavior split into a headless useLoginForm hook. rate limiting and lockout belong on the consumer's backend.
view
lyrics
time-synced lyrics with the current line lit and the rest receding. shares playhead's clock, so lines advance between polls; auto-scroll centres the active line and stands down for eight seconds after you scroll by hand. ships parseLrc() for .lrc sheets, and renders unsynced lyrics as a plain sheet.
view
manager-table
admin table with inline rename, swatch recolor, archive, and confirmed delete. every mutation is a callback — bring your own state. rows can be locked (no rename/delete), and every handler may be async — a rejection surfaces inline under the row.
view
marquee
infinite scrolling ticker band. speed is px/s and the duration is derived from the measured content width, so a short label and a long sentence travel at the same rate. the copy count is computed from the container width rather than hardcoded, so narrow content never leaves a hole. static under reduced motion.
view
menu
action dropdown: a trigger opening a list of items, each running its onSelect. optional selected markers (e.g. a sort menu). behavior split into a headless useMenu hook.
view
navbar
fixed top nav with inline desktop links and a hamburger-driven slide-in panel below md. routes are caller-supplied; behavior split into a headless useNavbar hook.
view
not-found
the justin06lee.dev 404 block: a random ascii cat fades in above a big mono headline, a muted excuse, and footer links. ten cats ship embedded. installs app/not-found.tsx so next.js picks it up with zero wiring.
view
now-playing-bar
sticky bottom bar for a running activity: live elapsed timer and an action slot. omit startedAt for an idle state.
view
pagination
page navigation with boundary pages, a sibling window and ellipsis gaps, plus a compact prev/next variant. the window shifts rather than shrinking at the ends, so the control keeps a constant width as you page through it, and a gap that would elide exactly one page renders that page instead. the range logic ships as a separate tested module.
view
pencil-rule
a rule that draws itself with a pencil riding the leading edge. the stroke is a scaled element rather than an animated width, so it composites and never causes layout; the pencil shares the stroke's timing function, which is what keeps the nib pinned to the end of the line. draws on scroll-into-view by default. under reduced motion the finished rule renders immediately and the pencil never appears.
view
pfp
profile-picture tile: an image framed in a bordered square that tilts in 3d on hover with a thick white cartoon glint sweeping diagonally across it. frame the subject with x/y/scale; size it via className.
view
playhead
playback scrubber with elapsed / total times, drag-and-key seeking, and a clock of its own — give it startedAt and it extrapolates between polls, so a remotely-sourced position moves smoothly instead of stepping. progress covers a bare determinate bar; this one knows about time.
view
progress
linear progress bar — square, three track heights, bare or outlined. determinate from value/max, or an indeterminate sweep for unknown durations. honors prefers-reduced-motion.
view
prose
markdown renderer with the justin06lee.dev prose styling — GFM, KaTeX math, heading slugs, and syntax-highlighted code blocks (via code-block). dark-only. pass markdown as the string child.
view
radio-group
single-choice group with a proper roving tabindex — arrows move focus and selection, wrap at the ends and skip disabled options, and the group is one tab stop. "cards" variant adds a description line and a trailing meta slot for choosing between things rather than values.
view
rainbow
wrapper that cycles every text character inside it through a staggered rainbow.
view
range
thin minimal slider. native input with a custom 12px thumb on a 2px track; thumb scales on hover.
view
scramble
wrapper that scrambles every word inside it on hover.
view
segmented
controlled segmented control — a row of mutually exclusive options, active one bordered. compact uppercase variant for mode toggles.
view
select
styled dropdown select with keyboard navigation and option prefix slots (e.g. palette swatches).
view
sheet
animated slide-in panel from a screen edge with a dimmed backdrop. closes on backdrop click, escape, or close button, and locks body scroll while open.
view
shelf
horizontally scrolling row of cards — the browsable counterpart to gallery's searchable grid. arrows appear only once the row genuinely overflows (measured, not assumed) and disable at their end; scrolling stays native, so trackpad, touch and keyboard all work untouched.
view
showcase
framed preview container with a dotted background, optional label, caption, and note. exports a Row helper for explicit row breaks.
view
sidebar
grouped docs sidebar with active-item highlighting and an optional search filter. framework-agnostic links via linkComponent.
view
skeleton
loading placeholder in block, text and circle shapes. shimmer keyframes ship inline via a hoisted style tag, so there is nothing to wire into globals.css. under reduced motion the sweep stops but the block stays — removing it would collapse the layout it exists to reserve.
view
slot-picker
column or grid of bookable times with a two-step confirm: picking a slot splits the row so the confirm button lands under the cursor that just chose the time, making the commit deliberate and a mis-tap free. one tab stop with arrow-key movement, because a day can hold thirty slots.
view
socials
row of social links from a links map — only supplied platforms render. tooltip on hover; the email entry copies to clipboard.
view
sound-bars
the little dancing meter that marks the row currently playing. pure css, no state — each bar's period and phase come from its index, so the pattern is identical on the server and the client. paused and reduced-motion hold resting heights rather than flattening.
view
sparkline
tiny inline svg trend line — 80x24 by default so it sits in a line of text. linear or catmull-rom smooth, optional area fill and square point markers, no chart library and no dependencies.
view
spectrum
live frequency analyser off a web audio AnalyserNode (or any sample callback). canvas, logarithmically-spaced columns, instant attack and gradual decay so it reads as loudness instead of strobing. waveform is the static counterpart — a shape that never repaints.
view
sprite-scrubber
scrub through a sprite-sheet grid by dragging across it — pointer x maps to a frame index.
view
stack
stacked paper card with hovered fan-out spring animation.
view
stamp
rubber-stamp overlay — mono uppercase inside a double rule, rotated off square, optionally distressed. unlike badge, which is a flat chip in a row of metadata, a stamp is an assertion applied on top of something: it rotates, it overlaps, it sits over the document it marks. the distress is a turbulence mask, so it inherits the ink colour and loads nothing.
view
stat-tile
big-number kpi tile — mono uppercase label, one headline figure with an optional unit, a delta chip that turns red only when the change is the bad one, plus footnote, icon and a slot for an inline sparkline. server-renderable; opts into count-up when animated.
view
stepper
numbered progress rail for a multi-step flow. unlike tabs — peers you can visit in any order — a stepper asserts sequence: it renders as an ordered list, marks the active step with aria-current, and only makes already-completed steps clickable.
view
streak
streak indicator — the current unbroken run, an optional all-time best, and a compact strip of recent hit/miss day cells so a near-miss stays visible. one sr-only sentence carries the whole thing to screen readers.
view
switch
instant on/off toggle with role="switch", for settings that take effect the moment they move — as opposed to checkbox, which states an intent a submit later commits. square track, square knob.
view
tabs
tab-strip in a bordered pill or underline style. controlled selection with roving-tabindex arrow-key nav and ARIA, split into a headless useTabs hook.
view
tag-input
chip input — enter or comma adds a tag, backspace removes the last, suggestions append on click. dedupes and trims.
view
textarea
minimal multiline input. matches input — thin border, square corners, vertical resize. optional live character counter that reads '120 / 500' against maxLength and warns as it fills.
view
timeline
day schedule — a 24h vertical axis with positioned event blocks and an optional live now-line. blocks placed by minutes-of-day; supports clickable blocks, multiple labeled tracks on one axis, streamed marker slots, and opt-in drag editing. generalized from the justin06lee.dev day view.
view
timer-ring
circular progress ring driven by stroke-dasharray. takes a value/max pair, or an endsAt deadline it counts down to on its own clock, with the remaining time in the center.
view
timezone-select
searchable iana timezone picker that shows what time it actually is in each zone, sorted by utc offset. combobox covers searchable select in general; this is the case where the label alone can't answer the question — you're choosing "the one where it's 4pm now". clock starts null and fills in after mount so ssr and hydration agree.
view
toast
stacked, auto-dismissing notifications. a ToastProvider plus a useToast() hook, with pause-on-hover, a polite live region, and six anchor corners.
view
toc
sticky table-of-contents with scroll-spy highlighting via IntersectionObserver. give it the page headings; the active row tracks scroll. behavior split into a headless useToc hook.
view
tooltip
white slide-up pill shown on hover or keyboard focus. pure CSS, wraps any trigger. aria-hidden — label the trigger itself.
view
track-list
queue, history or tracklist — title / artist / duration rows with the current one marked by a live sound-bars meter in place of its number, so nothing reflows when playback moves. each row is one real control: a link with href, a button with onSelect, inert otherwise.
view
transport
playback controls — skip, play/pause, shuffle and repeat. every control appears only when handed a callback, so the same component covers a full player and a listen-only page with nothing but a play button. repeat cycles off → all → one and announces the mode it moves to.
view
vinyl
a record on a platter — grooves as one repeating-radial-gradient, album art in the centre label, optional tonearm. pausing sets animation-play-state so the record holds where it stopped instead of snapping to twelve o'clock. round on purpose: it's the object, not a corner radius.
view
volume
level-reflecting icon that mutes, plus a filled slider. range is the general-purpose slider; this is the specific case — muting keeps the value untouched so unmuting restores exactly where you were, and the track can collapse to just the icon until hovered.
view
waveform
a track's amplitude envelope with the played portion filled in, seekable by click. bars are elements rather than a canvas — crisp at every dpr, hoverable, and the fill is a css transition instead of a repaint loop. ships samplePeaks() to downsample raw pcm.
view