UI
Installation
Add any component here to your own app with the shadcn CLI. It takes on your theme through shadcn's tokens.
Set up shadcn
The components install into any app set up for shadcn/ui with Tailwind CSS v4. If yours isn't yet, start there:
npx shadcn@latest initAdd a component
Point the shadcn CLI at a component's URL. It writes the source into your project, installs its npm dependencies, and pulls in any component it builds on.
npx shadcn@latest add https://www.syntaqx.com/r/timestamp.jsonThe code is yours from then on: edit it like anything else in components/ui.
Theming
Every component colors itself with shadcn's theme tokens and nothing else, so it looks like the rest of your app, not like this site. A test on this site fails the build if one reaches for any other color.
- --background
- --foreground
- --card
- --popover
- --primary
- --secondary
- --muted
- --accent
- --destructive
- --border
- --input
- --ring
Corners follow --radius, the same as shadcn's own components.
Components
buttonExamplesshadcn's Button with a loading state: a spinner over the label, and the button keeps its width.
npx shadcn@latest add https://www.syntaqx.com/r/button.jsoncopy-buttonExamplesThe copy button from shadcn's docs as an installable component: built on Button, with a fallback where the Clipboard API is blocked, icon-only or labeled, and its own confirmation for 2s.
npx shadcn@latest add https://www.syntaqx.com/r/copy-button.jsonlabelExamplesshadcn's Label, which dims with a disabled Field.
npx shadcn@latest add https://www.syntaqx.com/r/label.jsonfieldExamplesshadcn's Field, wired: the label, description, error and success messages connect to the control on their own, and invalid, disabled and required reach it from the Field.
npx shadcn@latest add https://www.syntaqx.com/r/field.jsoninputExamplesshadcn's Input with sm, default and lg sizes to match the Button. Inside a Field it wires itself up.
npx shadcn@latest add https://www.syntaqx.com/r/input.jsontextareaExamplesshadcn's Textarea that grows with its content up to a limit, then scrolls. Inside a Field it wires itself up.
npx shadcn@latest add https://www.syntaqx.com/r/textarea.jsoninput-groupExamplesshadcn's InputGroup with the Input's sizes: icons, text and buttons inside one border.
npx shadcn@latest add https://www.syntaqx.com/r/input-group.jsonpassword-inputExamplesA password field with a show/hide toggle that keeps the caret in place and a Caps Lock warning.
npx shadcn@latest add https://www.syntaqx.com/r/password-input.jsonnumber-inputExamplesA whole-number field with the numeric keypad on phones, arrow-key and button steppers, and clamping on blur.
npx shadcn@latest add https://www.syntaqx.com/r/number-input.jsonrequirement-listExamplesA field's rules, shown before the first keystroke and ticked off as each is met.
npx shadcn@latest add https://www.syntaqx.com/r/requirement-list.jsonerror-summaryExamplesThe GOV.UK error summary: on a failed submit it takes focus, counts the problems and links each one to its field.
npx shadcn@latest add https://www.syntaqx.com/r/error-summary.jsonhover-cardExamplesshadcn's HoverCard that can load its content on intent: give it a load function and a cache key, and render the loading, loaded and error states.
npx shadcn@latest add https://www.syntaqx.com/r/hover-card.jsontimestampExamplesAn instant in the viewer's timezone with the zone always visible; on intent, the same instant where it happened and in UTC.
npx shadcn@latest add https://www.syntaqx.com/r/timestamp.jsonseparatorExamplesshadcn's Separator.
npx shadcn@latest add https://www.syntaqx.com/r/separator.jsonskeletonExamplesshadcn's Skeleton: a placeholder sized to the content that's coming.
npx shadcn@latest add https://www.syntaqx.com/r/skeleton.jsonspinnerExamplesshadcn's Spinner, for waits with no shape to hold.
npx shadcn@latest add https://www.syntaqx.com/r/spinner.jsonemptyExamplesshadcn's Empty: what goes where there's nothing yet, nothing matching, or nothing left.
npx shadcn@latest add https://www.syntaqx.com/r/empty.jsonkbdExamplesshadcn's Kbd, for showing the key next to the action it triggers.
npx shadcn@latest add https://www.syntaqx.com/r/kbd.jsonbutton-groupExamplesshadcn's ButtonGroup: related actions in one row, which works as a toolbar.
npx shadcn@latest add https://www.syntaqx.com/r/button-group.jsondialogExamplesshadcn's Dialog: a modal that traps focus while open and hands it back when it closes.
npx shadcn@latest add https://www.syntaqx.com/r/dialog.jsonpaste-buttonExamplesThe Copy Button's other half: reads the clipboard into a field, icon-only or labeled, and confirms for 2s.
npx shadcn@latest add https://www.syntaqx.com/r/paste-button.jsontoggleExamplesshadcn's Toggle: a button that stays pressed until it's pressed again.
npx shadcn@latest add https://www.syntaqx.com/r/toggle.jsonselectExamplesshadcn's Select. Inside a Field it wires itself up, so the FieldLabel names it.
npx shadcn@latest add https://www.syntaqx.com/r/select.jsoncheckboxExamplesshadcn's Checkbox. Inside a Field it wires itself up, so the FieldLabel beside it names and toggles it.
npx shadcn@latest add https://www.syntaqx.com/r/checkbox.jsontoggle-groupExamplesshadcn's ToggleGroup: a segmented control for one choice, or a row of toggles for several.
npx shadcn@latest add https://www.syntaqx.com/r/toggle-group.jsonfile-dropExamplesA region that takes a dropped file or one chosen from the picker, through a button or a large dashed target, and marks itself while a file is dragged over.
npx shadcn@latest add https://www.syntaqx.com/r/file-drop.jsontooltipExamplesshadcn's Tooltip that works without a provider around the app.
npx shadcn@latest add https://www.syntaqx.com/r/tooltip.jsonalertExamplesshadcn's Alert: a message that stays on the page, announced when it appears.
npx shadcn@latest add https://www.syntaqx.com/r/alert.json