# Layout UI: Full Machine-Readable Reference Token-contracted, reskinnable React component system built for AI coding agents. 54 components on Base UI primitives, every component ships machine-readable usage rules. Themes compile from real company design systems. **Registry base URL:** https://ui.staging.layout.design/r/{name}.json **Registry manifest:** https://ui.staging.layout.design/r/registry.json **Install command pattern:** `npx shadcn add https://ui.staging.layout.design/r/.json` **MCP server:** `npx @layoutdesign/context serve` (package: `@layoutdesign/context`) **layout.design:** https://layout.design --- ## Token Contract Layout UI components reference only --layout-* semantic intent tokens. Changing a token value updates every component that uses it with no per-component overrides needed. ### Semantic tokens (--layout-*) | Token | Purpose | |-------|---------| | --layout-bg | Page/root background | | --layout-fg | Primary text and icons | | --layout-primary | Primary action colour (filled buttons, active indicators) | | --layout-primary-fg | Text/icons on primary surfaces | | --layout-secondary | Secondary action colour | | --layout-secondary-fg | Text/icons on secondary surfaces | | --layout-accent | Hover states, selected backgrounds, mild highlight | | --layout-accent-fg | Text/icons on accent surfaces | | --layout-muted | Subtle background fill (inputs, skeletons, muted cards) | | --layout-muted-fg | De-emphasised text (descriptions, placeholders, labels) | | --layout-border | Dividers, input outlines, card borders | | --layout-ring | Focus ring colour | | --layout-input | Input field background | | --layout-surface | Elevated card/panel background | | --layout-surface-fg | Text on surface | | --layout-overlay | Modal/dialog background (popover, sheet, drawer) | | --layout-overlay-fg | Text on overlay surfaces | | --layout-popover | Popover/dropdown background | | --layout-popover-fg | Text on popover surfaces | | --layout-danger | Destructive/error intent | | --layout-danger-fg | Text/icons on danger surfaces | | --layout-success | Success intent | | --layout-success-fg | Text/icons on success surfaces | | --layout-warning | Warning intent | | --layout-warning-fg | Text/icons on warning surfaces | | --layout-radius | Base border-radius (all components derive from this) | | --layout-shadow-xs | Subtlest elevation (buttons, badges) | | --layout-shadow-sm | Low elevation (cards) | | --layout-shadow-md | Medium elevation (popovers, dropdowns) | | --layout-shadow-lg | High elevation (modals, sheets) | | --layout-duration-fast | 100 ms, micro-interactions | | --layout-duration-base | 150 ms, standard transitions | | --layout-duration-slow | 250 ms, panel transitions/exit animations | | --layout-font-mono | Monospace font stack (kbd, code) | ### Theming model Themes are applied via HTML attributes on any ancestor element: - `data-brand=""`: Activates a brand's CSS custom properties. Apply to a scoping wrapper to limit the brand to a preview area, or to `` for global reskinning. - `data-theme="dark"`: Activates dark mode values. - `data-density="compact"`: Activates compact spacing (reduced padding/gap). Shadcn compatibility: the token fallback chain is `--layout-primary: var(--primary)`, so any project with shadcn CSS variables already set gets correct colours without any additional configuration. Install the default theme: `npx shadcn add https://ui.staging.layout.design/r/theme-layout.json` --- ## Components (54 total) ### Accordion (`accordion`) **Description:** Vertically stacked collapsible sections built on Base UI Accordion. The chevron rotates on open via data-[panel-open]. Supports single or multiple open items via the openMultiple prop. **Docs:** https://ui.staging.layout.design/docs/components/accordion **Registry JSON:** https://ui.staging.layout.design/r/accordion.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/accordion.json` **Usage rule:** Use for FAQ sections, settings groups, or sidebar navigation trees. Use openMultiple on the root to allow several panels open simultaneously. Each AccordionItem must have a unique value prop. **Never rules:** - Never use accordion for tab-like switching between mutually exclusive views; use Tabs - Never put accordions inside accordions more than two levels deep - Never hardcode the chevron rotation angle; rely on the data-[panel-open] selector in AccordionTrigger - Never remove AccordionHeader; it is required for the correct heading hierarchy and accessibility tree **Tokens consumed:** - --layout-border - --layout-fg - --layout-muted-fg - --layout-ring - --layout-duration-base --- ### Alert (`alert`) **Description:** Inline callout with default, destructive, success and warning variants. **Docs:** https://ui.staging.layout.design/docs/components/alert **Registry JSON:** https://ui.staging.layout.design/r/alert.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/alert.json` **Usage rule:** Static inline messaging scoped to a page section. Lead with a lucide icon sized size-4. For transient feedback use a toast instead. **Never rules:** - Never stack more than two alerts in a row; consolidate the message - Never use destructive alerts for warnings; warning exists for that **Tokens consumed:** - --layout-surface - --layout-border - --layout-danger - --layout-success - --layout-warning - --layout-radius --- ### Alert Dialog (`alert-dialog`) **Description:** Interruption dialog for irreversible or high-stakes actions. Built on Base UI AlertDialog with ARIA alertdialog role. Action button styled as default, cancel as outline. **Docs:** https://ui.staging.layout.design/docs/components/alert-dialog **Registry JSON:** https://ui.staging.layout.design/r/alert-dialog.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/alert-dialog.json` **Usage rule:** Use exclusively for destructive or irreversible actions such as deletion, account termination, or data loss. Always name the action button with the exact action (e.g. 'Delete project') not a generic 'OK'. Cancel always goes on the left, action on the right. For non-destructive confirmations use Dialog instead. **Never rules:** - Never use AlertDialog for non-destructive confirmations — use Dialog - Never label the action button 'OK' or 'Confirm' — use the specific action verb - Never omit AlertDialogCancel; the user must always have a safe exit - Never use AlertDialog for contextual or anchored content — use Popover **Tokens consumed:** - --layout-overlay - --layout-overlay-fg - --layout-border - --layout-shadow-lg - --layout-radius - --layout-duration-base - --layout-danger - --layout-danger-fg --- ### Aspect Ratio (`aspect-ratio`) **Description:** Pure CSS aspect-ratio wrapper. Server-compatible with no client JavaScript required. **Docs:** https://ui.staging.layout.design/docs/components/aspect-ratio **Registry JSON:** https://ui.staging.layout.design/r/aspect-ratio.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/aspect-ratio.json` **Usage rule:** Pass a ratio prop (e.g. 16/9, 4/3, 1) and place content inside that fills size-full. Wrap in a container with overflow-hidden and a border-radius to clip the content to the box. Suitable for images, iframes, and video embeds. **Never rules:** - Never set an explicit height on AspectRatio; the aspect-ratio CSS property derives height from width automatically - Never use AspectRatio for non-media content that has a natural height; it is for enforcing visual proportions only - Never rely on padding-top percentage hacks; this component uses the native CSS aspect-ratio property supported in all modern browsers **Tokens consumed:** (no specific tokens; inherits from parent) --- ### Avatar (`avatar`) **Description:** User avatar with image, fallback initials, and graceful error handling. Built on Base UI Avatar. **Docs:** https://ui.staging.layout.design/docs/components/avatar **Registry JSON:** https://ui.staging.layout.design/r/avatar.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/avatar.json` **Usage rule:** Wrap AvatarImage and AvatarFallback inside Avatar. AvatarFallback renders automatically when the image fails to load or no src is provided. Use initials (one or two characters) as the fallback child. Stack avatars with -space-x-* and ring-background to create groups. **Never rules:** - Never display an avatar without AvatarFallback; image loading failures must not produce a blank circle - Never hardcode background colours on AvatarFallback; it inherits bg-muted from the token contract - Never scale Avatar below size-6; initials become illegible at smaller sizes - Never use Avatar to display generic icons that are not user identity; use a Badge or Icon component instead **Tokens consumed:** - --layout-muted - --layout-muted-fg - --layout-radius --- ### Badge (`badge`) **Description:** Status and metadata label with six variants including success and warning. **Docs:** https://ui.staging.layout.design/docs/components/badge **Registry JSON:** https://ui.staging.layout.design/r/badge.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/badge.json` **Usage rule:** Compact status indicators, counts, and metadata. Use success/warning/destructive to communicate state, secondary or outline for neutral metadata. **Never rules:** - Never use badges as interactive buttons; wrap actions in Button - Never rely on colour alone for status; keep the text meaningful **Tokens consumed:** - --layout-primary - --layout-secondary - --layout-danger - --layout-success - --layout-warning - --layout-border --- ### Breadcrumb (`breadcrumb`) **Description:** A server-compatible breadcrumb trail showing the user's location within a hierarchy. BreadcrumbSeparator accepts a custom icon child; BreadcrumbEllipsis collapses long paths. **Docs:** https://ui.staging.layout.design/docs/components/breadcrumb **Registry JSON:** https://ui.staging.layout.design/r/breadcrumb.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/breadcrumb.json` **Usage rule:** Place at the top of content areas to help users navigate back. Use BreadcrumbPage (not BreadcrumbLink) for the final segment. Use BreadcrumbEllipsis with a DropdownMenu to reveal hidden intermediate crumbs on mobile. **Never rules:** - Never mark the current page with BreadcrumbLink; always use BreadcrumbPage - Never use breadcrumbs for flat or single-level navigation - Never hardcode colours; text colours resolve through text-foreground and text-muted-foreground - Never add interactive elements inside BreadcrumbPage; it is aria-disabled **Tokens consumed:** - --layout-fg - --layout-muted-fg - --layout-duration-base --- ### Button (`button`) **Description:** Button with six intent variants and four sizes. Polymorphic via the Base UI render prop. **Docs:** https://ui.staging.layout.design/docs/components/button **Registry JSON:** https://ui.staging.layout.design/r/button.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/button.json` **Usage rule:** Primary actions use the default variant; one default button per view section. Secondary and outline are for supporting actions, ghost for toolbars and dense UI, destructive only for irreversible actions, link for inline navigation. Use render={} to render as a link. **Never rules:** - Never hardcode colours; variants already map to intent tokens - Never place two default-variant buttons in the same action group - Never use destructive for cancel/dismiss actions - Never override border-radius directly; it derives from --layout-radius **Tokens consumed:** - --layout-primary - --layout-primary-fg - --layout-secondary - --layout-secondary-fg - --layout-accent - --layout-accent-fg - --layout-danger - --layout-danger-fg - --layout-input - --layout-ring - --layout-radius - --layout-shadow-xs - --layout-duration-base --- ### Button Group (`button-group`) **Description:** Wrapper that visually fuses adjacent Button children into a single segmented control, collapsing inner borders and radii. Server-compatible. **Docs:** https://ui.staging.layout.design/docs/components/button-group **Registry JSON:** https://ui.staging.layout.design/r/button-group.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/button-group.json` **Usage rule:** Place two or more Button components as direct children. Orientation defaults to horizontal; pass orientation="vertical" for a stacked group. All buttons in the group should share the same variant so the fused appearance is consistent. ButtonGroup only adjusts radius and border-margin; all other button styling comes from the Button component itself. **Never rules:** - Never mix Button variants within the same ButtonGroup; use a single variant across all children - Never use ButtonGroup for navigation tabs; use a Tabs component instead - Never place non-Button elements as direct children; the [&>*] selectors target sibling elements and may break non-button markup - Never add margin between buttons manually; ButtonGroup handles negative margin to collapse borders **Tokens consumed:** - --layout-radius - --layout-duration-base --- ### Calendar (`calendar`) **Description:** Date-picker calendar built on react-day-picker v10, styled with semantic tokens. Supports single, multiple, and range selection modes. **Docs:** https://ui.staging.layout.design/docs/components/calendar **Registry JSON:** https://ui.staging.layout.design/r/calendar.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/calendar.json` **Usage rule:** Use mode="single" for a standalone date picker, mode="range" for booking flows or date-range filters. Wrap in a Popover for inline-trigger UX. Always pass showOutsideDays (defaults true) to keep the grid size stable. **Never rules:** - Never import react-day-picker styles directly; all styling is handled via classNames prop using semantic tokens - Never hardcode colour values for selected, today, or outside states; use bg-primary, bg-accent, and muted-foreground - Never set a fixed width on the Calendar root; let the day grid dictate size - Never use mode="multiple" for date ranges; use mode="range" instead **Tokens consumed:** - --layout-primary - --layout-primary-fg - --layout-accent - --layout-accent-fg - --layout-muted-fg - --layout-border - --layout-ring - --layout-radius --- ### Card (`card`) **Description:** Surface container family: header, title, description, action, content, footer. **Docs:** https://ui.staging.layout.design/docs/components/card **Registry JSON:** https://ui.staging.layout.design/r/card.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/card.json` **Usage rule:** Group related content on a raised surface. CardAction slots into the header's top-right. Compose forms inside CardContent with CardFooter for actions. **Never rules:** - Never nest cards inside cards; use Separator to divide content - Never add custom box-shadows; elevation comes from the shadow tokens **Tokens consumed:** - --layout-surface - --layout-surface-fg - --layout-border - --layout-radius - --layout-shadow-sm --- ### Carousel (`carousel`) **Description:** Accessible carousel built on Embla Carousel with keyboard arrow-key navigation. Exports Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, and the useCarousel context hook. **Docs:** https://ui.staging.layout.design/docs/components/carousel **Registry JSON:** https://ui.staging.layout.design/r/carousel.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/carousel.json` **Usage rule:** Wrap slides in CarouselItem inside CarouselContent. Set orientation="vertical" and a fixed height on CarouselContent for vertical layouts. Pass opts to forwarded Embla options (loop, align, slidesToScroll). Use useCarousel() inside a child component to access the Embla API imperatively. **Never rules:** - Never place CarouselPrevious or CarouselNext outside a Carousel; they depend on context - Never set overflow-hidden on CarouselItem; that breaks the slide reveal animation - Never hardcode button colours on CarouselPrevious/CarouselNext; they inherit from buttonVariants outline - Never use CarouselContent without its parent Carousel; the embla ref will be undefined **Tokens consumed:** - --layout-border - --layout-ring - --layout-radius --- ### Chart (`chart`) **Description:** shadcn-style chart kit built on Recharts. ChartContainer scopes series colours as --color- CSS custom properties. ChartTooltip and ChartTooltipContent render token-styled tooltips. ChartLegend and ChartLegendContent render colour-dotted legend rows. Pair with any Recharts chart type. **Docs:** https://ui.staging.layout.design/docs/components/chart **Registry JSON:** https://ui.staging.layout.design/r/chart.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/chart.json` **Usage rule:** Wrap any Recharts chart in ChartContainer with a config map (keys match Recharts dataKey values, each entry has label and color). Reference colours in Recharts props as var(--color-). Pass ChartTooltipContent to Recharts Tooltip's content prop and ChartLegendContent to Legend's content prop, passing the same config to both so labels and colours stay consistent. **Never rules:** - Never hardcode hex or rgb colours in config entries; always use a var(--layout-*) token reference - Never use the same --color- name across two ChartContainers on the same page unless the colours are intentionally identical - Never pass config keys that do not match the Recharts dataKey values; colours will not resolve - Never render ChartContainer without a ResponsiveContainer child; without it the chart will not adapt to its parent width **Tokens consumed:** - --layout-primary - --layout-success - --layout-warning - --layout-danger - --layout-muted-fg - --layout-border - --layout-surface - --layout-overlay - --layout-fg - --layout-radius - --layout-shadow-md --- ### Checkbox (`checkbox`) **Description:** Accessible checkbox with checked, unchecked and indeterminate states. Built on Base UI Checkbox with a Lucide Check indicator. **Docs:** https://ui.staging.layout.design/docs/components/checkbox **Registry JSON:** https://ui.staging.layout.design/r/checkbox.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/checkbox.json` **Usage rule:** Pair with a Label via htmlFor/id. Use inside a form or with Field for validation. The indeterminate prop shows a minus icon for parent checkboxes that represent a partial selection. **Never rules:** - Never use as a toggle for immediate actions; use Switch instead - Never omit an associated label — pass aria-label if no visible label is present - Never override the checked background colour; it derives from --layout-primary - Never rely on colour alone to convey state **Tokens consumed:** - --layout-primary - --layout-primary-fg - --layout-input - --layout-ring - --layout-radius - --layout-duration-base --- ### Collapsible (`collapsible`) **Description:** A single show/hide panel built on Base UI Collapsible. Lower-level than Accordion; use when you need one independent collapsible section without the header/item structure. **Docs:** https://ui.staging.layout.design/docs/components/collapsible **Registry JSON:** https://ui.staging.layout.design/r/collapsible.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/collapsible.json` **Usage rule:** Use for sidebar nav sections, advanced filter panels, or repo-style expandable lists. Pair CollapsibleTrigger with asChild to use a Button or custom element as the toggle. Use open and onOpenChange for controlled mode. **Never rules:** - Never use Collapsible when you need multiple accordion-style sections; use Accordion - Never render CollapsibleContent without CollapsibleTrigger in the same Collapsible root - Never hardcode the open/close animation; rely on data-[starting-style] and data-[ending-style] selectors **Tokens consumed:** - --layout-ring - --layout-radius - --layout-duration-base --- ### Combobox (`combobox`) **Description:** Searchable select built on Base UI Combobox. Type to filter a fixed list; shows an empty state when no items match. Check indicator on selected item. **Docs:** https://ui.staging.layout.design/docs/components/combobox **Registry JSON:** https://ui.staging.layout.design/r/combobox.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/combobox.json` **Usage rule:** Use Combobox when users need to search or filter a fixed list of options by typing. Pass the full items array to the Combobox root so Base UI can handle filtering automatically. Use ComboboxTrigger as the input trigger (contains ComboboxInput internally). ComboboxContent wraps ComboboxList and ComboboxEmpty. Use Select instead when the list is short (under ~15 items) and filtering is unnecessary. Use a native for minimal-dependency autocomplete on plain HTML forms. **Never rules:** - Never use Combobox for free-form text entry where any value is valid; use Input instead - Never omit the items prop on the Combobox root; filtering will not work without it - Never wrap ComboboxContent in a custom portal; it already renders inside Base UI Portal - Never use Combobox for multi-select without setting multiple={true} on the root; single-mode selection will clear previous choices **Tokens consumed:** - --layout-input - --layout-ring - --layout-popover - --layout-popover-fg - --layout-accent - --layout-accent-fg - --layout-border - --layout-muted-fg - --layout-radius - --layout-shadow-md - --layout-duration-base - --layout-duration-fast --- ### Context Menu (`context-menu`) **Description:** A menu triggered by right-click or long-press on a target area, built on Base UI ContextMenu. Shares the same item family as DropdownMenu. **Docs:** https://ui.staging.layout.design/docs/components/context-menu **Registry JSON:** https://ui.staging.layout.design/r/context-menu.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/context-menu.json` **Usage rule:** Use for secondary actions on an element that the user already has focus on (file list rows, canvas objects, code editor). Wrap the target in ContextMenuTrigger. Mirror the same item structure as DropdownMenu for consistency. **Never rules:** - Never use ContextMenu as the only way to reach critical actions; it must complement visible controls - Never use ContextMenu instead of DropdownMenu for button-triggered menus - Never place more than eight items at the top level; group into sections with separators - Never hardcode colours; use the variant prop for destructive actions **Tokens consumed:** - --layout-overlay - --layout-overlay-fg - --layout-accent - --layout-accent-fg - --layout-danger - --layout-border - --layout-radius - --layout-shadow-md - --layout-duration-base --- ### Data Table (`data-table`) **Description:** Full-featured data table built on TanStack Table v8: sortable columns, column filter input, row selection with checkboxes, and Previous/Next pagination. Composed from the Table family, Input, Button, and Checkbox primitives. **Docs:** https://ui.staging.layout.design/docs/components/data-table **Registry JSON:** https://ui.staging.layout.design/r/data-table.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/data-table.json` **Usage rule:** Define columns with ColumnDef and pass them with your data array. Use createSelectColumn() as the first column to get a select-all header checkbox and per-row checkboxes. Set filterColumn to the accessorKey you want the filter input to search. For static read-only tables use the Table family directly instead. **Never rules:** - Never use DataTable for read-only presentational tables; use the Table primitive instead - Never hardcode colours in cell renderers; use token-backed Badge or text-muted-foreground - Never pass an unsorted data array and expect stable row order under selection; TanStack Table reorders under sorting - Never use filterColumn with a column that has no string or number values; filtering only works on primitive cell values **Tokens consumed:** - --layout-border - --layout-muted - --layout-muted-fg - --layout-primary - --layout-primary-fg - --layout-input - --layout-ring - --layout-radius - --layout-duration-base --- ### Date Picker (`date-picker`) **Description:** Composed date-picker pattern: a Popover-wrapped Button trigger with a Calendar inside. Exports DatePicker (single) and DateRangePicker (range). Not a primitive — installs Calendar, Popover, and Button as dependencies. **Docs:** https://ui.staging.layout.design/docs/components/date-picker **Registry JSON:** https://ui.staging.layout.design/r/date-picker.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/date-picker.json` **Usage rule:** Use DatePicker for single date inputs (booking, scheduling). Use DateRangePicker for filtering or reporting windows. Control state externally via date/onDateChange or dateRange/onDateRangeChange props. Set numberOfMonths={2} on DateRangePicker for wide viewports. **Never rules:** - Never import date-fns format separately when the component already formats the label - Never fix the popover width with w-* on PopoverContent; use w-auto so the calendar dictates size - Never use this pattern as an uncontrolled component; always lift date state up **Tokens consumed:** - --layout-primary - --layout-muted-fg - --layout-border - --layout-ring - --layout-radius --- ### Dialog (`dialog`) **Description:** Modal dialog with backdrop, centred popup, header, footer, and close button. Built on Base UI Dialog. **Docs:** https://ui.staging.layout.design/docs/components/dialog **Registry JSON:** https://ui.staging.layout.design/r/dialog.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/dialog.json` **Usage rule:** Use for tasks that require focused user attention and cannot be performed inline — forms, confirmations needing context, and detail views. Trigger with DialogTrigger using the render prop pattern. Always include a DialogTitle for accessibility. Use DialogClose inside DialogFooter for explicit dismiss actions. **Never rules:** - Never use Dialog for destructive confirmations — use AlertDialog instead so screen readers announce the alert role - Never use Dialog for contextual information anchored to a trigger — use Popover or HoverCard instead - Never use Dialog for mobile-first slide-up panels — use Sheet (side bottom) or Drawer instead - Never nest interactive dialogs; open a second dialog only after the first is closed **Tokens consumed:** - --layout-overlay - --layout-overlay-fg - --layout-border - --layout-shadow-lg - --layout-radius - --layout-duration-base - --layout-ring --- ### Drawer (`drawer`) **Description:** Bottom sheet with native drag-to-dismiss. Built on Base UI Drawer. Includes a drag handle bar and swipe gesture support. **Docs:** https://ui.staging.layout.design/docs/components/drawer **Registry JSON:** https://ui.staging.layout.design/r/drawer.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/drawer.json` **Usage rule:** Use for mobile-first action sheets, contextual menus, and bottom panels where touch swipe-to-dismiss is important. On desktop, prefer Sheet for side panels or Dialog for centred modals. Mount DrawerContent inside Drawer; the drag handle is rendered automatically inside DrawerContent. **Never rules:** - Never use Drawer for full-page flows on desktop — use Dialog or Sheet - Never use Drawer for critical destructive confirmations — use AlertDialog - Never hide the drag handle unless the interaction is purely button-driven - Never set a fixed height taller than 90dvh; content should scroll within DrawerContent **Tokens consumed:** - --layout-overlay - --layout-overlay-fg - --layout-border - --layout-shadow-lg - --layout-radius - --layout-duration-slow - --layout-muted-fg --- ### Dropdown Menu (`dropdown-menu`) **Description:** A menu anchored to a trigger button, built on Base UI Menu. Supports groups, labels, separators, keyboard shortcuts, checkboxes, radio groups, sub-menus, and a destructive item variant. **Docs:** https://ui.staging.layout.design/docs/components/dropdown-menu **Registry JSON:** https://ui.staging.layout.design/r/dropdown-menu.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/dropdown-menu.json` **Usage rule:** Use for actions triggered by a single button (e.g. account menu, row actions, sort options). Wrap items in DropdownMenuGroup and add DropdownMenuLabel for semantic sections. Apply variant="destructive" on irreversible items like sign out or delete. **Never rules:** - Never use DropdownMenu for navigation between pages; use NavigationMenu or plain links instead - Never open a dropdown on right-click; use ContextMenu for that pattern - Never put more than two levels of sub-menus; flatten or move to a dedicated page - Never hardcode colours on items; use the variant prop and token utilities only **Tokens consumed:** - --layout-overlay - --layout-overlay-fg - --layout-accent - --layout-accent-fg - --layout-danger - --layout-border - --layout-radius - --layout-shadow-md - --layout-duration-base --- ### Empty (`empty`) **Description:** Empty state component family with icon media, title, description, and CTA slot. Server-compatible plain markup. **Docs:** https://ui.staging.layout.design/docs/components/empty **Registry JSON:** https://ui.staging.layout.design/r/empty.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/empty.json` **Usage rule:** Use Empty as the outer wrapper. EmptyHeader groups the media, title, and description. EmptyMedia wraps a lucide icon (size-6) in a square bg-muted rounded container. EmptyContent holds action buttons below the header. Always include EmptyDescription to explain the empty state and guide the user's next action. **Never rules:** - Never show Empty during initial loading; use Skeleton instead and only render Empty once the data fetch confirms zero results - Never place EmptyContent outside of Empty; it relies on the parent's flex-col layout - Never use EmptyMedia for decorative images that do not represent the missing entity type - Never omit EmptyTitle; a blank media icon alone does not convey enough information **Tokens consumed:** - --layout-muted - --layout-muted-fg - --layout-radius --- ### Field (`field`) **Description:** Form field wrapper with automatic label association, description, and validation error display. Built on Base UI Field. Works without react-hook-form. **Docs:** https://ui.staging.layout.design/docs/components/field **Registry JSON:** https://ui.staging.layout.design/r/field.json **Install:** `npx shadcn add https://ui.staging.layout.design/r/field.json` **Usage rule:** Wrap any field control in Field. FieldLabel auto-associates with the control via Field.Root context — no htmlFor needed unless the control is outside Field. FieldError renders only when the field is invalid. Pass a validate function to Field for custom rules. **Never rules:** - Never use plain