llms.txt@packages/ui-kit · diff
git:20261020.1895609 to git:20261020.03fd5e8
11 added, 56 removed. Audit A to A.
# @gears-frontx/ui-kit
> Standard React component base for FrontX templates. Behavior comes from
> Base UI primitives, styling is compiled CSS on semantic design tokens,
> variants via cva-driven props — `variant` for the paint/kind axis and
> `size` for the scale one, plus the occasional extra axis where a component
> genuinely has one (Table's `density`, AvatarFallback/AvatarGroupCount's
> `tone`). Consumers need no CSS framework
> or build plugins.
Rules for generated code:
- Import the design tokens exactly once at the app entry:
`import '@gears-frontx/ui-kit/theme.css';`
- Two more global stylesheets ship alongside it, each imported at the app
entry only when needed — neither is pulled in by any component's own CSS
chunk, so a missing import fails silently:
`import '@gears-frontx/ui-kit/utilities.css';` supplies the `shimmer`,
- `scroll-fade-x`, `no-scrollbar` and `sr-only` (visually hidden text for
- markup that is not React; React code uses VisuallyHidden) classes. Attachment DEPENDS on it
+ `scroll-fade-x` and `no-scrollbar` classes. Attachment DEPENDS on it
(`AttachmentTitle` shimmers while uploading, `AttachmentGroup` scrolls
its row with the other two) and Marker pairs with `shimmer` for
streaming text — without it those components render, minus the effect.
`import '@gears-frontx/ui-kit/typeset.css';` styles rendered markdown/
HTML the app does not author (chat messages, docs, CMS content): wrap it
in `<div class="typeset">`, optionally with a rhythm preset — see
[Typeset](dist/docs/typeset.md).
- Import components from the package root: `import { Button } from '@gears-frontx/ui-kit';`
Each component ships its own CSS, pulled in automatically by importing the
component — there is no separate stylesheet import for component styles.
A component subpath also works (`import { Button } from '@gears-frontx/ui-kit/button';`)
and is the one to reach for on an esbuild-based build specifically: esbuild
tree-shakes unused components' JS from a root import already, but only
drops their CSS from a subpath import — Vite and webpack drop both either
way, so this only matters when esbuild is the actual bundler running.
- Icons are `lucide-react` components, imported directly at the use site
(`import { ChevronDownIcon } from 'lucide-react';`). The kit depends on
`lucide-react` itself, so it resolves without a separate install, and it is
also what to pass into any `icon` slot prop. Kit CSS sizes icons through
each part's own `svg` rule, so a plain `<SomeIcon />` picks up the right
size; pass `className`/`size` only to override it.
- In an RSC framework (Next.js App Router), a component is safe to import
and render directly from a Server Component — no wrapping
client-boundary module needed — unless it appears in the next line. The
kit components that carry a `'use client'` banner of their own:
- Alert, Attachment, Badge, Breadcrumb, Bubble, ButtonGroup, Card,
- Carousel, Chart, CodeBlock, Combobox, Command, ContextMenu, DataGrid,
- DataTable, Drawer, DropdownMenu, Empty, Heading, InputOtp, Item, Link,
- Marker, PageHeader, Sidebar, StatusDot, Table, Text, Toast,
- VisuallyHidden. Each calls a hook directly
- in its own render body, so it always renders on the client, wherever it
- is imported from.
+ Attachment, Badge, Breadcrumb, Bubble, ButtonGroup, Carousel, Chart,
+ Combobox, ContextMenu, DataGrid, DataTable, Drawer, DropdownMenu, Marker,
+ PageHeader, Sidebar, StatusDot, Table, Toast. Each calls a hook directly in
+ its own render body, so it always renders on the client, wherever it is
+ imported from.
- The kit paints the page itself from its tokens and sets `color-scheme`: with
no `data-theme` attribute anywhere, `prefers-color-scheme: dark` alone
yields a correct, legible dark page (background, text, and UA-owned
surfaces like the scrollbar) out of the box — no setup step required for
that case.
- Fonts come from the kit's own tokens: `--font-sans` (Inter, then system
fallbacks) is set on the page by theme.css, `--font-mono` (JetBrains
Mono) is for code-like text. The kit ships no font FILES — load Inter/
JetBrains Mono in the app for the true Studio look (the fallbacks stay
legible without them), or override the tokens to rebrand.
- Font overrides AND, for explicit control instead of following the OS
preference, `data-theme` go on `<html>`/`<body>`, not on an inner
container: overlay components (Select, Dialog, DropdownMenu, Tooltip,
Toaster) portal their popup to `<body>` and inherit theme tokens and
font from there. A
`data-theme` subtree (anywhere, not just `<html>`/`<body>`) paints its own
surface, not just its descendants' tokens, so it can be nested inside a
page carrying the opposite theme. If a subtree must carry its own theme,
pass that element as `container` to `SelectContent` / `DialogContent` /
`DropdownMenuContent` / `TooltipContent` / `Toaster`.
- Brand/appearance changes go through theme tokens (CSS variables in
`theme.css`, light/dark via `data-theme`), never through inline styles or
overriding kit class names.
- Rounding is a scale derived from `--radius` (`--radius-xs|sm|md|lg|xl|2xl`);
override `--radius` alone and every component follows.
- Page typography uses the Studio type ramp tokens:
`--text-<role>-size|line-height|weight|tracking` for roles
display|heading-1|heading-2|body|label|meta|mono|micro (`micro` is the
10/14 step in the UI face, `mono` the same metrics in the monospace
face) (e.g. a page title is
`font-size: var(--text-heading-1-size)` etc.; medium-weight body text is
the body role at `font-weight: 500`). Use the ramp for template text
instead of inventing sizes — kit components already sit on it.
- Per-component docs below list the kit-level props; everything else is the
underlying native element's props.
## Components
- [Accordion](dist/docs/accordion.md): vertically stacked headers that
expand to reveal content (Accordion/AccordionItem/AccordionTrigger/
AccordionContent); wraps Base UI Accordion; single-item expansion by
default, `multiple` allows more than one open; height-animated panel.
- [Alert](dist/docs/alert.md): page-level banner callout
(Alert/AlertTitle/AlertDescription/AlertAction); variant
default|destructive; no Base UI primitive, `role="alert"`; a leading
`<svg>` child switches to a two-column icon layout, detected
- structurally; `AlertTitle` takes `render` for a real heading
- (`render={<h3 />}`).
+ structurally.
- [AlertDialog](dist/docs/alert-dialog.md): modal confirmation the user
must explicitly acknowledge (AlertDialog/AlertDialogTrigger/
AlertDialogContent/AlertDialogHeader/AlertDialogFooter/
AlertDialogAction/AlertDialogCancel); unlike `Dialog`, never closes on
outside press; `AlertDialogContent` size default|sm (sm stacks the two
actions into columns).
- [AspectRatio](dist/docs/aspect-ratio.md): constrains a child to a fixed
width/height ratio via CSS `aspect-ratio`; `ratio` prop only, no Base UI
primitive, no variants; reserves the box, does not crop its content.
- [Attachment](dist/docs/attachment.md): file/image attachment card for
chat composers and message threads (Attachment/AttachmentMedia/
AttachmentContent/AttachmentActions/AttachmentTrigger, AttachmentGroup);
upload-state axis drives the `shimmer` utility automatically via
context; no Base UI primitive. `AttachmentGroup` is a tab stop only
while its row overflows (arrow keys scroll it; a caller `tabIndex`
wins); its `label` gives `role="group"` + `aria-label`.
- [Avatar](dist/docs/avatar.md): profile picture with a loading fallback
(Avatar/AvatarImage/AvatarFallback/AvatarBadge, AvatarGroup+
AvatarGroupCount); sizes sm|default|lg; wraps the Base UI Avatar
primitive for image/fallback timing. AvatarFallback and AvatarGroupCount
share one fill matrix — `tone` neutral|accent|info|success|warning|danger
crossed with `variant` solid|soft (default neutral/soft, matching
upstream's single look byte for byte) — so a "+N" chip can match the toned
members it caps; `tone` is identity styling (derive it from who the
avatar is, e.g. a hash of the user id), never a live state — use
`AvatarBadge` for that. AvatarGroupCount takes no `size`; it reads its
size off its sibling Avatars' `size` within the same AvatarGroup.
- [Badge](dist/docs/badge.md): compact inline label; variants
default|secondary|destructive|outline|ghost|link|success|warning|danger|info|accent
(paint only — no semantic-state axis), two groups on one axis: six
upstream paints (same names/meaning as Button's) plus five tones — a
soft tinted fill with the tone's own color as the label (`secondary`
doubles as the tone row's Neutral, so there is no separate `neutral`
name); a tone still paints, it does not track state — don't let color
alone carry the meaning, keep the label text itself explicit; no Base
UI primitive, but gets `render`-prop polymorphism via
`useRender`/`mergeProps` (e.g. `<a>`) for a badge that is actually a
link.
- [Breadcrumb](dist/docs/breadcrumb.md): ancestor trail ending in the
current page (Breadcrumb/BreadcrumbList/BreadcrumbItem/BreadcrumbLink/
BreadcrumbPage/BreadcrumbSeparator/BreadcrumbEllipsis); no Base UI
primitive; `BreadcrumbLink` gets `render`-prop polymorphism for routing
through a consumer's own link component.
- [Bubble](dist/docs/bubble.md): framed chat-message surface
(Bubble/BubbleContent/BubbleReactions, BubbleGroup); variants
default|secondary|muted|tinted|outline|ghost|destructive; `align`
start|end both positions the bubble and squares its speaker-side top
corner (the shape cue that separates a message from a button; `ghost`
has no frame and no notch); scoped to the message surface only — pair
with `Message` for the full row.
- [Button](dist/docs/button.md): action button; variants
default|destructive|outline|secondary|ghost|link, sizes default|sm|lg; a
consumer className can recolor a button in every state via
`--button-bg`/`--button-fg`/`--button-bg-hover`/`--button-fg-hover`/
`--button-border` — no new variant needed; icons go in the `icon` slot
prop, NEVER in children — `icon` with no children leaves the button with no
accessible name (pass `aria-label` unless `end` holds announced text), and
with no `end` either it is a square icon-only button; `end` is the
trailing slot after the label (a chevron, a sort arrow, a count; its
content joins the accessible name, so hide a glyph with `aria-hidden`);
`loading` spins,
disables, and keeps the width and accessible name; render prop for
button-semantic actions over a real anchor (not a link substitute);
`buttonVariants` is exported for styling other elements to match, such
as the app's link component for navigation drawn as a button (it keeps
the link role).
- [ButtonGroup](dist/docs/button-group.md): visually joins a row/column of
controls into one strip (ButtonGroup/ButtonGroupText/
ButtonGroupSeparator); orientation horizontal|vertical; works on any
direct child, not just buttons.
- [Calendar](dist/docs/calendar.md): month grid for picking a day or
range, wrapping react-day-picker; every `DayPicker` prop passes through;
`captionLayout` label|dropdown|dropdown-months|dropdown-years;
`DatePicker` composes this behind a trigger.
- [Card](dist/docs/card.md): bounded content surface (Card/CardHeader/
CardTitle/CardDescription/CardAction/CardContent/CardFooter); header
becomes a two-column/two-row grid automatically when it contains a
- CardAction/CardDescription; sizes default|sm; `variant="panel"` is the
- lifted workbench frame (16px corner, --panel-shadow, no inset). `Card`
- takes `render`
- (`render={<a href />}` makes the whole card a link, with a hover border
- and focus ring; it must then hold no other link or button), `CardTitle`
- takes `render` for a real heading.
+ CardAction/CardDescription; sizes default|sm.
- [Carousel](dist/docs/carousel.md): embla-carousel-react scroll-snapping
slide track (Carousel/CarouselContent/CarouselItem/CarouselPrevious/
CarouselNext); orientation horizontal|vertical; `useCarousel()` exported
for custom controls; no Base UI primitive.
- [Chart](dist/docs/chart.md): themeable Recharts wrapper
(ChartContainer/ChartTooltip+ChartTooltipContent/ChartLegend+
ChartLegendContent); draws no chart type itself — series colors come
from a per-instance `ChartConfig`, not `--chart-*` tokens; no
variant/size axis; 16:9 by default, `--chart-aspect-ratio: auto` lets a
height or a stretching parent size it.
- [Checkbox](dist/docs/checkbox.md): on/off tick box for independent
options; `checked`/`onCheckedChange`; nest inside Label for one click
target.
- - [CodeBlock](dist/docs/code-block.md): a command or file excerpt the
- app places on a screen (CodeBlock/CodeBlockHeader/CodeBlockTitle/
- CodeBlockCopyButton); `code` is shown verbatim and copied, `label` names
- the keyboard-scrollable region, `wrap` soft-wraps instead, size
- default|sm; no syntax highlighting (`language` is reflected as
- `data-language`).
- [Collapsible](dist/docs/collapsible.md): single expandable/collapsible
section (Collapsible/CollapsibleTrigger/CollapsibleContent); no
variants; unmounts while closed unless `keepMounted`; height-animates
via Base UI's measured panel height.
- [Combobox](dist/docs/combobox.md): filterable text field picking from a
list, wrapping Base UI's dedicated Combobox primitive (not a
Popover+search composition); single-select (ComboboxInput) or
multi-select chips (ComboboxChips+ComboboxChip); a select-looking field
with the search input in the popup is `ComboboxTrigger variant="select"`
plus `<ComboboxInput showTrigger={false} />` first in ComboboxContent
(render the trigger as a `div` to hold chips, and name that `div` with
`aria-labelledby` or `aria-label`, since a `<label for>` cannot name it; a
chip is removed there by toggling its option off in the list); always pass
`items`.
- [Command](dist/docs/command.md): searchable, keyboard-navigable
command/option list built on `cmdk` (Command/CommandInput/CommandList/
CommandGroup/CommandItem/CommandSeparator); `CommandDialog` composes the
kit's own `Dialog`, not cmdk's bundled dialog.
- [ContextMenu](dist/docs/context-menu.md): right-click/long-press action
menu (ContextMenu/ContextMenuTrigger/ContextMenuContent + the same
item/checkbox/radio/submenu parts as DropdownMenu); always modal, no
hover-open; opens at the pointer position.
- [DataGrid](dist/docs/data-grid.md): server-driven data grid (`DataGrid`
with a `load(ctx)` callback, `columns`, a slot-based layout and
`createDataGridPlugin`) rendered on `Table`; the built-in plugins are
opt-in entries of their own - pagination, text search, ordering and a
custom empty state, imported from `@gears-frontx/ui-kit/data-grid/<plugin>`
or the package root; state can persist to local/session storage, the URL
or memory.
- [DataTable](dist/docs/data-table.md): sortable, paginated, optionally
row-selectable table built on `Table` + `@tanstack/react-table` v9;
productizes upstream's data-table *guide* into a real component
(`dataTableColumnHelper`, `dataTableSelectionColumn`,
`DataTableSortButton`); no filtering/column-visibility/
virtualization/resizing.
- [DatePicker](dist/docs/date-picker.md): field that opens a `Calendar` in
a `Popover` to pick a day or range; productizes upstream's
Popover+Calendar *recipe* into one component; mode single|range,
variant button|input (single mode only).
- - [DescriptionList](dist/docs/description-list.md): name and value pairs
- on real `dl`/`dt`/`dd` (DescriptionList/DescriptionListItem/
- DescriptionListTerm/DescriptionListDetails); orientation
- vertical|horizontal (terms aligned in one column), size default|sm,
- details typography body|mono.
- [Dialog](dist/docs/dialog.md): modal overlay for a focused task or
confirmation (Dialog/DialogTrigger/DialogContent/DialogHeader/
DialogFooter/DialogTitle/DialogDescription/DialogClose); traps focus,
closes on Escape/outside click; `DialogContent` takes `container` and
`showCloseButton`.
- [Direction](dist/docs/direction.md): thin re-export of Base UI's
`DirectionProvider`/`useDirection`; no styling, no DOM element of its
own; shares a reading direction (`ltr`|`rtl`) with every RTL-aware Base
UI-backed kit component below it.
- [Drawer](dist/docs/drawer.md): edge-anchored panel dismissible by swipe
gesture, wrapping Base UI's dedicated Drawer primitive (Drawer/
DrawerTrigger/DrawerContent/DrawerHeader/DrawerFooter, optional
DrawerSwipeHandle); `side` top|right|bottom|left; supports nested
drawers and snap points.
- [DropdownMenu](dist/docs/dropdown-menu.md): actions/options anchored to
a trigger (DropdownMenu/DropdownMenuTrigger/DropdownMenuContent/
DropdownMenuItem/DropdownMenuCheckboxItem/DropdownMenuRadioGroup+
DropdownMenuRadioItem/DropdownMenuSeparator/DropdownMenuShortcut/
DropdownMenuSub+DropdownMenuSubTrigger+DropdownMenuSubContent); item
variants default|destructive; `DropdownMenuContent` takes `container`.
- [Empty](dist/docs/empty.md): placeholder for a list/table/panel with
nothing to show (Empty/EmptyHeader/EmptyMedia/EmptyTitle/
EmptyDescription/EmptyDetail/EmptyContent/EmptyActions); no Base UI
primitive; `EmptyMedia` variant default|icon; `EmptyDetail` goes last
inside the header, `EmptyActions` is the button row and needs no top
- margin of its own; `EmptyTitle` takes `render` for a real heading.
+ margin of its own.
- [Field](dist/docs/field.md): primitive-free form-layout system
(Field/FieldLabel/FieldDescription/FieldError/FieldGroup/FieldSet/
FieldLegend/FieldSeparator/FieldContent/FieldTitle); Field's `orientation`
is vertical|horizontal|responsive (responsive switches to horizontal at
the `@container/field-group` mid breakpoint — wrap fields in
`FieldGroup`); FieldLegend's `variant` is legend|label; no automatic id/
htmlFor/aria-describedby wiring — wire `FieldLabel`'s `htmlFor` to the
control's `id` yourself, same as upstream shadcn; `data-invalid`/
`data-disabled` are plain attributes you set, not derived state.
- - [Heading](dist/docs/heading.md): a heading on the type ramp;
- typography display|heading-1|heading-2 picks the role, `render` picks
- the element (default `h2`), so the outline level and the look stay
- independent; no margin. Use the kit part's own title inside a kit
- component.
- [HoverCard](dist/docs/hover-card.md): portalled preview panel opened on
hover/focus (HoverCard/HoverCardTrigger/HoverCardContent), wrapping Base
UI's PreviewCard primitives under the shadcn `hover-card` name; `delay`
measures hover intent, not entry.
- [Input](dist/docs/input.md): single-line text field; `onValueChange`
for the string value, `aria-invalid` for the error state; `icon` for a
leading decorative icon, `end` for trailing interactive content (e.g. a
clear button; rendered after the input, so tab order is field → slot) —
neither renders automatically; `type="search"` gives the searchbox role
but no icon by itself — pass one via `icon`; inside `Field`, wire
`id`/`aria-describedby` by hand like every other control.
- [InputGroup](dist/docs/input-group.md): composes Input/Textarea with
icon/text/button addons into one visually unified field (InputGroup/
InputGroupAddon/InputGroupButton/InputGroupText/InputGroupInput/
InputGroupTextarea); the group draws the border/focus/error ring, the
wrapped control draws none of its own — focus is keyed to the control's
`:focus-visible` (not any focus-within), error is `aria-invalid` on the
control, and disabled is scoped to the field: a disabled
`InputGroupButton` inside an addon dims only itself, not the group;
`InputGroupAddon`'s `align` is inline-start|inline-end|block-start|
block-end, composable on both axes at once; `InputGroupButton` size is
xs|sm (default xs).
- [InputOtp](dist/docs/input-otp.md): one-time-passcode entry with paste/
auto-advance/completion built in, on Base UI's OTPField primitive
(InputOtp/InputOtpGroup/InputOtpSlot/InputOtpSeparator); `length`
required; `validationType` numeric|alphanumeric|...; `mask` for
password-style entry.
- [Item](dist/docs/item.md): a single row in a list of similar things
(ItemGroup/Item/ItemMedia/ItemContent/ItemTitle/ItemDescription/
ItemActions/ItemHeader/ItemFooter); `Item`'s `render` prop makes the
whole row a link (it keeps the text colour, no underline);
variant default|outline|muted, size default|sm|xs. `ItemTitle` is one
- line and ends with an ellipsis at its column's width. In `ItemGroup`
- rows are list items (a link or button row is wrapped in one); a chosen
- row is marked with aria-pressed/aria-selected/aria-current="true"
- (--secondary pair) or aria-current="page" (--accent pair).
- `ItemMedia` variant chip|chip-round is an icon tile.
+ line and ends with an ellipsis at its column's width.
`ItemDescription` clamps to two lines by default; `lineClamp={n}` sets
another count and `lineClamp="none"` shows the full text (use the prop,
not a className that resets the clamp); long tokens always wrap.
- [Kbd](dist/docs/kbd.md): visual keyboard-key/shortcut representation
(Kbd, KbdGroup); plain `<kbd>`, no interactive or ARIA behavior —
decoration only.
- [Label](dist/docs/label.md): caption for a form control; native
`<label>` props; associate via `htmlFor` or by nesting the control.
- - [Link](dist/docs/link.md): an inline anchor that keeps the line box of
- its text (unlike Button's `link` variant); variant default|muted|inherit,
- `render` hands it to the app's router link, `external` opens a new tab
- with a hidden arrow; an svg inside it scales with the text and sits on
- its baseline. `linkVariants` styles a router link that takes no
- `render`.
- [Marker](dist/docs/marker.md): inline conversation marker for status
updates, system notes, and labeled separators (Marker/MarkerContent/
MarkerIcon); variants incl. border|separator; pairs with the `shimmer`
utility class for a streaming-text effect (opt-in, not automatic).
- [Menubar](dist/docs/menubar.md): horizontal row of menus like a desktop
app's File/Edit/View bar (Menubar/MenubarMenu/MenubarTrigger + the same
content parts as DropdownMenu); Base UI coordinates keyboard/hover
switching between sibling menus.
- [Message](dist/docs/message.md): a conversation row owning avatar/
alignment/header/footer layout (Message/MessageAvatar/MessageContent/
MessageHeader/MessageFooter, MessageGroup); no Base UI primitive;
render the visible surface inside it with `Bubble`.
- [MessageScroller](dist/docs/message-scroller.md): chat-transcript
scroller with auto-follow-to-newest and a jump-back button
(MessageScrollerProvider/MessageScroller/MessageScrollerViewport/
MessageScrollerContent/MessageScrollerItem/MessageScrollerButton);
behavior from `@shadcn/react/message-scroller` (approved non-Base-UI
dependency), kit supplies styling only.
- [NativeSelect](dist/docs/native-select.md): a real `<select>` styled to
match the kit's field chrome (NativeSelect/NativeSelectOption/
NativeSelectOptGroup); no Base UI primitive; for platform-native
pickers or no-JS/SSR fallback contexts.
- [NavigationMenu](dist/docs/navigation-menu.md): horizontal nav bar whose
items expand into a rich dropdown panel (NavigationMenu/
NavigationMenuList/NavigationMenuItem/NavigationMenuTrigger/
NavigationMenuContent/NavigationMenuLink); one shared popup/Viewport
morphs to each active item's measured size.
- [PageHeader](dist/docs/page-header.md): the bar at the top of a page or
a section (PageHeader/PageHeaderLeading/PageHeaderContent/
PageHeaderEyebrow/PageHeaderTitle/PageHeaderMeta/PageHeaderDescription/
PageHeaderActions); no Base UI primitive; `size` sm|default|lg (56/64/80
minimum height), `border={false}` paints the rule transparent, so the
height stays the same; `PageHeaderTitle` is an `h1` (`render={<h2 />}`
for a section) with
`typography` heading|display; Leading, Meta and Actions take any content;
`--page-header-inset` sets the side inset (default `--space-6`); a header
kept above `main` passes `role="group"` so it is not a second banner.
- [Pagination](dist/docs/pagination.md): page-number navigation from real
anchors (Pagination/PaginationContent/PaginationItem/PaginationLink/
PaginationPrevious/PaginationNext/PaginationEllipsis); `isActive` paints
the current page and sets `aria-current`. For paging held in state, with
no URL per page, use the button twins PaginationButton/
PaginationPreviousButton/PaginationNextButton (`disabled` at the ends of
the range, plus `focusableWhenDisabled` so a focused button keeps focus
there); a custom non-blank `text` on Previous/Next is also their accessible
name unless an `aria-label` is passed (blank keeps the default name); the
Previous/Next chevrons mirror in right-to-left.
- [Popover](dist/docs/popover.md): portalled panel anchored to a trigger,
opened by click by default (Popover/PopoverTrigger/PopoverContent/
PopoverHeader/PopoverTitle/PopoverDescription); non-modal by default —
no focus trap, no backdrop; `PopoverTrigger`'s `openOnHover` opts into
hover-open.
- [Progress](dist/docs/progress.md): completion bar (Progress/
ProgressTrack/ProgressIndicator/ProgressLabel/ProgressValue); `value`
required, `null` for indeterminate; reports `role="progressbar"` with
`aria-valuenow`/min/max.
- [Questionnaire](dist/docs/questionnaire.md): single-item-at-a-time
multi-step form with progress/required/skip/invalid state
(Questionnaire/QuestionnaireItem/QuestionnaireChoices+
QuestionnaireChoice/QuestionnaireInput/QuestionnaireActions); behavior
from `@shadcn/react/questionnaire` (approved non-Base-UI dependency).
- [RadioGroup](dist/docs/radio-group.md): mutually exclusive options
(RadioGroup + RadioGroupItem); `value`/`onValueChange` on the group;
arrow-key navigation built in.
- [Resizable](dist/docs/resizable.md): react-resizable-panels wrapper for
user-draggable split panes (ResizablePanelGroup/ResizablePanel/
ResizableHandle); no Base UI primitive; nest groups for IDE-style
multi-pane layouts.
- [ScrollArea](dist/docs/scroll-area.md): custom-styled scrollable
container replacing the browser's native scrollbar (ScrollArea,
ScrollBar); wraps Base UI ScrollArea for scroll physics/overflow
detection/thumb drag; no variants; not for the page's own root scroll.
- [Select](dist/docs/select.md): dropdown picking one value from a
list (Select/SelectTrigger/SelectValue/SelectContent/SelectGroup/
SelectItem); trigger sizes default|sm, trigger variants default|filter
(filter = compact toolbar filter chip, label stays muted); the popup
always opens below the trigger (never overlays it), scrolling a selected
item into view when it sits beyond the fold; keyboard and typeahead
built in.
- [Separator](dist/docs/separator.md): thin visual divider between content
sections; orientation horizontal|vertical (default horizontal); no
`decorative` prop — pass `aria-hidden="true"` for a purely visual
divider; not for use inside DropdownMenu/Select popups, which have their
own separator styling; no portal.
- [Sheet](dist/docs/sheet.md): edge-anchored panel for a focused task/form
without leaving the page (Sheet/SheetTrigger/SheetContent/SheetHeader/
SheetFooter/SheetTitle/SheetDescription); wraps the same Base UI Dialog
primitives as `Dialog`; `side` top|right|bottom|left; modal by default;
`--sheet-inset` sets the 24px inset of the panel's regions (`0` on one
region runs it edge to edge).
- [Sidebar](dist/docs/sidebar.md): composable app-shell sidebar with an
expand/collapse state machine (SidebarProvider+useSidebar plus ~20
layout parts); persists desktop open state in a cookie, toggles on
- Cmd/Ctrl+B, switches to a slide-in `Sheet` on mobile; `contained` on
- SidebarProvider with `collapsible="none"` lays it out inside a panel
- instead of the viewport; built entirely
+ Cmd/Ctrl+B, switches to a slide-in `Sheet` on mobile; built entirely
from other kit parts.
- [Skeleton](dist/docs/skeleton.md): pulsing placeholder shape shown while
content loads; no Base UI primitive, no variants — size it yourself via
`className`/`style`; no ARIA of its own, put `role="status"`/`aria-busy`
on the surrounding container; pulse animation is removed under
`prefers-reduced-motion: reduce`; no portal.
- [Slider](dist/docs/slider.md): draggable control for a number or range
from a bounded scale (pointer drag/click-on-track/arrow-keys); `value`/
`defaultValue`'s length determines the number of rendered thumbs;
orientation horizontal|vertical.
- [Spinner](dist/docs/spinner.md): CSS-spun lucide `loader-circle`;
no Base UI primitive, no variants; use `Button`'s own `loading` prop
inside a button instead of nesting this. `label`/`description` compose
it into a loading block (glyph in a 36 indicator box, text beneath),
which becomes the live region while the glyph turns decorative;
`compact` takes that pair to 28/14 and `size="lg"` up to 64/32 (a bare
spinner goes to 32).
- [StatusDot](dist/docs/status-dot.md): inline status - a 6px round dot
plus an optional 12/16 label, both in the tone's colour; tone
neutral|success|warning|danger|info, `live` for a 2s pulse; no box of
its own, unlike `Badge dot`; no Base UI primitive, but gets `render`-prop
polymorphism via `useRender`/`mergeProps` (e.g. `<li>`) for the wrapping
element only - still never a link or button.
- [Switch](dist/docs/switch.md): immediate on/off toggle;
`checked`/`onCheckedChange`, sizes default|sm; use checkbox for
submit-time options.
- [Table](dist/docs/table.md): styled native table markup
(Table/TableHeader/TableBody/TableFooter/TableRow/TableHead/TableCell/
TableCaption); no Base UI primitive, no sorting/filtering/pagination —
primitive markup only; `density` compact|default on Table; row-state
rings via `data-state="selected|stale|restricted"` on TableRow (your
logic sets the attribute, the kit paints it); Table's own wrapper
scrolls horizontally and is keyboard-reachable (`tabIndex`); cap the
height on that wrapper (`containerClassName`/`containerStyle`), never on
an outer div, or a sticky header will not stick; `containerRef` reaches
that wrapper, and `stickyHeader` pins the header on any table without the
`collection` variant's layout; size a column via `className`/`style` width on TableHead/TableCell; no portal.
- [Tabs](dist/docs/tabs.md): switch between panels sharing the same
space (Tabs/TabsList/TabsTrigger/TabsContent); list variants
default|line; orientation horizontal|vertical (default horizontal);
inactive panels unmount unless `keepMounted`; the active panel replays a
short fade-up on every switch, `animate={false}` per panel to opt out;
no portal.
- - [Text](dist/docs/text.md): text on the type ramp; typography
- body|label|meta|mono|micro|kpi|kpi-lg (kpi = dashboard figures with
- tabular digits), tone default|muted, `render` picks the
- element (default `p`); no margin.
- [Textarea](dist/docs/textarea.md): multi-line text field; a plain styled
native `<textarea>` — no primitive, no Field auto-wiring; native
`<textarea>` props; grows with content; `aria-invalid` for the error
state.
- [Toast](dist/docs/toast.md): brief transient notification stacked
bottom-right; fired imperatively (`toast.add({...})`), not composed as
JSX; mount `Toaster` once; type-driven icon
success|info|warning|error|loading, optional action button; `Toaster`
takes `container`.
- [Toggle](dist/docs/toggle.md): two-state on/off button (`pressed`/
`defaultPressed`/`onPressedChange`); variant default|outline, size
default|sm|lg; standalone or as an item inside `ToggleGroup`.
- [ToggleGroup](dist/docs/toggle-group.md): a set of related toggle
buttons sharing pressed state (ToggleGroup/ToggleGroupItem); single- or
multiple-selection via `multiple`, arrow-key navigation between items;
item-level variant/size fall back to the group's.
- [Tooltip](dist/docs/tooltip.md): visual-only hint on hover/focus of a
trigger (Tooltip/TooltipTrigger/TooltipContent); optional
`TooltipProvider` shares delay/grouping across many tooltips;
`TooltipContent` takes `container`; disabled on touch devices — never
the only carrier of essential information.
## Stylesheets
- - [VisuallyHidden](dist/docs/visually-hidden.md): text a screen reader
- reads and the screen does not show (a `span`, `render` swaps it); the
- `sr-only` class in utilities.css is the same rule for markup that is
- not React.
- [Typeset](dist/docs/typeset.md): prose styling for rendered markdown/HTML
(`typeset.css`); wrapper class `typeset` plus rhythm presets
`typeset-chat|docs|reading|compact|large`, `not-typeset` to opt a subtree
out, `typeset-scroll` for one wide block; no component, no JS.
## Optional
- [README](README.md): installation, setup, package layout.