component library
Components
63 components across 9 categories. Each page documents the API, variants, anatomy, do/don’t guidelines, and live examples.
Layout
BoxPolymorphic surface — padding, background, border, radius pinned to tokens.
StackFlex container with token-driven gap, alignment, justification. Replaces 90% of inline flexbox.
TextTypography primitive — size × weight × color all driven by --t-font-*. Polymorphic via `as`.
PanelHeaderTop-of-section row — title on the left, action buttons on the right.
Action
ButtonA single discrete action. The variant axis encodes emphasis, the accent axis encodes tone — keep one primary-blue per surface.
IconButtonSquare button for a single icon — same variant × accent matrix as Button. Requires aria-label.
ButtonGroup · ToggleGroupA row of related actions (ButtonGroup) or mutually exclusive / multi-pick toggles (ToggleGroup).
Form
InputSingle-line text entry — token-driven hover, focus ring, validity styling.
TextareaMulti-line text entry — same chrome as Input, vertical resize handle, focus ring.
NumberInputNumeric value with stepper buttons. Inline-edit friendly — Enter commits, Escape reverts.
LabelForm label wired to a control via htmlFor — uses Radix Label.Root for click-to-focus.
FieldLabel + control + hint / error composition. Owns the id and aria-invalid wiring.
CheckboxBoolean (or tri-state) toggle for a single value. Radix-backed — keyboard and a11y handled.
SwitchOn / off toggle with sliding thumb. Use for settings where the change takes effect immediately.
Radio · RadioGroupPick exactly one value out of a small set. Always grouped — never use a lone Radio.
SelectSingle-value picker from a known short list. Radix-backed — keyboard arrows, type-to-jump, escape.
SearchInputMagnifier + text field + optional clear. Type="search" — Esc clears, screen-reader-friendly.
ComboboxSingle-pick from a long or fuzzy-searchable list. cmdk-backed — keyboard nav, type-to-filter, groups.
MultiSelectPick many values from a list. Chip-summary in the trigger; cmdk-backed search; "Clear all" footer.
SliderNumeric value (or range) on a continuous scale. Radix-backed — keyboard arrows, focus ring, tooltip support.
RatingStar rating from 0 to max. Optional half-step, read-only mode for displaying aggregated values.
DatePicker · TimePicker · DateRangePickerNative browser pickers themed with --t-*. Work inside Twenty's Web Worker — no Date library shipped.
ColorPicker30-swatch palette of Twenty named tag colors. Picked value is a token name, not a hex.
FormSection · FormRow · FormGroupComposition primitives for typical settings / record-edit forms.
SegmentedControlSmall inline pill-style toggle — exactly one option selected.
PresetRowRow of compact suggestion chips — preset values the user can pick.
DiscountControllerMode toggle (—/%/$) + preset chips + manual input — discount editor.
MoneyInputNumeric input with a currency-symbol prefix — stores micros.
RecordPickerInline picker — search input, alphabet bar, scrollable list of records.
InputShellThe "looks like a text input" chrome, generic over its content.
Overlay
TooltipShort, hover-revealed label or hint anchored to a trigger. Requires <TooltipProvider> at app root.
PopoverFloating panel anchored to a trigger. Interactive content (forms, lists, mini-tools) goes here.
Modal · ConfirmDialogCentred full-attention surface with backdrop. ConfirmDialog is a thin Modal preset for destructive confirms.
DropdownMenuClick-triggered menu of actions — items, checkbox items, separators, labels, sub-menus.
ContextMenuRight-click triggered menu. Same shape as DropdownMenu, different gesture.
HoverCardRich, hover-revealed preview of a record (user, document, deal). Opens after delay, closes on outside hover.
ToastBottom-right non-blocking notification with auto-dismiss. Use useToast() to fire from anywhere.
Data display
TagCompact coloured pill — picks a colour from Twenty's 30-tone palette (--t-tag-text-* / --t-tag-background-*).
Avatar · AvatarGroup · ChipRound (or squared) person / company avatar. AvatarGroup stacks them with overflow. Chip = Avatar + label.
StatusColoured pill or dot indicating a deal / record / system state. Three variants: solid, soft, dot.
BadgeTwo shapes in one component: notification (count / dot anchored to a child) and label pill (standalone text tag).
TableGeneric <Table<T>> with sortable headers, optional row selection, custom cell render, sticky header.
DataTableHigher-level Table — built-in search, client-side sort, page size selector, selection counter, toolbar slot.
TimelineVertical event log with coloured dots. Record-page activity feeds, deploy history, audit trails.
VirtualList@tanstack/react-virtual list — render thousands of rows without dropping frames.
CodeBlockSyntax-highlighted code block — prism-react-renderer with Twenty-coloured theme. Copy button included.
JsonViewerCollapsible JSON tree — useful for inspecting API responses, webhook payloads, debug surfaces.
SummaryRowOne label↔value line for totals/recap rows in the panel footer.
LineItemCardOne row of a priced line — header / body / footer slots + optional delete.
TotalsBlockSubtotal + discount controls + total — the panel footer recap.
EntityChipColour-coded letter avatar + name — the visual handle for one record.
Container
CardThemed surface — border, radius, optional light shadow. Three variants: surface, outlined, subtle.
AccordionStacked collapsible sections. Single or multiple-open mode, Radix-backed keyboard nav.
DividerThin line between sections — horizontal or vertical, with optional label.
EmptyStateIcon + title + description + action — for "no records yet" surfaces.
SkeletonShimmering placeholder block — used while data is loading. Matches the eventual content shape.
SpinnerTiny indeterminate loading ring. Use inline next to a label, never as a primary "loading" surface.
ProgressLinear bar with determinate value (0–100) or indeterminate sweep. Radix-backed.
ScrollAreaConstrained-height surface with a themed Radix scrollbar that only appears on hover.