{
  "schemaVersion": "0.1.0",
  "library": {
    "name": "sparkdesign",
    "versionSource": "package.json",
    "agentContract": "Use this manifest to choose components by intent, constraints, and composition rules before reading source code.",
    "defaultConsumption": "cli",
    "consumptionModes": {
      "cli": {
        "when": "Business applications that should own and customize copied component source.",
        "init": "npx sparkdesign@latest init",
        "add": "npx sparkdesign@latest add <component>"
      },
      "package": {
        "when": "Fast prototypes, showcase usage, or projects that explicitly install the package runtime.",
        "install": "npm install sparkdesign",
        "styleImport": "import 'sparkdesign/style'"
      }
    }
  },
  "globalRules": [
    "Prefer existing Spark components over creating visually similar one-off UI.",
    "Use design tokens and semantic utility classes; do not hard-code hex colors, ad-hoc radii, or arbitrary shadows in product UI.",
    "For portaled UI, preserve data-theme and data-style inheritance through ThemeStyleProvider or component wrappers.",
    "Choose chat components only for conversational, agentic, tool, file, or reasoning flows; use basic components for product UI primitives.",
    "Read antiPatterns before composing a component into a generated screen."
  ],
  "tokenRules": {
    "color": {
      "preferred": [
        "text-text",
        "text-text-secondary",
        "text-text-tertiary",
        "bg-bg-base",
        "bg-bg-elevated",
        "bg-fill-secondary",
        "border-border",
        "bg-primary",
        "text-primary-foreground"
      ],
      "forbidden": [
        "hard-coded hex colors",
        "raw rgb/rgba values unless binding to a tokenized CSS variable",
        "semantic misuse such as destructive colors for neutral emphasis"
      ]
    },
    "spacing": {
      "preferred": [
        "gap-*",
        "p-*",
        "px-*",
        "py-*",
        "var(--spacing-*)"
      ],
      "forbidden": [
        "pixel-perfect arbitrary spacing without a component-specific reason",
        "layout rhythm that changes across sibling components"
      ]
    },
    "motion": {
      "preferred": [
        "short functional transitions for feedback",
        "Framer Motion only when state transition clarity improves"
      ],
      "forbidden": [
        "decorative motion that delays task completion",
        "motion without reduced-motion consideration for complex scenes"
      ]
    }
  },
  "components": {
    "alert": {
      "id": "alert",
      "name": "Alert",
      "category": "basic",
      "status": "stable",
      "intent": "Inline callout for contextual status, warnings, or explanatory feedback inside page flow.",
      "packageImport": "import { Alert, AlertTitle, AlertDescription } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add alert",
      "slots": [
        "Alert",
        "AlertTitle",
        "AlertDescription",
        "leading icon"
      ],
      "states": [
        "default",
        "info",
        "success",
        "warning",
        "destructive"
      ],
      "a11y": [
        "Use semantic text content, not icon-only alerts.",
        "Use destructive only for high-impact errors or irreversible risk.",
        "Keep title and description concise so screen reader output stays useful."
      ],
      "composition": [
        "Card",
        "Form",
        "PermissionCard",
        "ChatInput"
      ],
      "antiPatterns": [
        "Do not use Alert as a toast replacement for transient feedback.",
        "Do not stack multiple alerts when one grouped message is clearer."
      ],
      "agentHints": [
        "Choose Alert when the message belongs in the layout and should remain visible.",
        "Prefer Toast for ephemeral success notifications."
      ]
    },
    "alert-dialog": {
      "id": "alert-dialog",
      "name": "AlertDialog",
      "category": "basic",
      "status": "stable",
      "intent": "Modal confirmation surface for destructive, risky, or irreversible user decisions.",
      "packageImport": "import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add alert-dialog",
      "slots": [
        "AlertDialog",
        "AlertDialogTrigger",
        "AlertDialogContent",
        "AlertDialogTitle",
        "AlertDialogDescription",
        "AlertDialogAction",
        "AlertDialogCancel"
      ],
      "states": [
        "open",
        "closed",
        "focus-trapped",
        "destructive",
        "loading by composition"
      ],
      "a11y": [
        "Always provide AlertDialogTitle.",
        "Use AlertDialogDescription to explain the consequence.",
        "Keep cancel and confirm actions keyboard reachable.",
        "Return focus to the trigger after close."
      ],
      "composition": [
        "Button",
        "IconButton",
        "DropdownMenu",
        "PermissionCard",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use AlertDialog for ordinary passive information; use Dialog or Alert.",
        "Do not hide the cancel action for destructive decisions.",
        "Do not use vague confirm labels like OK for irreversible actions."
      ],
      "agentHints": [
        "Choose AlertDialog when the user must explicitly confirm risk.",
        "Use PermissionCard instead when the confirmation is part of an agent tool approval flow."
      ]
    },
    "accordion": {
      "id": "accordion",
      "name": "Accordion",
      "category": "basic",
      "status": "stable",
      "intent": "Tokenized disclosure set for vertically stacked expandable sections.",
      "packageImport": "import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add accordion",
      "slots": [
        "Accordion",
        "AccordionItem",
        "AccordionTrigger",
        "AccordionContent"
      ],
      "states": [
        "single",
        "multiple",
        "expanded item",
        "collapsed item",
        "disabled item",
        "collapsible"
      ],
      "a11y": [
        "Use trigger text that describes the hidden content.",
        "Keep keyboard activation available on every trigger.",
        "Do not hide required errors or critical instructions without a visible summary."
      ],
      "composition": [
        "Card",
        "Separator",
        "Badge",
        "Button"
      ],
      "antiPatterns": [
        "Do not use Accordion as primary app navigation.",
        "Do not collapse content that users must compare side by side.",
        "Do not nest many accordions without clear hierarchy."
      ],
      "agentHints": [
        "Choose Accordion for FAQ, settings, and grouped details.",
        "Use Collapsible for one independent disclosure and Collapse for Spark's existing collapse pattern."
      ]
    },
    "aspect-ratio": {
      "id": "aspect-ratio",
      "name": "AspectRatio",
      "category": "basic",
      "status": "stable",
      "intent": "Responsive media or preview frame that preserves a fixed width-to-height ratio.",
      "packageImport": "import { AspectRatio } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add aspect-ratio",
      "slots": [
        "AspectRatio",
        "media content",
        "overlay by composition"
      ],
      "states": [
        "fixed ratio",
        "responsive width",
        "loading by composition",
        "empty by composition"
      ],
      "a11y": [
        "Keep image and media children semantically labeled.",
        "Do not crop important content without an accessible alternative.",
        "Preserve keyboard access for interactive children."
      ],
      "composition": [
        "Skeleton",
        "Empty",
        "Card",
        "GeneratedImagesGrid"
      ],
      "antiPatterns": [
        "Do not use AspectRatio for arbitrary spacing.",
        "Do not hard-code fixed pixel heights when a ratio should preserve media shape.",
        "Do not place long text content inside a forced media ratio."
      ],
      "agentHints": [
        "Choose AspectRatio for thumbnails, generated image previews, video embeds, and fixed-ratio canvases.",
        "Pair with Skeleton while media loads."
      ]
    },
    "avatar": {
      "id": "avatar",
      "name": "Avatar",
      "category": "basic",
      "status": "stable",
      "intent": "User, agent, organization, or entity identity marker with image, fallback, badge, and group support.",
      "packageImport": "import { Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add avatar",
      "slots": [
        "Avatar",
        "AvatarImage",
        "AvatarFallback",
        "AvatarBadge",
        "AvatarGroup",
        "AvatarGroupCount"
      ],
      "states": [
        "image loaded",
        "fallback",
        "with badge",
        "grouped",
        "overflow count"
      ],
      "a11y": [
        "Provide meaningful alt text for identity images when the image adds information.",
        "Use fallback text that remains understandable when the image fails.",
        "Do not rely on badge color alone to communicate status."
      ],
      "composition": [
        "HoverCard",
        "Tooltip",
        "UserMessage",
        "Card"
      ],
      "antiPatterns": [
        "Do not use Avatar as a decorative icon when identity is not involved.",
        "Do not place unrelated badges on an avatar without a visible explanation.",
        "Do not use tiny fallback text that cannot be read."
      ],
      "agentHints": [
        "Choose Avatar for people, agents, teams, providers, and collaborators.",
        "Use AvatarGroup when multiple identities share ownership or presence."
      ]
    },
    "badge": {
      "id": "badge",
      "name": "Badge",
      "category": "basic",
      "status": "stable",
      "intent": "Compact Spark label for status, category, count, or short metadata.",
      "packageImport": "import { Badge } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add badge",
      "slots": [
        "Badge",
        "label",
        "icon by composition"
      ],
      "states": [
        "default",
        "secondary",
        "destructive",
        "outline",
        "asChild"
      ],
      "a11y": [
        "Use readable text inside every badge.",
        "Do not rely on badge color alone for status meaning.",
        "Keep destructive badges reserved for real risk or error state."
      ],
      "composition": [
        "Card",
        "Item",
        "DataTable",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Badge as an action button.",
        "Do not use many badge colors without a clear taxonomy.",
        "Do not use Badge for removable tokens; use Tag when close behavior is needed."
      ],
      "agentHints": [
        "Choose Badge for non-interactive labels and statuses.",
        "Choose Tag when the label is closable or needs richer color taxonomy."
      ]
    },
    "breadcrumb": {
      "id": "breadcrumb",
      "name": "Breadcrumb",
      "category": "basic",
      "status": "stable",
      "intent": "Hierarchical navigation trail showing the current page or resource location.",
      "packageImport": "import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add breadcrumb",
      "slots": [
        "Breadcrumb",
        "BreadcrumbList",
        "BreadcrumbItem",
        "BreadcrumbLink",
        "BreadcrumbPage",
        "BreadcrumbSeparator",
        "BreadcrumbEllipsis"
      ],
      "states": [
        "linked ancestor",
        "current page",
        "truncated",
        "custom separator"
      ],
      "a11y": [
        "Keep the root element labeled as breadcrumb navigation.",
        "Mark only the current page with aria-current.",
        "Use real links for navigable ancestors."
      ],
      "composition": [
        "NavigationMenu",
        "DropdownMenu",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Breadcrumb for tab navigation or step progress.",
        "Do not make the current page clickable when it represents the current location.",
        "Do not replace the semantic list with plain slash-separated text."
      ],
      "agentHints": [
        "Choose Breadcrumb for nested app sections, files, projects, and documentation pages.",
        "Use Pagination for page-by-page result navigation."
      ]
    },
    "button-group": {
      "id": "button-group",
      "name": "ButtonGroup",
      "category": "basic",
      "status": "stable",
      "intent": "Visually connected group of related controls, actions, or inline control text.",
      "packageImport": "import { ButtonGroup, ButtonGroupText, ButtonGroupSeparator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add button-group",
      "slots": [
        "ButtonGroup",
        "ButtonGroupText",
        "ButtonGroupSeparator",
        "Button by composition",
        "Input by composition"
      ],
      "states": [
        "horizontal",
        "vertical by composition",
        "with separator",
        "mixed controls",
        "disabled child"
      ],
      "a11y": [
        "Keep each child control individually labeled.",
        "Use group labels when the relationship is not visually obvious.",
        "Do not remove focus visibility from grouped controls."
      ],
      "composition": [
        "Button",
        "IconButton",
        "Input",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use ButtonGroup for mutually exclusive selected state; use ToggleGroup or RadioGroup.",
        "Do not group unrelated commands just to reduce spacing.",
        "Do not put long form layouts inside a button group."
      ],
      "agentHints": [
        "Choose ButtonGroup when controls act as one compact unit.",
        "Use ToggleGroup when the group represents selectable modes."
      ]
    },
    "button": {
      "id": "button",
      "name": "Button",
      "category": "basic",
      "status": "stable",
      "intent": "Primary, secondary, ghost, or destructive action trigger with tokenized sizing and interaction states.",
      "packageImport": "import { Button } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add button",
      "slots": [
        "label",
        "leading icon",
        "trailing icon"
      ],
      "states": [
        "default",
        "hover",
        "focus-visible",
        "disabled",
        "loading by composition"
      ],
      "a11y": [
        "Use a visible label or aria-label for icon-only actions.",
        "Keep destructive actions visually and semantically explicit.",
        "Do not disable without preserving an explanation nearby when the reason is unclear."
      ],
      "composition": [
        "DialogTrigger",
        "DropdownMenuTrigger",
        "Tooltip",
        "ChatInputActions",
        "PermissionCard"
      ],
      "antiPatterns": [
        "Do not use links styled as buttons for navigation unless the semantic element remains an anchor.",
        "Do not place multiple primary buttons in the same decision group."
      ],
      "agentHints": [
        "Use one primary action per surface.",
        "Pair dangerous actions with AlertDialog or PermissionCard."
      ]
    },
    "checkbox": {
      "id": "checkbox",
      "name": "Checkbox",
      "category": "basic",
      "status": "stable",
      "intent": "Binary form control for independent yes/no choices or multi-select option lists.",
      "packageImport": "import { Checkbox } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add checkbox",
      "slots": [
        "Checkbox",
        "indicator",
        "label by composition",
        "description by composition"
      ],
      "states": [
        "checked",
        "unchecked",
        "indeterminate",
        "disabled",
        "focus-visible",
        "error by composition"
      ],
      "a11y": [
        "Pair with Label or aria-label so the purpose is announced.",
        "Use indeterminate only when representing mixed child selection.",
        "Do not rely on the checkmark alone when disabled or error state needs explanation."
      ],
      "composition": [
        "Label",
        "Field",
        "Alert",
        "PermissionCard",
        "DataTable"
      ],
      "antiPatterns": [
        "Do not use Checkbox for mutually exclusive choices; use RadioGroup.",
        "Do not use Checkbox as a command button.",
        "Do not hide labels for settings that change persistent state."
      ],
      "agentHints": [
        "Choose Checkbox when each choice can be toggled independently.",
        "For a single on/off setting with immediate effect, prefer Switch."
      ]
    },
    "collapse": {
      "id": "collapse",
      "name": "Collapse",
      "category": "basic",
      "status": "stable",
      "intent": "Multi-item disclosure set for grouped expandable content such as FAQs, settings, or inspector sections.",
      "packageImport": "import { Collapse, CollapseItem, CollapseTrigger, CollapseContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add collapse",
      "slots": [
        "Collapse",
        "CollapseItem",
        "CollapseTrigger",
        "CollapseContent"
      ],
      "states": [
        "expanded item",
        "collapsed item",
        "multiple items",
        "single item by composition",
        "disabled by composition"
      ],
      "a11y": [
        "Use trigger text that describes the hidden content.",
        "Keep keyboard activation available on every trigger.",
        "Do not hide critical errors or required fields in collapsed sections without an indicator."
      ],
      "composition": [
        "Card",
        "Field",
        "IconButton",
        "Separator"
      ],
      "antiPatterns": [
        "Do not use Collapse as primary navigation.",
        "Do not collapse tiny content that should simply remain visible.",
        "Do not nest many collapse sets without clear hierarchy."
      ],
      "agentHints": [
        "Choose Collapse for repeated expandable sections.",
        "Use Collapsible for one independent disclosure region."
      ]
    },
    "collapsible": {
      "id": "collapsible",
      "name": "Collapsible",
      "category": "basic",
      "status": "stable",
      "intent": "Single independent disclosure primitive for showing or hiding nearby content.",
      "packageImport": "import { Collapsible, CollapsibleTrigger, CollapsibleContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add collapsible",
      "slots": [
        "Collapsible",
        "CollapsibleTrigger",
        "CollapsibleContent"
      ],
      "states": [
        "open",
        "closed",
        "controlled",
        "uncontrolled",
        "disabled by composition"
      ],
      "a11y": [
        "Use a button-like trigger with clear text or aria-label.",
        "Keep the expanded content close to its trigger in the DOM.",
        "Do not hide content required to understand the current task."
      ],
      "composition": [
        "Button",
        "IconButton",
        "Tooltip",
        "CollapsibleCard"
      ],
      "antiPatterns": [
        "Do not use Collapsible for modal or overlay behavior.",
        "Do not use it for mutually exclusive tab panels.",
        "Do not make the trigger icon-only without an accessible name."
      ],
      "agentHints": [
        "Choose Collapsible for a single expandable details region.",
        "Use Collapse when rendering a list of expandable items."
      ]
    },
    "collapsible-card": {
      "id": "collapsible-card",
      "name": "CollapsibleCard",
      "category": "basic",
      "status": "stable",
      "intent": "Card-like disclosure surface with header, content, and compact collapse behavior.",
      "packageImport": "import { CollapsibleCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add collapsible-card",
      "slots": [
        "CollapsibleCard",
        "header",
        "title",
        "actions",
        "content"
      ],
      "states": [
        "expanded",
        "collapsed",
        "with actions",
        "loading by composition",
        "error by composition"
      ],
      "a11y": [
        "Ensure the header control clearly announces expanded state.",
        "Keep action buttons separate from the collapse trigger.",
        "Do not collapse active validation errors without a visible summary."
      ],
      "composition": [
        "Collapsible",
        "Card",
        "IconButton",
        "Spinner",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use CollapsibleCard for every static card on a page.",
        "Do not hide primary actions in collapsed content.",
        "Do not nest cards inside cards without a strong information hierarchy."
      ],
      "agentHints": [
        "Choose CollapsibleCard for compact inspectors, tool results, and expandable summaries.",
        "Use Card when the content should always remain visible."
      ]
    },
    "dropdown-menu": {
      "id": "dropdown-menu",
      "name": "DropdownMenu",
      "category": "basic",
      "status": "stable",
      "intent": "Command menu for contextual actions, grouped commands, submenus, shortcuts, and non-form choices.",
      "packageImport": "import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add dropdown-menu",
      "slots": [
        "DropdownMenu",
        "DropdownMenuTrigger",
        "DropdownMenuContent",
        "DropdownMenuItem",
        "DropdownMenuLabel",
        "DropdownMenuSeparator",
        "DropdownMenuShortcut",
        "DropdownMenuSub"
      ],
      "states": [
        "open",
        "closed",
        "disabled item",
        "checked item",
        "radio item",
        "submenu"
      ],
      "a11y": [
        "Use menu items for commands, not form field values.",
        "Keep destructive items clearly labeled and visually distinct.",
        "Ensure trigger text or aria-label explains the menu purpose."
      ],
      "composition": [
        "Button",
        "IconButton",
        "Tooltip",
        "AlertDialog",
        "Command"
      ],
      "antiPatterns": [
        "Do not use DropdownMenu for selecting a persistent form value; use Select.",
        "Do not hide primary actions in a menu when they should be visible.",
        "Do not put long forms inside menu content."
      ],
      "agentHints": [
        "Choose DropdownMenu for action overflow, row actions, and command groups.",
        "Use Select when the user is choosing one value to store."
      ]
    },
    "dotm-square-3": {
      "id": "dotm-square-3",
      "name": "DotmSquare3",
      "category": "motion",
      "status": "stable",
      "intent": "Animated 5x5 dot-matrix mark for loading, thinking, generation, and compact agent activity states.",
      "packageImport": "import { DotmSquare3 } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add dotm-square-3",
      "slots": [
        "DotmSquare3 root",
        "5x5 dot grid",
        "accessible status label"
      ],
      "states": [
        "animated",
        "static",
        "muted",
        "hover animated",
        "reduced motion",
        "pattern variants"
      ],
      "a11y": [
        "Provide ariaLabel when the loading or thinking state needs a specific announcement.",
        "Use animated=false for purely decorative marks next to explicit text.",
        "Respect reduced motion; the component automatically disables CSS animation when the user requests reduced motion."
      ],
      "composition": [
        "Button",
        "ChatInput",
        "Response",
        "ToolInvocationCard",
        "ThinkingIndicator",
        "GenerationStatusBar"
      ],
      "antiPatterns": [
        "Do not use DotmSquare3 as a replacement for progress when determinate progress is available.",
        "Do not stack several animated dot matrices in one compact surface.",
        "Do not hard-code brand colors; use Spark tokens or semantic CSS variables."
      ],
      "agentHints": [
        "Choose DotmSquare3 for compact AI activity, background thinking, or generation micro-states.",
        "Pair with concise text when the status must be understood without motion.",
        "Use Spinner for generic app loading where an AI-specific activity mark would be too expressive."
      ]
    },
    "context-menu": {
      "id": "context-menu",
      "name": "ContextMenu",
      "category": "basic",
      "status": "stable",
      "intent": "Right-click or context-triggered command menu for actions tied to a specific surface or item.",
      "packageImport": "import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add context-menu",
      "slots": [
        "ContextMenu",
        "ContextMenuTrigger",
        "ContextMenuContent",
        "ContextMenuItem",
        "ContextMenuLabel",
        "ContextMenuSeparator",
        "ContextMenuSub"
      ],
      "states": [
        "open",
        "closed",
        "disabled item",
        "checked item",
        "submenu",
        "destructive by composition"
      ],
      "a11y": [
        "Do not make context menu the only way to access critical actions.",
        "Keep menu item labels readable and action-oriented.",
        "Ensure destructive context actions require clear confirmation when needed."
      ],
      "composition": [
        "AlertDialog",
        "DropdownMenu",
        "IconButton",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not hide primary workflows behind right-click only.",
        "Do not use ContextMenu for persistent form values; use Select or Combobox.",
        "Do not put long forms inside context menu content."
      ],
      "agentHints": [
        "Choose ContextMenu for item-specific secondary actions.",
        "Also expose frequent actions through visible buttons or row actions."
      ]
    },
    "hover-card": {
      "id": "hover-card",
      "name": "HoverCard",
      "category": "basic",
      "status": "stable",
      "intent": "Hover/focus preview surface for supplemental details about a person, item, link, or entity.",
      "packageImport": "import { HoverCard, HoverCardTrigger, HoverCardContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add hover-card",
      "slots": [
        "HoverCard",
        "HoverCardTrigger",
        "HoverCardContent",
        "preview content"
      ],
      "states": [
        "closed",
        "open on hover",
        "open on focus",
        "delayed",
        "rich preview"
      ],
      "a11y": [
        "Do not put required task information only in HoverCard.",
        "Keep trigger content meaningful without hover.",
        "Ensure focus users can access the same supplemental information."
      ],
      "composition": [
        "Avatar",
        "Button",
        "Card",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use HoverCard for interactive forms or destructive choices.",
        "Do not use as the only source of validation or error feedback.",
        "Do not overload hover previews with long documentation."
      ],
      "agentHints": [
        "Choose HoverCard for supplemental previews.",
        "Use Popover or Dialog when the user needs to interact with the content."
      ]
    },
    "menubar": {
      "id": "menubar",
      "name": "Menubar",
      "category": "basic",
      "status": "stable",
      "intent": "Application-style menu bar for grouped top-level commands and nested command menus.",
      "packageImport": "import { Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add menubar",
      "slots": [
        "Menubar",
        "MenubarMenu",
        "MenubarTrigger",
        "MenubarContent",
        "MenubarItem",
        "MenubarShortcut",
        "MenubarSub"
      ],
      "states": [
        "open menu",
        "closed",
        "disabled item",
        "submenu",
        "checked item"
      ],
      "a11y": [
        "Use clear top-level command group labels.",
        "Keep keyboard traversal predictable across menus.",
        "Expose shortcuts as supplementary text, not the only command label."
      ],
      "composition": [
        "Command",
        "AlertDialog",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Menubar as ordinary site navigation; use NavigationMenu.",
        "Do not place form fields inside Menubar content.",
        "Do not overload it with unrelated product navigation and destructive commands."
      ],
      "agentHints": [
        "Choose Menubar for desktop-like application command groups.",
        "Choose NavigationMenu for page/site navigation."
      ]
    },
    "navigation-menu": {
      "id": "navigation-menu",
      "name": "NavigationMenu",
      "category": "basic",
      "status": "stable",
      "intent": "Primary or sectional navigation menu with grouped links and optional flyout content.",
      "packageImport": "import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add navigation-menu",
      "slots": [
        "NavigationMenu",
        "NavigationMenuList",
        "NavigationMenuItem",
        "NavigationMenuTrigger",
        "NavigationMenuContent",
        "NavigationMenuLink",
        "NavigationMenuViewport"
      ],
      "states": [
        "active link",
        "open flyout",
        "closed",
        "nested groups",
        "responsive by composition"
      ],
      "a11y": [
        "Use real links for navigation destinations.",
        "Keep labels short and route-oriented.",
        "Do not mix command actions and navigation without clear grouping."
      ],
      "composition": [
        "Button",
        "Popover",
        "Sheet",
        "SidebarMenu"
      ],
      "antiPatterns": [
        "Do not use NavigationMenu for contextual row actions; use DropdownMenu.",
        "Do not hide primary navigation behind hover-only flyouts.",
        "Do not use for desktop app command menus; use Menubar."
      ],
      "agentHints": [
        "Choose NavigationMenu for top-level page or section navigation.",
        "Use SidebarMenu for persistent app side navigation."
      ]
    },
    "pagination": {
      "id": "pagination",
      "name": "Pagination",
      "category": "basic",
      "status": "stable",
      "intent": "Page navigation controls for paginated lists, tables, and search results.",
      "packageImport": "import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add pagination",
      "slots": [
        "Pagination",
        "PaginationContent",
        "PaginationItem",
        "PaginationLink",
        "PaginationPrevious",
        "PaginationNext",
        "PaginationEllipsis"
      ],
      "states": [
        "current page",
        "previous disabled",
        "next disabled",
        "ellipsis",
        "page links"
      ],
      "a11y": [
        "Provide readable labels for previous and next controls.",
        "Mark the current page semantically.",
        "Do not rely on pagination alone when filtering or search would better reduce results."
      ],
      "composition": [
        "DataTable",
        "Table",
        "Search",
        "Button"
      ],
      "antiPatterns": [
        "Do not paginate very small result sets.",
        "Do not hide current page context.",
        "Do not use Pagination for tab-like mode switching."
      ],
      "agentHints": [
        "Choose Pagination when users browse large result sets page by page.",
        "Use infinite scroll only when the product explicitly calls for it."
      ]
    },
    "popover": {
      "id": "popover",
      "name": "Popover",
      "category": "basic",
      "status": "stable",
      "intent": "Anchored interactive floating panel for compact controls, pickers, or contextual editing.",
      "packageImport": "import { Popover, PopoverTrigger, PopoverContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add popover",
      "slots": [
        "Popover",
        "PopoverTrigger",
        "PopoverContent",
        "PopoverAnchor"
      ],
      "states": [
        "open",
        "closed",
        "anchored",
        "interactive content",
        "dismissible"
      ],
      "a11y": [
        "Ensure the trigger has a clear accessible name.",
        "Keep focus behavior predictable for interactive content.",
        "Do not put long multi-step workflows inside a small popover."
      ],
      "composition": [
        "Button",
        "Calendar",
        "Command",
        "Combobox",
        "Input"
      ],
      "antiPatterns": [
        "Do not use Popover for destructive confirmations; use AlertDialog.",
        "Do not use Popover for passive hover help; use Tooltip or HoverCard.",
        "Do not make the user complete long forms in a constrained popover."
      ],
      "agentHints": [
        "Choose Popover for compact pickers and contextual controls.",
        "Use Dialog or Drawer when the content needs more space."
      ]
    },
    "sidebar-menu": {
      "id": "sidebar-menu",
      "name": "SidebarMenu",
      "category": "basic",
      "status": "stable",
      "intent": "Lightweight data-driven side navigation menu for app sections and per-item actions, without owning the full app shell.",
      "packageImport": "import { SidebarMenu } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add sidebar-menu",
      "slots": [
        "SidebarMenu",
        "menu item",
        "item action",
        "nested group by composition",
        "active state"
      ],
      "states": [
        "active item",
        "collapsed by composition",
        "expanded by composition",
        "disabled item",
        "with actions"
      ],
      "a11y": [
        "Use readable item labels and real navigation links when navigating.",
        "Do not encode active state only with color.",
        "Keep item actions keyboard reachable."
      ],
      "composition": [
        "NavigationMenu",
        "Tooltip",
        "DropdownMenu",
        "Sheet"
      ],
      "antiPatterns": [
        "Do not use SidebarMenu for transient action menus.",
        "Do not hide core navigation labels without an accessible collapsed pattern.",
        "Do not mix unrelated settings, commands, and navigation in one flat list.",
        "Do not use SidebarMenu when the layout needs provider-managed collapse, mobile sheet behavior, or an inset content area; use Sidebar instead."
      ],
      "agentHints": [
        "Choose SidebarMenu for a simple controlled list of navigation items with optional item actions.",
        "Choose Sidebar when generating a complete app shell with SidebarProvider, SidebarTrigger, and SidebarInset.",
        "Use NavigationMenu for top navigation and DropdownMenu for contextual actions."
      ]
    },
    "sidebar": {
      "id": "sidebar",
      "name": "Sidebar",
      "category": "basic",
      "status": "stable",
      "intent": "Application sidebar system with provider-managed collapse, mobile sheet behavior, inset content, groups, and menu primitives.",
      "packageImport": "import { Sidebar, SidebarProvider, SidebarTrigger, SidebarInset, SidebarNavMenu } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add sidebar",
      "slots": [
        "SidebarProvider",
        "Sidebar",
        "SidebarTrigger",
        "SidebarInset",
        "SidebarHeader",
        "SidebarContent",
        "SidebarGroup",
        "SidebarNavMenu"
      ],
      "states": [
        "expanded",
        "collapsed",
        "mobile sheet",
        "offcanvas",
        "icon collapsed",
        "active menu item"
      ],
      "a11y": [
        "Provide readable labels for sidebar trigger and menu buttons.",
        "Do not hide core navigation labels without tooltip or accessible names in icon mode.",
        "Keep the main content reachable when the sidebar is collapsed or mobile."
      ],
      "composition": [
        "Button",
        "Sheet",
        "Tooltip",
        "Input",
        "Separator",
        "Skeleton"
      ],
      "antiPatterns": [
        "Do not use Sidebar for transient context menus.",
        "Do not put unrelated commands, settings, and navigation in one flat sidebar.",
        "Do not rely on collapsed icon visuals alone for navigation meaning.",
        "Do not use Sidebar for a single static menu list when SidebarMenu is enough."
      ],
      "agentHints": [
        "Choose Sidebar for complete app shells that need provider state, responsive collapse, a trigger, and an inset content area.",
        "In package imports, use SidebarNavMenu and SidebarNavMenuItem for the menu list exported from Sidebar; the name SidebarMenu is reserved for Spark's lightweight data-driven menu.",
        "Choose SidebarMenu for Spark's lightweight data-driven menu list."
      ]
    },
    "empty": {
      "id": "empty",
      "name": "Empty",
      "category": "basic",
      "status": "stable",
      "intent": "Empty-state layout for blank pages, lists, panels, or first-run surfaces with guidance and optional actions.",
      "packageImport": "import { Empty, EmptyHeader, EmptyTitle, EmptyDescription, EmptyContent, EmptyMedia } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add empty",
      "slots": [
        "Empty",
        "EmptyHeader",
        "EmptyTitle",
        "EmptyDescription",
        "EmptyContent",
        "EmptyMedia"
      ],
      "states": [
        "blank",
        "first-run",
        "no-results",
        "filtered-empty",
        "error by composition"
      ],
      "a11y": [
        "Use a clear title that explains what is empty.",
        "Do not make illustration or icon the only explanation.",
        "Keep primary recovery or start action keyboard reachable."
      ],
      "composition": [
        "Button",
        "ChatInput",
        "RelatedPrompts",
        "Alert",
        "Card"
      ],
      "antiPatterns": [
        "Do not use Empty when data is still loading; use Skeleton or Spinner.",
        "Do not show many competing calls to action.",
        "Do not use generic copy that fails to explain the user's next step."
      ],
      "agentHints": [
        "Choose Empty for no-content states that need guidance.",
        "Pair with ChatInput or RelatedPrompts when the next step is AI-assisted."
      ]
    },
    "ellipsis-text": {
      "id": "ellipsis-text",
      "name": "EllipsisText",
      "category": "basic",
      "status": "stable",
      "intent": "Single-line or constrained text truncation with optional tooltip for full content.",
      "packageImport": "import { EllipsisText } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add ellipsis-text",
      "slots": [
        "EllipsisText",
        "visible text",
        "tooltip by composition"
      ],
      "states": [
        "fits",
        "truncated",
        "tooltip enabled",
        "custom element"
      ],
      "a11y": [
        "Do not truncate labels where the full value is required to complete a task.",
        "Expose the full text through title, Tooltip, or adjacent details when needed.",
        "Avoid truncating text that differs only at the end, such as file names, without another disambiguator."
      ],
      "composition": [
        "Tooltip",
        "Table",
        "DataTable",
        "FileCard"
      ],
      "antiPatterns": [
        "Do not use EllipsisText as a substitute for responsive layout.",
        "Do not truncate critical error messages.",
        "Do not place multi-line rich content inside EllipsisText."
      ],
      "agentHints": [
        "Choose EllipsisText for dense tables, file paths, titles, and IDs that may overflow.",
        "Prefer wrapping text when readability is more important than density."
      ]
    },
    "calendar": {
      "id": "calendar",
      "name": "Calendar",
      "category": "basic",
      "status": "stable",
      "intent": "Calendar grid for visible date selection, date ranges, or scheduling surfaces.",
      "packageImport": "import { Calendar } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add calendar",
      "slots": [
        "Calendar",
        "CalendarDayButton",
        "month navigation",
        "day grid"
      ],
      "states": [
        "single date",
        "range by composition",
        "disabled dates",
        "selected date",
        "today",
        "outside month"
      ],
      "a11y": [
        "Preserve keyboard navigation through dates.",
        "Use readable date labels for selected and disabled dates.",
        "Do not rely on color alone to indicate selected or unavailable days."
      ],
      "composition": [
        "Popover",
        "DatePicker",
        "Button",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use Calendar for free-form date text entry; use Input or DatePicker.",
        "Do not show a full calendar when a compact date picker is sufficient.",
        "Do not hide unavailable date rules from the user."
      ],
      "agentHints": [
        "Choose Calendar when the user benefits from seeing the month layout.",
        "Choose DatePicker for a compact form field."
      ]
    },
    "carousel": {
      "id": "carousel",
      "name": "Carousel",
      "category": "basic",
      "status": "stable",
      "intent": "Horizontal or vertical slide collection for browsable media, cards, examples, or featured content.",
      "packageImport": "import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add carousel",
      "slots": [
        "Carousel",
        "CarouselContent",
        "CarouselItem",
        "CarouselPrevious",
        "CarouselNext",
        "CarouselApi"
      ],
      "states": [
        "first slide",
        "last slide",
        "scrollable",
        "disabled previous",
        "disabled next",
        "loop by configuration"
      ],
      "a11y": [
        "Provide context for what the carousel contains.",
        "Keep previous and next controls keyboard reachable and named.",
        "Do not hide essential content only in off-screen slides."
      ],
      "composition": [
        "Card",
        "AspectRatio",
        "Button",
        "GeneratedImagesGrid"
      ],
      "antiPatterns": [
        "Do not use Carousel for primary navigation.",
        "Do not put unrelated forms or critical decisions across slides.",
        "Do not auto-advance content without a clear product reason."
      ],
      "agentHints": [
        "Choose Carousel for browsable previews or media collections.",
        "Use a grid or list when users need to compare all items at once."
      ]
    },
    "chart": {
      "id": "chart",
      "name": "Chart",
      "category": "basic",
      "status": "stable",
      "intent": "Tokenized chart container and tooltip/legend primitives for data visualization.",
      "packageImport": "import { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add chart",
      "slots": [
        "ChartContainer",
        "ChartTooltip",
        "ChartTooltipContent",
        "ChartLegend",
        "ChartLegendContent",
        "ChartStyle"
      ],
      "states": [
        "loading by composition",
        "empty by composition",
        "interactive tooltip",
        "legend",
        "responsive"
      ],
      "a11y": [
        "Provide surrounding text that explains the chart insight.",
        "Do not rely on color alone to distinguish series.",
        "Ensure important values are available outside hover-only tooltips."
      ],
      "composition": [
        "Card",
        "Skeleton",
        "Empty",
        "Table"
      ],
      "antiPatterns": [
        "Do not use Chart for decorative metrics without readable values.",
        "Do not hide critical data only inside hover states.",
        "Do not use charts when a table or simple metric is clearer."
      ],
      "agentHints": [
        "Choose Chart for trends, comparisons, or distributions.",
        "Pair with Table when exact values must be inspected."
      ]
    },
    "combobox": {
      "id": "combobox",
      "name": "Combobox",
      "category": "basic",
      "status": "stable",
      "intent": "Searchable picker for choosing from a small to medium local option set.",
      "packageImport": "import { Combobox } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add combobox",
      "slots": [
        "Combobox",
        "trigger",
        "search input",
        "option list",
        "empty state"
      ],
      "states": [
        "open",
        "closed",
        "searching",
        "selected",
        "empty",
        "disabled"
      ],
      "a11y": [
        "Provide a label or accessible name for the picker.",
        "Keep option labels readable and unique.",
        "Preserve keyboard search and selection behavior."
      ],
      "composition": [
        "Command",
        "Popover",
        "Button",
        "Label",
        "Field"
      ],
      "antiPatterns": [
        "Do not use Combobox for command execution; use Command or DropdownMenu.",
        "Do not use for tiny 2-3 option sets where RadioGroup or Select is clearer.",
        "Do not use for large remote datasets without explicit loading and empty states."
      ],
      "agentHints": [
        "Choose Combobox when users need to search a list before selecting one value.",
        "Choose Select when search is unnecessary."
      ]
    },
    "command": {
      "id": "command",
      "name": "Command",
      "category": "basic",
      "status": "stable",
      "intent": "Command palette or searchable action/list surface with grouped results and keyboard-first selection.",
      "packageImport": "import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add command",
      "slots": [
        "Command",
        "CommandInput",
        "CommandList",
        "CommandEmpty",
        "CommandGroup",
        "CommandItem",
        "CommandShortcut"
      ],
      "states": [
        "searching",
        "empty",
        "grouped",
        "selected item",
        "disabled item",
        "dialog mode"
      ],
      "a11y": [
        "Keep command labels action-oriented and readable.",
        "Expose keyboard shortcuts as supplementary text, not the only label.",
        "Preserve keyboard navigation and selection semantics."
      ],
      "composition": [
        "Dialog",
        "Popover",
        "Combobox",
        "DropdownMenu"
      ],
      "antiPatterns": [
        "Do not use Command as a normal form Select unless command search behavior is needed.",
        "Do not bury destructive commands without confirmation.",
        "Do not mix navigation, destructive actions, and form values without grouping."
      ],
      "agentHints": [
        "Choose Command for command palettes, quick switchers, and searchable actions.",
        "Choose Combobox for searchable value selection."
      ]
    },
    "data-table": {
      "id": "data-table",
      "name": "DataTable",
      "category": "basic",
      "status": "stable",
      "intent": "Structured tabular data surface with columns, rows, and optional row actions.",
      "packageImport": "import { DataTable } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add data-table",
      "slots": [
        "columns",
        "rows",
        "header",
        "cell renderers",
        "row actions by composition"
      ],
      "states": [
        "loading by composition",
        "empty",
        "sortable by composition",
        "selectable by composition",
        "error by composition"
      ],
      "a11y": [
        "Use meaningful column headers.",
        "Keep row actions reachable by keyboard.",
        "Do not rely on visual alignment alone to communicate relationships."
      ],
      "composition": [
        "Table",
        "DropdownMenu",
        "Checkbox",
        "Skeleton",
        "Empty"
      ],
      "antiPatterns": [
        "Do not use DataTable for simple key-value details; use Card or Item.",
        "Do not hide critical row actions behind unlabeled icon-only menus.",
        "Do not put unrelated layouts inside cells when a card list is clearer."
      ],
      "agentHints": [
        "Choose DataTable for scan-heavy lists with repeated fields.",
        "Use Table primitives for custom static tables."
      ]
    },
    "date-picker": {
      "id": "date-picker",
      "name": "DatePicker",
      "category": "basic",
      "status": "stable",
      "intent": "Compact form control for choosing a date through a trigger and calendar popover.",
      "packageImport": "import { DatePicker } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add date-picker",
      "slots": [
        "DatePicker",
        "trigger",
        "calendar popover",
        "selected date label"
      ],
      "states": [
        "selected",
        "placeholder",
        "open",
        "closed",
        "disabled",
        "invalid by composition"
      ],
      "a11y": [
        "Pair with Label or an accessible name in forms.",
        "Expose the selected date as readable text.",
        "Preserve keyboard access to the calendar popover."
      ],
      "composition": [
        "Calendar",
        "Popover",
        "Button",
        "Label",
        "Field"
      ],
      "antiPatterns": [
        "Do not use DatePicker for arbitrary date ranges unless the component supports the range flow.",
        "Do not use a plain Input when users need calendar validation.",
        "Do not hide date format expectations."
      ],
      "agentHints": [
        "Choose DatePicker for date fields in forms.",
        "Choose Calendar for visible scheduling surfaces."
      ]
    },
    "direction": {
      "id": "direction",
      "name": "DirectionProvider",
      "category": "basic",
      "status": "stable",
      "intent": "Direction context provider for left-to-right and right-to-left UI rendering.",
      "packageImport": "import { DirectionProvider, useDirection } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add direction",
      "slots": [
        "DirectionProvider",
        "children",
        "dir"
      ],
      "states": [
        "ltr",
        "rtl",
        "inherited",
        "explicit"
      ],
      "a11y": [
        "Set direction at a meaningful subtree boundary.",
        "Do not mix opposing directions inside a single phrase unless the content requires it.",
        "Keep icon mirroring and reading order consistent with the selected direction."
      ],
      "composition": [
        "NavigationMenu",
        "Tabs",
        "DropdownMenu",
        "Table"
      ],
      "antiPatterns": [
        "Do not use DirectionProvider as a layout alignment shortcut.",
        "Do not hard-code direction when content locale should decide it.",
        "Do not wrap tiny isolated controls when the whole app direction is known."
      ],
      "agentHints": [
        "Choose DirectionProvider when generating RTL-ready demos, localized shells, or bidirectional component examples.",
        "Use CSS alignment utilities for visual alignment that is unrelated to language direction."
      ]
    },
    "field": {
      "id": "field",
      "name": "Field",
      "category": "basic",
      "status": "stable",
      "intent": "Form field structure for labels, descriptions, errors, grouped controls, and fieldsets.",
      "packageImport": "import { Field, FieldLabel, FieldDescription, FieldError, FieldGroup } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add field",
      "slots": [
        "Field",
        "FieldLabel",
        "FieldDescription",
        "FieldError",
        "FieldContent",
        "FieldGroup",
        "FieldSet",
        "FieldLegend"
      ],
      "states": [
        "default",
        "invalid",
        "disabled by composition",
        "required by composition",
        "grouped"
      ],
      "a11y": [
        "Associate labels and descriptions with the underlying control.",
        "Expose errors as readable text.",
        "Use FieldSet and FieldLegend for grouped related controls."
      ],
      "composition": [
        "Input",
        "Textarea",
        "Select",
        "Checkbox",
        "RadioGroup",
        "Switch"
      ],
      "antiPatterns": [
        "Do not use Field as generic spacing wrapper.",
        "Do not show errors only through border color.",
        "Do not duplicate labels between FieldLabel and placeholder."
      ],
      "agentHints": [
        "Choose Field when generated forms need label, help text, and validation.",
        "Use Label alone for very small inline controls."
      ]
    },
    "form": {
      "id": "form",
      "name": "Form",
      "category": "basic",
      "status": "stable",
      "intent": "React Hook Form composition helpers for validated forms.",
      "packageImport": "import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add form",
      "slots": [
        "Form",
        "FormField",
        "FormItem",
        "FormLabel",
        "FormControl",
        "FormDescription",
        "FormMessage"
      ],
      "states": [
        "valid",
        "invalid",
        "dirty",
        "submitted",
        "described",
        "controlled field"
      ],
      "a11y": [
        "Connect every FormLabel to its FormControl.",
        "Expose validation errors through FormMessage.",
        "Do not rely on placeholder text as the only field label."
      ],
      "composition": [
        "Input",
        "Textarea",
        "Select",
        "Checkbox",
        "Button"
      ],
      "antiPatterns": [
        "Do not use Form without react-hook-form context.",
        "Do not use Form helpers for static display-only fields.",
        "Do not hide validation errors outside the field reading order."
      ],
      "agentHints": [
        "Choose Form when generating validated forms with React Hook Form wiring.",
        "Choose Field for layout-only form rows that do not need react-hook-form."
      ]
    },
    "icon-button": {
      "id": "icon-button",
      "name": "IconButton",
      "category": "basic",
      "status": "stable",
      "intent": "Icon-only action button with enforced accessible naming for dense toolbars and compact controls.",
      "packageImport": "import { IconButton } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add icon-button",
      "slots": [
        "icon",
        "accessible name",
        "loading by composition",
        "tooltip by composition"
      ],
      "states": [
        "default",
        "hover",
        "focus-visible",
        "disabled",
        "pressed by composition"
      ],
      "a11y": [
        "Provide aria-label, aria-labelledby, or title.",
        "Use Tooltip to clarify unfamiliar icons, but keep the button itself named.",
        "Do not rely on icon shape alone for meaning."
      ],
      "composition": [
        "Tooltip",
        "DropdownMenu",
        "ButtonGroup",
        "AlertDialog"
      ],
      "antiPatterns": [
        "Do not use IconButton for primary labeled actions when text would reduce ambiguity.",
        "Do not omit accessible names.",
        "Do not use decorative icons as controls."
      ],
      "agentHints": [
        "Choose IconButton for compact repeated actions like edit, remove, copy, or more.",
        "Use Button when the action needs a visible label."
      ]
    },
    "input": {
      "id": "input",
      "name": "Input",
      "category": "basic",
      "status": "stable",
      "intent": "Single-line text, search, URL, email, number, password, or file input with Spark token styling.",
      "packageImport": "import { Input } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add input",
      "slots": [
        "Input",
        "native input attributes",
        "label by composition",
        "description by composition",
        "error by composition"
      ],
      "states": [
        "default",
        "focus-visible",
        "disabled",
        "read-only",
        "invalid",
        "file"
      ],
      "a11y": [
        "Associate every user-facing input with Label or aria-label.",
        "Expose validation errors with readable text and aria-invalid when applicable.",
        "Use the correct native type instead of masking semantics with custom UI."
      ],
      "composition": [
        "Label",
        "Field",
        "InputGroup",
        "Button",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use Input for multi-line text; use Textarea.",
        "Do not rely on placeholder text as the only label.",
        "Do not build custom combobox behavior from Input when Combobox or Command fits."
      ],
      "agentHints": [
        "Choose Input for short free-form values.",
        "Wrap with Field when the generated UI needs label, description, and error structure."
      ]
    },
    "input-group": {
      "id": "input-group",
      "name": "InputGroup",
      "category": "basic",
      "status": "stable",
      "intent": "Compound input wrapper for inputs with addons, buttons, text, or textarea affordances.",
      "packageImport": "import { InputGroup, InputGroupInput, InputGroupAddon, InputGroupButton, InputGroupTextarea } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add input-group",
      "slots": [
        "InputGroup",
        "InputGroupInput",
        "InputGroupTextarea",
        "InputGroupAddon",
        "InputGroupButton",
        "InputGroupText"
      ],
      "states": [
        "default",
        "focused child",
        "disabled child",
        "with leading addon",
        "with trailing action",
        "textarea"
      ],
      "a11y": [
        "Keep the actual input or textarea labeled.",
        "Use buttons inside InputGroup only for related field actions.",
        "Do not put unrelated controls into the group."
      ],
      "composition": [
        "Input",
        "Textarea",
        "Button",
        "Tooltip",
        "Field"
      ],
      "antiPatterns": [
        "Do not use InputGroup as a generic horizontal layout container.",
        "Do not hide the field label inside an addon only.",
        "Do not place multiple competing submit actions inside one field group."
      ],
      "agentHints": [
        "Choose InputGroup for URL prefixes, search actions, copy buttons, and inline units.",
        "Use plain Input when no attached affordance is needed."
      ]
    },
    "input-otp": {
      "id": "input-otp",
      "name": "InputOTP",
      "category": "basic",
      "status": "stable",
      "intent": "Segmented one-time passcode, verification code, or short token entry.",
      "packageImport": "import { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add input-otp",
      "slots": [
        "InputOTP",
        "InputOTPGroup",
        "InputOTPSlot",
        "InputOTPSeparator"
      ],
      "states": [
        "empty",
        "partially filled",
        "filled",
        "focused slot",
        "invalid by composition",
        "disabled"
      ],
      "a11y": [
        "Label the verification code field clearly.",
        "Expose validation errors as readable text.",
        "Do not split ordinary text input into OTP slots."
      ],
      "composition": [
        "Field",
        "Label",
        "Button",
        "Alert",
        "Spinner"
      ],
      "antiPatterns": [
        "Do not use InputOTP for passwords, names, or arbitrary numeric input.",
        "Do not hide resend or recovery options when verification can fail.",
        "Do not assume every verification code has the same length without product rules."
      ],
      "agentHints": [
        "Choose InputOTP for authentication, invite, or device verification codes.",
        "Use Input for normal short strings and numbers."
      ]
    },
    "item": {
      "id": "item",
      "name": "Item",
      "category": "basic",
      "status": "stable",
      "intent": "Composable list row or detail item with media, content, actions, footer, and separators.",
      "packageImport": "import { Item, ItemContent, ItemTitle, ItemDescription, ItemActions } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add item",
      "slots": [
        "Item",
        "ItemMedia",
        "ItemContent",
        "ItemHeader",
        "ItemTitle",
        "ItemDescription",
        "ItemActions",
        "ItemFooter",
        "ItemGroup",
        "ItemSeparator"
      ],
      "states": [
        "default",
        "interactive by composition",
        "with media",
        "with actions",
        "grouped",
        "disabled by composition"
      ],
      "a11y": [
        "Keep row actions keyboard reachable and clearly named.",
        "Use semantic links or buttons inside the item when it navigates or performs an action.",
        "Do not make the whole item clickable when it contains nested controls unless event behavior is clear."
      ],
      "composition": [
        "Avatar",
        "IconButton",
        "DropdownMenu",
        "Separator",
        "Tag"
      ],
      "antiPatterns": [
        "Do not use Item for tabular data that needs column relationships; use Table or DataTable.",
        "Do not overload one item with many unrelated actions.",
        "Do not nest Card inside Item without a clear hierarchy."
      ],
      "agentHints": [
        "Choose Item for settings rows, activity rows, file rows, search results, and compact resource summaries.",
        "Use Card when the content needs a standalone framed surface."
      ]
    },
    "kbd": {
      "id": "kbd",
      "name": "Kbd",
      "category": "basic",
      "status": "stable",
      "intent": "Keyboard shortcut or key token display for command hints and documentation.",
      "packageImport": "import { Kbd, KbdGroup } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add kbd",
      "slots": [
        "Kbd",
        "KbdGroup",
        "key text"
      ],
      "states": [
        "single key",
        "key group",
        "shortcut sequence",
        "inline"
      ],
      "a11y": [
        "Keep shortcut text readable and not the only way to invoke a command.",
        "Use platform-appropriate key labels when the product knows the platform.",
        "Do not use Kbd styling for ordinary badges or tags."
      ],
      "composition": [
        "Command",
        "Menubar",
        "Tooltip",
        "Typography"
      ],
      "antiPatterns": [
        "Do not use Kbd as a generic pill component.",
        "Do not hide command labels and show only shortcuts.",
        "Do not use misleading platform-specific shortcut symbols."
      ],
      "agentHints": [
        "Choose Kbd for visible keyboard shortcuts and key names.",
        "Use Tag for labels, statuses, or categories."
      ]
    },
    "label": {
      "id": "label",
      "name": "Label",
      "category": "basic",
      "status": "stable",
      "intent": "Accessible text label for form controls and settings.",
      "packageImport": "import { Label } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add label",
      "slots": [
        "Label",
        "htmlFor target",
        "children"
      ],
      "states": [
        "default",
        "disabled by composition",
        "required by composition"
      ],
      "a11y": [
        "Connect Label to its control with htmlFor or a wrapping pattern.",
        "Keep labels concise and specific.",
        "Do not replace labels with placeholder-only copy."
      ],
      "composition": [
        "Input",
        "Textarea",
        "Select",
        "Checkbox",
        "RadioGroup",
        "Switch"
      ],
      "antiPatterns": [
        "Do not use Label as a generic typography component.",
        "Do not point htmlFor at a non-control element.",
        "Do not make required state visible only through color."
      ],
      "agentHints": [
        "Use Label for every visible form field in generated forms.",
        "Use Typography or plain text for non-form captions."
      ]
    },
    "radio-group": {
      "id": "radio-group",
      "name": "RadioGroup",
      "category": "basic",
      "status": "stable",
      "intent": "Mutually exclusive option picker where all or most choices should be visible at once.",
      "packageImport": "import { RadioGroup, RadioGroupItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add radio-group",
      "slots": [
        "RadioGroup",
        "RadioGroupItem",
        "label by composition",
        "description by composition"
      ],
      "states": [
        "selected",
        "unselected",
        "disabled",
        "focus-visible",
        "horizontal by layout",
        "vertical by layout"
      ],
      "a11y": [
        "Give the group a visible label or accessible name.",
        "Pair each item with readable text.",
        "Use RadioGroup only when exactly one option can be selected."
      ],
      "composition": [
        "Label",
        "Field",
        "Card",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use RadioGroup for independent toggles; use Checkbox or Switch.",
        "Do not use RadioGroup when the option list is very long; consider Select or Combobox.",
        "Do not make option meaning depend only on icons."
      ],
      "agentHints": [
        "Choose RadioGroup for 2-6 visible exclusive options.",
        "Choose Select when space is tight or choices are numerous."
      ]
    },
    "progress": {
      "id": "progress",
      "name": "Progress",
      "category": "basic",
      "status": "stable",
      "intent": "Linear progress indicator for determinate task completion, uploads, generation, or setup flows.",
      "packageImport": "import { Progress } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add progress",
      "slots": [
        "Progress",
        "value",
        "label by composition",
        "status text by composition"
      ],
      "states": [
        "determinate",
        "indeterminate by composition",
        "complete",
        "error by composition",
        "disabled by composition"
      ],
      "a11y": [
        "Provide readable status text when progress matters to the task.",
        "Use aria values correctly for determinate progress.",
        "Do not rely on bar length alone for critical status."
      ],
      "composition": [
        "AgentTaskList",
        "GenerationStatusBar",
        "Card",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use Progress as decorative loading chrome.",
        "Do not show fake precision when actual progress is unknown.",
        "Do not replace short inline loading with a full progress bar."
      ],
      "agentHints": [
        "Choose Progress when there is meaningful completion percentage.",
        "Use Spinner for brief unknown-duration loading."
      ]
    },
    "rating": {
      "id": "rating",
      "name": "Rating",
      "category": "basic",
      "status": "stable",
      "intent": "Star-based score or preference input for reviews, quality signals, and lightweight sentiment feedback.",
      "packageImport": "import { Rating } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add rating",
      "slots": [
        "Rating",
        "stars",
        "numeric value by option",
        "accessible label"
      ],
      "states": [
        "controlled",
        "uncontrolled",
        "whole precision",
        "half precision",
        "read-only",
        "disabled"
      ],
      "a11y": [
        "Provide a clear label when the rating is an input.",
        "Use readOnly for static review summaries.",
        "Do not rely on star color alone when numeric precision matters."
      ],
      "composition": [
        "Card",
        "Field",
        "Label",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Rating for exact numeric entry; use Input or Slider.",
        "Do not ask for ratings when the user needs categorical choices.",
        "Do not hide the current value in dense analytics summaries."
      ],
      "agentHints": [
        "Choose Rating for familiar 1-5 preference capture or review display.",
        "Use precision={0.5} only when half steps are meaningful to users."
      ]
    },
    "resizable": {
      "id": "resizable",
      "name": "Resizable",
      "category": "basic",
      "status": "stable",
      "intent": "Resizable panel group primitives for split panes, inspectors, sidebars, and adjustable workspaces.",
      "packageImport": "import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add resizable",
      "slots": [
        "ResizablePanelGroup",
        "ResizablePanel",
        "ResizableHandle"
      ],
      "states": [
        "horizontal",
        "vertical",
        "dragging",
        "collapsed by configuration",
        "with handle",
        "keyboard resize"
      ],
      "a11y": [
        "Keep panel content reachable when resized small.",
        "Use handles only between panels that can actually resize.",
        "Do not make critical controls disappear without a recovery path."
      ],
      "composition": [
        "SidebarMenu",
        "ScrollArea",
        "Tabs",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Resizable for simple fixed columns.",
        "Do not nest many resizable groups unless the workspace model requires it.",
        "Do not let text or controls overflow when panels become narrow."
      ],
      "agentHints": [
        "Choose Resizable for IDE-like shells, split inspectors, preview panes, and data workspaces.",
        "Use normal CSS grid or flex for static layouts."
      ]
    },
    "select": {
      "id": "select",
      "name": "Select",
      "category": "basic",
      "status": "stable",
      "intent": "Dropdown form control for choosing one persistent value from a known option set.",
      "packageImport": "import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add select",
      "slots": [
        "Select",
        "SelectTrigger",
        "SelectValue",
        "SelectContent",
        "SelectItem",
        "SelectGroup",
        "SelectLabel",
        "SelectSeparator"
      ],
      "states": [
        "open",
        "closed",
        "selected",
        "placeholder",
        "disabled",
        "invalid by composition"
      ],
      "a11y": [
        "Pair with Label or otherwise provide an accessible name.",
        "Use placeholder copy only as a hint, not as the label.",
        "Keep option labels concise and unique."
      ],
      "composition": [
        "Label",
        "Field",
        "Popover",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use Select for command menus; use DropdownMenu.",
        "Do not use Select for free-form search across large remote datasets; use Combobox or Command.",
        "Do not put destructive commands inside SelectItem."
      ],
      "agentHints": [
        "Choose Select when the value will be saved as field state.",
        "Use NativeSelect when platform-native behavior is more important than custom popover styling."
      ]
    },
    "native-select": {
      "id": "native-select",
      "name": "NativeSelect",
      "category": "basic",
      "status": "stable",
      "intent": "Browser-native select control for simple form value selection with platform behavior.",
      "packageImport": "import { NativeSelect, NativeSelectOption, NativeSelectOptGroup } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add native-select",
      "slots": [
        "NativeSelect",
        "NativeSelectOption",
        "NativeSelectOptGroup"
      ],
      "states": [
        "selected",
        "placeholder option",
        "disabled",
        "invalid",
        "small size"
      ],
      "a11y": [
        "Pair with Label or an accessible name.",
        "Use native option text that is readable without custom formatting.",
        "Keep disabled placeholder behavior explicit."
      ],
      "composition": [
        "Field",
        "Label",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use NativeSelect for rich option rendering, search, or command menus.",
        "Do not put destructive actions in native options.",
        "Do not use when custom trigger/content styling is required; use Select."
      ],
      "agentHints": [
        "Choose NativeSelect for simple forms, settings, and platform-native behavior.",
        "Choose Select or Combobox when the option UI needs richer behavior."
      ]
    },
    "option-list": {
      "id": "option-list",
      "name": "OptionList",
      "category": "basic",
      "status": "stable",
      "intent": "Keyboard-friendly selectable option list for generated suggestions, choices, or lightweight pickers.",
      "packageImport": "import { OptionList } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add option-list",
      "slots": [
        "OptionList",
        "OptionItem",
        "prefix",
        "label",
        "description"
      ],
      "states": [
        "selected",
        "focused",
        "disabled",
        "dimmed",
        "multi-select by selectedIds"
      ],
      "a11y": [
        "Provide unique labels for each option.",
        "Use descriptions when options need disambiguation.",
        "Do not rely on numeric prefixes alone to explain choices."
      ],
      "composition": [
        "Command",
        "Card",
        "ChatInput",
        "RelatedPrompts"
      ],
      "antiPatterns": [
        "Do not use OptionList for persistent form values when Select, RadioGroup, or Checkbox is semantically clearer.",
        "Do not use it for complex row actions that need menus.",
        "Do not omit disabled state when an option cannot be chosen."
      ],
      "agentHints": [
        "Choose OptionList for AI-generated suggestions, prompt choices, quick pickers, and lightweight selection flows.",
        "Use Combobox when the list needs search."
      ]
    },
    "switch": {
      "id": "switch",
      "name": "Switch",
      "category": "basic",
      "status": "stable",
      "intent": "Immediate on/off control for a setting or feature flag.",
      "packageImport": "import { Switch } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add switch",
      "slots": [
        "Switch",
        "thumb",
        "label by composition",
        "description by composition"
      ],
      "states": [
        "on",
        "off",
        "disabled",
        "focus-visible",
        "segment variant"
      ],
      "a11y": [
        "Pair with Label or aria-label.",
        "Make the resulting state clear in surrounding copy.",
        "Avoid switch controls for irreversible or destructive actions."
      ],
      "composition": [
        "Label",
        "Field",
        "Card",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Switch for multi-option selection; use RadioGroup, Select, or ToggleGroup.",
        "Do not use Switch when the user must confirm before changing state.",
        "Do not hide the setting name inside a tooltip only."
      ],
      "agentHints": [
        "Choose Switch for settings that can be applied immediately.",
        "Use Checkbox when the control is part of a form submitted later."
      ]
    },
    "skeleton": {
      "id": "skeleton",
      "name": "Skeleton",
      "category": "basic",
      "status": "stable",
      "intent": "Placeholder shape for content that is loading while preserving layout stability.",
      "packageImport": "import { Skeleton } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add skeleton",
      "slots": [
        "Skeleton",
        "shape by className",
        "layout by composition"
      ],
      "states": [
        "loading",
        "content-replaced",
        "reduced-motion by environment"
      ],
      "a11y": [
        "Pair with readable loading state when the wait is meaningful.",
        "Avoid skeletons that shift layout when content loads.",
        "Do not expose decorative skeleton blocks as meaningful content."
      ],
      "composition": [
        "Card",
        "Table",
        "Response",
        "FileCard"
      ],
      "antiPatterns": [
        "Do not use Skeleton after an error; use Alert or Empty with recovery.",
        "Do not use for very short interactions where Spinner is clearer.",
        "Do not create fake text density that misrepresents the final layout."
      ],
      "agentHints": [
        "Choose Skeleton for page, card, table, or response placeholders.",
        "Use Spinner for small inline operations."
      ]
    },
    "spinner": {
      "id": "spinner",
      "name": "Spinner",
      "category": "basic",
      "status": "stable",
      "intent": "Compact indeterminate loading indicator for short or inline operations.",
      "packageImport": "import { Spinner } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add spinner",
      "slots": [
        "Spinner",
        "label by composition",
        "container by composition"
      ],
      "states": [
        "loading",
        "inline",
        "button-loading by composition",
        "hidden after complete"
      ],
      "a11y": [
        "Add readable loading text when the action is not otherwise clear.",
        "Do not rely on motion alone to convey loading.",
        "Avoid trapping focus on spinner-only content."
      ],
      "composition": [
        "Button",
        "ChatInput",
        "ToolInvocationCard",
        "AgentTaskList"
      ],
      "antiPatterns": [
        "Do not use Spinner for long determinate tasks; use Progress.",
        "Do not leave spinner visible after an error or success state.",
        "Do not use as decorative motion."
      ],
      "agentHints": [
        "Choose Spinner for brief unknown-duration operations.",
        "Pair with status text for agent tool or generation loading."
      ]
    },
    "tabs": {
      "id": "tabs",
      "name": "Tabs",
      "category": "basic",
      "status": "stable",
      "intent": "Switch between peer views, panels, or categories without leaving the current surface.",
      "packageImport": "import { Tabs, TabsList, TabsTrigger, TabsContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add tabs",
      "slots": [
        "Tabs",
        "TabsList",
        "TabsTrigger",
        "TabsContent"
      ],
      "states": [
        "active tab",
        "inactive tab",
        "disabled tab",
        "focus-visible",
        "horizontal",
        "vertical by layout"
      ],
      "a11y": [
        "Keep trigger labels short and descriptive.",
        "Ensure each TabsContent corresponds to a TabsTrigger value.",
        "Do not hide critical information behind a tab that users may miss."
      ],
      "composition": [
        "Card",
        "Table",
        "Form",
        "Response"
      ],
      "antiPatterns": [
        "Do not use Tabs as primary navigation across unrelated pages.",
        "Do not create one-tab tab lists.",
        "Do not use Tabs when content should be compared side-by-side."
      ],
      "agentHints": [
        "Choose Tabs for sibling modes such as Overview, Activity, Settings.",
        "Use segmented Switch or ToggleGroup for compact option changes."
      ]
    },
    "textarea": {
      "id": "textarea",
      "name": "Textarea",
      "category": "basic",
      "status": "stable",
      "intent": "Multi-line text field for notes, prompts, descriptions, comments, and longer free-form input.",
      "packageImport": "import { Textarea } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add textarea",
      "slots": [
        "Textarea",
        "native textarea attributes",
        "label by composition",
        "description by composition",
        "error by composition"
      ],
      "states": [
        "default",
        "focus-visible",
        "disabled",
        "read-only",
        "invalid",
        "resizable"
      ],
      "a11y": [
        "Associate with Label or aria-label.",
        "Use aria-invalid and readable error text for validation.",
        "Keep helper text outside placeholder when users need it after typing."
      ],
      "composition": [
        "Label",
        "Field",
        "Button",
        "Alert",
        "ChatInput"
      ],
      "antiPatterns": [
        "Do not use Textarea for chat composition when ChatInput is expected.",
        "Do not use Textarea for short single values; use Input.",
        "Do not disable resizing when longer text is expected unless layout requires it."
      ],
      "agentHints": [
        "Choose Textarea for long-form user-authored text.",
        "Choose ChatInput for conversational prompt entry with send actions."
      ]
    },
    "table": {
      "id": "table",
      "name": "Table",
      "category": "basic",
      "status": "stable",
      "intent": "Semantic table primitives for static tabular content, comparison data, or custom table layouts.",
      "packageImport": "import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add table",
      "slots": [
        "Table",
        "TableHeader",
        "TableBody",
        "TableRow",
        "TableHead",
        "TableCell",
        "TableCaption"
      ],
      "states": [
        "static",
        "captioned",
        "empty by composition",
        "loading by composition",
        "custom layout"
      ],
      "a11y": [
        "Use table headers for data relationships.",
        "Use captions or surrounding headings when context is not obvious.",
        "Do not use tables for purely visual grid layout."
      ],
      "composition": [
        "Card",
        "DataTable",
        "Skeleton",
        "Empty"
      ],
      "antiPatterns": [
        "Do not use Table for non-tabular card grids.",
        "Do not omit headers for data tables.",
        "Do not use Table when DataTable behavior such as repeated columns and row actions is needed."
      ],
      "agentHints": [
        "Choose Table for static or custom tabular data.",
        "Choose DataTable for reusable row/column datasets and actions."
      ]
    },
    "tag": {
      "id": "tag",
      "name": "Tag",
      "category": "basic",
      "status": "stable",
      "intent": "Compact label, category, status, or removable token displayed inline with content.",
      "packageImport": "import { Tag } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add tag",
      "slots": [
        "Tag",
        "label",
        "close button",
        "close icon"
      ],
      "states": [
        "filled",
        "outline",
        "color variants",
        "closable",
        "hover close affordance"
      ],
      "a11y": [
        "Use readable text inside every tag.",
        "Provide a specific closeAriaLabel for removable tags.",
        "Do not rely on color alone for status meaning."
      ],
      "composition": [
        "Item",
        "DataTable",
        "FileCard",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Tag as a button when the user expects a command.",
        "Do not use many colored tags without a clear taxonomy.",
        "Do not use Tag for keyboard shortcuts; use Kbd."
      ],
      "agentHints": [
        "Choose Tag for statuses, categories, filters, labels, and removable tokens.",
        "Use Alert for important status messages that need explanation."
      ]
    },
    "scroll-area": {
      "id": "scroll-area",
      "name": "ScrollArea",
      "category": "basic",
      "status": "stable",
      "intent": "Tokenized scroll container with styled scrollbars for constrained panels or dense content regions.",
      "packageImport": "import { ScrollArea, ScrollBar } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add scroll-area",
      "slots": [
        "ScrollArea",
        "ScrollBar",
        "viewport",
        "content"
      ],
      "states": [
        "vertical scroll",
        "horizontal scroll",
        "both axes",
        "keyboard focus",
        "overflowing",
        "not overflowing"
      ],
      "a11y": [
        "Keep keyboard focus visible inside the scroll region.",
        "Ensure important content is not hidden without an obvious scroll affordance.",
        "Use semantic structure inside the scroll content."
      ],
      "composition": [
        "Command",
        "Dialog",
        "Sheet",
        "Table",
        "Markdown"
      ],
      "antiPatterns": [
        "Do not wrap whole pages in nested ScrollArea without a layout reason.",
        "Do not use ScrollArea to hide layout overflow bugs.",
        "Do not create nested scroll traps inside small modals."
      ],
      "agentHints": [
        "Choose ScrollArea for command lists, side panels, long markdown, and bounded tables.",
        "Prefer normal page scroll for primary page content."
      ]
    },
    "scrollbar": {
      "id": "scrollbar",
      "name": "Scrollbar",
      "category": "basic",
      "status": "stable",
      "intent": "Custom scrollbar utility for scrollable containers that need explicit visibility behavior.",
      "packageImport": "import { Scrollbar } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add scrollbar",
      "slots": [
        "Scrollbar",
        "scroll container",
        "thumb"
      ],
      "states": [
        "auto",
        "always",
        "hidden",
        "horizontal",
        "vertical"
      ],
      "a11y": [
        "Do not hide scroll affordance when users may miss overflow content.",
        "Keep scrollable regions operable by keyboard and touch.",
        "Use visible state for dense panels where overflow is common."
      ],
      "composition": [
        "ScrollArea",
        "Markdown",
        "Response",
        "Table"
      ],
      "antiPatterns": [
        "Do not use Scrollbar as decoration.",
        "Do not hide native scrolling without a tested alternative.",
        "Do not combine with nested scroll areas that trap interaction."
      ],
      "agentHints": [
        "Choose Scrollbar when a custom scroll container needs tokenized scrollbar visibility.",
        "Use ScrollArea when you need the full scroll container primitive."
      ]
    },
    "separator": {
      "id": "separator",
      "name": "Separator",
      "category": "basic",
      "status": "stable",
      "intent": "Semantic or decorative divider between related groups of content or controls.",
      "packageImport": "import { Separator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add separator",
      "slots": [
        "Separator",
        "orientation"
      ],
      "states": [
        "horizontal",
        "vertical",
        "decorative",
        "semantic"
      ],
      "a11y": [
        "Use decorative separators when the divider is purely visual.",
        "Do not rely on separators alone to create information hierarchy.",
        "Keep vertical separators out of places where they confuse reading order."
      ],
      "composition": [
        "DropdownMenu",
        "Menubar",
        "Field",
        "Item",
        "ButtonGroup"
      ],
      "antiPatterns": [
        "Do not use Separator as a spacer.",
        "Do not over-segment dense UIs with repeated dividers.",
        "Do not replace headings or grouping labels with separators only."
      ],
      "agentHints": [
        "Choose Separator to clarify groups inside menus, forms, and sidebars.",
        "Use spacing and headings first when hierarchy needs explanation."
      ]
    },
    "shimmering-text": {
      "id": "shimmering-text",
      "name": "ShimmeringText",
      "category": "basic",
      "status": "stable",
      "intent": "Animated text emphasis for active generation, premium affordances, or short status labels.",
      "packageImport": "import { ShimmeringText } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add shimmering-text",
      "slots": [
        "ShimmeringText",
        "text",
        "motion props"
      ],
      "states": [
        "animated",
        "paused by environment",
        "inline",
        "status"
      ],
      "a11y": [
        "Keep the underlying text readable without motion.",
        "Use sparingly so animated emphasis does not distract from task content.",
        "Avoid shimmering text for critical errors or required labels."
      ],
      "composition": [
        "Spinner",
        "GenerationStatusBar",
        "ThinkingIndicator",
        "Card"
      ],
      "antiPatterns": [
        "Do not use ShimmeringText for long paragraphs.",
        "Do not animate multiple competing text elements on the same surface.",
        "Do not use as the only indicator of loading or success."
      ],
      "agentHints": [
        "Choose ShimmeringText for short AI activity labels or lightweight delight.",
        "Use Spinner, Progress, or Skeleton when loading state needs stronger feedback."
      ]
    },
    "slider": {
      "id": "slider",
      "name": "Slider",
      "category": "basic",
      "status": "stable",
      "intent": "Continuous or stepped numeric value control for ranges like volume, size, threshold, or intensity.",
      "packageImport": "import { Slider } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add slider",
      "slots": [
        "Slider",
        "track",
        "range",
        "thumb",
        "label by composition",
        "value text by composition"
      ],
      "states": [
        "default",
        "dragging",
        "focused",
        "disabled",
        "single thumb",
        "range by composition"
      ],
      "a11y": [
        "Provide a label and readable value when the value matters.",
        "Use sensible min, max, and step values.",
        "Do not rely on position alone when precise values are required."
      ],
      "composition": [
        "Field",
        "Label",
        "Input",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use Slider for categorical choices; use RadioGroup, Select, or ToggleGroup.",
        "Do not use when exact typed numeric entry is required without also offering Input.",
        "Do not hide units or scale meaning."
      ],
      "agentHints": [
        "Choose Slider for adjustable numeric settings with immediate visual feedback.",
        "Pair with Input when users need precise values."
      ]
    },
    "stepper": {
      "id": "stepper",
      "name": "Stepper",
      "category": "basic",
      "status": "stable",
      "intent": "Linear workflow progress for setup, checkout, approval, onboarding, and multi-step task status.",
      "packageImport": "import { Stepper, StepperItem, StepperIndicator, StepperContent, StepperTitle, StepperDescription, StepperSeparator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add stepper",
      "slots": [
        "Stepper",
        "StepperItem",
        "StepperIndicator",
        "StepperContent",
        "StepperTitle",
        "StepperDescription",
        "StepperSeparator"
      ],
      "states": [
        "horizontal",
        "vertical",
        "complete",
        "current",
        "upcoming",
        "error"
      ],
      "a11y": [
        "Use ordered steps when sequence matters.",
        "Make the current step visible in text, not only color.",
        "Do not hide validation errors behind completed-looking steps."
      ],
      "composition": [
        "Button",
        "Progress",
        "Alert",
        "Card"
      ],
      "antiPatterns": [
        "Do not use Stepper for non-linear tabs; use Tabs.",
        "Do not show too many steps when grouped milestones would scan better.",
        "Do not mark future steps as interactive unless navigation is supported."
      ],
      "agentHints": [
        "Choose Stepper when users need to understand where they are in a process.",
        "Use vertical orientation for verbose workflow history or mobile layouts."
      ]
    },
    "timeline": {
      "id": "timeline",
      "name": "Timeline",
      "category": "basic",
      "status": "stable",
      "intent": "Chronological event list for activity history, releases, audit logs, and milestone narratives.",
      "packageImport": "import { Timeline, TimelineItem, TimelineMarker, TimelineConnector, TimelineContent, TimelineTitle, TimelineDescription, TimelineTime } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add timeline",
      "slots": [
        "Timeline",
        "TimelineItem",
        "TimelineMarker",
        "TimelineConnector",
        "TimelineContent",
        "TimelineTitle",
        "TimelineDescription",
        "TimelineTime"
      ],
      "states": [
        "default",
        "primary",
        "success",
        "warning",
        "error",
        "last item without connector"
      ],
      "a11y": [
        "Keep event order clear and consistent.",
        "Include timestamps or labels when chronology matters.",
        "Do not encode event meaning only through marker color."
      ],
      "composition": [
        "Badge",
        "Tag",
        "Card",
        "Separator"
      ],
      "antiPatterns": [
        "Do not use Timeline for dense tabular audit data; use Table or DataTable.",
        "Do not mix ascending and descending order in the same view.",
        "Do not overload markers with unrelated status meanings."
      ],
      "agentHints": [
        "Choose Timeline for readable event progression or product release histories.",
        "Use tone sparingly for the few events that need semantic emphasis."
      ]
    },
    "toggle": {
      "id": "toggle",
      "name": "Toggle",
      "category": "basic",
      "status": "stable",
      "intent": "Pressed/unpressed button control for a single mode, formatting option, or transient UI state.",
      "packageImport": "import { Toggle } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add toggle",
      "slots": [
        "Toggle",
        "icon",
        "label",
        "pressed state"
      ],
      "states": [
        "pressed",
        "not pressed",
        "disabled",
        "focus-visible",
        "icon-only"
      ],
      "a11y": [
        "Expose the pressed state through the component semantics.",
        "Give icon-only toggles an accessible name.",
        "Do not use Toggle for persistent form fields that should be submitted as checkboxes."
      ],
      "composition": [
        "Tooltip",
        "ButtonGroup",
        "ToggleGroup",
        "IconButton"
      ],
      "antiPatterns": [
        "Do not use Toggle for irreversible actions.",
        "Do not use Toggle when the user must pick exactly one option from a set; use ToggleGroup or RadioGroup.",
        "Do not make state depend on color only."
      ],
      "agentHints": [
        "Choose Toggle for toolbar modes such as bold, preview, pin, or visibility.",
        "Use Switch for settings that turn a feature on or off."
      ]
    },
    "toggle-group": {
      "id": "toggle-group",
      "name": "ToggleGroup",
      "category": "basic",
      "status": "stable",
      "intent": "Grouped toggle controls for selecting one or multiple compact modes.",
      "packageImport": "import { ToggleGroup, ToggleGroupItem } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add toggle-group",
      "slots": [
        "ToggleGroup",
        "ToggleGroupItem",
        "icons",
        "labels"
      ],
      "states": [
        "single selection",
        "multiple selection",
        "selected item",
        "unselected item",
        "disabled item",
        "roving focus"
      ],
      "a11y": [
        "Label the group when the option meaning is not obvious.",
        "Give icon-only items accessible names.",
        "Make selected state clear without relying on color alone."
      ],
      "composition": [
        "Tooltip",
        "ButtonGroup",
        "Field",
        "Kbd"
      ],
      "antiPatterns": [
        "Do not use ToggleGroup for long option labels; use RadioGroup or Select.",
        "Do not use it for primary navigation across pages.",
        "Do not mix single and multiple selection behavior in one group."
      ],
      "agentHints": [
        "Choose ToggleGroup for compact view modes, alignment controls, density controls, and formatting groups.",
        "Use RadioGroup when labels and descriptions need more space."
      ]
    },
    "typography": {
      "id": "typography",
      "name": "Typography",
      "category": "basic",
      "status": "stable",
      "intent": "Tokenized prose, headings, lists, quotes, tables, inline code, and muted text primitives.",
      "packageImport": "import { TypographyH1, TypographyH2, TypographyH3, TypographyP, TypographyMuted } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add typography",
      "slots": [
        "TypographyH1",
        "TypographyH2",
        "TypographyH3",
        "TypographyH4",
        "TypographyP",
        "TypographyBlockquote",
        "TypographyList",
        "TypographyInlineCode",
        "TypographyLead",
        "TypographyMuted"
      ],
      "states": [
        "heading",
        "body",
        "lead",
        "muted",
        "quote",
        "inline code",
        "list"
      ],
      "a11y": [
        "Preserve heading hierarchy instead of choosing headings by visual size only.",
        "Keep long prose readable with appropriate line length.",
        "Do not use muted text for required labels or critical warnings."
      ],
      "composition": [
        "Card",
        "Alert",
        "Markdown",
        "Empty"
      ],
      "antiPatterns": [
        "Do not use Typography components as generic layout wrappers.",
        "Do not skip heading levels for visual effect.",
        "Do not use inline code styling for emphasis that is not code-like."
      ],
      "agentHints": [
        "Choose Typography primitives for documentation, settings descriptions, and static prose.",
        "Use Markdown for generated or user-authored rich text content."
      ]
    },
    "toast": {
      "id": "toast",
      "name": "Toast",
      "category": "basic",
      "status": "stable",
      "intent": "Ephemeral notification for short-lived success, failure, or status feedback outside the main layout.",
      "packageImport": "import { Toaster, toast } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add toast",
      "slots": [
        "Toaster",
        "toast function",
        "title",
        "description",
        "action by composition"
      ],
      "states": [
        "success",
        "error",
        "warning",
        "info",
        "loading by composition",
        "dismissed"
      ],
      "a11y": [
        "Use concise notification text.",
        "Do not put required decisions only in Toast.",
        "Ensure critical errors also appear inline when users need to recover."
      ],
      "composition": [
        "Button",
        "Alert",
        "Form",
        "ToolInvocationCard"
      ],
      "antiPatterns": [
        "Do not use Toast for persistent validation or destructive confirmation.",
        "Do not stack noisy success toasts for every small state change.",
        "Do not hide important recovery actions inside an auto-dismissing toast."
      ],
      "agentHints": [
        "Choose Toast for transient acknowledgement after an action.",
        "Use Alert for feedback that must remain visible."
      ]
    },
    "tooltip": {
      "id": "tooltip",
      "name": "Tooltip",
      "category": "basic",
      "status": "stable",
      "intent": "Short contextual help for icon buttons, dense controls, or unfamiliar affordances.",
      "packageImport": "import { Tooltip } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add tooltip",
      "slots": [
        "Tooltip",
        "trigger",
        "content",
        "portal"
      ],
      "states": [
        "closed",
        "open on hover",
        "open on focus",
        "delayed",
        "disabled by composition"
      ],
      "a11y": [
        "Do not put essential instructions only in Tooltip.",
        "Use Tooltip to clarify an already focusable or hoverable trigger.",
        "Keep content short enough to be read quickly."
      ],
      "composition": [
        "IconButton",
        "Button",
        "DropdownMenu",
        "ChatInput"
      ],
      "antiPatterns": [
        "Do not use Tooltip for long documentation or validation errors.",
        "Do not use Tooltip as the only accessible name for a control.",
        "Do not attach tooltips to non-interactive decorative elements."
      ],
      "agentHints": [
        "Add Tooltip to icon-only actions when the icon may be ambiguous.",
        "Use Alert or FieldDescription for persistent guidance."
      ]
    },
    "card": {
      "id": "card",
      "name": "Card",
      "category": "basic",
      "status": "stable",
      "intent": "Bounded surface for grouped content, settings, forms, summaries, or preview blocks.",
      "packageImport": "import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add card",
      "slots": [
        "Card",
        "CardHeader",
        "CardTitle",
        "CardDescription",
        "CardAction",
        "CardContent",
        "CardFooter"
      ],
      "states": [
        "static",
        "interactive by composition",
        "empty",
        "loading by composition"
      ],
      "a11y": [
        "Use heading hierarchy intentionally inside CardTitle.",
        "Avoid making the full card clickable when nested controls exist.",
        "Keep focus order aligned with visual order."
      ],
      "composition": [
        "Button",
        "Alert",
        "Input",
        "Textarea",
        "Skeleton",
        "Badge"
      ],
      "antiPatterns": [
        "Do not use Card only to add decoration around unrelated content.",
        "Do not nest cards more than one level deep unless the information architecture requires it."
      ],
      "agentHints": [
        "Use Card to create scan-friendly groups, not as the default wrapper for every element."
      ]
    },
    "chat-input": {
      "id": "chat-input",
      "name": "ChatInput",
      "category": "chat",
      "status": "stable",
      "intent": "Agent prompt composer with attachments, actions, model/status affordances, and send behavior.",
      "packageImport": "import { ChatInput } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add chat-input",
      "slots": [
        "ChatInputRoot",
        "ChatInputAbove",
        "ChatInputBox",
        "ChatInputAttachments",
        "ChatInputInput",
        "ChatInputActions",
        "ChatInputActionsLeft",
        "ChatInputActionsRight",
        "ChatInputSendButton",
        "ChatInputFooterLeft"
      ],
      "states": [
        "idle",
        "focused",
        "composing",
        "disabled",
        "streaming",
        "attachments-present",
        "permission-required"
      ],
      "a11y": [
        "Preserve textarea semantics and keyboard submission behavior.",
        "Keep send action reachable by keyboard.",
        "Expose attachment removal with accessible labels.",
        "Do not hide status text from assistive technology when it communicates task state."
      ],
      "composition": [
        "SendButton",
        "FileAttachment",
        "ImageAttachment",
        "GenerationStatusBar",
        "PermissionCard",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use ChatInput as a generic form textarea.",
        "Do not hard-code model labels or footer actions into the component when they are product state.",
        "Do not place unrelated navigation controls inside ChatInputActions."
      ],
      "agentHints": [
        "Choose ChatInput for conversational or agent command entry.",
        "Use the compound API when the generated layout needs custom action placement."
      ]
    },
    "attachment": {
      "id": "attachment",
      "name": "Attachment",
      "category": "chat",
      "status": "stable",
      "intent": "Composable file or image attachment primitive with media, metadata, processing state, and action slots.",
      "packageImport": "import { Attachment, AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription, AttachmentActions, AttachmentAction } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add attachment",
      "slots": [
        "Attachment",
        "AttachmentMedia",
        "AttachmentContent",
        "AttachmentTitle",
        "AttachmentDescription",
        "AttachmentActions",
        "AttachmentAction"
      ],
      "states": [
        "pending",
        "uploading",
        "done",
        "error",
        "custom actions"
      ],
      "a11y": [
        "Keep the attachment title readable and unique enough to distinguish files.",
        "Provide aria-label values for icon-only AttachmentAction buttons.",
        "Do not communicate upload state only through color."
      ],
      "composition": [
        "ChatInput",
        "Message",
        "Bubble",
        "FileAttachment",
        "ImageAttachment"
      ],
      "antiPatterns": [
        "Do not use Attachment for detailed file review workflows; use FileCard or FileReviewCard.",
        "Do not hide retry or remove actions behind hover-only behavior.",
        "Do not hard-code file-type colors outside Spark tokens."
      ],
      "agentHints": [
        "Choose Attachment when a generated chat UI needs shadcn-style attachment slots.",
        "Use FileAttachment for the compact QoderWork composer token."
      ]
    },
    "bubble": {
      "id": "bubble",
      "name": "Bubble",
      "category": "chat",
      "status": "stable",
      "intent": "Low-level chat bubble surface for sent, received, note, or unframed conversational content.",
      "packageImport": "import { Bubble, BubbleContent, BubbleGroup, BubbleReactions } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add bubble",
      "slots": [
        "Bubble",
        "BubbleContent",
        "BubbleGroup",
        "BubbleReactions"
      ],
      "states": [
        "start aligned",
        "end aligned",
        "received",
        "sent",
        "note",
        "ghost"
      ],
      "a11y": [
        "Do not rely on alignment alone to identify the speaker.",
        "Keep reaction controls keyboard reachable when they are interactive.",
        "Preserve readable message text instead of rendering decorative-only content."
      ],
      "composition": [
        "Message",
        "MessageScroller",
        "Attachment",
        "Marker"
      ],
      "antiPatterns": [
        "Do not use Bubble as a generic Card replacement.",
        "Do not put full tool execution state in Bubble; use ToolInvocationCard.",
        "Do not nest multiple BubbleContent surfaces inside one Bubble without clear hierarchy."
      ],
      "agentHints": [
        "Choose Bubble for shadcn-style chat primitive layouts.",
        "Use UserMessage or Response when the product needs Spark's higher-level QoderWork message behavior."
      ]
    },
    "marker": {
      "id": "marker",
      "name": "Marker",
      "category": "chat",
      "status": "stable",
      "intent": "Compact inline status marker for chat events, checkpoints, and transcript annotations.",
      "packageImport": "import { Marker, MarkerIcon, MarkerContent } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add marker",
      "slots": [
        "Marker",
        "MarkerIcon",
        "MarkerContent"
      ],
      "states": [
        "neutral",
        "info",
        "success",
        "warning",
        "error"
      ],
      "a11y": [
        "Use text in MarkerContent to name the status.",
        "Do not rely only on icon shape or color.",
        "Keep marker text concise in dense transcripts."
      ],
      "composition": [
        "Message",
        "Bubble",
        "MessageScroller",
        "Timeline"
      ],
      "antiPatterns": [
        "Do not use Marker for primary actions.",
        "Do not overuse markers between every message.",
        "Do not use warning or error variants for neutral emphasis."
      ],
      "agentHints": [
        "Choose Marker for transcript dividers like Context loaded, Tool approved, or Tests passed.",
        "Use Badge for general app metadata outside conversational flows."
      ]
    },
    "message": {
      "id": "message",
      "name": "Message",
      "category": "chat",
      "status": "stable",
      "intent": "Composable chat message row with avatar, header, content, and footer slots.",
      "packageImport": "import { Message, MessageAvatar, MessageContent, MessageHeader, MessageFooter, MessageGroup } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add message",
      "slots": [
        "Message",
        "MessageAvatar",
        "MessageContent",
        "MessageHeader",
        "MessageFooter",
        "MessageGroup"
      ],
      "states": [
        "start aligned",
        "end aligned",
        "with avatar",
        "with header",
        "with footer",
        "grouped"
      ],
      "a11y": [
        "Expose author identity in text when avatar or alignment is not enough.",
        "Keep chronological order in DOM order.",
        "Do not put controls before message content if the visual order suggests the opposite."
      ],
      "composition": [
        "Bubble",
        "Attachment",
        "Marker",
        "MessageScroller",
        "MarkdownBody"
      ],
      "antiPatterns": [
        "Do not use Message for non-conversational list rows.",
        "Do not duplicate UserMessage and Response behavior unless primitive composition is needed.",
        "Do not encode message role only through color."
      ],
      "agentHints": [
        "Choose Message when building shadcn-style custom chat transcripts.",
        "Use Response for full assistant streaming, reasoning, and Markdown behavior."
      ]
    },
    "message-scroller": {
      "id": "message-scroller",
      "name": "MessageScroller",
      "category": "chat",
      "status": "stable",
      "intent": "Scrollable message viewport primitive for transcript panes with optional auto-scroll and jump controls.",
      "packageImport": "import { MessageScroller, MessageScrollerContent, MessageScrollerButton } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add message-scroller",
      "slots": [
        "MessageScroller",
        "MessageScrollerContent",
        "MessageScrollerButton"
      ],
      "states": [
        "scrollable",
        "auto-scroll",
        "manual scroll",
        "jump action by composition"
      ],
      "a11y": [
        "Keep message order chronological in the DOM.",
        "Provide aria-label values for icon-only jump buttons.",
        "Avoid stealing focus when new messages arrive."
      ],
      "composition": [
        "Message",
        "Bubble",
        "Attachment",
        "Marker",
        "ConversationAnchorNav"
      ],
      "antiPatterns": [
        "Do not use MessageScroller as a page-level layout container.",
        "Do not force auto-scroll when the user is reading previous context.",
        "Do not hide important history outside the scroll region without navigation."
      ],
      "agentHints": [
        "Choose MessageScroller for embedded iframe/workbench chat panes.",
        "Pair with ConversationAnchorNav for very long AI sessions."
      ]
    },
    "chat-context-tag": {
      "id": "chat-context-tag",
      "name": "ChatContextTag",
      "category": "chat",
      "status": "stable",
      "intent": "Compact context chip for agent composers, selected files, screenshots, documents, or workspace context attached to a prompt.",
      "packageImport": "import { ChatContextTag } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add chat-context-tag",
      "slots": [
        "ChatContextTag",
        "leading icon",
        "label",
        "remove action"
      ],
      "states": [
        "default",
        "with icon",
        "removable",
        "truncated label"
      ],
      "a11y": [
        "Keep the label meaningful when truncated.",
        "Provide a clear removeLabel when onRemove is available.",
        "Do not communicate context type only through color."
      ],
      "composition": [
        "ChatInput",
        "Tooltip",
        "FileAttachment",
        "Attachment"
      ],
      "antiPatterns": [
        "Do not use ChatContextTag as a general status Badge outside agent input context.",
        "Do not hide the only remove affordance behind hover.",
        "Do not show many tags without wrapping or overflow handling."
      ],
      "agentHints": [
        "Choose ChatContextTag for selected files, screenshots, links, or snippets attached to a prompt.",
        "Use FileAttachment when the context is specifically an uploaded file token."
      ]
    },
    "compression-divider": {
      "id": "compression-divider",
      "name": "ContextCompressionDivider",
      "category": "chat",
      "status": "stable",
      "intent": "Conversation separator that marks summarized, compacted, or compressed context in long agent transcripts.",
      "packageImport": "import { ContextCompressionDivider, CompressionAnimationIcon } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add compression-divider",
      "slots": [
        "ContextCompressionDivider",
        "CompressionAnimationIcon",
        "custom icon",
        "text"
      ],
      "states": [
        "compressed",
        "compressing",
        "custom label",
        "custom icon"
      ],
      "a11y": [
        "Keep ariaLabel descriptive for screen readers.",
        "Do not use animation as the only signal that compression is active.",
        "Respect reduced motion through CSS motion-safe animation utilities."
      ],
      "composition": [
        "Message",
        "AssistantResponse",
        "MessageScroller",
        "ConversationAnchorNav"
      ],
      "antiPatterns": [
        "Do not use ContextCompressionDivider as a generic page Separator.",
        "Do not insert it between unrelated non-chat sections.",
        "Do not imply information was compressed unless the product actually summarized or compacted context."
      ],
      "agentHints": [
        "Choose ContextCompressionDivider when a transcript crosses a compaction or context-summary boundary.",
        "CompressionDivider remains available as a legacy alias.",
        "Use Separator for ordinary UI section division."
      ]
    },
    "ask-user-part": {
      "id": "ask-user-part",
      "name": "AgentQuestionCard",
      "category": "chat",
      "status": "stable",
      "intent": "Agent-to-user question card with explicit skip/run actions and optional ask-timing control.",
      "packageImport": "import { AgentQuestionCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add ask-user-part",
      "slots": [
        "AgentQuestionCard",
        "title",
        "question",
        "skip action",
        "run action",
        "ask timing control"
      ],
      "states": [
        "expanded",
        "collapsed",
        "waiting for user",
        "skipped",
        "run requested"
      ],
      "a11y": [
        "Keep the question text readable and specific.",
        "Expose skip and run actions as real buttons.",
        "Do not make keyboard shortcut text the only action label."
      ],
      "composition": [
        "CollapsibleCard",
        "Button",
        "UserQuestion",
        "UserQuestionAnswer"
      ],
      "antiPatterns": [
        "Do not use AgentQuestionCard for passive status messages.",
        "Do not ask multiple unrelated questions in one card.",
        "Do not hide a required user decision in collapsed content."
      ],
      "agentHints": [
        "Choose AgentQuestionCard when an agent needs a focused user decision before continuing.",
        "AskUserPart remains available as a legacy alias.",
        "Use UserQuestion for structured multi-question option flows."
      ]
    },
    "browser-action-part": {
      "id": "browser-action-part",
      "name": "BrowserActionCard",
      "category": "chat",
      "status": "stable",
      "intent": "Agent browser action approval/status card with run, skip, permission preference, and failure states.",
      "packageImport": "import { BrowserActionCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add browser-action-part",
      "slots": [
        "BrowserActionCard",
        "description",
        "content",
        "permission select",
        "skip action",
        "run action",
        "detail action"
      ],
      "states": [
        "normal",
        "failed",
        "skipped",
        "expanded",
        "collapsible",
        "permission selected"
      ],
      "a11y": [
        "Keep browser action descriptions explicit about what will happen.",
        "Expose failed/skipped status in text, not only icon color.",
        "Do not hide permission choices behind unlabeled controls."
      ],
      "composition": [
        "CollapsibleCard",
        "Button",
        "Select",
        "Alert",
        "ToolInvocationCard"
      ],
      "antiPatterns": [
        "Do not use BrowserActionCard for non-browser tools.",
        "Do not run risky browser actions without an explicit product-level policy.",
        "Do not bury failure detail when the user needs recovery."
      ],
      "agentHints": [
        "Choose BrowserActionCard for browser automation steps that need approval or auditability.",
        "BrowserActionPart remains available as a legacy alias.",
        "Use ToolInvocationCard for generic tool execution status."
      ]
    },
    "conversation-anchor-nav": {
      "id": "conversation-anchor-nav",
      "name": "ConversationAnchorNav",
      "category": "chat",
      "status": "stable",
      "intent": "Floating anchor navigation for long conversation streams with message summaries and visible-section tracking.",
      "packageImport": "import { ConversationAnchorNav } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add conversation-anchor-nav",
      "slots": [
        "ConversationAnchorNav",
        "anchor items",
        "tooltip summary",
        "active marker",
        "custom anchor render"
      ],
      "states": [
        "hidden",
        "visible",
        "active anchor",
        "bar variant",
        "punch variant",
        "controlled active index"
      ],
      "a11y": [
        "Provide a clear aria-label for the anchor nav.",
        "Keep summaries concise and useful for navigation.",
        "Do not replace normal scroll behavior with anchor-only navigation."
      ],
      "composition": [
        "Tooltip",
        "Response",
        "UserMessage",
        "ScrollArea"
      ],
      "antiPatterns": [
        "Do not show anchors for very short conversations.",
        "Do not use it for page-level site navigation.",
        "Do not create anchors without stable target elements."
      ],
      "agentHints": [
        "Choose ConversationAnchorNav for long AI transcripts where users need to jump between user turns.",
        "Use SidebarMenu or NavigationMenu for app navigation."
      ]
    },
    "file-attachment": {
      "id": "file-attachment",
      "name": "FileAttachment",
      "category": "chat",
      "status": "stable",
      "intent": "Compatibility alias for FileCard attachment mode in chat composers and workbench attachment previews.",
      "packageImport": "import { FileAttachment } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add file-attachment",
      "slots": [
        "file cover",
        "filename",
        "metadata",
        "remove action"
      ],
      "states": [
        "default",
        "removable",
        "folder",
        "deleted",
        "icon filename override"
      ],
      "a11y": [
        "Keep filenames readable and distinguishable.",
        "Provide a clear remove label when onRemove is available.",
        "Do not rely only on file icon color to communicate file type."
      ],
      "composition": [
        "FileCard",
        "ChatInput",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not treat FileAttachment as a separate visual system; it renders FileCard variant=\"attachment\".",
        "Do not use FileAttachment for full file review states; use FileReviewCard.",
        "Do not truncate filenames without another way to inspect the full name.",
        "Do not make removal ambiguous in multi-file composers."
      ],
      "agentHints": [
        "Prefer FileCard variant=\"attachment\" when writing new code; use FileAttachment when a shorter compatibility import is useful.",
        "Use type=\"folder\" for workspace or directory attachments.",
        "Use iconFilename when the visible label omits the extension but the card should still match the file type."
      ]
    },
    "folder-button": {
      "id": "folder-button",
      "name": "FolderButton",
      "category": "chat",
      "status": "stable",
      "intent": "Chat composer folder/workspace permission button with compact states and optional notification dot.",
      "packageImport": "import { FolderButton } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add folder-button",
      "slots": [
        "FolderButton",
        "icon",
        "status dot",
        "tooltip by composition"
      ],
      "states": [
        "idle",
        "active",
        "disabled",
        "has notification",
        "focused"
      ],
      "a11y": [
        "Provide an aria-label or visible context for the folder action.",
        "Do not communicate permission state only through a dot.",
        "Keep disabled state explainable in surrounding UI."
      ],
      "composition": [
        "ChatInput",
        "Tooltip",
        "PermissionCard",
        "IconButton"
      ],
      "antiPatterns": [
        "Do not use FolderButton as a generic file picker button outside chat context.",
        "Do not show a notification dot without a meaningful reason.",
        "Do not replace visible permission flows with this button alone."
      ],
      "agentHints": [
        "Choose FolderButton inside ChatInput or agent composer toolbars for workspace/folder access.",
        "Use Button or IconButton for non-chat file actions."
      ]
    },
    "generation-status-bar": {
      "id": "generation-status-bar",
      "name": "GenerationStatusBar",
      "category": "chat",
      "status": "stable",
      "intent": "Inline generation status strip for active AI output, timed work, or streaming response phases.",
      "packageImport": "import { GenerationStatusBar } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add generation-status-bar",
      "slots": [
        "GenerationStatusBar",
        "icon",
        "status",
        "children",
        "time"
      ],
      "states": [
        "idle hidden",
        "generating",
        "with icon",
        "with time",
        "custom content"
      ],
      "a11y": [
        "Use readable status text for long-running generation.",
        "Do not rely on animated dots alone to explain progress.",
        "Avoid noisy repeated status changes that are not useful."
      ],
      "composition": [
        "ChatInput",
        "Response",
        "Progress",
        "ThinkingIndicator"
      ],
      "antiPatterns": [
        "Do not use GenerationStatusBar for non-AI page loading.",
        "Do not show fake elapsed time.",
        "Do not keep the bar visible after the response has settled unless status still matters."
      ],
      "agentHints": [
        "Choose GenerationStatusBar for active AI generation or streaming status.",
        "Use Progress when completion percentage is meaningful."
      ]
    },
    "hint-banner": {
      "id": "hint-banner",
      "name": "HintBanner",
      "category": "chat",
      "status": "stable",
      "intent": "Compact chat guidance banner for warnings, tips, or contextual next steps inside agent flows.",
      "packageImport": "import { HintBanner } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add hint-banner",
      "slots": [
        "HintBanner",
        "icon",
        "title",
        "description",
        "action by composition"
      ],
      "states": [
        "info",
        "warning by composition",
        "dismissible by composition",
        "with action",
        "hidden when no content"
      ],
      "a11y": [
        "Keep banner text concise and actionable.",
        "Do not hide required errors in a low-emphasis hint.",
        "Make any action control keyboard reachable."
      ],
      "composition": [
        "Alert",
        "Button",
        "ChatInput",
        "RelatedPrompts"
      ],
      "antiPatterns": [
        "Do not use HintBanner for destructive confirmation.",
        "Do not stack multiple hint banners in one chat turn.",
        "Do not use generic hints that do not change user behavior."
      ],
      "agentHints": [
        "Choose HintBanner for contextual AI workflow guidance.",
        "Use Alert for persistent errors or warnings that require attention."
      ]
    },
    "image-attachment": {
      "id": "image-attachment",
      "name": "ImageAttachment",
      "category": "chat",
      "status": "stable",
      "intent": "Chat image attachment thumbnail with optional preview dialog and remove action.",
      "packageImport": "import { ImageAttachment } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add image-attachment",
      "slots": [
        "ImageAttachment",
        "thumbnail",
        "preview dialog",
        "remove action",
        "alt text"
      ],
      "states": [
        "previewable",
        "not previewable",
        "preview open",
        "removable",
        "small",
        "medium",
        "large"
      ],
      "a11y": [
        "Provide useful alt text when the image content matters.",
        "Keep preview close action keyboard reachable.",
        "Do not make preview the only way to understand the attachment."
      ],
      "composition": [
        "ChatInput",
        "IconButton",
        "GeneratedImagesGrid",
        "FileCard"
      ],
      "antiPatterns": [
        "Do not use ImageAttachment for generated image galleries; use GeneratedImagesGrid.",
        "Do not omit alt text for meaningful images.",
        "Do not hide remove actions when attachments can be edited."
      ],
      "agentHints": [
        "Choose ImageAttachment for images attached to prompts or messages.",
        "Use GeneratedImagesGrid for AI output image sets."
      ]
    },
    "image-generating": {
      "id": "image-generating",
      "name": "ImageGenerationPlaceholder",
      "category": "chat",
      "status": "stable",
      "intent": "AI image generation placeholder card for pending image output before final assets arrive.",
      "packageImport": "import { ImageGenerationPlaceholder } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add image-generating",
      "slots": [
        "ImageGenerationPlaceholder",
        "status text",
        "animated placeholder",
        "container"
      ],
      "states": [
        "generating",
        "queued",
        "failed by composition",
        "completed by replacement"
      ],
      "a11y": [
        "Provide readable generation status text.",
        "Do not rely on animation alone to communicate that work is ongoing.",
        "Replace with actual generated assets when ready."
      ],
      "composition": [
        "GeneratedImagesGrid",
        "Skeleton",
        "GenerationStatusBar",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use ImageGenerating after the image result exists.",
        "Do not use for non-image loading states.",
        "Do not show multiple competing animated loaders for the same generation."
      ],
      "agentHints": [
        "Choose ImageGenerationPlaceholder for pending AI image results.",
        "ImageGenerating remains available as a legacy alias.",
        "Use Skeleton for generic media loading and GeneratedImagesGrid for completed image output."
      ]
    },
    "mermaid-part": {
      "id": "mermaid-part",
      "name": "MermaidDiagramCard",
      "category": "chat",
      "status": "stable",
      "intent": "Collapsible rendered Mermaid diagram block inside AI responses or tool output.",
      "packageImport": "import { MermaidDiagramCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add mermaid-part",
      "slots": [
        "MermaidDiagramCard",
        "diagram content",
        "header icon",
        "rendered diagram",
        "error by composition"
      ],
      "states": [
        "rendering",
        "rendered",
        "empty",
        "error",
        "collapsed by composition"
      ],
      "a11y": [
        "Provide surrounding text that explains the diagram purpose.",
        "Do not rely on the diagram alone for critical instructions.",
        "Keep fallback/error text readable when rendering fails."
      ],
      "composition": [
        "CollapsibleCard",
        "ScrollArea",
        "Alert",
        "Markdown"
      ],
      "antiPatterns": [
        "Do not use MermaidDiagramCard for arbitrary code blocks; use CodeBlockCard.",
        "Do not pass untrusted diagram text without the product's sanitization policy.",
        "Do not hide critical workflow details only inside a diagram."
      ],
      "agentHints": [
        "Choose MermaidDiagramCard for AI-generated flowcharts, sequence diagrams, and state diagrams.",
        "MermaidPart remains available as a legacy alias.",
        "Use Markdown for prose and CodeBlockCard for source code."
      ]
    },
    "queue-indicator": {
      "id": "queue-indicator",
      "name": "QueueIndicator",
      "category": "chat",
      "status": "stable",
      "intent": "Compact queue/status indicator for pending agent tasks, tool calls, or background work items.",
      "packageImport": "import { QueueIndicator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add queue-indicator",
      "slots": [
        "QueueIndicator",
        "queue items",
        "labels",
        "active item",
        "count"
      ],
      "states": [
        "empty hidden",
        "queued",
        "running",
        "completed",
        "failed",
        "expanded by composition"
      ],
      "a11y": [
        "Expose queue counts and active labels as readable text.",
        "Do not use color alone for item status.",
        "Keep updates calm and avoid excessive live-region noise."
      ],
      "composition": [
        "AgentTaskList",
        "Progress",
        "Spinner",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not use QueueIndicator for static lists.",
        "Do not show stale queued items after work has finished.",
        "Do not hide failure state when user action is needed."
      ],
      "agentHints": [
        "Choose QueueIndicator for queued or background agent work.",
        "Use AgentTaskList for detailed per-task status."
      ]
    },
    "related-prompts": {
      "id": "related-prompts",
      "name": "PromptSuggestions",
      "category": "chat",
      "status": "stable",
      "intent": "Small set of clickable suggested prompts that help users continue an AI conversation.",
      "packageImport": "import { PromptSuggestions } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add related-prompts",
      "slots": [
        "PromptSuggestions",
        "prompt item",
        "item icon",
        "tooltip in single-line mode"
      ],
      "states": [
        "empty hidden",
        "up to three prompts",
        "single-line",
        "multi-line",
        "clickable",
        "read-only"
      ],
      "a11y": [
        "Use prompt text that describes the resulting action.",
        "Keep clickable suggestions keyboard reachable.",
        "Do not rely on icons alone to explain suggestions."
      ],
      "composition": [
        "ChatInput",
        "Empty",
        "AssistantResponse",
        "Tooltip"
      ],
      "antiPatterns": [
        "Do not show too many suggestions at once.",
        "Do not use PromptSuggestions for primary navigation.",
        "Do not generate vague prompts that do not help users proceed."
      ],
      "agentHints": [
        "Choose PromptSuggestions after empty states, answers, or task completion to guide the next AI turn.",
        "RelatedPrompts remains available as a legacy alias.",
        "Use OptionList when the user must choose one of several structured options."
      ]
    },
    "send-button": {
      "id": "send-button",
      "name": "SendButton",
      "category": "chat",
      "status": "stable",
      "intent": "Chat composer send/stop action button with loading, disabled, and icon states.",
      "packageImport": "import { SendButton } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add send-button",
      "slots": [
        "SendButton",
        "send icon",
        "stop icon by composition",
        "loading indicator"
      ],
      "states": [
        "ready",
        "disabled",
        "loading",
        "streaming by composition",
        "focused"
      ],
      "a11y": [
        "Provide a clear aria-label such as Send message or Stop generation.",
        "Do not rely only on icon shape to communicate send versus stop.",
        "Keep disabled state aligned with composer validity."
      ],
      "composition": [
        "ChatInput",
        "Tooltip",
        "Spinner",
        "IconButton"
      ],
      "antiPatterns": [
        "Do not use SendButton for ordinary form submission outside chat.",
        "Do not show enabled send state when the prompt cannot be submitted.",
        "Do not omit stop/cancel affordance when streaming can be interrupted."
      ],
      "agentHints": [
        "Choose SendButton inside ChatInput or custom agent composers.",
        "Use Button for non-chat submit actions."
      ]
    },
    "thinking-indicator": {
      "id": "thinking-indicator",
      "name": "ThinkingIndicator",
      "category": "chat",
      "status": "stable",
      "intent": "Subtle AI thinking indicator for brief reasoning or response preparation states.",
      "packageImport": "import { ThinkingIndicator } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add thinking-indicator",
      "slots": [
        "ThinkingIndicator",
        "text",
        "animated dots",
        "icon by composition"
      ],
      "states": [
        "thinking",
        "hidden",
        "inline",
        "with custom label"
      ],
      "a11y": [
        "Use readable text when the wait is meaningful.",
        "Do not rely on animation alone.",
        "Avoid leaving thinking state visible after output starts."
      ],
      "composition": [
        "Response",
        "GenerationStatusBar",
        "ShimmeringText",
        "Spinner"
      ],
      "antiPatterns": [
        "Do not use ThinkingIndicator for long determinate tasks; use Progress or AgentTaskList.",
        "Do not show multiple thinking indicators for one response.",
        "Do not use as decorative ambient motion."
      ],
      "agentHints": [
        "Choose ThinkingIndicator for short AI preparation states before text appears.",
        "Use GenerationStatusBar for more prominent generation status."
      ]
    },
    "user-question-answer": {
      "id": "user-question-answer",
      "name": "UserQuestionAnswer",
      "category": "chat",
      "status": "stable",
      "intent": "Compact summary card of user-provided answers to agent questions.",
      "packageImport": "import { UserQuestionAnswer } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add user-question-answer",
      "slots": [
        "UserQuestionAnswer",
        "header",
        "question label",
        "answer text",
        "icon"
      ],
      "states": [
        "single answer",
        "multiple answers",
        "header hidden",
        "empty hidden"
      ],
      "a11y": [
        "Keep question and answer text visible in the same reading order.",
        "Do not use icon-only headers without text.",
        "Avoid hiding answers that affect subsequent agent behavior."
      ],
      "composition": [
        "UserQuestion",
        "AskUserPart",
        "Response",
        "Card"
      ],
      "antiPatterns": [
        "Do not use UserQuestionAnswer for editable question forms.",
        "Do not collapse answer summaries when they explain why the agent acted.",
        "Do not use for generic key-value details unrelated to agent questions."
      ],
      "agentHints": [
        "Choose UserQuestionAnswer after the user has responded to an agent question.",
        "Use UserQuestion for collecting the answers."
      ]
    },
    "user-question-part": {
      "id": "user-question-part",
      "name": "UserQuestion",
      "category": "chat",
      "status": "stable",
      "intent": "Structured multi-question agent form with option cards, keyboard navigation, and submit behavior.",
      "packageImport": "import { UserQuestion } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add user-question-part",
      "slots": [
        "UserQuestion",
        "UserQuestion.Header",
        "UserQuestion.Cards",
        "UserQuestion.Card",
        "UserQuestion.Footer",
        "options"
      ],
      "states": [
        "unanswered",
        "answered",
        "focused option",
        "submitting",
        "skipped",
        "keyboard navigation"
      ],
      "a11y": [
        "Use clear question text and option labels.",
        "Keep keyboard selection and submit paths available.",
        "Do not make option meaning depend only on visual styling."
      ],
      "composition": [
        "OptionList",
        "Button",
        "UserQuestionAnswer",
        "AskUserPart"
      ],
      "antiPatterns": [
        "Do not use UserQuestion for ordinary product settings forms.",
        "Do not ask too many unrelated questions in one step.",
        "Do not auto-submit ambiguous choices without user confirmation."
      ],
      "agentHints": [
        "Choose UserQuestion when an agent needs structured answers before continuing.",
        "Use AskUserPart for one focused question with simple run/skip actions."
      ]
    },
    "dialog": {
      "id": "dialog",
      "name": "Dialog",
      "category": "basic",
      "status": "stable",
      "intent": "Focused modal surface for short tasks, confirmations, or contextual forms that block background interaction.",
      "packageImport": "import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add dialog",
      "slots": [
        "Dialog",
        "DialogTrigger",
        "DialogPortal",
        "DialogOverlay",
        "DialogContent",
        "DialogHeader",
        "DialogFooter",
        "DialogTitle",
        "DialogDescription",
        "DialogClose"
      ],
      "states": [
        "open",
        "closed",
        "focus-trapped",
        "dismissible",
        "non-dismissible by composition"
      ],
      "a11y": [
        "Provide DialogTitle for every DialogContent.",
        "Use DialogDescription when title alone does not explain the task.",
        "Keep keyboard focus trapped while open.",
        "Return focus to the trigger after close."
      ],
      "composition": [
        "Button",
        "Input",
        "Textarea",
        "Alert",
        "Card"
      ],
      "antiPatterns": [
        "Do not use Dialog for long multi-step workflows that need persistent navigation.",
        "Do not nest Dialog inside Dialog unless no simpler flow exists.",
        "Do not use Dialog for passive information that can live inline."
      ],
      "agentHints": [
        "Choose Dialog when the user must complete or dismiss a focused task before continuing.",
        "Use AlertDialog for destructive confirmation flows."
      ]
    },
    "drawer": {
      "id": "drawer",
      "name": "Drawer",
      "category": "basic",
      "status": "stable",
      "intent": "Side sheet for contextual settings, details, filters, or secondary tasks that should preserve the underlying page context.",
      "packageImport": "import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add drawer",
      "slots": [
        "Drawer",
        "DrawerTrigger",
        "DrawerPortal",
        "DrawerOverlay",
        "DrawerContent",
        "DrawerHeader",
        "DrawerFooter",
        "DrawerTitle",
        "DrawerDescription",
        "DrawerClose"
      ],
      "states": [
        "open",
        "closed",
        "focus-trapped",
        "dismissible",
        "side-top",
        "side-right",
        "side-bottom",
        "side-left"
      ],
      "a11y": [
        "Provide DrawerTitle for every DrawerContent.",
        "Use DrawerDescription when the title does not fully explain the task.",
        "Keep keyboard focus inside the drawer while open.",
        "Return focus to the trigger after close."
      ],
      "composition": [
        "Button",
        "Card",
        "Alert",
        "ChatInput",
        "PermissionCard"
      ],
      "antiPatterns": [
        "Do not use Drawer for destructive confirmations that require explicit acknowledgement; use AlertDialog.",
        "Do not use Drawer for primary app navigation unless the product pattern explicitly calls for a side panel.",
        "Do not place long multi-page workflows in a drawer."
      ],
      "agentHints": [
        "Choose Drawer when the user should keep page context while editing settings or inspecting details.",
        "Prefer side=right for settings and details; use bottom mainly for compact/mobile task surfaces."
      ]
    },
    "file-review-part": {
      "id": "file-review-part",
      "name": "FileReviewCard",
      "category": "chat",
      "status": "stable",
      "intent": "Structured review surface for files changed, inspected, or proposed by an agent.",
      "packageImport": "import { FileReviewCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add file-review-part",
      "slots": [
        "summary",
        "file list",
        "file icon",
        "status",
        "approve action",
        "request changes action"
      ],
      "states": [
        "pending",
        "approved",
        "changes-requested",
        "expanded",
        "collapsed",
        "empty"
      ],
      "a11y": [
        "Expose file names as readable text, not only icons.",
        "Keep approval and request-changes actions keyboard reachable.",
        "Do not rely on file icon color as the only file type signal."
      ],
      "composition": [
        "Response",
        "ToolInvocationCard",
        "PermissionCard",
        "Button",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use FileReviewCard for static file attachments; use FileAttachment or FileCard.",
        "Do not hide risky file changes behind a collapsed-only summary.",
        "Do not use for generic table data."
      ],
      "agentHints": [
        "Use when an agent proposes or reviews file changes.",
        "FileReviewPart remains available as a legacy alias.",
        "Pair with PermissionCard when applying changes needs explicit approval."
      ]
    },
    "code-block-part": {
      "id": "code-block-part",
      "name": "CodeBlockCard",
      "category": "chat",
      "status": "stable",
      "intent": "Syntax-highlighted code block card for generated, reviewed, or referenced source code.",
      "packageImport": "import { CodeBlockCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add code-block-part",
      "slots": [
        "filename",
        "language",
        "code",
        "diff summary",
        "header icon"
      ],
      "states": [
        "expanded",
        "collapsed",
        "generating",
        "diff-add",
        "diff-remove",
        "empty"
      ],
      "a11y": [
        "Keep code selectable and readable as text.",
        "Expose filename and language in the header.",
        "Do not rely on syntax color alone to communicate meaning."
      ],
      "composition": [
        "Response",
        "ToolInvocationCard",
        "FileReviewCard",
        "CollapsibleCard"
      ],
      "antiPatterns": [
        "Do not use CodeBlockCard for terminal output; use TerminalOutputCard.",
        "Do not collapse security-relevant code changes without a visible summary.",
        "Do not use for short inline code snippets inside prose."
      ],
      "agentHints": [
        "Choose CodeBlockCard for source code or config files.",
        "CodeBlockPart remains available as a legacy alias.",
        "Set filename when the code belongs to a specific file."
      ]
    },
    "file-card": {
      "id": "file-card",
      "name": "FileCard",
      "category": "chat",
      "status": "stable",
      "intent": "QoderWork-style file or folder preview card for chat, workbench, and third-party iframe surfaces.",
      "packageImport": "import { FileCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add file-card",
      "slots": [
        "file cover",
        "file name",
        "metadata",
        "status",
        "action by composition"
      ],
      "states": [
        "default",
        "attachment",
        "folder",
        "deleted",
        "error",
        "disabled"
      ],
      "a11y": [
        "Expose file name and type as text.",
        "Do not use file icon color as the only type signal.",
        "Keep remove or open actions keyboard reachable when present."
      ],
      "composition": [
        "ChatInput",
        "FileAttachment",
        "FileReviewCard",
        "Button"
      ],
      "antiPatterns": [
        "Do not use FileCard for agent-proposed file diffs; use FileReviewCard.",
        "Do not hide upload or processing errors.",
        "Do not truncate the only distinguishing part of a filename without Tooltip or title.",
        "Do not use private icon packages; provide public Remix-compatible icons through IconsProvider if custom mapping is needed."
      ],
      "agentHints": [
        "Use FileCard for QoderWork-style file references, folder references, and removable attachment previews.",
        "Set variant=\"attachment\" with onRemove for composer or iframe attachment rows.",
        "Set type=\"folder\" for workspaces, repositories, or project directories.",
        "Use iconFilename when the visible label omits the extension but the card should still match the file type."
      ]
    },
    "generated-images-grid": {
      "id": "generated-images-grid",
      "name": "GeneratedImagesGrid",
      "category": "chat",
      "status": "stable",
      "intent": "Grid display for AI-generated image results, variants, or selectable visual outputs.",
      "packageImport": "import { GeneratedImagesGrid } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add generated-images-grid",
      "slots": [
        "image grid",
        "image item",
        "caption by composition",
        "selection action by composition"
      ],
      "states": [
        "loading",
        "complete",
        "empty",
        "selectable",
        "error by composition"
      ],
      "a11y": [
        "Provide meaningful alt text or adjacent descriptions for generated images.",
        "Keep image actions keyboard reachable.",
        "Do not rely on thumbnails alone when a result needs status or provenance."
      ],
      "composition": [
        "Response",
        "ImageGenerating",
        "Button",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use for arbitrary product card grids.",
        "Do not omit loading or failure states during image generation.",
        "Do not make image selection depend only on hover UI."
      ],
      "agentHints": [
        "Use inside Response when an agent returns generated image candidates.",
        "Pair with ImageGenerating while generation is still in progress."
      ]
    },
    "plan-part": {
      "id": "plan-part",
      "name": "AgentPlanCard",
      "category": "chat",
      "status": "stable",
      "intent": "Structured plan display for agent steps, checkpoints, or proposed execution phases.",
      "packageImport": "import { AgentPlanCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add plan-part",
      "slots": [
        "title",
        "summary",
        "plan steps",
        "step status",
        "actions by composition"
      ],
      "states": [
        "draft",
        "active",
        "completed",
        "blocked",
        "expanded",
        "collapsed"
      ],
      "a11y": [
        "Expose each plan step as readable text.",
        "Do not communicate progress through color alone.",
        "Keep approve, revise, or continue actions keyboard reachable when present."
      ],
      "composition": [
        "Response",
        "AgentTaskList",
        "PermissionCard",
        "Button",
        "Alert"
      ],
      "antiPatterns": [
        "Do not replace a plan with an unstructured Markdown paragraph when steps need status.",
        "Do not use AgentPlanCard for completed task logs; use AgentTaskList or ToolInvocationCard.",
        "Do not hide blockers in a collapsed-only state."
      ],
      "agentHints": [
        "Use AgentPlanCard when an agent needs to show intended future work.",
        "PlanPart remains available as a legacy alias.",
        "Pair with PermissionCard when the plan needs explicit approval before execution."
      ]
    },
    "reasoning-step": {
      "id": "reasoning-step",
      "name": "ReasoningStep",
      "category": "chat",
      "status": "stable",
      "intent": "Readable reasoning or progress step for assistant thinking, analysis phases, or multi-step response construction.",
      "packageImport": "import { ReasoningStep } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add reasoning-step",
      "slots": [
        "header",
        "status",
        "summary",
        "details",
        "detail row"
      ],
      "states": [
        "thinking",
        "running",
        "complete",
        "error",
        "expanded",
        "collapsed"
      ],
      "a11y": [
        "Expose status text, not only spinner or color.",
        "Keep details reachable by keyboard.",
        "Do not over-announce every token-level reasoning update."
      ],
      "composition": [
        "Response",
        "ToolInvocationCard",
        "ThinkingIndicator",
        "Alert"
      ],
      "antiPatterns": [
        "Do not expose private chain-of-thought or hidden system reasoning.",
        "Do not use ReasoningStep for final answer prose; use Response or MarkdownBody.",
        "Do not show a completed state before the step has actually resolved."
      ],
      "agentHints": [
        "Use for high-level progress summaries, not raw internal reasoning.",
        "Prefer short, inspectable details that explain what happened."
      ]
    },
    "streaming-markdown-block": {
      "id": "streaming-markdown-block",
      "name": "StreamingMarkdownBlock",
      "category": "chat",
      "status": "stable",
      "intent": "Animated Markdown renderer for active assistant text streaming with token-level reveal behavior.",
      "packageImport": "import { StreamingMarkdownBlock } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add streaming-markdown-block",
      "slots": [
        "content",
        "active streaming state",
        "token delay",
        "completion callback"
      ],
      "states": [
        "idle",
        "streaming",
        "complete",
        "interrupted",
        "empty"
      ],
      "a11y": [
        "Avoid excessive live announcements during token streaming.",
        "Render final content as semantic Markdown.",
        "Respect reduced-motion preferences when adding streaming effects around the component."
      ],
      "composition": [
        "Response",
        "MarkdownBody",
        "ThinkingIndicator"
      ],
      "antiPatterns": [
        "Do not use for static documentation that is not streaming.",
        "Do not restart the stream on unrelated parent re-renders.",
        "Do not use streaming animation to hide slow tool or network states."
      ],
      "agentHints": [
        "Use inside Response.Content when assistant answer text is arriving incrementally.",
        "Use MarkdownBody directly for already-complete content."
      ]
    },
    "task-part": {
      "id": "task-part",
      "name": "AgentTaskList",
      "category": "chat",
      "status": "stable",
      "intent": "Task progress card for agent work items, substeps, status, and completion state.",
      "packageImport": "import { AgentTaskList } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add task-part",
      "slots": [
        "task title",
        "task list",
        "task status",
        "progress summary",
        "actions by composition"
      ],
      "states": [
        "todo",
        "running",
        "completed",
        "failed",
        "cancelled",
        "expanded",
        "collapsed"
      ],
      "a11y": [
        "Expose task status as text.",
        "Keep task order logical and chronological.",
        "Do not rely on progress color as the only state indicator."
      ],
      "composition": [
        "Response",
        "AgentPlanCard",
        "ToolInvocationCard",
        "Progress",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use AgentTaskList for a proposed future plan; use AgentPlanCard.",
        "Do not hide failed tasks behind a collapsed summary.",
        "Do not use for generic checklist forms where Checkbox is the actual control."
      ],
      "agentHints": [
        "Use AgentTaskList to show execution progress after work has started.",
        "TaskPart remains available as a legacy alias.",
        "Pair with ToolInvocationCard when tasks correspond to concrete tool calls."
      ]
    },
    "terminal-code-block-part": {
      "id": "terminal-code-block-part",
      "name": "TerminalOutputCard",
      "category": "chat",
      "status": "stable",
      "intent": "Terminal-style command or log block for shell commands, process output, and agent execution traces.",
      "packageImport": "import { TerminalOutputCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add terminal-code-block-part",
      "slots": [
        "command",
        "output",
        "status",
        "exit code by composition",
        "header"
      ],
      "states": [
        "running",
        "success",
        "error",
        "empty",
        "expanded",
        "collapsed"
      ],
      "a11y": [
        "Keep terminal output selectable as text.",
        "Expose running, success, and error states in readable text.",
        "Avoid dumping extremely large logs without summary or truncation."
      ],
      "composition": [
        "ToolInvocationCard",
        "Response",
        "CodeBlockCard",
        "Alert"
      ],
      "antiPatterns": [
        "Do not use TerminalOutputCard for source code; use CodeBlockCard.",
        "Do not mark output as successful before the command exits.",
        "Do not hide dangerous commands from the visible header or summary."
      ],
      "agentHints": [
        "Use for shell commands and process output.",
        "TerminalCodeBlockPart remains available as a legacy alias.",
        "Pair with PermissionCard before risky command execution."
      ]
    },
    "user-message": {
      "id": "user-message",
      "name": "UserMessage",
      "category": "chat",
      "status": "stable",
      "intent": "Human-authored message bubble or prompt display in a conversation thread.",
      "packageImport": "import { UserMessage } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add user-message",
      "slots": [
        "message text",
        "avatar by composition",
        "metadata by composition",
        "attachments by composition"
      ],
      "states": [
        "default",
        "with attachments",
        "edited by composition",
        "pending by composition"
      ],
      "a11y": [
        "Preserve the message text as readable content.",
        "Do not encode author identity only through alignment or color.",
        "Keep attachment names accessible when attachments are shown."
      ],
      "composition": [
        "Response",
        "FileCard",
        "ImageAttachment",
        "MarkdownBody"
      ],
      "antiPatterns": [
        "Do not use UserMessage for assistant output; use Response.",
        "Do not put tool execution details in UserMessage.",
        "Do not hide long user prompts behind hover-only UI."
      ],
      "agentHints": [
        "Use UserMessage for the user's side of an AI conversation.",
        "Use Response for assistant messages even when the content is short."
      ]
    },
    "markdown": {
      "id": "markdown",
      "name": "MarkdownBody",
      "category": "chat",
      "status": "stable",
      "intent": "Tokenized Markdown renderer for assistant responses, documentation snippets, math, and structured generated text.",
      "packageImport": "import { MarkdownBody } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add markdown",
      "slots": [
        "MarkdownBody",
        "paragraph",
        "heading",
        "list",
        "table",
        "code",
        "math"
      ],
      "states": [
        "static",
        "rich-content",
        "code-heavy",
        "math-heavy",
        "empty"
      ],
      "a11y": [
        "Preserve semantic Markdown structure.",
        "Avoid rendering untrusted HTML.",
        "Ensure tables remain readable on narrow screens."
      ],
      "composition": [
        "Response",
        "StreamingMarkdownBlock",
        "CodeBlockCard",
        "Typography"
      ],
      "antiPatterns": [
        "Do not use MarkdownBody for arbitrary user-authored HTML.",
        "Do not wrap every short label or UI copy in MarkdownBody."
      ],
      "agentHints": [
        "Use MarkdownBody for assistant-generated rich text.",
        "Use plain Typography components for static product copy."
      ]
    },
    "permission-card": {
      "id": "permission-card",
      "name": "PermissionCard",
      "category": "chat",
      "status": "stable",
      "intent": "Inline permission request surface for agent actions that need explicit user approval.",
      "packageImport": "import { PermissionCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add permission-card",
      "slots": [
        "title",
        "description",
        "metadata",
        "primary action",
        "secondary action"
      ],
      "states": [
        "pending",
        "approved",
        "denied",
        "loading",
        "expired"
      ],
      "a11y": [
        "Make the requested permission explicit in text, not only button labels.",
        "Keep approve and deny actions both keyboard reachable.",
        "Use clear status text after the decision changes."
      ],
      "composition": [
        "Button",
        "Alert",
        "ToolInvocationCard",
        "ChatInput"
      ],
      "antiPatterns": [
        "Do not auto-approve risky tool actions.",
        "Do not hide denial or cancel actions.",
        "Do not use PermissionCard for ordinary form confirmation."
      ],
      "agentHints": [
        "Use for file, shell, network, credential, or external side-effect approvals.",
        "Pair with ToolInvocationCard when the approval unlocks a visible tool run."
      ]
    },
    "response": {
      "id": "response",
      "name": "AssistantResponse",
      "category": "chat",
      "status": "stable",
      "intent": "Structured assistant response renderer for answer text, reasoning, tool calls, files, tasks, and generated artifacts.",
      "packageImport": "import { AssistantResponse } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add response",
      "slots": [
        "message",
        "round",
        "step",
        "markdown",
        "reasoning",
        "tool call",
        "file review",
        "task",
        "plan"
      ],
      "states": [
        "streaming",
        "complete",
        "error",
        "empty",
        "tool-running",
        "tool-complete"
      ],
      "a11y": [
        "Expose streaming updates without causing excessive announcements.",
        "Keep generated code and tool output keyboard selectable.",
        "Preserve logical order for reasoning, tool, and answer sections."
      ],
      "composition": [
        "MarkdownBody",
        "StreamingMarkdownBlock",
        "ReasoningStep",
        "ToolCallCard",
        "FileReviewCard",
        "AgentTaskList",
        "AgentPlanCard",
        "CodeBlockCard",
        "TerminalOutputCard",
        "GeneratedImagesGrid"
      ],
      "antiPatterns": [
        "Do not use AssistantResponse for user-authored messages.",
        "Do not flatten tool calls into plain Markdown when structured components exist.",
        "Do not hide error or partial states during long-running agent work."
      ],
      "agentHints": [
        "Choose AssistantResponse as the default output surface for assistant messages.",
        "Response remains available as a legacy alias.",
        "Use UserMessage for human-authored chat bubbles."
      ]
    },
    "tool-invocation-card": {
      "id": "tool-invocation-card",
      "name": "ToolCallCard",
      "category": "chat",
      "status": "stable",
      "intent": "Compact disclosure card for agent tool calls, their status, inputs, and outputs.",
      "packageImport": "import { ToolCallCard } from 'sparkdesign'",
      "cliAdd": "npx sparkdesign@latest add tool-invocation-card",
      "slots": [
        "tool icon",
        "tool name",
        "status",
        "summary",
        "details",
        "output"
      ],
      "states": [
        "queued",
        "running",
        "success",
        "error",
        "cancelled",
        "expanded",
        "collapsed"
      ],
      "a11y": [
        "Expose status changes as readable text.",
        "Keep disclosure controls keyboard reachable.",
        "Do not rely on color alone for success or error status."
      ],
      "composition": [
        "AssistantResponse",
        "PermissionCard",
        "CodeBlockCard",
        "TerminalOutputCard",
        "Alert"
      ],
      "antiPatterns": [
        "Do not dump large logs directly into the collapsed summary.",
        "Do not mark a tool as successful before its output is available.",
        "Do not use for static documentation sections."
      ],
      "agentHints": [
        "Use for shell, browser, file, search, MCP, or external tool activity.",
        "Pair with PermissionCard for actions that need explicit approval.",
        "ToolInvocationCard remains available as a legacy alias."
      ]
    }
  },
  "recipes": {
    "structured-form": {
      "id": "structured-form",
      "intent": "Build a tokenized form or settings section with accessible labels, helper text, validation, and clear submission actions.",
      "useWhen": [
        "The UI collects structured values from the user.",
        "The task needs labeled fields, selection controls, validation, and submit/cancel actions.",
        "The flow is deterministic rather than conversational."
      ],
      "components": [
        "input",
        "textarea",
        "label",
        "select",
        "checkbox",
        "radio-group",
        "switch",
        "button",
        "alert"
      ],
      "layout": [
        "Pair each field with Label or Field-style composition.",
        "Group related controls by task, not by component type.",
        "Use one primary Button for submission and keep validation feedback close to the field or form section."
      ],
      "accessibility": [
        "Every control needs a visible label or accessible name.",
        "Use native form semantics where possible.",
        "Do not rely on placeholder text as the only instruction or label."
      ],
      "antiPatterns": [
        "Do not use ChatInput for deterministic forms.",
        "Do not use DropdownMenu as a form select.",
        "Do not hide validation feedback in Tooltip."
      ]
    },
    "assistant-composer": {
      "id": "assistant-composer",
      "intent": "Build the bottom or inline prompt entry area for an AI assistant.",
      "useWhen": [
        "The user needs to send prompts, files, or instructions to an agent.",
        "The UI needs model/status/action controls around a prompt textarea."
      ],
      "components": [
        "chat-input",
        "button",
        "permission-card",
        "alert"
      ],
      "layout": [
        "Place ChatInput at the primary interaction point.",
        "Keep secondary actions in ChatInputActionsLeft and submit in ChatInputActionsRight.",
        "Render blocking permission needs above the input, not hidden in a menu."
      ],
      "accessibility": [
        "Keyboard users must be able to compose, attach, and submit without pointer input.",
        "Status or permission text must remain readable by assistive technology."
      ],
      "antiPatterns": [
        "Do not turn ChatInput into a general settings form.",
        "Do not hide send behind a dropdown."
      ]
    },
    "assistant-response-stream": {
      "id": "assistant-response-stream",
      "intent": "Render assistant output with structured reasoning, tools, and generated text.",
      "useWhen": [
        "The UI displays AI-generated answers.",
        "The response may include tool calls, code, files, tasks, plans, or Markdown."
      ],
      "components": [
        "response",
        "streaming-markdown-block",
        "reasoning-step",
        "markdown",
        "tool-invocation-card",
        "code-block-part",
        "terminal-code-block-part",
        "plan-part",
        "task-part",
        "generated-images-grid",
        "permission-card",
        "alert"
      ],
      "layout": [
        "Use Response as the parent renderer for assistant output.",
        "Use StreamingMarkdownBlock for active answer text and MarkdownBody for complete static content.",
        "Use ToolInvocationCard for each tool step rather than plain text logs.",
        "Use CodeBlockCard for source code and TerminalOutputCard for command output.",
        "Use AgentPlanCard for proposed work and AgentTaskList for execution progress.",
        "Use Alert for inline errors that belong to the response."
      ],
      "accessibility": [
        "Keep response sections in chronological order.",
        "Avoid excessive live-region announcements during token streaming."
      ],
      "antiPatterns": [
        "Do not collapse all structured output into Markdown.",
        "Do not hide failed tool states."
      ]
    },
    "focused-task-modal": {
      "id": "focused-task-modal",
      "intent": "Collect or confirm a short, focused task without navigating away.",
      "useWhen": [
        "The user must complete or dismiss a blocking task.",
        "The content fits in a compact modal with a clear title and action row."
      ],
      "components": [
        "dialog",
        "button",
        "card",
        "input",
        "textarea",
        "alert"
      ],
      "layout": [
        "Use DialogContent with DialogHeader, DialogTitle, optional DialogDescription, and DialogFooter.",
        "Use one primary action and one secondary dismissal action.",
        "Place validation or risk messages inline with Alert."
      ],
      "accessibility": [
        "Always provide DialogTitle.",
        "Return focus to the trigger after close.",
        "Do not remove Escape behavior unless there is a clear safety reason."
      ],
      "antiPatterns": [
        "Do not use Dialog for long workflows that need persistent navigation.",
        "Do not nest modals."
      ]
    },
    "settings-drawer": {
      "id": "settings-drawer",
      "intent": "Expose contextual settings or detail editing while preserving the underlying page.",
      "useWhen": [
        "The user needs to adjust settings without leaving the current workflow.",
        "The task is secondary to the page but benefits from a persistent side surface.",
        "The content fits in a single panel with a clear title and action footer."
      ],
      "components": [
        "drawer",
        "button",
        "card",
        "input",
        "select",
        "switch",
        "tabs",
        "alert"
      ],
      "layout": [
        "Use DrawerContent with DrawerHeader, DrawerTitle, optional DrawerDescription, content sections, and DrawerFooter.",
        "Group dense settings inside Card or clear section blocks.",
        "Place save/cancel actions in DrawerFooter and keep the primary action singular."
      ],
      "accessibility": [
        "Always provide DrawerTitle.",
        "Keep focus trapped while the drawer is open.",
        "Return focus to DrawerTrigger after close."
      ],
      "antiPatterns": [
        "Do not use Drawer for destructive confirmations.",
        "Do not put full application navigation in a contextual settings drawer.",
        "Do not create nested drawers."
      ]
    },
    "tool-approval-flow": {
      "id": "tool-approval-flow",
      "intent": "Request explicit user approval before an agent performs a risky or external side-effecting tool action.",
      "useWhen": [
        "The agent wants to run shell, browser, file, network, credential, or external integration actions.",
        "The user must understand and approve the consequence before execution.",
        "The approval unlocks a visible tool run."
      ],
      "components": [
        "permission-card",
        "tool-invocation-card",
        "response",
        "button",
        "alert"
      ],
      "layout": [
        "Render PermissionCard before the tool starts.",
        "Render ToolInvocationCard after approval to show queued, running, success, or error state.",
        "Use Alert for risks, denials, or failed preconditions."
      ],
      "accessibility": [
        "Make approve and deny choices both keyboard reachable.",
        "Expose the requested permission and consequence as readable text.",
        "Do not rely on color alone for risk or status."
      ],
      "antiPatterns": [
        "Do not auto-approve risky actions.",
        "Do not hide the deny path.",
        "Do not show a successful tool state before output exists."
      ]
    },
    "file-review-flow": {
      "id": "file-review-flow",
      "intent": "Present agent-proposed file changes for review, approval, or requested revisions.",
      "useWhen": [
        "The assistant has inspected, generated, or modified files.",
        "The user needs a concise review surface before accepting changes.",
        "The flow includes file-specific status or approval decisions."
      ],
      "components": [
        "file-review-part",
        "permission-card",
        "tool-invocation-card",
        "response",
        "alert"
      ],
      "layout": [
        "Use FileReviewCard for the file list and review actions.",
        "Use ToolInvocationCard for the underlying file operation when visible provenance matters.",
        "Use PermissionCard when applying or committing file changes requires approval."
      ],
      "accessibility": [
        "Keep file names and review status available as text.",
        "Make approve and request-changes actions keyboard reachable.",
        "Preserve chronological order between tool execution and review result."
      ],
      "antiPatterns": [
        "Do not replace file review with a plain Markdown bullet list when actions are needed.",
        "Do not hide changed files in a collapsed-only summary.",
        "Do not use FileReviewCard for unrelated data tables."
      ]
    },
    "empty-state-with-prompts": {
      "id": "empty-state-with-prompts",
      "intent": "Help users start an AI or product workflow from an empty state with clear prompts and one primary action.",
      "useWhen": [
        "A page, panel, or chat has no user content yet.",
        "The product should suggest next actions instead of showing a blank surface.",
        "The recommended action can be expressed as a prompt or compact action set."
      ],
      "components": [
        "card",
        "button",
        "chat-input",
        "alert"
      ],
      "layout": [
        "Use Card for the empty-state container when the state belongs inside a page section.",
        "Use one primary Button for the most important setup action.",
        "Use ChatInput when the best next step is a natural-language prompt."
      ],
      "accessibility": [
        "Use a real heading or clear title text.",
        "Ensure prompt suggestions are reachable by keyboard.",
        "Avoid placeholder-only instructions."
      ],
      "antiPatterns": [
        "Do not show more than a small set of competing starting actions.",
        "Do not use decorative illustration as the only explanation.",
        "Do not use ChatInput if the flow is a deterministic form task."
      ]
    }
  }
}
