@fragments-sdk/ui 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fragments.json +1 -1
- package/package.json +2 -2
- package/src/components/AppShell/AppShell.module.scss +12 -6
- package/src/components/AppShell/index.tsx +1 -4
- package/src/components/Combobox/Combobox.fragment.tsx +220 -0
- package/src/components/Combobox/Combobox.module.scss +268 -0
- package/src/components/Combobox/index.tsx +398 -0
- package/src/index.ts +13 -0
package/fragments.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.0","generatedAt":"2026-02-05T22:56:00.397Z","packageName":"@fragments-sdk/ui","segments":{"Accordion":{"filePath":"src/components/Accordion/Accordion.fragment.tsx","meta":{"name":"Accordion","description":"Vertically stacked, collapsible content sections. Use for organizing related content that can be progressively disclosed.","category":"layout","status":"stable","tags":["accordion","collapse","expand","disclosure","faq"],"since":"0.2.0"},"usage":{"when":["FAQ pages with multiple questions and answers","Settings panels with grouped options","Long forms that benefit from progressive disclosure","Navigation menus with nested items"],"whenNot":["Primary content that all users need to see","Very short content (just display inline)","Sequential steps (use Stepper or wizard)","Tab-like navigation (use Tabs instead)"],"guidelines":["Keep section headers concise and descriptive","Use single mode when only one section should be open at a time","Use multiple mode when users may need to compare sections","Consider defaulting important sections to open","Avoid nesting accordions more than one level deep"],"accessibility":["Keyboard navigation with Enter/Space to toggle","Arrow keys navigate between accordion headers","Uses proper ARIA expanded/controls attributes","Focus is visible on accordion triggers"]},"props":{"children":{"type":"node","description":"Accordion items (use Accordion.Item with Accordion.Trigger and Accordion.Content)","required":true},"type":{"type":"enum","description":"Whether one or multiple items can be open","default":"single","values":["single","multiple"]},"value":{"type":"string | string[]","description":"Controlled open item(s)"},"defaultValue":{"type":"string | string[]","description":"Initially open item(s) for uncontrolled usage"},"onValueChange":{"type":"function","description":"Called when open items change"},"collapsible":{"type":"boolean","description":"Whether all items can be closed (single mode only)","default":"false"}},"relations":[{"component":"Tabs","relationship":"alternative","note":"Use Tabs for horizontal switching between related views"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for focused content that interrupts the flow"},{"component":"Card","relationship":"complementary","note":"Accordion items can contain Card-like content"}],"variants":[{"name":"Basic","description":"Single accordion with collapsible sections","code":"<Accordion type=\"single\" collapsible defaultValue=\"item-1\">\n <Accordion.Item value=\"item-1\">\n <Accordion.Trigger>What is Fragments UI?</Accordion.Trigger>\n <Accordion.Content>\n Fragments UI is a modern React component library built on Base UI primitives, providing accessible and customizable components.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-2\">\n <Accordion.Trigger>How do I install it?</Accordion.Trigger>\n <Accordion.Content>\n Install via npm or pnpm: <code>pnpm add @fragments-sdk/ui</code>\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-3\">\n <Accordion.Trigger>Is it accessible?</Accordion.Trigger>\n <Accordion.Content>\n Yes! All components follow WAI-ARIA guidelines and support keyboard navigation.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"},{"name":"Multiple Open","description":"Allows multiple sections to be open simultaneously","code":"<Accordion type=\"multiple\" defaultValue={['features', 'pricing']}>\n <Accordion.Item value=\"features\">\n <Accordion.Trigger>Features</Accordion.Trigger>\n <Accordion.Content>\n Comprehensive component library with theming support, accessibility built-in, and TypeScript-first development.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"pricing\">\n <Accordion.Trigger>Pricing</Accordion.Trigger>\n <Accordion.Content>\n Free and open source. MIT licensed for both personal and commercial use.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"support\">\n <Accordion.Trigger>Support</Accordion.Trigger>\n <Accordion.Content>\n Community support via GitHub issues and discussions.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"},{"name":"With Disabled","description":"Accordion with a disabled item","code":"<Accordion type=\"single\" collapsible>\n <Accordion.Item value=\"available\">\n <Accordion.Trigger>Available Section</Accordion.Trigger>\n <Accordion.Content>\n This section can be expanded and collapsed.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"disabled\" disabled>\n <Accordion.Trigger>Disabled Section</Accordion.Trigger>\n <Accordion.Content>\n This content is not accessible because the item is disabled.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"another\">\n <Accordion.Trigger>Another Section</Accordion.Trigger>\n <Accordion.Content>\n This section is also available for interaction.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"}],"ai":{"compositionPattern":"compound","subComponents":["Item","Trigger","Content"],"requiredChildren":["Item"],"commonPatterns":["<Accordion type=\"single\" collapsible><Accordion.Item value=\"item-1\"><Accordion.Trigger>{title}</Accordion.Trigger><Accordion.Content>{content}</Accordion.Content></Accordion.Item></Accordion>"]}},"Alert":{"filePath":"src/components/Alert/Alert.fragment.tsx","meta":{"name":"Alert","description":"Contextual feedback messages for user actions or system status. Supports multiple severity levels with optional actions and dismissibility.","category":"feedback","status":"stable","tags":["notification","message","feedback","banner","toast"],"since":"0.1.0"},"usage":{"when":["Communicating the result of a user action (success, error)","Warning about potential issues before they occur","Providing important contextual information inline","System status notifications that require attention"],"whenNot":["Brief status labels (use Badge instead)","Transient notifications (use Toast/Snackbar)","Form-field-level errors (use Input error prop)","Confirmation before destructive actions (use Dialog)"],"guidelines":["Match severity to the actual importance: info for context, warning for potential issues, error for failures","Always provide actionable guidance in error alerts","Use Alert.Title for complex messages; skip titles for brief one-liners","Limit to one action per alert to avoid decision paralysis","Use Alert.Close only for non-critical information"],"accessibility":["Uses role=\"alert\" for screen reader announcement","Error and warning alerts are announced immediately by assistive technology","Alert.Close must have an accessible label","Color alone must not convey meaning - icons and text reinforce severity"]},"props":{"children":{"type":"node","description":"Alert content - use Alert.Icon, Alert.Body, Alert.Title, Alert.Content, Alert.Actions, Alert.Close sub-components","required":true},"severity":{"type":"enum","description":"Visual severity level","default":"info","values":["info","success","warning","error"]}},"relations":[{"component":"Badge","relationship":"alternative","note":"Use Badge for compact, inline status labels"},{"component":"Toast","relationship":"alternative","note":"Use Toast for transient notifications that auto-dismiss"},{"component":"Dialog","relationship":"sibling","note":"Use Dialog for blocking confirmations"}],"variants":[{"name":"Info","description":"Informational context for the user","code":"<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n Your session will expire in 15 minutes. Save your work to avoid losing changes.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Success","description":"Positive confirmation of completed action","code":"<Alert severity=\"success\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Payment processed</Alert.Title>\n <Alert.Content>\n Your order #12345 has been confirmed. You will receive a confirmation email shortly.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Warning","description":"Caution about potential issues","code":"<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Storage almost full</Alert.Title>\n <Alert.Content>\n You have used 90% of your storage quota. Consider deleting unused files.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Error","description":"Error state requiring user attention","code":"<Alert severity=\"error\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Upload failed</Alert.Title>\n <Alert.Content>\n The file could not be uploaded. Check your connection and try again.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"With Action","description":"Alert with an actionable button","code":"<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Update available</Alert.Title>\n <Alert.Content>\n A new version is available with important security fixes.\n </Alert.Content>\n <Alert.Actions>\n <Alert.Action onClick={() => {}}>Update now</Alert.Action>\n </Alert.Actions>\n </Alert.Body>\n</Alert>"},{"name":"Dismissible","description":"Alert that can be closed by the user","code":"<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n You can customize your notification preferences in Settings.\n </Alert.Content>\n </Alert.Body>\n <Alert.Close />\n</Alert>"}],"ai":{"compositionPattern":"compound","subComponents":["Icon","Body","Title","Content","Actions","Action","Close"],"requiredChildren":["Body"],"commonPatterns":["<Alert severity=\"info\"><Alert.Icon /><Alert.Body><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>","<Alert severity=\"warning\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>","<Alert severity=\"error\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body><Alert.Close /></Alert>"]}},"AppShell":{"filePath":"src/components/AppShell/AppShell.fragment.tsx","meta":{"name":"AppShell","description":"Full layout wrapper integrating sidebar, header, main content, and optional aside panel. Supports two layout modes: stacked (header on top) and sidebar-inset (sidebar full height).","category":"layout","status":"stable","tags":["layout","shell","scaffold","dashboard","app-layout"],"since":"0.5.0"},"usage":{"when":["Building dashboard-style applications","Apps with persistent sidebar navigation","Layouts requiring header, sidebar, and main content areas","Responsive layouts that need mobile drawer behavior"],"whenNot":["Simple marketing pages (use standard layout)","Content-first sites without navigation (use simpler layout)","Single-page apps with minimal UI (use minimal layout)"],"guidelines":["Use layout=\"stacked\" when header should span full width (logo in header)","Use layout=\"sidebar-inset\" when sidebar should be full height (logo in sidebar)","AppShell automatically wraps with SidebarProvider","Use AppShell.Sidebar to configure sidebar width and collapse behavior","Main content responds to sidebar collapsed state","Aside panel is hidden on mobile automatically"],"accessibility":["Main content area has id=\"main-content\" for skip links","Use Header.SkipLink for keyboard navigation","Sidebar drawer has proper focus trap on mobile","Keyboard navigation supported throughout"]},"props":{"children":{"type":"node","description":"Layout content (use AppShell.Header, AppShell.Sidebar, AppShell.Main, AppShell.Aside)","required":true},"layout":{"type":"enum","description":"Layout mode for header/sidebar positioning","default":"stacked","values":["stacked","sidebar-inset","inset"]}},"relations":[{"component":"ThemeProvider","relationship":"parent","note":"AppShell should be wrapped in ThemeProvider"},{"component":"Header","relationship":"child","note":"Header is placed inside AppShell.Header"},{"component":"Sidebar","relationship":"child","note":"Sidebar content goes inside AppShell.Sidebar"}],"variants":[{"name":"Stacked Layout","description":"Header spans full width above sidebar (default). Best when brand/logo should be prominent in header.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Brand>MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem active>Dashboard</Header.NavItem>\n <Header.NavItem>Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Stacked Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Header spans full width. Logo is in the header.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"Sidebar Inset Layout","description":"Sidebar is full height, header sits next to it. Best for documentation sites or when sidebar branding is preferred.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 12px', background: 'var(--fui-bg-secondary)', borderRadius: '6px', color: 'var(--fui-text-tertiary)', fontSize: '14px' }}>\n <SearchIcon /> Search...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Sidebar Inset Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Sidebar is full height. Logo is in the sidebar header.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"With Aside Panel","description":"App shell with optional right panel for additional context or actions","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Brand>App</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"180px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Stats</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Main Content</h2>\n <p style={{ margin: 0 }}>Content with aside panel on the right.</p>\n </AppShell.Main>\n\n <AppShell.Aside width=\"180px\">\n <div style={{ padding: '16px' }}>\n <h3 style={{ margin: '0 0 8px', fontSize: '14px' }}>Aside Panel</h3>\n <p style={{ margin: 0, fontSize: '13px', color: 'var(--fui-text-secondary)' }}>\n Additional context, filters, or quick actions.\n </p>\n </div>\n </AppShell.Aside>\n </AppShell>\n</div>"},{"name":"Collapsible Icon Sidebar","description":"Sidebar that collapses to icons only on desktop","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar collapsible=\"icon\" width=\"200px\" collapsedWidth=\"56px\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <p style={{ margin: 0 }}>Click the collapse button in the sidebar footer to toggle between expanded and icon-only modes.</p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"Inset Layout","description":"Modern shadcn-style layout with rounded main content area and visual separation from sidebar.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 12px', background: 'var(--fui-bg-primary)', borderRadius: '6px', color: 'var(--fui-text-tertiary)', fontSize: '14px', border: '1px solid var(--fui-border)' }}>\n <SearchIcon /> Search...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Inset Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Main content has rounded corners and visual separation from the sidebar.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"}]},"Avatar":{"filePath":"src/components/Avatar/Avatar.fragment.tsx","meta":{"name":"Avatar","description":"Visual representation of a user or entity","category":"display","status":"stable","tags":["user","profile","image","identity"]},"usage":{"when":["Displaying user profile pictures","Showing team member lists","Representing entities in lists or cards","User identification in comments or messages"],"whenNot":["Decorative images (use Image)","Logo display (use Logo component)","Large profile headers (use custom layout)"],"guidelines":["Always provide alt text or name for accessibility","Use consistent sizes within the same context","Provide fallback initials when image may not load","Use Avatar.Group for multiple avatars in a row"],"accessibility":["Include meaningful alt text describing the user","Initials should be derived from name for screen readers","Decorative avatars should have empty alt"]},"props":{"src":{"type":"string","description":"Image source URL"},"alt":{"type":"string","description":"Alt text for the image"},"name":{"type":"string","description":"Full name - used to generate initials"},"initials":{"type":"string","description":"Fallback initials (1-2 characters)"},"size":{"type":"enum","description":"Size variant","default":"md","values":["xs","sm","md","lg","xl"]},"shape":{"type":"enum","description":"Shape variant","default":"circle","values":["circle","square"]}},"relations":[{"component":"AvatarGroup","relationship":"parent","note":"Use Avatar.Group for stacked avatar displays"}],"variants":[{"name":"Default","description":"Avatar with image","code":"<Avatar\n src=\"https://i.pravatar.cc/150?u=jane\"\n alt=\"Jane Doe\"\n name=\"Jane Doe\"\n/>"},{"name":"With Initials","description":"Fallback when no image is provided","code":"<Avatar name=\"John Smith\" />"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Avatar name=\"XS\" size=\"xs\" />\n <Avatar name=\"SM\" size=\"sm\" />\n <Avatar name=\"MD\" size=\"md\" />\n <Avatar name=\"LG\" size=\"lg\" />\n <Avatar name=\"XL\" size=\"xl\" />\n</div>"},{"name":"Square Shape","description":"Square variant for app icons or brands","code":"<Avatar name=\"App\" shape=\"square\" />"},{"name":"Group","description":"Multiple avatars stacked together","code":"<Avatar.Group max={3} size=\"md\">\n <Avatar name=\"Alice Johnson\" />\n <Avatar name=\"Bob Smith\" />\n <Avatar name=\"Carol Williams\" />\n <Avatar name=\"David Brown\" />\n <Avatar name=\"Eve Davis\" />\n</Avatar.Group>"}]},"Badge":{"filePath":"src/components/Badge/Badge.fragment.tsx","meta":{"name":"Badge","description":"Compact label for status, counts, or categorization. Draws attention to metadata without dominating the layout.","category":"display","status":"stable","tags":["status","label","tag","count","chip"],"since":"0.1.0"},"usage":{"when":["Showing item status (active, pending, archived)","Displaying counts or quantities inline","Categorizing or tagging content","Highlighting new or updated items"],"whenNot":["Conveying critical errors (use Alert instead)","Long-form status messages (use Alert)","Interactive filtering (use chip/toggle group)","Navigation labels (use tabs or links)"],"guidelines":["Keep badge text under 20 characters","Use dot variant for live status indicators","Pair success/error variants with meaningful labels, not just colors","Use onRemove for user-created tags only, not system-generated badges"],"accessibility":["Badge text must be meaningful without relying on color alone","Removable badges must have accessible dismiss button labels","Avoid using badges as the sole indicator of important state changes"]},"props":{"children":{"type":"node","description":"Badge label text","required":true},"variant":{"type":"enum","description":"Visual style indicating severity or category","default":"default","values":["default","success","warning","error","info"]},"size":{"type":"enum","description":"Badge size","default":"md","values":["sm","md"]},"dot":{"type":"boolean","description":"Show a colored dot indicator before the label","default":"false"},"icon":{"type":"node","description":"Optional icon element before the text"},"onRemove":{"type":"function","description":"Makes the badge removable. Called when X is clicked."}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for prominent, longer messages with actions"},{"component":"Tag","relationship":"sibling","note":"Tag is interactive (clickable/filterable); Badge is display-only"}],"variants":[{"name":"Default","description":"Neutral badge for general labels","code":"<Badge>Default</Badge>"},{"name":"Status Variants","description":"All severity variants for different contexts","code":"<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>\n <Badge variant=\"default\">Default</Badge>\n <Badge variant=\"success\">Active</Badge>\n <Badge variant=\"warning\">Pending</Badge>\n <Badge variant=\"error\">Failed</Badge>\n <Badge variant=\"info\">New</Badge>\n</div>"},{"name":"With Dot","description":"Live status indicators using dot prefix","code":"<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>\n <Badge variant=\"success\" dot>Online</Badge>\n <Badge variant=\"warning\" dot>Away</Badge>\n <Badge variant=\"error\" dot>Offline</Badge>\n</div>"},{"name":"Small Size","description":"Compact badges for dense UIs","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Badge size=\"sm\" variant=\"info\">v2.1</Badge>\n <Badge size=\"sm\" variant=\"success\">Stable</Badge>\n <Badge size=\"md\" variant=\"info\">Standard</Badge>\n</div>"},{"name":"Removable","description":"User-created tags that can be dismissed","code":"<div style={{ display: 'flex', gap: '8px' }}>\n <Badge variant=\"info\" onRemove={() => {}}>React</Badge>\n <Badge variant=\"info\" onRemove={() => {}}>TypeScript</Badge>\n <Badge variant=\"info\" onRemove={() => {}}>CSS</Badge>\n</div>"}]},"Box":{"filePath":"src/components/Box/Box.fragment.tsx","meta":{"name":"Box","description":"Primitive layout component for applying spacing, backgrounds, and borders. A flexible container for building custom layouts.","category":"layout","status":"stable","tags":["layout","container","spacing","primitive","box"],"since":"0.1.0"},"usage":{"when":["Applying consistent padding or margin to content sections","Creating bordered or elevated containers","Wrapping content with semantic HTML elements","Building custom layouts not covered by Stack or Grid"],"whenNot":["Horizontal or vertical stacking (use Stack)","Grid-based layouts (use Grid)","Card-like containers with header/body/footer (use Card)","Simple text styling (use Text)"],"guidelines":["Use padding props instead of inline styles for consistency","Choose semantic HTML elements (section, article) where appropriate","Combine with Stack or Grid for complex layouts","Use background variants from the design system, not custom colors"],"accessibility":["Choose semantic as prop values for proper document structure","Avoid div-soup; use meaningful elements like section, article","Ensure proper heading hierarchy within Box containers"]},"props":{"children":{"type":"node","description":"Content to render inside the box"},"as":{"type":"enum","description":"HTML element to render","default":"div","values":["div","section","article","aside","main","header","footer","nav","span"]},"padding":{"type":"enum","description":"Padding on all sides","values":["none","xs","sm","md","lg","xl"]},"paddingX":{"type":"enum","description":"Horizontal padding","values":["none","xs","sm","md","lg","xl"]},"paddingY":{"type":"enum","description":"Vertical padding","values":["none","xs","sm","md","lg","xl"]},"margin":{"type":"enum","description":"Margin on all sides","values":["none","xs","sm","md","lg","xl","auto"]},"marginX":{"type":"enum","description":"Horizontal margin","values":["none","xs","sm","md","lg","xl","auto"]},"marginY":{"type":"enum","description":"Vertical margin","values":["none","xs","sm","md","lg","xl","auto"]},"background":{"type":"enum","description":"Background color","values":["none","primary","secondary","tertiary","elevated"]},"rounded":{"type":"enum","description":"Border radius","values":["none","sm","md","lg","full"]},"border":{"type":"boolean","description":"Show border","default":"false"},"display":{"type":"enum","description":"Display type","values":["block","inline","inline-block","flex","inline-flex","grid","none"]}},"relations":[{"component":"Stack","relationship":"alternative","note":"Use Stack for directional layouts with gap"},{"component":"Grid","relationship":"alternative","note":"Use Grid for column-based layouts"},{"component":"Card","relationship":"alternative","note":"Use Card for content containers with structure"}],"variants":[{"name":"Default","description":"Basic box with padding","code":"<Box padding=\"md\" background=\"secondary\" rounded=\"md\">\n Content with padding and background\n</Box>"},{"name":"With Border","description":"Bordered container","code":"<Box padding=\"lg\" border rounded=\"md\">\n Bordered content area\n</Box>"},{"name":"Directional Padding","description":"Different horizontal and vertical padding","code":"<Box paddingX=\"xl\" paddingY=\"sm\" background=\"tertiary\" rounded=\"sm\">\n Wide horizontal padding, short vertical\n</Box>"},{"name":"Centered with Auto Margin","description":"Centered content using margin auto","code":"<Box padding=\"md\" marginX=\"auto\" background=\"elevated\" rounded=\"lg\" style={{ maxWidth: '300px' }}>\n Centered content\n</Box>"}]},"Button":{"filePath":"src/components/Button/Button.fragment.tsx","meta":{"name":"Button","description":"Interactive element for user actions and form submissions","category":"forms","status":"stable","tags":["action","button","form","interactive"]},"usage":{"when":["Triggering an action (save, submit, delete, etc.)","Form submission","Opening dialogs or menus","Navigation when action context is needed"],"whenNot":["Simple navigation (use Link)","Toggling state (use Switch or Checkbox)","Selecting from options (use Select or RadioGroup)"],"guidelines":["Use Primary for the main action in a context","Only one Primary button per section/form","Use Danger variant for destructive actions","Loading state should disable the button"],"accessibility":["Button text should describe the action","Avoid generic labels like \"Click here\"","Icon-only buttons need aria-label"]},"props":{"children":{"type":"node","description":"Button label content","required":true},"variant":{"type":"enum","description":"Visual style variant","default":"primary","values":["primary","secondary","ghost","danger"],"constraints":["Only one primary button per context"]},"size":{"type":"enum","description":"Button size","default":"md","values":["sm","md","lg"]},"disabled":{"type":"boolean","description":"Whether the button is disabled","default":false},"onClick":{"type":"function","description":"Click handler"},"type":{"type":"enum","description":"HTML button type attribute","default":"button","values":["button","submit","reset"]}},"relations":[{"component":"Link","relationship":"alternative","note":"Use Link for navigation without action context"},{"component":"IconButton","relationship":"alternative","note":"Use IconButton for icon-only actions"},{"component":"ButtonGroup","relationship":"parent","note":"Use ButtonGroup for related action sets"}],"variants":[{"name":"Primary","description":"Default action button for primary actions","code":"<Button variant=\"primary\">Save Changes</Button>"},{"name":"Secondary","description":"Less prominent action button","code":"<Button variant=\"secondary\">Cancel</Button>"},{"name":"Ghost","description":"Minimal visual weight for subtle actions","code":"<Button variant=\"ghost\">Learn More</Button>"},{"name":"Danger","description":"Destructive action requiring attention","code":"<Button variant=\"danger\">Delete Item</Button>"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n</div>"},{"name":"Disabled","description":"Non-interactive state","code":"<Button disabled>Cannot Click</Button>"}]},"ButtonGroup":{"filePath":"src/components/ButtonGroup/ButtonGroup.fragment.tsx","meta":{"name":"ButtonGroup","description":"Groups related buttons together with consistent spacing and alignment. Useful for action bars, toolbars, and related button sets.","category":"forms","status":"stable","tags":["button","group","toolbar","actions","layout"],"since":"0.2.0"},"usage":{"when":["Grouping related actions together","Creating toolbars or action bars","Form submit/cancel button pairs","Pagination controls"],"whenNot":["Unrelated buttons (use Stack instead)","Navigation links (use nav element)","Single button (no grouping needed)"],"guidelines":["Keep button groups focused on related actions","Use consistent button variants within a group","Consider visual hierarchy - primary action should stand out","Limit to 2-4 buttons per group for clarity"],"accessibility":["Group provides semantic relationship between buttons","Each button remains individually focusable","Consider using role=\"group\" with aria-label for screen readers"]},"props":{"children":{"type":"node","description":"Button elements to group together","required":true},"gap":{"type":"enum","description":"Spacing between buttons","default":"sm","values":["none","xs","sm","md"]},"wrap":{"type":"boolean","description":"Allow buttons to wrap to next line","default":"false"},"align":{"type":"enum","description":"Alignment of buttons","values":["start","center","end"]}},"relations":[{"component":"Button","relationship":"child","note":"ButtonGroup contains Button components"},{"component":"Stack","relationship":"alternative","note":"Use Stack for more general layout needs"}],"variants":[{"name":"Default","description":"Basic button group with default spacing","code":"<ButtonGroup>\n <Button variant=\"secondary\">Cancel</Button>\n <Button variant=\"primary\">Save</Button>\n</ButtonGroup>"},{"name":"Gap Variants","description":"Different spacing options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <ButtonGroup gap=\"none\">\n <Button variant=\"secondary\" size=\"sm\">None</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"xs\">\n <Button variant=\"secondary\" size=\"sm\">XS</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"sm\">\n <Button variant=\"secondary\" size=\"sm\">SM</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"md\">\n <Button variant=\"secondary\" size=\"sm\">MD</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n</div>"},{"name":"Alignment","description":"Different alignment options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <ButtonGroup align=\"start\">\n <Button variant=\"secondary\" size=\"sm\">Start</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"center\">\n <Button variant=\"secondary\" size=\"sm\">Center</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"end\">\n <Button variant=\"secondary\" size=\"sm\">End</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n</div>"},{"name":"Form Actions","description":"Common pattern for form submit/cancel","code":"<ButtonGroup align=\"end\">\n <Button variant=\"ghost\">Cancel</Button>\n <Button variant=\"primary\">Submit</Button>\n</ButtonGroup>"}]},"Card":{"filePath":"src/components/Card/Card.fragment.tsx","meta":{"name":"Card","description":"Container for grouping related content","category":"layout","status":"stable","tags":["container","layout","surface"]},"usage":{"when":["Grouping related pieces of content together","Creating visual separation between content sections","Displaying a preview or summary of an item","Building dashboard widgets or tiles"],"whenNot":["Simple text content that does not need grouping","Modal or dialog content (use Dialog component)","Navigation items (use NavItem or similar)"],"guidelines":["Use consistent card variants within the same context","Cards in a grid should have uniform sizing","Use elevated variant sparingly for emphasis","Interactive cards should have clear hover states"],"accessibility":["Interactive cards should use button or link semantics","Card titles should be appropriate heading levels"]},"props":{"children":{"type":"node","description":"Card content - use Card.Header, Card.Body, Card.Footer sub-components"},"variant":{"type":"enum","description":"Visual style of the card surface","default":"default","values":["default","outlined","elevated"],"constraints":["Use \"elevated\" sparingly to maintain visual hierarchy"]},"padding":{"type":"enum","description":"Internal padding size","default":"md","values":["none","sm","md","lg"]},"onClick":{"type":"function","description":"Click handler - makes card interactive"}},"relations":[{"component":"CardGrid","relationship":"parent","note":"Use CardGrid for responsive card layouts"},{"component":"ListItem","relationship":"alternative","note":"Use ListItem for linear list layouts"}],"variants":[{"name":"Default","description":"Standard card with subtle shadow","code":"<Card>\n <Card.Header>\n <Card.Title>Card Title</Card.Title>\n <Card.Description>A brief description</Card.Description>\n </Card.Header>\n <Card.Body>Card content goes here.</Card.Body>\n</Card>"},{"name":"Outlined","description":"Card with border instead of shadow","code":"<Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Outlined Card</Card.Title>\n </Card.Header>\n <Card.Body>Content with border.</Card.Body>\n</Card>"},{"name":"Elevated","description":"Card with prominent shadow for emphasis","code":"<Card variant=\"elevated\">\n <Card.Header>\n <Card.Title>Featured Item</Card.Title>\n </Card.Header>\n <Card.Body>Important content.</Card.Body>\n</Card>"},{"name":"Interactive","description":"Clickable card","code":"<Card onClick={() => alert('Card clicked!')}>\n <Card.Header>\n <Card.Title>Click Me</Card.Title>\n <Card.Description>This card is interactive</Card.Description>\n </Card.Header>\n <Card.Body>Click anywhere on this card.</Card.Body>\n</Card>"},{"name":"With Footer","description":"Card with header, body, and footer","code":"<Card>\n <Card.Header>\n <Card.Title>Card with Footer</Card.Title>\n <Card.Description>Complete card layout</Card.Description>\n </Card.Header>\n <Card.Body>Main content area.</Card.Body>\n <Card.Footer>Footer actions go here</Card.Footer>\n</Card>"},{"name":"Content Only","description":"Card with just body content","code":"<Card>\n <Card.Body>Just content, no header or footer.</Card.Body>\n</Card>"}],"ai":{"compositionPattern":"compound","subComponents":["Header","Title","Description","Body","Footer"],"requiredChildren":["Body"],"commonPatterns":["<Card><Card.Body>{content}</Card.Body></Card>","<Card><Card.Header><Card.Title>{title}</Card.Title></Card.Header><Card.Body>{content}</Card.Body></Card>","<Card><Card.Header><Card.Title>{title}</Card.Title><Card.Description>{desc}</Card.Description></Card.Header><Card.Body>{content}</Card.Body><Card.Footer>{actions}</Card.Footer></Card>"]}},"Chart":{"filePath":"src/components/Chart/Chart.fragment.tsx","meta":{"name":"Chart","description":"Composable chart wrapper for recharts with theme-aware tooltips, legends, and color integration.","category":"display","status":"stable","tags":["chart","graph","data-visualization","recharts"],"since":"0.3.0"},"usage":{"when":["Displaying data trends over time","Comparing categorical data","Showing distribution or composition","Dashboard data visualizations"],"whenNot":["Simple numeric values (use Text or Badge)","Progress toward a goal (use Progress)","Tabular data without visualization (use Table)"],"guidelines":["Use ChartContainer to wrap recharts chart components","Define a ChartConfig to map data keys to labels and colors","Use FUI CSS variables for colors so charts adapt to theme changes","Use ChartTooltip and ChartLegend for consistent themed overlays"],"accessibility":["Charts include recharts accessibilityLayer by default","Provide meaningful labels in ChartConfig for screen readers","Consider providing a data table alternative for complex charts"]},"props":{"config":{"type":"object","description":"ChartConfig mapping data keys to labels and colors"},"children":{"type":"ReactElement","description":"A recharts chart component (LineChart, BarChart, etc.)"}},"relations":[{"component":"Card","relationship":"parent","note":"Charts are typically placed inside Cards"},{"component":"Progress","relationship":"alternative","note":"Use Progress for single-value completion"},{"component":"Table","relationship":"sibling","note":"Combine with Table for full data views"}],"variants":[{"name":"Line Chart","description":"Multi-series line chart showing trends over time","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n users: { label: 'Users', color: 'var(--fui-color-info)' },\n }}\n >\n <LineChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <ChartLegend />\n <Line type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" strokeWidth={2} dot={false} />\n <Line type=\"monotone\" dataKey=\"users\" stroke=\"var(--fui-color-info)\" strokeWidth={2} dot={false} />\n </LineChart>\n </ChartContainer>\n</div>"},{"name":"Bar Chart","description":"Categorical bar chart comparing device sessions","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n sessions: { label: 'Sessions', color: 'var(--fui-color-accent)' },\n }}\n >\n <BarChart data={deviceData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"device\" />\n <YAxis />\n <ChartTooltip />\n <Bar dataKey=\"sessions\" fill=\"var(--fui-color-accent)\" radius={[4, 4, 0, 0]} />\n </BarChart>\n </ChartContainer>\n</div>"},{"name":"Area Chart","description":"Filled area chart showing revenue trend","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n }}\n >\n <AreaChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <Area type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" fill=\"var(--fui-color-accent)\" fillOpacity={0.15} strokeWidth={2} />\n </AreaChart>\n </ChartContainer>\n</div>"},{"name":"Pie Chart","description":"Donut chart showing browser share distribution","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n Chrome: { label: 'Chrome', color: 'var(--fui-color-accent)' },\n Firefox: { label: 'Firefox', color: 'var(--fui-color-info)' },\n Safari: { label: 'Safari', color: 'var(--fui-color-success)' },\n Edge: { label: 'Edge', color: 'var(--fui-color-warning)' },\n }}\n >\n <PieChart>\n <ChartTooltip />\n <ChartLegend />\n <Pie\n data={browserData}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={60}\n outerRadius={90}\n strokeWidth={2}\n >\n {browserData.map((entry) => (\n <Cell key={entry.name} fill={entry.color} />\n ))}\n </Pie>\n </PieChart>\n </ChartContainer>\n</div>"}]},"Checkbox":{"filePath":"src/components/Checkbox/Checkbox.fragment.tsx","meta":{"name":"Checkbox","description":"Binary toggle for form fields. Use for options that require explicit submission, unlike Toggle which takes effect immediately.","category":"forms","status":"stable","tags":["checkbox","form","boolean","selection","input"],"since":"0.1.0"},"usage":{"when":["Form fields requiring explicit submission","Multi-select from a list of options","Terms and conditions acceptance","Filter or preference checklists"],"whenNot":["Immediate effect settings (use Toggle)","Single selection from options (use RadioGroup)","Selecting from many options (use Select)"],"guidelines":["Always include a visible label","Use description for additional context when needed","Group related checkboxes visually","Use indeterminate state for parent/child relationships"],"accessibility":["Proper label association","Keyboard accessible (Space to toggle)","Visible focus indicator","Indeterminate state properly announced"]},"props":{"checked":{"type":"boolean","description":"Controlled checked state"},"defaultChecked":{"type":"boolean","description":"Default checked state (uncontrolled)"},"onCheckedChange":{"type":"function","description":"Called when checked state changes"},"indeterminate":{"type":"boolean","description":"Indeterminate state (partial selection)","default":"false"},"disabled":{"type":"boolean","description":"Disable the checkbox","default":"false"},"label":{"type":"string","description":"Label text"},"description":{"type":"string","description":"Description text below the label"},"size":{"type":"enum","description":"Checkbox size","default":"md","values":["sm","md","lg"]}},"relations":[{"component":"Toggle","relationship":"alternative","note":"Use Toggle for immediate-effect settings"},{"component":"Input","relationship":"sibling","note":"Checkbox handles boolean; Input handles text"}],"variants":[{"name":"Default","description":"Basic checkbox with label","code":"<StatefulCheckbox label=\"Accept terms and conditions\" />"},{"name":"With Description","description":"Checkbox with helper text","code":"<StatefulCheckbox\n label=\"Email notifications\"\n description=\"Receive email updates about your account activity\"\n/>"},{"name":"Checked","description":"Pre-checked checkbox","code":"<StatefulCheckbox defaultChecked label=\"Subscribe to newsletter\" />"},{"name":"Indeterminate","description":"Partial selection state","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Checkbox indeterminate label=\"Select all\" />\n <div style={{ marginLeft: '24px', display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <StatefulCheckbox defaultChecked label=\"Option 1\" />\n <StatefulCheckbox label=\"Option 2\" />\n <StatefulCheckbox defaultChecked label=\"Option 3\" />\n </div>\n</div>"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <StatefulCheckbox size=\"sm\" label=\"Small checkbox\" />\n <StatefulCheckbox size=\"md\" label=\"Medium checkbox\" />\n <StatefulCheckbox size=\"lg\" label=\"Large checkbox\" />\n</div>"},{"name":"Disabled","description":"Non-interactive states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Checkbox disabled label=\"Disabled unchecked\" />\n <Checkbox disabled checked label=\"Disabled checked\" />\n</div>"}]},"Collapsible":{"filePath":"src/components/Collapsible/Collapsible.fragment.tsx","meta":{"name":"Collapsible","description":"An interactive component that expands/collapses to show or hide content","category":"layout","status":"stable","tags":["collapsible","expandable","accordion","disclosure","toggle"]},"usage":{"when":["Showing/hiding additional content on demand","Building accordions or expandable sections","Collapsible navigation sections","FAQ sections with expandable answers","Settings panels with grouped options"],"whenNot":["Single item disclosure (use Accordion instead)","Navigation menus with complex interactions (use Menu)","Modal or overlay content (use Dialog or Popover)"],"guidelines":["Use clear trigger labels that indicate expandable content","Consider defaultOpen for primary content users often need","Keep trigger text concise but descriptive","Use chevron icons consistently to indicate collapsible state"],"accessibility":["Trigger must have aria-expanded to indicate state","Content region needs aria-labelledby pointing to trigger","Keyboard: Enter/Space toggles open state","Focus should remain on trigger after toggle"]},"props":{"defaultOpen":{"type":"boolean","description":"Whether the collapsible is initially open (uncontrolled)","default":false},"open":{"type":"boolean","description":"Controlled open state"},"onOpenChange":{"type":"function","description":"Callback when open state changes - (open: boolean) => void"},"disabled":{"type":"boolean","description":"Whether the collapsible is disabled","default":false},"children":{"type":"node","description":"Collapsible.Trigger and Collapsible.Content components","required":true}},"relations":[{"component":"Accordion","relationship":"alternative","note":"Use Accordion for multiple exclusive collapsible sections"},{"component":"Sidebar","relationship":"used-by","note":"Sidebar uses Collapsible for section expand/collapse"},{"component":"Menu","relationship":"alternative","note":"Use Menu for dropdown navigation with actions"}],"variants":[{"name":"Default","description":"Basic collapsible with trigger and content","code":"<Collapsible>\n <Collapsible.Trigger>Click to expand</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content is hidden by default and revealed when the trigger is clicked.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Default Open","description":"Collapsible that starts in the expanded state","code":"<Collapsible defaultOpen>\n <Collapsible.Trigger>Section Title</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content is visible by default. Click the trigger to collapse.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Chevron Start","description":"Collapsible with chevron icon on the left","code":"<Collapsible>\n <Collapsible.Trigger chevronPosition=\"start\">Navigation</Collapsible.Trigger>\n <Collapsible.Content>\n <ul style={{ margin: 0, paddingLeft: '1.5rem' }}>\n <li>Dashboard</li>\n <li>Settings</li>\n <li>Profile</li>\n </ul>\n </Collapsible.Content>\n</Collapsible>"},{"name":"No Chevron","description":"Collapsible without chevron indicator","code":"<Collapsible>\n <Collapsible.Trigger showChevron={false}>Show more details</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Hidden details that appear when triggered.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Disabled","description":"Collapsible in disabled state","code":"<Collapsible disabled>\n <Collapsible.Trigger>Cannot toggle (disabled)</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content cannot be shown because the collapsible is disabled.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Multiple Sections","description":"Multiple independent collapsible sections","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <Collapsible defaultOpen>\n <Collapsible.Trigger>Getting Started</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Introduction and setup instructions.</p>\n </Collapsible.Content>\n </Collapsible>\n <Collapsible>\n <Collapsible.Trigger>Advanced Usage</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Advanced configuration options.</p>\n </Collapsible.Content>\n </Collapsible>\n <Collapsible>\n <Collapsible.Trigger>API Reference</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Complete API documentation.</p>\n </Collapsible.Content>\n </Collapsible>\n</div>"}]},"CodeBlock":{"filePath":"src/components/CodeBlock/CodeBlock.fragment.tsx","meta":{"name":"CodeBlock","description":"Syntax-highlighted code display with copy functionality, theming, diff view, and collapsible sections","category":"display","status":"stable","tags":["code","syntax","highlighting","documentation","developer","diff"]},"usage":{"when":["Displaying code examples in documentation","Showing installation commands","Presenting configuration snippets","Teaching programming concepts","Showing code diffs or changes","Displaying long code files with collapse functionality"],"whenNot":["User-editable code (use code editor)","Very short inline code (use <code> element)","Non-code content (use Text or Card)"],"guidelines":["Always specify the correct language for accurate highlighting","Use filename prop to show source file name in header bar","Use title prop for external labels above the code block","Enable line numbers for longer code samples","Use highlightLines to draw attention to key lines","Use addedLines/removedLines for diff highlighting","Set maxHeight for very long code blocks to prevent layout issues","Use collapsible for code samples that users may want to skim","Choose a theme that matches your documentation style","Keep code examples concise and focused"],"accessibility":["Code is presented in a semantic pre/code structure","Copy button has appropriate aria-label","Keyboard accessible copy functionality","Collapse button has aria-expanded state"]},"props":{"code":{"type":"string","description":"The code string to display","required":true},"language":{"type":"enum","description":"Programming language for syntax highlighting","default":"tsx","values":["tsx","typescript","javascript","jsx","bash","shell","css","scss","sass","json","html","xml","markdown","md","yaml","yml","python","py","ruby","go","rust","java","kotlin","swift","c","cpp","csharp","php","sql","graphql","diff","plaintext"]},"theme":{"type":"enum","description":"Syntax highlighting theme","default":"synthwave-84","values":["synthwave-84","github-dark","github-light","one-dark-pro","dracula","nord","monokai","vitesse-dark","vitesse-light","min-dark","min-light"]},"showCopy":{"type":"boolean","description":"Whether to show the copy button","default":true},"title":{"type":"string","description":"Optional title displayed above the code block (external label)"},"filename":{"type":"string","description":"Optional filename shown in header bar inside code block"},"caption":{"type":"string","description":"Optional caption displayed below the code block"},"showLineNumbers":{"type":"boolean","description":"Whether to display line numbers","default":false},"startLineNumber":{"type":"number","description":"Starting line number (useful for code excerpts)","default":1},"highlightLines":{"type":"array","description":"Lines to highlight (e.g., [1, 3, \"5-7\"])"},"addedLines":{"type":"array","description":"Lines marked as added in diff view (e.g., [2, \"4-6\"])"},"removedLines":{"type":"array","description":"Lines marked as removed in diff view (e.g., [1, 3])"},"wordWrap":{"type":"boolean","description":"Enable word wrapping for long lines","default":false},"maxHeight":{"type":"number","description":"Maximum height in pixels (enables scrolling)"},"collapsible":{"type":"boolean","description":"Allow collapsing/expanding the code block","default":false},"defaultCollapsed":{"type":"boolean","description":"Initial collapsed state (only applies when collapsible is true)","default":false},"collapsedLines":{"type":"number","description":"Number of lines to show when collapsed","default":5},"className":{"type":"string","description":"Additional CSS class name"}},"relations":[{"component":"Card","relationship":"parent","note":"Can be wrapped in Card for additional context"},{"component":"Tabs","relationship":"child","note":"Use in Tabs for showing code in multiple languages"}],"variants":[{"name":"Default","description":"Basic code block with syntax highlighting","code":"<CodeBlock code={`import { Button } from '@fragments-sdk/ui';\n\nfunction App() {\n return <Button>Click me</Button>;\n}`} language=\"tsx\" />"},{"name":"With Filename","description":"Code block with filename in header bar","code":"<CodeBlock filename=\"app.tsx\" code={`import { Button, Card } from '@fragments-sdk/ui';\n\nfunction App() {\n return (\n <Card>\n <Card.Header>Welcome</Card.Header>\n <Card.Content>\n <Button>Get Started</Button>\n </Card.Content>\n </Card>\n );\n}`} language=\"tsx\" />"},{"name":"With Title","description":"Code block with external title label","code":"<CodeBlock title=\"Installation\" code=\"npm install @fragments-sdk/ui\" language=\"bash\" />"},{"name":"With Caption","description":"Code block with footer caption","code":"<CodeBlock\n code={`const API_URL = process.env.NEXT_PUBLIC_API_URL;`}\n language=\"typescript\"\n caption=\"Environment variables must be prefixed with NEXT_PUBLIC_ to be available in the browser.\"\n/>"},{"name":"With Line Numbers","description":"Shows line numbers for reference","code":"<CodeBlock code={`const greeting = \"Hello\";\nconst name = \"World\";\nconsole.log(\\`\\${greeting}, \\${name}!\\`);`} language=\"typescript\" showLineNumbers />"},{"name":"Custom Start Line","description":"Shows code excerpt starting from a specific line number","code":"<CodeBlock\n code={` return (\n <button onClick={() => setCount(c => c + 1)}>\n Count: {count}\n </button>\n );\n}`}\n language=\"tsx\"\n showLineNumbers\n startLineNumber={15}\n caption=\"Lines 15-20 from Counter.tsx\"\n/>"},{"name":"With Highlighted Lines","description":"Emphasizes specific lines of code","code":"<CodeBlock code={`import { useState } from 'react';\n\nfunction Counter() {\n const [count, setCount] = useState(0);\n\n return (\n <button onClick={() => setCount(c => c + 1)}>\n Count: {count}\n </button>\n );\n}`} language=\"tsx\" showLineNumbers highlightLines={[4, '7-9']} />"},{"name":"Diff View","description":"Shows added and removed lines in a diff-like format","code":"<CodeBlock\n code={`import { useState } from 'react';\nimport { useCallback } from 'react';\n\nfunction Counter() {\n const [count, setCount] = useState(0);\n const increment = () => setCount(c => c + 1);\n const increment = useCallback(() => setCount(c => c + 1), []);\n\n return <button onClick={increment}>Count: {count}</button>;\n}`}\n language=\"tsx\"\n showLineNumbers\n removedLines={[6]}\n addedLines={[2, 7]}\n/>"},{"name":"GitHub Dark Theme","description":"Using the GitHub Dark theme","code":"<CodeBlock\n code={`async function fetchUser(id: string) {\n const response = await fetch(\\`/api/users/\\${id}\\`);\n return response.json();\n}`}\n language=\"typescript\"\n theme=\"github-dark\"\n/>"},{"name":"GitHub Light Theme","description":"Using the GitHub Light theme for light backgrounds","code":"<CodeBlock\n code={`def fibonacci(n):\n if n <= 1:\n return n\n return fibonacci(n - 1) + fibonacci(n - 2)`}\n language=\"python\"\n theme=\"github-light\"\n/>"},{"name":"Dracula Theme","description":"Using the popular Dracula theme","code":"<CodeBlock\n code={`fn main() {\n println!(\"Hello, Rust!\");\n}`}\n language=\"rust\"\n theme=\"dracula\"\n/>"},{"name":"Word Wrap","description":"Long lines wrap instead of scrolling horizontally","code":"<CodeBlock\n code={`const longString = \"This is a very long string that would normally cause horizontal scrolling, but with word wrap enabled it will break to the next line instead.\";`}\n language=\"typescript\"\n wordWrap\n/>"},{"name":"Max Height with Scroll","description":"Constrains height with scrollable content","code":"<CodeBlock\n code={`// This code block has a maximum height\nfunction processItems(items: string[]) {\n const results = [];\n for (const item of items) {\n if (item.startsWith('_')) {\n continue;\n }\n const processed = item.trim().toLowerCase();\n if (processed.length > 0) {\n results.push(processed);\n }\n }\n return results;\n}\n\nexport default processItems;`}\n language=\"typescript\"\n maxHeight={150}\n showLineNumbers\n/>"},{"name":"Collapsible","description":"Long code that can be expanded/collapsed","code":"<CodeBlock\n code={`import React, { useState, useEffect } from 'react';\n\ninterface User {\n id: string;\n name: string;\n email: string;\n avatar?: string;\n}\n\nexport function UserProfile({ userId }: { userId: string }) {\n const [user, setUser] = useState<User | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n async function fetchUser() {\n try {\n setLoading(true);\n const response = await fetch(\\`/api/users/\\${userId}\\`);\n if (!response.ok) throw new Error('Failed to fetch');\n const data = await response.json();\n setUser(data);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n }\n fetchUser();\n }, [userId]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div>Error: {error}</div>;\n if (!user) return null;\n\n return (\n <div>\n <h1>{user.name}</h1>\n <p>{user.email}</p>\n </div>\n );\n}`}\n language=\"tsx\"\n showLineNumbers\n collapsible\n defaultCollapsed\n collapsedLines={8}\n/>"},{"name":"JSON","description":"Configuration file example","code":"<CodeBlock title=\"package.json\" code={`{\n \"name\": \"my-app\",\n \"dependencies\": {\n \"@fragments-sdk/ui\": \"^0.3.0\"\n }\n}`} language=\"json\" />"},{"name":"Without Copy Button","description":"Minimal display without copy functionality","code":"<CodeBlock code=\"const simple = true;\" language=\"typescript\" showCopy={false} />"}]},"ColorPicker":{"filePath":"src/components/ColorPicker/ColorPicker.fragment.tsx","meta":{"name":"ColorPicker","description":"Color selection control with hex input and visual picker. Displays a swatch that opens a full color picker on click.","category":"forms","status":"stable","tags":["color","picker","input","hex","swatch","theme"],"since":"0.2.0"},"usage":{"when":["Theme customization interfaces","Brand color selection","Design tool color inputs","User preference settings for colors"],"whenNot":["Predefined color options only (use RadioGroup with swatches)","Simple color display without editing (use a colored Badge)","Color indication only (use semantic color tokens)"],"guidelines":["Always provide a label to describe what the color is for","Use description to explain color usage or constraints","Consider providing color presets alongside the picker for common choices","Validate hex format (#RRGGBB) on input"],"accessibility":["Label is associated with the color input","Swatch button has appropriate aria-label","Color picker popup is keyboard accessible","Hex input allows direct text entry"]},"props":{"value":{"type":"string","description":"Controlled color value in hex format (#RRGGBB)"},"defaultValue":{"type":"string","description":"Default color for uncontrolled usage","default":"#000000"},"onChange":{"type":"function","description":"Called with new color value when changed"},"label":{"type":"string","description":"Label text above the picker"},"description":{"type":"string","description":"Helper text below the picker"},"disabled":{"type":"boolean","description":"Disable the color picker","default":"false"},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md"]},"showInput":{"type":"boolean","description":"Show the hex input field","default":"true"}},"relations":[{"component":"Input","relationship":"sibling","note":"ColorPicker is a specialized input for colors"},{"component":"RadioGroup","relationship":"alternative","note":"Use RadioGroup for predefined color choices"},{"component":"Field","relationship":"parent","note":"ColorPicker uses Field internally for structure"}],"variants":[{"name":"Default","description":"Basic color picker with label","code":"<ColorPicker\n label=\"Brand Color\"\n defaultValue=\"#3b82f6\"\n/>"},{"name":"With Description","description":"Color picker with helper text","code":"<ColorPicker\n label=\"Primary Color\"\n defaultValue=\"#10b981\"\n description=\"This color will be used for buttons and links\"\n/>"},{"name":"Controlled","description":"Controlled color picker that logs changes","code":"{\n const [color, setColor] = React.useState('#ef4444');\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <ColorPicker\n label=\"Accent Color\"\n value={color}\n onChange={setColor}\n />\n <div style={{ fontSize: '14px', color: 'var(--fui-text-secondary)' }}>\n Selected: {color}\n </div>\n </div>\n );\n}"},{"name":"Multiple Pickers","description":"Multiple color pickers for theme configuration","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '240px' }}>\n <ColorPicker label=\"Primary\" defaultValue=\"#3b82f6\" />\n <ColorPicker label=\"Success\" defaultValue=\"#22c55e\" />\n <ColorPicker label=\"Warning\" defaultValue=\"#f59e0b\" />\n <ColorPicker label=\"Danger\" defaultValue=\"#ef4444\" />\n</div>"},{"name":"Compact","description":"Small size with swatch only (no input)","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <ColorPicker defaultValue=\"#ef4444\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#f59e0b\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#22c55e\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#3b82f6\" size=\"sm\" showInput={false} />\n</div>"},{"name":"Sizes","description":"Different size variants","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '240px' }}>\n <ColorPicker label=\"Small\" defaultValue=\"#3b82f6\" size=\"sm\" />\n <ColorPicker label=\"Medium (default)\" defaultValue=\"#3b82f6\" size=\"md\" />\n</div>"},{"name":"Disabled","description":"Disabled color picker","code":"<ColorPicker\n label=\"Locked Color\"\n defaultValue=\"#64748b\"\n description=\"This color cannot be changed\"\n disabled\n/>"}]},"ConversationList":{"filePath":"src/components/ConversationList/ConversationList.fragment.tsx","meta":{"name":"ConversationList","description":"Scrollable message container with auto-scroll and history loading","category":"ai","status":"stable","tags":["conversation","chat","messages","scroll","ai","list"]},"usage":{"when":["Building a chat interface with multiple messages","Need auto-scroll behavior when new messages arrive","Require infinite scroll for loading message history","Want date separators between message groups"],"whenNot":["Simple list of items without chat context (use List)","Single message display (use Message directly)","Non-scrolling message layout"],"guidelines":["Use autoScroll=\"smart\" for best UX (only auto-scrolls when near bottom)","Implement onScrollTop for loading older messages","Provide an emptyState for new conversations","Use DateSeparator between messages from different days"],"accessibility":["Uses proper ARIA roles for separators","Typing indicator has aria-label","Smooth scroll respects reduced motion preferences","Keyboard navigation works within scrollable container"]},"props":{"children":{"type":"ReactNode","description":"Message components","required":true},"autoScroll":{"type":"boolean | \"smart\"","description":"Auto-scroll behavior: true (always), false (never), or \"smart\" (only when near bottom)","default":"\"smart\""},"onScrollTop":{"type":"function","description":"Callback when user scrolls to top (for loading history)"},"loadingHistory":{"type":"boolean","description":"Show loading spinner at top when loading history","default":"false"},"emptyState":{"type":"ReactNode","description":"Content to show when conversation is empty"},"scrollTopThreshold":{"type":"number","description":"Pixels from top to trigger onScrollTop","default":"50"},"scrollBottomThreshold":{"type":"number","description":"Pixels from bottom for smart auto-scroll","default":"100"}},"relations":[{"component":"Message","relationship":"child","note":"ConversationList contains Message components"},{"component":"ThinkingIndicator","relationship":"child","note":"Show ThinkingIndicator at bottom while awaiting response"},{"component":"Prompt","relationship":"sibling","note":"Typically paired with Prompt for input"}],"variants":[{"name":"Basic","description":"Simple conversation with messages","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <Message role=\"user\">\n <Message.Content>Hello!</Message.Content>\n </Message>\n <Message role=\"assistant\">\n <Message.Content>Hi there! How can I help you today?</Message.Content>\n </Message>\n <Message role=\"user\">\n <Message.Content>Can you explain React hooks?</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"With Date Separators","description":"Messages grouped by date","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <ConversationList.DateSeparator date={new Date(Date.now() - 86400000)} />\n <Message role=\"user\">\n <Message.Content>A message from yesterday</Message.Content>\n </Message>\n <ConversationList.DateSeparator date={new Date()} />\n <Message role=\"assistant\">\n <Message.Content>And a message from today!</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"With Typing Indicator","description":"Shows assistant is typing","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <Message role=\"user\">\n <Message.Content>What is TypeScript?</Message.Content>\n </Message>\n <ConversationList.TypingIndicator name=\"Assistant\" />\n </ConversationList>\n</div>"},{"name":"Loading History","description":"Loading older messages","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList loadingHistory>\n <Message role=\"user\">\n <Message.Content>This is the latest message</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"Empty State","description":"No messages yet","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList\n emptyState={\n <div style={{ textAlign: 'center', color: '#71717a', padding: '2rem' }}>\n <p>No messages yet</p>\n <p style={{ fontSize: '12px' }}>Start a conversation!</p>\n </div>\n }\n >\n {/* No messages */}\n </ConversationList>\n</div>"}]},"Dialog":{"filePath":"src/components/Dialog/Dialog.fragment.tsx","meta":{"name":"Dialog","description":"Modal overlay for focused user interactions. Use for confirmations, forms, or content requiring full attention.","category":"feedback","status":"stable","tags":["modal","dialog","overlay","popup","confirmation"],"since":"0.1.0"},"usage":{"when":["Confirming destructive actions (delete, discard changes)","Collecting focused input (forms, settings)","Displaying content that requires acknowledgment","Multi-step workflows that need isolation"],"whenNot":["Simple tooltips or hints (use Tooltip)","Contextual menus (use Menu or Popover)","Non-blocking notifications (use Toast or Alert)","Simple confirmation that can be inline (use Alert)"],"guidelines":["Keep dialog content focused on a single task","Provide clear primary and secondary actions","Use descriptive title that explains the purpose","Allow dismissal via backdrop click or close button for non-critical dialogs","Trap focus within the dialog for accessibility"],"accessibility":["Automatically traps focus within the dialog","Closes on Escape key press","Returns focus to trigger element on close","Uses role=\"dialog\" with proper aria attributes"]},"props":{"children":{"type":"node","description":"Dialog content (use Dialog.Content, Dialog.Header, etc.)","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether to render as modal (blocks interaction with rest of page)","default":"true"}},"relations":[{"component":"Popover","relationship":"alternative","note":"Use Popover for non-modal contextual content"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action lists"},{"component":"Alert","relationship":"sibling","note":"Use Alert for inline notifications"}],"variants":[{"name":"Default","description":"Basic dialog with header, body, and footer","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button>Open Dialog</Button>\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Close />\n <Dialog.Header>\n <Dialog.Title>Dialog Title</Dialog.Title>\n <Dialog.Description>\n A brief description of what this dialog is for.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <p>Dialog content goes here. You can include forms, text, or any other content.</p>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"primary\">Confirm</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"},{"name":"Confirmation","description":"Destructive action confirmation","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button variant=\"danger\">Delete Item</Button>\n </Dialog.Trigger>\n <Dialog.Content size=\"sm\">\n <Dialog.Header>\n <Dialog.Title>Delete item?</Dialog.Title>\n <Dialog.Description>\n This action cannot be undone. The item will be permanently removed.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"danger\">Delete</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"},{"name":"Large","description":"Large dialog for complex content","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button>Open Large Dialog</Button>\n </Dialog.Trigger>\n <Dialog.Content size=\"lg\">\n <Dialog.Close />\n <Dialog.Header>\n <Dialog.Title>Settings</Dialog.Title>\n <Dialog.Description>\n Configure your application preferences.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <p>This dialog has more space for complex forms or content layouts.</p>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"primary\">Save Changes</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Close","Header","Title","Description","Body","Footer"],"requiredChildren":["Content"],"commonPatterns":["<Dialog><Dialog.Trigger><Button>Open</Button></Dialog.Trigger><Dialog.Content><Dialog.Header><Dialog.Title>{title}</Dialog.Title></Dialog.Header><Dialog.Body>{content}</Dialog.Body><Dialog.Footer><Dialog.Close><Button variant=\"secondary\">Cancel</Button></Dialog.Close><Button>Confirm</Button></Dialog.Footer></Dialog.Content></Dialog>"]}},"EmptyState":{"filePath":"src/components/EmptyState/EmptyState.fragment.tsx","meta":{"name":"EmptyState","description":"Placeholder for empty content areas. Provides context, guidance, and actions when no data is available.","category":"feedback","status":"stable","tags":["empty","placeholder","no-data","zero-state","blank-slate"],"since":"0.1.0"},"usage":{"when":["Empty lists, tables, or search results","New user onboarding (no content yet)","Filtered views with no matches","Error states where content failed to load"],"whenNot":["Loading states (use skeleton or spinner)","Error messages with retry (use Alert)","Temporary messages (use Toast)"],"guidelines":["Always explain why the area is empty","Provide a clear action to resolve the empty state","Use appropriate icons to reinforce the message","Keep messaging positive and actionable"],"accessibility":["Empty state content is accessible to screen readers","Action buttons follow button accessibility guidelines"]},"props":{"children":{"type":"node","description":"EmptyState content - use EmptyState.Icon, EmptyState.Title, EmptyState.Description, EmptyState.Actions sub-components"},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md","lg"]}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for error states with retry"},{"component":"Progress","relationship":"alternative","note":"Use Progress/Spinner for loading states"}],"variants":[{"name":"Default","description":"Basic empty state with action","code":"<EmptyState>\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>No projects yet</EmptyState.Title>\n <EmptyState.Description>Get started by creating your first project.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Project</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"No Results","description":"Empty search results","code":"<EmptyState>\n <EmptyState.Icon><SearchIcon /></EmptyState.Icon>\n <EmptyState.Title>No results found</EmptyState.Title>\n <EmptyState.Description>Try adjusting your search terms or filters.</EmptyState.Description>\n <EmptyState.Actions>\n <Button variant=\"secondary\">Clear Filters</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"With Secondary Action","description":"Empty state with two actions","code":"<EmptyState>\n <EmptyState.Icon><InboxIcon /></EmptyState.Icon>\n <EmptyState.Title>Inbox is empty</EmptyState.Title>\n <EmptyState.Description>You have no new messages.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Compose Message</Button>\n <Button variant=\"secondary\">View Archive</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"Small","description":"Compact empty state for inline use","code":"<EmptyState size=\"sm\">\n <EmptyState.Title>No items</EmptyState.Title>\n <EmptyState.Description>Add items to see them here.</EmptyState.Description>\n</EmptyState>"},{"name":"Large","description":"Prominent empty state for full-page use","code":"<EmptyState size=\"lg\">\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>Welcome to your workspace</EmptyState.Title>\n <EmptyState.Description>\n This is where your projects will appear. Create your first project to get started.\n </EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Your First Project</Button>\n </EmptyState.Actions>\n</EmptyState>"}],"ai":{"compositionPattern":"compound","subComponents":["Icon","Title","Description","Actions"],"requiredChildren":["Title"],"commonPatterns":["<EmptyState><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description></EmptyState>","<EmptyState><EmptyState.Icon>{icon}</EmptyState.Icon><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description><EmptyState.Actions><Button>{action}</Button></EmptyState.Actions></EmptyState>"]}},"Field":{"filePath":"src/components/Field/Field.fragment.tsx","meta":{"name":"Field","description":"Compositional form field wrapper providing validation, labels, descriptions, and error messages. Use for advanced form needs beyond baked-in Input/Textarea props.","category":"forms","status":"stable","tags":["form","field","validation","label","error","input","accessible"],"since":"0.4.0"},"usage":{"when":["You need granular validation with match-based error messages","Custom form controls need accessible labels and descriptions","Server-side errors need to be distributed to specific fields","You need dirty/touched tracking or custom validation logic"],"whenNot":["Simple inputs with basic label and helper text (use Input with label prop)","Standalone selects or textareas with built-in error display"],"guidelines":["Always provide a Field.Label for accessibility","Wrap any form control in Field.Control to connect it to the field context","Use match prop on Field.Error for granular native validation messages","Wrap in Form to enable server-side error distribution by field name"],"accessibility":["Label automatically linked to control via aria-labelledby","Description linked via aria-describedby","Error messages announced to screen readers","Supports data-disabled and data-invalid attributes for styling"]},"props":{"name":{"type":"string","description":"Field name, used for error distribution from Form"},"disabled":{"type":"boolean","description":"Disables the field and its control"},"invalid":{"type":"boolean","description":"Marks the field as invalid"},"validate":{"type":"function","description":"Custom validation function returning error string(s) or null"},"validationMode":{"type":"enum","description":"When to trigger validation","values":["onSubmit","onBlur","onChange"]},"validationDebounceTime":{"type":"number","description":"Debounce time in ms for onChange validation"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for simple fields with built-in label/error"},{"component":"Form","relationship":"parent","note":"Wrap in Form for server-side error distribution"},{"component":"Fieldset","relationship":"sibling","note":"Use Fieldset to group related fields"}],"variants":[{"name":"Single field","description":"A single field with label, control, and description","code":"<Field name=\"email\">\n <Field.Label>Email address</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Description>We will never share your email.</Field.Description>\n</Field>"},{"name":"Two-column layout","description":"Fields arranged in a two-column grid","code":"<Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"typeMismatch\">Enter a valid email address</Field.Error>\n </Field>\n </Grid.Item>\n</Grid>"},{"name":"Custom validation","description":"Field with custom validate function","code":"<Field\n name=\"age\"\n validate={(value) => {\n const num = Number(value);\n if (isNaN(num) || num < 18) return 'Must be 18 or older';\n return null;\n }}\n validationMode=\"onChange\"\n validationDebounceTime={500}\n>\n <Field.Label>Age</Field.Label>\n <Field.Control>\n <Input type=\"number\" placeholder=\"18\" />\n </Field.Control>\n <Field.Description>You must be at least 18 years old.</Field.Description>\n <Field.Error match=\"customError\" />\n</Field>"}]},"Fieldset":{"filePath":"src/components/Fieldset/Fieldset.fragment.tsx","meta":{"name":"Fieldset","description":"Groups related form fields with an accessible legend. Use to organize forms into logical sections.","category":"forms","status":"stable","tags":["form","fieldset","group","legend","accessible"],"since":"0.4.0"},"usage":{"when":["Grouping related fields in a form (e.g., address, personal info)","Disabling a group of fields together","Providing an accessible group label for screen readers"],"whenNot":["Generic visual grouping (use Card)","Single field wrapping (use Field)"],"guidelines":["Always include a Fieldset.Legend for accessibility","Use disabled prop to disable all fields within the group","Use Grid inside Fieldset for multi-column layouts"],"accessibility":["Renders semantic fieldset element","Legend provides accessible group label","Disabled state propagates to all child fields"]},"props":{"disabled":{"type":"boolean","description":"Disables all fields within the fieldset"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Field","relationship":"sibling","note":"Contains Field components"},{"component":"Form","relationship":"parent","note":"Used within a Form"},{"component":"Card","relationship":"alternative","note":"Use Card for non-form visual grouping"}],"variants":[{"name":"Two-column layout","description":"Fieldset with Grid for side-by-side fields","code":"<Fieldset>\n <Fieldset.Legend>Personal Information</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n </Grid>\n</Fieldset>"},{"name":"Mixed controls","description":"Fieldset with textarea, select, and checkbox","code":"<Fieldset>\n <Fieldset.Legend>Preferences</Fieldset.Legend>\n <Field name=\"bio\">\n <Field.Label>Bio</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"Tell us about yourself\" rows={3} />\n </Field.Control>\n <Field.Description>Brief description for your profile.</Field.Description>\n </Field>\n <Field name=\"role\">\n <Field.Label>Role</Field.Label>\n <Field.Control>\n <Select placeholder=\"Select a role\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"admin\">Admin</Select.Item>\n <Select.Item value=\"editor\">Editor</Select.Item>\n <Select.Item value=\"viewer\">Viewer</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n <Field name=\"newsletter\">\n <Field.Control>\n <Checkbox label=\"Subscribe to newsletter\" />\n </Field.Control>\n </Field>\n</Fieldset>"},{"name":"Disabled","description":"Disabled fieldset prevents interaction with all children","code":"<Fieldset disabled>\n <Fieldset.Legend>Locked Section</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"lockedFirst\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lockedLast\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Doe\" />\n </Field.Control>\n </Field>\n </Grid>\n <Field name=\"lockedCheck\">\n <Field.Control>\n <Checkbox label=\"Cannot toggle\" defaultChecked />\n </Field.Control>\n </Field>\n</Fieldset>"}]},"Form":{"filePath":"src/components/Form/Form.fragment.tsx","meta":{"name":"Form","description":"Form wrapper that handles server-side error distribution to Field components. Pairs with Field for complete form validation.","category":"forms","status":"stable","tags":["form","validation","errors","submit","server"],"since":"0.4.0"},"usage":{"when":["Building forms that need server-side error handling","Distributing validation errors to specific fields by name","Combining client and server validation in one form"],"whenNot":["Simple forms with only client-side validation (use native form or Field alone)","Non-form layouts (use Grid or Card)"],"guidelines":["Pass errors as Record<string, string | string[]> keyed by field name","Use onClearErrors to clear errors when fields are modified","Use onFormSubmit for form submission handling","Field components with matching name prop display errors automatically","Use Grid inside Form or Fieldset for multi-column layouts"],"accessibility":["Renders semantic form element","Error messages linked to fields via aria-describedby"]},"props":{"errors":{"type":"object","description":"Server-side errors keyed by field name"},"onFormSubmit":{"type":"function","description":"Form submission handler"},"onClearErrors":{"type":"function","description":"Called with field name when errors should be cleared"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Field","relationship":"sibling","note":"Contains Field components for error distribution"},{"component":"Fieldset","relationship":"sibling","note":"Use Fieldset to group fields within a Form"},{"component":"Button","relationship":"sibling","note":"Use Button type=\"submit\" for form submission"}],"variants":[{"name":"Sign up","description":"Registration form with two-column name fields","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"typeMismatch\">Enter a valid email address</Field.Error>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"password\">\n <Field.Label>Password</Field.Label>\n <Field.Control>\n <Input type=\"password\" placeholder=\"At least 8 characters\" />\n </Field.Control>\n <Field.Description>Must be at least 8 characters</Field.Description>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"terms\">\n <Field.Control>\n <Checkbox label=\"I agree to the terms and conditions\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Create Account</Button>\n </Grid.Item>\n </Grid>\n</Form>"},{"name":"Profile settings","description":"Multi-section form with Fieldsets, toggles, and radio group","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Fieldset>\n <Fieldset.Legend>Profile</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"displayName\">\n <Field.Label>Display Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"How others see you\" />\n </Field.Control>\n </Field>\n <Field name=\"timezone\">\n <Field.Label>Timezone</Field.Label>\n <Field.Control>\n <Select placeholder=\"Select timezone\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"utc\">UTC</Select.Item>\n <Select.Item value=\"est\">Eastern (EST)</Select.Item>\n <Select.Item value=\"pst\">Pacific (PST)</Select.Item>\n <Select.Item value=\"gmt\">GMT</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"bio\">\n <Field.Label>Bio</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"Tell us about yourself\" rows={3} maxLength={280} />\n </Field.Control>\n <Field.Description>Max 280 characters</Field.Description>\n </Field>\n </Grid.Item>\n </Grid>\n </Fieldset>\n <Fieldset>\n <Fieldset.Legend>Notifications</Fieldset.Legend>\n <Field name=\"emailNotifs\">\n <Field.Control>\n <Toggle label=\"Email notifications\" />\n </Field.Control>\n </Field>\n <Field name=\"marketingEmails\">\n <Field.Control>\n <Toggle label=\"Marketing emails\" />\n </Field.Control>\n </Field>\n <Field name=\"frequency\">\n <Field.Label>Digest frequency</Field.Label>\n <Field.Control>\n <RadioGroup name=\"frequency\" orientation=\"vertical\">\n <RadioGroup.Item value=\"daily\" label=\"Daily\" />\n <RadioGroup.Item value=\"weekly\" label=\"Weekly\" />\n <RadioGroup.Item value=\"monthly\" label=\"Monthly\" />\n </RadioGroup>\n </Field.Control>\n </Field>\n </Fieldset>\n <Button type=\"submit\" variant=\"primary\">Save Changes</Button>\n</Form>"},{"name":"Contact form","description":"Contact form with select, textarea, and checkbox","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"name\">\n <Field.Label>Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Your name\" />\n </Field.Control>\n </Field>\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"you@example.com\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"subject\">\n <Field.Label>Subject</Field.Label>\n <Field.Control>\n <Select placeholder=\"What is this about?\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"general\">General Inquiry</Select.Item>\n <Select.Item value=\"support\">Technical Support</Select.Item>\n <Select.Item value=\"billing\">Billing</Select.Item>\n <Select.Item value=\"feedback\">Feedback</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"message\">\n <Field.Label>Message</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"How can we help?\" rows={5} />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"copy\">\n <Field.Control>\n <Checkbox label=\"Send me a copy\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Send Message</Button>\n </Grid.Item>\n </Grid>\n</Form>"},{"name":"With server errors","description":"Form displaying server-side validation errors","code":"<Form errors={{ username: 'Username is already taken', email: 'Email is already registered' }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"username\">\n <Field.Label>Username</Field.Label>\n <Field.Control>\n <Input defaultValue=\"janedoe\" />\n </Field.Control>\n <Field.Error match=\"customError\" />\n </Field>\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" defaultValue=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"customError\" />\n </Field>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Submit</Button>\n </Grid.Item>\n </Grid>\n</Form>"}]},"Grid":{"filePath":"src/components/Grid/Grid.fragment.tsx","meta":{"name":"Grid","description":"Responsive grid layout for arranging items in columns with consistent spacing","category":"layout","status":"stable","tags":["grid","layout","columns","responsive"]},"usage":{"when":["Arranging cards, tiles, or media in a responsive grid","Building form layouts with multi-column fields","Creating dashboard layouts with widgets","Any content that should reflow across breakpoints"],"whenNot":["Single-column stacked content (use a simple flex column or Stack)","Navigation bars or toolbars (use a dedicated nav component)","Content that must not wrap (use inline layout)"],"guidelines":["Use columns=\"auto\" with minChildWidth for grids that adapt without breakpoints","Use responsive object { base: 1, md: 2, lg: 3 } when you need explicit control per breakpoint","Use fixed column counts when exact column control is needed and responsiveness is not required","Use Grid.Item with colSpan to create asymmetric layouts within a fixed grid","Keep gap consistent within a context — md is the default and works for most cases"],"accessibility":["Grid is purely visual — it does not affect reading order or semantics","Ensure logical source order matches visual order for screen readers"]},"props":{"columns":{"type":"union","description":"Number of columns: a number (1-12), a responsive object { base, sm, md, lg, xl }, or \"auto\" for auto-fill","default":1,"constraints":["Use \"auto\" with minChildWidth for fully fluid layouts","Use responsive object for explicit breakpoint control: { base: 1, md: 2, lg: 3 }"]},"minChildWidth":{"type":"string","description":"Minimum width for auto-fill columns (e.g., \"16rem\", \"250px\")","constraints":["Only applies when columns=\"auto\""]},"gap":{"type":"enum","description":"Gap between grid items, mapped to spacing tokens","default":"md","values":["none","xs","sm","md","lg","xl"]},"alignItems":{"type":"enum","description":"Vertical alignment of items within their cells","values":["start","center","end","stretch"]},"justifyItems":{"type":"enum","description":"Horizontal alignment of items within their cells","values":["start","center","end","stretch"]},"padding":{"type":"enum","description":"Internal padding of the grid container","default":"none","values":["none","sm","md","lg"]}},"relations":[{"component":"Card","relationship":"child","note":"Grid commonly contains Card components for dashboard and tile layouts"},{"component":"Separator","relationship":"sibling","note":"Use Separator between grid sections"}],"variants":[{"name":"Default","description":"Basic 3-column grid","code":"<Grid columns={3} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 3</div>\n</Grid>"},{"name":"Responsive","description":"1 column on mobile, 2 on tablet, 3 on desktop","code":"<Grid columns={{ base: 1, md: 2, lg: 3 }} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 3</div>\n</Grid>"},{"name":"Auto-fill","description":"Responsive grid that auto-fills based on minimum child width","code":"<Grid columns=\"auto\" minChildWidth=\"12rem\" gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 3</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 4</div>\n</Grid>"},{"name":"With Spanning","description":"Grid items spanning multiple columns","code":"<Grid columns={4} gap=\"md\">\n <Grid.Item colSpan={2}>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Spans 2 cols</div>\n </Grid.Item>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>1 col</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>1 col</div>\n <Grid.Item colSpan=\"full\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Full width</div>\n </Grid.Item>\n</Grid>"},{"name":"Form Layout","description":"Two-column form that collapses to single column on mobile","code":"<Grid columns={{ base: 1, md: 2 }} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>First Name</div>\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>Last Name</div>\n <Grid.Item colSpan=\"full\">\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>Email Address</div>\n </Grid.Item>\n</Grid>"}]},"Header":{"filePath":"src/components/Header/Header.fragment.tsx","meta":{"name":"Header","description":"Composable header with slots for brand, navigation, search, and actions. Designed for use within AppShell with responsive mobile support.","category":"navigation","status":"stable","tags":["header","navigation","navbar","brand","layout"],"since":"0.5.0"},"usage":{"when":["Primary site or app header inside AppShell","Navigation bar with branding (stacked layout)","Search and actions bar (sidebar-inset layout)","Header with responsive mobile menu trigger"],"whenNot":["Simple page titles (use heading elements)","Footer navigation (use Footer component)","Standalone sidebar navigation (use Sidebar directly)"],"guidelines":["Use Header.SkipLink for accessibility (skip to main content)","In stacked layout: include Header.Brand for logo","In sidebar-inset layout: omit Header.Brand (logo in sidebar)","Header.Trigger integrates with SidebarProvider for mobile menus","Header.Nav is hidden on mobile; use sidebar for mobile navigation","Use Header.Spacer to push items apart"],"accessibility":["Include Header.SkipLink for keyboard users","Navigation has aria-label for screen readers","Active nav items use aria-current=\"page\"","Mobile trigger has aria-expanded state"]},"props":{"children":{"type":"node","description":"Header content (use Header.Brand, Header.Nav, etc.)","required":true},"height":{"type":"string","description":"Header height","default":"56px"},"position":{"type":"enum","description":"Position behavior (usually controlled by AppShell)","default":"static","values":["static","fixed","sticky"]}},"relations":[{"component":"AppShell","relationship":"parent","note":"Header is typically used inside AppShell.Header"},{"component":"Sidebar","relationship":"sibling","note":"Header.Trigger toggles Sidebar on mobile"},{"component":"ThemeToggle","relationship":"child","note":"ThemeToggle is commonly placed in Header.Actions"}],"variants":[{"name":"For Stacked Layout","description":"Header with brand, nav, and actions. Use with AppShell layout=\"stacked\".","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Brand href=\"/\">MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/dashboard\" active>Dashboard</Header.NavItem>\n <Header.NavItem href=\"/projects\">Projects</Header.NavItem>\n <Header.NavItem href=\"/settings\">Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n <Button variant=\"secondary\" size=\"sm\">Sign In</Button>\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"For Sidebar Inset Layout","description":"Header without brand (logo is in sidebar). Use with AppShell layout=\"sidebar-inset\".","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Search>\n <Input placeholder=\"Search...\" style={{ width: '240px' }} />\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"Minimal","description":"Clean header with just trigger and actions","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"With Search","description":"Header featuring a prominent search input","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.Brand>Docs</Header.Brand>\n <Header.Search>\n <div style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n background: 'var(--fui-bg-secondary)',\n borderRadius: '6px',\n color: 'var(--fui-text-tertiary)',\n fontSize: '14px',\n width: '280px'\n }}>\n <SearchIcon /> Search documentation...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"With Skip Link","description":"Accessible header with skip link for keyboard navigation","code":"<Header>\n <Header.SkipLink href=\"#main-content\">Skip to content</Header.SkipLink>\n <Header.Brand>Accessible App</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/\" active>Home</Header.NavItem>\n <Header.NavItem href=\"/about\">About</Header.NavItem>\n </Header.Nav>\n</Header>"}],"ai":{"compositionPattern":"compound","subComponents":["SkipLink","Trigger","Brand","Nav","NavItem","Search","Spacer","Actions"],"commonPatterns":["<Header><Header.Brand href=\"/\">{appName}</Header.Brand><Header.Nav><Header.NavItem href=\"/home\" active>Home</Header.NavItem></Header.Nav><Header.Spacer /><Header.Actions>{actions}</Header.Actions></Header>"]}},"Icon":{"filePath":"src/components/Icon/Icon.fragment.tsx","meta":{"name":"Icon","description":"Wrapper for Phosphor icons with consistent sizing and semantic colors. Provides standardized icon rendering across the design system.","category":"display","status":"stable","tags":["icon","phosphor","visual","symbol","graphic"],"since":"0.1.0"},"usage":{"when":["Displaying UI icons alongside text or in buttons","Indicating status or state visually","Adding visual hierarchy to feature lists","Decorating cards or stats with relevant symbols"],"whenNot":["Large decorative illustrations (use Image or custom SVG)","Logo display (use dedicated Logo component)","Complex graphics with multiple colors","Animated icons (use custom implementation)"],"guidelines":["Use semantic color variants (success, error, warning) for status indication","Pair icons with text labels for accessibility","Match icon weight to surrounding text weight for visual consistency","Use consistent sizes within the same context"],"accessibility":["Icons are decorative by default (aria-hidden)","Always pair with visible or visually-hidden text for meaning","Do not rely on color alone to convey information","Consider using VisuallyHidden for icon-only buttons"]},"props":{"icon":{"type":"component","description":"Phosphor icon component to render","required":true},"size":{"type":"enum","description":"Icon size","default":"md","values":["xs","sm","md","lg","xl"]},"weight":{"type":"enum","description":"Icon stroke weight/style","default":"regular","values":["thin","light","regular","bold","fill","duotone"]},"variant":{"type":"enum","description":"Semantic color variant","default":"default","values":["default","primary","secondary","tertiary","accent","success","warning","error"]}},"relations":[{"component":"Button","relationship":"child","note":"Use inside icon-only buttons with VisuallyHidden label"},{"component":"VisuallyHidden","relationship":"sibling","note":"Pair with VisuallyHidden for accessible icon-only elements"},{"component":"Badge","relationship":"child","note":"Can be used as badge icon prop"}],"variants":[{"name":"Default","description":"Basic icon with default styling","code":"<Icon icon={Heart} />"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Star} size=\"xs\" />\n <Icon icon={Star} size=\"sm\" />\n <Icon icon={Star} size=\"md\" />\n <Icon icon={Star} size=\"lg\" />\n <Icon icon={Star} size=\"xl\" />\n</div>"},{"name":"Semantic Colors","description":"Status and semantic color variants","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Check} variant=\"success\" />\n <Icon icon={Warning} variant=\"warning\" />\n <Icon icon={Warning} variant=\"error\" />\n <Icon icon={Info} variant=\"accent\" />\n</div>"},{"name":"Weights","description":"Icon weight/style options","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Heart} weight=\"thin\" />\n <Icon icon={Heart} weight=\"light\" />\n <Icon icon={Heart} weight=\"regular\" />\n <Icon icon={Heart} weight=\"bold\" />\n <Icon icon={Heart} weight=\"fill\" />\n <Icon icon={Heart} weight=\"duotone\" />\n</div>"}]},"Image":{"filePath":"src/components/Image/Image.fragment.tsx","meta":{"name":"Image","description":"Responsive image component with aspect ratio control, loading states, and error fallbacks. Handles image display with consistent styling.","category":"display","status":"stable","tags":["image","media","photo","picture","visual"],"since":"0.1.0"},"usage":{"when":["Displaying product images in cards or grids","Hero images with specific aspect ratios","User-uploaded content that may fail to load","Thumbnails in lists or galleries"],"whenNot":["User avatars (use Avatar component)","Icons or symbols (use Icon component)","Background images (use CSS background-image)","SVG illustrations (use inline SVG or Image component)"],"guidelines":["Always provide meaningful alt text for accessibility","Use appropriate aspect ratios for consistent layouts","Provide fallback content for failed loads","Use objectFit=\"contain\" for logos to preserve aspect ratio"],"accessibility":["Alt text is required and must describe the image content","Decorative images should have empty alt=\"\"","Avoid text in images; if necessary, describe the text in alt","Ensure sufficient contrast between image and surrounding content"]},"props":{"src":{"type":"string","description":"Image source URL","required":true},"alt":{"type":"string","description":"Alt text for accessibility (required)","required":true},"aspectRatio":{"type":"enum","description":"Aspect ratio of the image container","default":"auto","values":["1:1","4:3","16:9","21:9","auto"]},"objectFit":{"type":"enum","description":"How the image fits within its container","default":"cover","values":["cover","contain","fill","none"]},"width":{"type":"string | number","description":"Width of the image container"},"height":{"type":"string | number","description":"Height of the image container"},"rounded":{"type":"enum","description":"Border radius","default":"none","values":["none","sm","md","lg","full"]},"fallback":{"type":"node","description":"Content to show while loading or on error"}},"relations":[{"component":"Card","relationship":"child","note":"Common pattern to use Image at top of product cards"},{"component":"Avatar","relationship":"alternative","note":"Use Avatar for user profile pictures"}],"variants":[{"name":"Default","description":"Basic image display","code":"<Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=400&h=300&fit=crop\"\n alt=\"Code on a screen\"\n width={300}\n/>"},{"name":"Aspect Ratios","description":"Different aspect ratio options","code":"<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=200&h=200&fit=crop\"\n alt=\"Square image\"\n aspectRatio=\"1:1\"\n width={100}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=200&h=150&fit=crop\"\n alt=\"4:3 image\"\n aspectRatio=\"4:3\"\n width={120}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=320&h=180&fit=crop\"\n alt=\"16:9 image\"\n aspectRatio=\"16:9\"\n width={160}\n />\n</div>"},{"name":"Rounded Corners","description":"Border radius options","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"No rounding\"\n rounded=\"none\"\n width={80}\n height={80}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"Medium rounding\"\n rounded=\"md\"\n width={80}\n height={80}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"Full rounding\"\n rounded=\"full\"\n width={80}\n height={80}\n />\n</div>"},{"name":"With Fallback","description":"Fallback content for loading/error states","code":"<Image\n src=\"https://invalid-url.example/image.jpg\"\n alt=\"Image that will fail\"\n width={200}\n height={150}\n rounded=\"md\"\n fallback={\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', background: 'var(--fui-color-surface-secondary)' }}>\n <span style={{ color: 'var(--fui-color-text-tertiary)' }}>No image</span>\n </div>\n }\n/>"}]},"Input":{"filePath":"src/components/Input/Input.fragment.tsx","meta":{"name":"Input","description":"Text input field for single-line user data entry","category":"forms","status":"stable","tags":["form","input","text"]},"usage":{"when":["Collecting single-line text data from users","Email, password, phone number, or URL input","Search fields","Short form fields (name, title, etc.)"],"whenNot":["Multi-line text (use Textarea)","Selecting from predefined options (use Select)","Boolean input (use Checkbox or Switch)","Date/time input (use DatePicker)"],"guidelines":["Always provide a label for accessibility","Use appropriate input type for data validation","Show validation errors with error prop and helperText","Use placeholder for format hints, not labels"],"accessibility":["Labels must be associated with inputs","Error messages should be announced to screen readers","Required fields should be indicated"]},"props":{"value":{"type":"string","description":"Current input value (controlled)"},"placeholder":{"type":"string","description":"Placeholder text shown when empty","constraints":["Use for format hints only, not as a replacement for labels"]},"type":{"type":"enum","description":"HTML input type for validation and keyboard","default":"text","values":["text","email","password","number","tel","url"]},"disabled":{"type":"boolean","description":"Whether the input is interactive","default":false},"error":{"type":"boolean","description":"Whether to show error styling","default":false},"label":{"type":"string","description":"Label text displayed above input"},"helperText":{"type":"string","description":"Helper or error message below input"},"onChange":{"type":"function","description":"Called with new value on change"}},"relations":[{"component":"Textarea","relationship":"alternative","note":"Use Textarea for multi-line text input"},{"component":"Select","relationship":"alternative","note":"Use Select when choosing from predefined options"},{"component":"FormField","relationship":"parent","note":"Wrap in FormField for consistent form layout"}],"variants":[{"name":"Default","description":"Basic text input","code":"<Input label=\"Name\" placeholder=\"Enter your name\" />"},{"name":"With Value","description":"Input with pre-filled value","code":"<Input label=\"Email\" type=\"email\" value=\"user@example.com\" />"},{"name":"With Helper","description":"Input with helper text","code":"<Input\n label=\"Password\"\n type=\"password\"\n placeholder=\"Create a password\"\n helperText=\"Must be at least 8 characters\"\n/>"},{"name":"Error State","description":"Input showing validation error","code":"<Input\n label=\"Email\"\n type=\"email\"\n value=\"invalid-email\"\n error\n helperText=\"Please enter a valid email address\"\n/>"},{"name":"Disabled","description":"Non-interactive input","code":"<Input label=\"Username\" value=\"readonly-user\" disabled />"}]},"Link":{"filePath":"src/components/Link/Link.fragment.tsx","meta":{"name":"Link","description":"Styled anchor element for navigation. Supports internal and external links with consistent visual treatment.","category":"navigation","status":"stable","tags":["link","anchor","navigation","href","url"],"since":"0.1.0"},"usage":{"when":["Inline text links within paragraphs","Navigation links in footers or sidebars","\"Forgot password?\" or \"Sign up\" links in forms","External links to documentation or resources"],"whenNot":["Primary call-to-action (use Button instead)","Navigation tabs (use Tabs component)","Menu items in dropdowns (use Menu component)","Cards that link to detail pages (use Card with onClick)"],"guidelines":["Link text should describe the destination, not \"click here\"","Use external prop for links that open in new tabs","Use subtle variant for secondary/contextual links","Ensure links are distinguishable from regular text"],"accessibility":["Link text must be descriptive of the destination","External links should indicate they open in new window","Links must have visible focus indicators","Avoid using links that look like buttons without button semantics"]},"props":{"children":{"type":"node","description":"Link text content","required":true},"href":{"type":"string","description":"URL destination"},"variant":{"type":"enum","description":"Visual style variant","default":"default","values":["default","subtle","muted"]},"underline":{"type":"enum","description":"Underline behavior","default":"hover","values":["always","hover","none"]},"external":{"type":"boolean","description":"Opens in new tab with noopener noreferrer","default":"false"}},"relations":[{"component":"Button","relationship":"alternative","note":"Use Button for primary actions, Link for navigation"},{"component":"Text","relationship":"parent","note":"Links often appear within Text components"}],"variants":[{"name":"Default","description":"Standard link with hover underline","code":"<Link href=\"#\">Learn more about our services</Link>"},{"name":"Variants","description":"Visual style options","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Link href=\"#\" variant=\"default\">Default</Link>\n <Link href=\"#\" variant=\"subtle\">Subtle</Link>\n <Link href=\"#\" variant=\"muted\">Muted</Link>\n</div>"},{"name":"Underline Styles","description":"Different underline behaviors","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Link href=\"#\" underline=\"always\">Always underlined</Link>\n <Link href=\"#\" underline=\"hover\">Underline on hover</Link>\n <Link href=\"#\" underline=\"none\">No underline</Link>\n</div>"},{"name":"External Link","description":"Link that opens in new tab","code":"<Link href=\"https://example.com\" external>\n View documentation ↗\n</Link>"}]},"List":{"filePath":"src/components/List/List.fragment.tsx","meta":{"name":"List","description":"Compound component for rendering ordered or unordered lists with consistent styling. Supports bullet, numbered, and icon-prefixed items.","category":"display","status":"stable","tags":["list","items","bullet","ordered","unordered"],"since":"0.1.0"},"usage":{"when":["Feature lists with checkmarks or icons","Ordered steps or instructions","Navigation lists in sidebars","Pricing plan feature comparisons"],"whenNot":["Interactive selection lists (use Menu or Select)","Data tables with columns (use Table)","Cards in a grid (use Grid with Card)","Navigation tabs (use Tabs)"],"guidelines":["Use as=\"ol\" for sequential or numbered content","Use variant=\"icon\" with meaningful icons for feature lists","Keep list items concise and parallel in structure","Use consistent icons within a single list"],"accessibility":["Use semantic list elements (ul, ol) for screen reader support","List items are automatically announced with count","Icons are decorative; ensure text conveys meaning","Avoid deeply nested lists (3+ levels)"]},"props":{"children":{"type":"node","description":"List.Item components","required":true},"as":{"type":"enum","description":"List type","default":"ul","values":["ul","ol"]},"variant":{"type":"enum","description":"List style variant","default":"disc","values":["none","disc","decimal","icon"]},"gap":{"type":"enum","description":"Spacing between items","default":"sm","values":["none","xs","sm","md","lg"]}},"relations":[{"component":"Icon","relationship":"child","note":"Use Icon as List.Item icon prop"},{"component":"Stack","relationship":"alternative","note":"Use Stack for non-semantic vertical lists"}],"variants":[{"name":"Bullet List","description":"Default unordered list with bullets","code":"<List variant=\"disc\">\n <List.Item>First item</List.Item>\n <List.Item>Second item</List.Item>\n <List.Item>Third item</List.Item>\n</List>"},{"name":"Numbered List","description":"Ordered list with numbers","code":"<List as=\"ol\" variant=\"decimal\">\n <List.Item>Create your account</List.Item>\n <List.Item>Configure your settings</List.Item>\n <List.Item>Start building</List.Item>\n</List>"},{"name":"Icon List","description":"List with custom icons per item","code":"<List variant=\"icon\">\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Unlimited projects\n </List.Item>\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Priority support\n </List.Item>\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Advanced analytics\n </List.Item>\n</List>"},{"name":"No Style","description":"Plain list without markers","code":"<List variant=\"none\" gap=\"md\">\n <List.Item>Dashboard</List.Item>\n <List.Item>Settings</List.Item>\n <List.Item>Profile</List.Item>\n</List>"}]},"Listbox":{"filePath":"src/components/Listbox/Listbox.fragment.tsx","meta":{"name":"Listbox","description":"Controlled listbox for search results, autocomplete dropdowns, and command menus. Provides Menu-like styling without requiring a trigger.","category":"forms","status":"stable","tags":["listbox","search","autocomplete","combobox","command","dropdown"],"since":"0.3.0"},"usage":{"when":["Search result dropdowns","Autocomplete suggestions","Command palette results","Keyboard-navigable option lists"],"whenNot":["Static lists without selection (use List)","Action menus with trigger button (use Menu)","Form field selection (use Select)","Navigation menus (use Sidebar or Tabs)"],"guidelines":["Control open/close state externally based on input focus or query","Implement keyboard navigation (arrow keys, enter, escape) in parent","Use Listbox.Empty for no results state","Group related items with Listbox.Group when appropriate"],"accessibility":["Uses listbox and option ARIA roles","aria-selected indicates current selection","aria-disabled for non-interactive items","Connect to input with aria-controls for full combobox pattern"]},"props":{"children":{"type":"node","description":"Listbox.Item, Listbox.Group, or Listbox.Empty components","required":true},"className":{"type":"string","description":"Additional CSS class"},"style":{"type":"object","description":"Inline styles"}},"relations":[{"component":"Input","relationship":"sibling","note":"Pair with Input for search/autocomplete patterns"},{"component":"Menu","relationship":"alternative","note":"Use Menu when you need a trigger button"},{"component":"Select","relationship":"alternative","note":"Use Select for form field selection"},{"component":"List","relationship":"alternative","note":"Use List for static, non-interactive lists"}],"variants":[{"name":"Default","description":"Basic listbox with selectable items","code":"<Listbox aria-label=\"Options\">\n <Listbox.Item selected>First option</Listbox.Item>\n <Listbox.Item>Second option</Listbox.Item>\n <Listbox.Item>Third option</Listbox.Item>\n</Listbox>"},{"name":"Search Results","description":"Typical search results pattern with label and metadata","code":"<Listbox aria-label=\"Search results\">\n <Listbox.Item selected>\n <span style={{ fontWeight: 500 }}>Button</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Components</span>\n </Listbox.Item>\n <Listbox.Item>\n <span style={{ fontWeight: 500 }}>Badge</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Components</span>\n </Listbox.Item>\n <Listbox.Item>\n <span style={{ fontWeight: 500 }}>Box</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Layout</span>\n </Listbox.Item>\n</Listbox>"},{"name":"With Groups","description":"Grouped items with labels","code":"<Listbox aria-label=\"Commands\">\n <Listbox.Group label=\"Recent\">\n <Listbox.Item selected>Open file...</Listbox.Item>\n <Listbox.Item>Save as...</Listbox.Item>\n </Listbox.Group>\n <Listbox.Group label=\"Actions\">\n <Listbox.Item>Copy</Listbox.Item>\n <Listbox.Item>Paste</Listbox.Item>\n <Listbox.Item disabled>Cut</Listbox.Item>\n </Listbox.Group>\n</Listbox>"},{"name":"Empty State","description":"No results found message","code":"<Listbox aria-label=\"Search results\">\n <Listbox.Empty>No results found</Listbox.Empty>\n</Listbox>"},{"name":"With Disabled Items","description":"Mix of enabled and disabled items","code":"<Listbox aria-label=\"Options\">\n <Listbox.Item>Available option</Listbox.Item>\n <Listbox.Item disabled>Disabled option</Listbox.Item>\n <Listbox.Item>Another option</Listbox.Item>\n</Listbox>"}],"ai":{"compositionPattern":"compound","subComponents":["Item","Group","Empty"],"requiredChildren":["Item"],"commonPatterns":["<Listbox aria-label=\"Search results\">{results.map(item => <Listbox.Item key={item.id} selected={item.id === selectedId} onClick={() => onSelect(item)}>{item.label}</Listbox.Item>)}</Listbox>"]}},"Loading":{"filePath":"src/components/Loading/Loading.fragment.tsx","meta":{"name":"Loading","description":"Versatile loading indicator with multiple variants for showing progress or waiting states","category":"feedback","status":"stable","tags":["loading","spinner","progress","feedback","indicator","async"]},"usage":{"when":["Indicating content is being fetched or processed","Showing a pending state while waiting for an async operation","Displaying loading state for buttons, forms, or page sections","Full-screen loading during initial app/page load"],"whenNot":["For showing determinate progress - use Progress component instead","For showing skeleton placeholders - use Skeleton component instead","For AI-specific thinking states - use ThinkingIndicator instead"],"guidelines":["Use spinner variant for general loading states","Use dots variant for chat/messaging contexts","Use pulse variant for subtle, ambient loading","Always provide a meaningful label for screen readers","Consider using Loading.Screen for initial page loads","Use Loading.Inline when loading indicator should flow with text"],"accessibility":["Component uses role=\"status\" and aria-live=\"polite\"","Always provide descriptive label prop for screen readers","Animations respect prefers-reduced-motion preference"]},"props":{"size":{"type":"enum","description":"Size of the loading indicator","default":"md","values":["sm","md","lg","xl"]},"variant":{"type":"enum","description":"Visual style of the loading animation","default":"spinner","values":["spinner","dots","pulse"]},"label":{"type":"string","description":"Accessible label for screen readers","default":"Loading..."},"centered":{"type":"boolean","description":"Whether to center the loading indicator in its container","default":false},"fill":{"type":"boolean","description":"Whether to fill the parent container","default":false},"overlay":{"type":"boolean","description":"Whether to show with a backdrop overlay","default":false},"color":{"type":"enum","description":"Color variant - accent uses theme color, current inherits text color","default":"accent","values":["accent","current","muted"]}},"relations":[],"variants":[{"name":"Default","description":"Default spinner loading indicator","code":"<Loading />"},{"name":"Sizes","description":"Loading indicators in different sizes","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '24px' }}>\n <Loading size=\"sm\" />\n <Loading size=\"md\" />\n <Loading size=\"lg\" />\n <Loading size=\"xl\" />\n</div>"},{"name":"Dots","description":"Bouncing dots animation","code":"<Loading variant=\"dots\" />"},{"name":"Pulse","description":"Pulsing circle animation","code":"<Loading variant=\"pulse\" />"},{"name":"Colors","description":"Different color variants","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '24px' }}>\n <Loading color=\"accent\" />\n <Loading color=\"muted\" />\n <span style={{ color: '#3b82f6' }}>\n <Loading color=\"current\" />\n </span>\n</div>"},{"name":"Inline","description":"Inline loading indicator that flows with text","code":"<p style={{ margin: 0 }}>\n Processing your request <Loading.Inline /> please wait...\n</p>"},{"name":"Centered","description":"Centered in container","code":"<div style={{ width: '200px', height: '100px', border: '1px dashed #ccc', borderRadius: '8px' }}>\n <Loading centered fill />\n</div>"},{"name":"Screen","description":"Full-screen loading state with optional label","code":"<div style={{ position: 'relative', width: '300px', height: '200px', border: '1px solid #ccc', borderRadius: '8px', overflow: 'hidden' }}>\n <Loading.Screen size=\"lg\" label=\"Loading application...\" showLabel />\n</div>"}]},"Menu":{"filePath":"src/components/Menu/Menu.fragment.tsx","meta":{"name":"Menu","description":"Dropdown menu for actions and commands. Use for contextual actions, overflow menus, or grouped commands.","category":"feedback","status":"stable","tags":["menu","dropdown","actions","context-menu","commands"],"since":"0.1.0"},"usage":{"when":["Overflow actions that dont fit in the toolbar","Context menus (right-click)","User account menus","Grouped actions with separators"],"whenNot":["Selecting from options (use Select)","Navigation (use Tabs or navigation components)","Form selection (use Select or RadioGroup)"],"guidelines":["Group related actions with Menu.Group","Use separators to divide action categories","Include keyboard shortcuts where applicable","Use danger variant for destructive actions","Keep menu items under 10-12 for usability"],"accessibility":["Full keyboard navigation with arrow keys","Type-ahead search for items","Focus returns to trigger on close","Proper ARIA menu roles"]},"props":{"children":{"type":"node","description":"Menu trigger and content","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether menu is modal","default":"true"}},"relations":[{"component":"Select","relationship":"alternative","note":"Use Select for form field selection"},{"component":"Popover","relationship":"alternative","note":"Use Popover for rich non-action content"}],"variants":[{"name":"Default","description":"Basic dropdown menu","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Actions</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item onSelect={() => {}}>Edit</Menu.Item>\n <Menu.Item onSelect={() => {}}>Duplicate</Menu.Item>\n <Menu.Separator />\n <Menu.Item danger onSelect={() => {}}>Delete</Menu.Item>\n </Menu.Content>\n</Menu>"},{"name":"With Shortcuts","description":"Menu items with keyboard shortcuts","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Edit</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item shortcut=\"Ctrl+Z\" onSelect={() => {}}>Undo</Menu.Item>\n <Menu.Item shortcut=\"Ctrl+Y\" onSelect={() => {}}>Redo</Menu.Item>\n <Menu.Separator />\n <Menu.Item shortcut=\"Ctrl+C\" onSelect={() => {}}>Copy</Menu.Item>\n <Menu.Item shortcut=\"Ctrl+V\" onSelect={() => {}}>Paste</Menu.Item>\n </Menu.Content>\n</Menu>"},{"name":"With Groups","description":"Menu with labeled groups","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Options</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Group>\n <Menu.GroupLabel>View</Menu.GroupLabel>\n <Menu.Item onSelect={() => {}}>Zoom In</Menu.Item>\n <Menu.Item onSelect={() => {}}>Zoom Out</Menu.Item>\n </Menu.Group>\n <Menu.Separator />\n <Menu.Group>\n <Menu.GroupLabel>Layout</Menu.GroupLabel>\n <Menu.Item onSelect={() => {}}>Grid View</Menu.Item>\n <Menu.Item onSelect={() => {}}>List View</Menu.Item>\n </Menu.Group>\n </Menu.Content>\n</Menu>"},{"name":"With Checkboxes","description":"Menu with toggleable options","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Display</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.CheckboxItem defaultChecked>Show Grid</Menu.CheckboxItem>\n <Menu.CheckboxItem defaultChecked>Show Rulers</Menu.CheckboxItem>\n <Menu.CheckboxItem>Show Guides</Menu.CheckboxItem>\n </Menu.Content>\n</Menu>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Item","CheckboxItem","RadioGroup","RadioItem","Group","GroupLabel","Separator"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Menu><Menu.Trigger asChild><Button>Actions</Button></Menu.Trigger><Menu.Content><Menu.Item>{action1}</Menu.Item><Menu.Separator /><Menu.Item danger>{delete}</Menu.Item></Menu.Content></Menu>"]}},"Message":{"filePath":"src/components/Message/Message.fragment.tsx","meta":{"name":"Message","description":"Individual chat message display with role-based styling","category":"ai","status":"stable","tags":["message","chat","ai","conversation","bubble"]},"usage":{"when":["Displaying individual messages in a chat interface","Building AI assistant or chatbot UIs","Need role-based message styling (user vs assistant)","Messages need actions like copy, regenerate, or feedback"],"whenNot":["Simple text display without chat context (use Text)","Notification-style messages (use Alert or Toast)","Comment threads with nested replies (use Card with custom layout)"],"guidelines":["Always provide a role prop to determine styling","Use status prop to show message state (sending, streaming, error)","Consider showing timestamps for longer conversations","Provide hover actions for assistant messages (copy, regenerate)"],"accessibility":["Uses semantic HTML for message structure","Role-based styling has sufficient color contrast","Actions are keyboard accessible","Streaming indicator respects reduced motion preferences"]},"props":{"role":{"type":"\"user\" | \"assistant\" | \"system\"","description":"Message role determines styling and alignment","required":true},"children":{"type":"ReactNode","description":"Message content","required":true},"status":{"type":"\"sending\" | \"streaming\" | \"complete\" | \"error\"","description":"Message state","default":"\"complete\""},"timestamp":{"type":"Date","description":"When the message was sent"},"avatar":{"type":"ReactNode","description":"Custom avatar override (null to hide)"},"actions":{"type":"ReactNode","description":"Hover actions (copy, regenerate)"}},"relations":[{"component":"ConversationList","relationship":"parent","note":"Messages are typically used within ConversationList"},{"component":"Avatar","relationship":"child","note":"Use Avatar component for custom avatar content"},{"component":"ThinkingIndicator","relationship":"sibling","note":"Show ThinkingIndicator while awaiting assistant response"}],"variants":[{"name":"User Message","description":"Message from the user (right-aligned)","code":"<Message role=\"user\">\n <Message.Content>\n Hello! Can you help me with a coding question?\n </Message.Content>\n</Message>"},{"name":"Assistant Message","description":"Response from the AI assistant","code":"<Message role=\"assistant\">\n <Message.Content>\n Of course! I'd be happy to help. What would you like to know?\n </Message.Content>\n</Message>"},{"name":"System Message","description":"System notification or context","code":"<Message role=\"system\">\n <Message.Content>\n Conversation started. Model: GPT-4\n </Message.Content>\n</Message>"},{"name":"Streaming","description":"Message being streamed (with cursor)","code":"<Message role=\"assistant\" status=\"streaming\">\n <Message.Content>\n I'm currently generating a response for you\n </Message.Content>\n</Message>"},{"name":"With Timestamp","description":"Message with timestamp display","code":"<Message role=\"assistant\" timestamp={new Date(Date.now() - 300000)}>\n <Message.Content>\n This message was sent 5 minutes ago.\n </Message.Content>\n <Message.Timestamp />\n</Message>"},{"name":"Error State","description":"Message that failed to send","code":"<Message role=\"user\" status=\"error\">\n <Message.Content>\n This message failed to send.\n </Message.Content>\n</Message>"},{"name":"With Actions","description":"Message with hover actions","code":"<Message\n role=\"assistant\"\n actions={\n <>\n <button style={{ padding: '4px 8px', fontSize: '12px' }}>Copy</button>\n <button style={{ padding: '4px 8px', fontSize: '12px' }}>Regenerate</button>\n </>\n }\n>\n <Message.Content>\n Hover over this message to see the actions.\n </Message.Content>\n</Message>"}]},"Popover":{"filePath":"src/components/Popover/Popover.fragment.tsx","meta":{"name":"Popover","description":"Rich content overlay anchored to a trigger element. Use for forms, detailed information, or interactive content that should stay in context.","category":"feedback","status":"stable","tags":["popover","overlay","dropdown","floating","contextual"],"since":"0.1.0"},"usage":{"when":["Inline editing forms","Rich preview content","Filter panels","Date/color pickers","Content that needs more space than a tooltip"],"whenNot":["Simple hints (use Tooltip)","Action lists (use Menu)","Blocking user interaction (use Dialog)","System notifications (use Toast or Alert)"],"guidelines":["Keep popover content focused and minimal","Include a clear way to close (X button or action buttons)","Position to avoid covering important content","Use arrow to visually connect popover to trigger"],"accessibility":["Focus is moved to popover content on open","Closes on Escape key","Focus returns to trigger on close"]},"props":{"children":{"type":"node","description":"Popover trigger and content","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether to block page interaction","default":"false"}},"relations":[{"component":"Tooltip","relationship":"alternative","note":"Use Tooltip for brief, non-interactive hints"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action lists"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for blocking interactions"}],"variants":[{"name":"Default","description":"Basic popover with content","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Open Popover</Button>\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Close />\n <Popover.Title>Popover Title</Popover.Title>\n <Popover.Description>\n This is a popover with some content. It can contain text, forms, or other elements.\n </Popover.Description>\n </Popover.Content>\n</Popover>"},{"name":"With Form","description":"Popover containing a form","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Edit Name</Button>\n </Popover.Trigger>\n <Popover.Content size=\"sm\">\n <Popover.Close />\n <Popover.Title>Edit Name</Popover.Title>\n <Popover.Body>\n <Input label=\"Display Name\" placeholder=\"Enter name\" />\n </Popover.Body>\n <Popover.Footer>\n <Popover.Close asChild>\n <Button variant=\"secondary\" size=\"sm\">Cancel</Button>\n </Popover.Close>\n <Button variant=\"primary\" size=\"sm\">Save</Button>\n </Popover.Footer>\n </Popover.Content>\n</Popover>"},{"name":"With Arrow","description":"Popover with pointing arrow","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Info</Button>\n </Popover.Trigger>\n <Popover.Content arrow>\n <Popover.Title>Quick Tip</Popover.Title>\n <Popover.Description>\n This popover has an arrow pointing to its trigger element.\n </Popover.Description>\n </Popover.Content>\n</Popover>"},{"name":"Positions","description":"Popover on different sides","code":"<div style={{ display: 'flex', gap: '16px', padding: '60px' }}>\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Top</Button>\n </Popover.Trigger>\n <Popover.Content side=\"top\" size=\"sm\">\n <Popover.Description>Popover on top</Popover.Description>\n </Popover.Content>\n </Popover>\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Bottom</Button>\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" size=\"sm\">\n <Popover.Description>Popover on bottom</Popover.Description>\n </Popover.Content>\n </Popover>\n</div>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Close","Title","Description","Body","Footer"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Popover><Popover.Trigger asChild><Button>Open</Button></Popover.Trigger><Popover.Content><Popover.Close /><Popover.Title>{title}</Popover.Title><Popover.Description>{description}</Popover.Description></Popover.Content></Popover>"]}},"Progress":{"filePath":"src/components/Progress/Progress.fragment.tsx","meta":{"name":"Progress","description":"Visual indicator of task completion or loading state. Available in linear and circular variants.","category":"feedback","status":"stable","tags":["progress","loading","indicator","percentage","status"],"since":"0.1.0"},"usage":{"when":["Showing upload/download progress","Displaying task completion percentage","Form completion indicators","Loading states with known duration"],"whenNot":["Unknown loading duration (use Spinner)","Step-based progress (use Stepper)","Status without percentage (use Badge)"],"guidelines":["Use determinate progress when you know the completion percentage","Use indeterminate for unknown durations","Include a label for context when the purpose isnt obvious","Use appropriate color variants for success/warning/danger states"],"accessibility":["Uses role=\"progressbar\" with aria-valuenow","Label is associated with the progress bar","State changes are announced to screen readers"]},"props":{"value":{"type":"number","description":"Current progress value (0-100). Null for indeterminate."},"size":{"type":"enum","description":"Size of the progress bar","default":"md","values":["sm","md","lg"]},"variant":{"type":"enum","description":"Color variant","default":"default","values":["default","success","warning","danger"]},"label":{"type":"string","description":"Label text above the progress bar"},"showValue":{"type":"boolean","description":"Show percentage value","default":"false"}},"relations":[{"component":"Badge","relationship":"alternative","note":"Use Badge for status without percentage"},{"component":"Alert","relationship":"sibling","note":"Use Alert for completion messages"}],"variants":[{"name":"Default","description":"Basic progress bar with percentage","code":"<Progress value={60} label=\"Uploading...\" showValue />"},{"name":"Variants","description":"Different color variants for different states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <Progress value={75} variant=\"default\" label=\"Processing\" showValue />\n <Progress value={100} variant=\"success\" label=\"Complete\" showValue />\n <Progress value={80} variant=\"warning\" label=\"Almost full\" showValue />\n <Progress value={95} variant=\"danger\" label=\"Storage critical\" showValue />\n</div>"},{"name":"Sizes","description":"Different progress bar sizes","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <Progress value={50} size=\"sm\" label=\"Small\" />\n <Progress value={50} size=\"md\" label=\"Medium\" />\n <Progress value={50} size=\"lg\" label=\"Large\" />\n</div>"},{"name":"Indeterminate","description":"Loading state with unknown duration","code":"<Progress value={null} label=\"Loading...\" />"},{"name":"Circular","description":"Circular progress indicator","code":"<div style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>\n <CircularProgress value={25} size=\"sm\" />\n <CircularProgress value={50} size=\"md\" showValue />\n <CircularProgress value={75} size=\"lg\" showValue variant=\"success\" />\n <CircularProgress value={null} size=\"md\" />\n</div>"}]},"Prompt":{"filePath":"src/components/Prompt/Prompt.fragment.tsx","meta":{"name":"Prompt","description":"Multi-line input with toolbar for AI/chat interfaces","category":"ai","status":"stable","tags":["prompt","chat","ai","input","textarea","form"]},"usage":{"when":["Building chat or AI assistant interfaces","Need multi-line input with submit action","Require toolbar with actions like attachments or model selection"],"whenNot":["Simple single-line text input (use Input)","Basic multi-line without toolbar (use Textarea)","Search-only interface (use Input with search variant)"],"guidelines":["Always provide an onSubmit handler","Use loading state during API calls","Consider showing usage/token limits for AI contexts"],"accessibility":["Enter submits, Shift+Enter for newline","Submit button is keyboard accessible","Loading state prevents duplicate submissions"]},"props":{"value":{"type":"string","description":"Controlled input value"},"defaultValue":{"type":"string","description":"Uncontrolled default value"},"onChange":{"type":"function","description":"Called when value changes"},"onSubmit":{"type":"function","description":"Called on form submission"},"placeholder":{"type":"string","description":"Placeholder text for the textarea","default":"\"Ask, Search or Chat...\""},"disabled":{"type":"boolean","description":"Disable the entire prompt","default":"false"},"loading":{"type":"boolean","description":"Show loading state","default":"false"},"minRows":{"type":"number","description":"Minimum number of visible rows","default":"1"},"maxRows":{"type":"number","description":"Maximum number of visible rows","default":"8"},"autoResize":{"type":"boolean","description":"Enable auto-resize based on content","default":"true"},"submitOnEnter":{"type":"boolean","description":"Submit on Enter (Shift+Enter for newline)","default":"true"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for simple single-line text input"},{"component":"Textarea","relationship":"alternative","note":"Use Textarea for multi-line without toolbar"}],"variants":[{"name":"Basic","description":"Simple prompt with submit button","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions />\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"With Actions","description":"Prompt with attachment and mode buttons","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"With Usage","description":"Shows token usage indicator","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton active>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"Loading State","description":"During API submission","code":"<Prompt\n onSubmit={(value) => console.log(value)}\n loading\n defaultValue=\"Tell me about the weather...\"\n>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"Disabled","description":"Non-interactive prompt","code":"<Prompt onSubmit={(value) => console.log(value)} disabled>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"}]},"RadioGroup":{"filePath":"src/components/RadioGroup/RadioGroup.fragment.tsx","meta":{"name":"RadioGroup","description":"Single selection from a list of mutually exclusive options","category":"forms","status":"stable","tags":["form","radio","selection","options"]},"usage":{"when":["User must select exactly one option from a small set","Options are mutually exclusive","All options should be visible at once","2-5 options available"],"whenNot":["Multiple selections allowed (use Checkbox group)","Many options (use Select)","Binary on/off choice (use Toggle/Switch)","Options need to be searchable (use Combobox)"],"guidelines":["Always have one option pre-selected when possible","Order options logically (alphabetical, frequency, etc.)","Keep option labels concise","Use descriptions for complex options"],"accessibility":["Group must have an accessible label","Use arrow keys to navigate between options","Selected option should be clearly indicated"]},"props":{"value":{"type":"string","description":"Controlled selected value"},"defaultValue":{"type":"string","description":"Default value (uncontrolled)"},"onValueChange":{"type":"function","description":"Callback when selection changes"},"orientation":{"type":"enum","description":"Layout orientation","default":"vertical","values":["horizontal","vertical"]},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md","lg"]},"disabled":{"type":"boolean","description":"Disable all options","default":false},"label":{"type":"string","description":"Group label"},"error":{"type":"string","description":"Error message"}},"relations":[{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox for multiple selections"},{"component":"Select","relationship":"alternative","note":"Use Select for many options or limited space"},{"component":"Toggle","relationship":"alternative","note":"Use Toggle for binary on/off choices"}],"variants":[{"name":"Default","description":"Basic radio group with labels","code":"<RadioGroup defaultValue=\"option1\" label=\"Select an option\">\n <RadioGroup.Item value=\"option1\" label=\"Option 1\" />\n <RadioGroup.Item value=\"option2\" label=\"Option 2\" />\n <RadioGroup.Item value=\"option3\" label=\"Option 3\" />\n</RadioGroup>"},{"name":"With Descriptions","description":"Radio items with additional context","code":"<RadioGroup defaultValue=\"standard\" label=\"Shipping Method\">\n <RadioGroup.Item\n value=\"standard\"\n label=\"Standard\"\n description=\"5-7 business days\"\n />\n <RadioGroup.Item\n value=\"express\"\n label=\"Express\"\n description=\"2-3 business days\"\n />\n <RadioGroup.Item\n value=\"overnight\"\n label=\"Overnight\"\n description=\"Next business day\"\n />\n</RadioGroup>"},{"name":"Horizontal","description":"Side-by-side layout","code":"<RadioGroup orientation=\"horizontal\" defaultValue=\"small\" label=\"Size\">\n <RadioGroup.Item value=\"small\" label=\"S\" />\n <RadioGroup.Item value=\"medium\" label=\"M\" />\n <RadioGroup.Item value=\"large\" label=\"L\" />\n <RadioGroup.Item value=\"xlarge\" label=\"XL\" />\n</RadioGroup>"},{"name":"With Error","description":"Validation error state","code":"<RadioGroup label=\"Required selection\" error=\"Please select an option\">\n <RadioGroup.Item value=\"a\" label=\"Option A\" />\n <RadioGroup.Item value=\"b\" label=\"Option B\" />\n</RadioGroup>"},{"name":"Disabled","description":"Non-interactive state","code":"<RadioGroup disabled defaultValue=\"locked\" label=\"Locked selection\">\n <RadioGroup.Item value=\"locked\" label=\"This is locked\" />\n <RadioGroup.Item value=\"other\" label=\"Cannot select\" />\n</RadioGroup>"}]},"Select":{"filePath":"src/components/Select/Select.fragment.tsx","meta":{"name":"Select","description":"Dropdown for choosing from a list of options. Use when there are more than 4-5 choices that would clutter the UI.","category":"forms","status":"stable","tags":["select","dropdown","form","options","picker"],"since":"0.1.0"},"usage":{"when":["Choosing from a predefined list of options","More than 4-5 options that would clutter UI as radio buttons","Space-constrained forms","When users need to see all options at once"],"whenNot":["Very few options (2-3) - use radio buttons","Users might type custom values - use Combobox","Multiple selections needed - use Checkbox group or MultiSelect","Actions, not selection - use Menu"],"guidelines":["Include a placeholder that explains what to select","Group related options with SelectGroup","Keep option text concise","Order options logically (alphabetical, by frequency, or by category)"],"accessibility":["Full keyboard navigation support","Type-ahead search within options","Proper ARIA roles and attributes"]},"props":{"children":{"type":"node","description":"Select trigger and content","required":true},"value":{"type":"string","description":"Controlled selected value"},"defaultValue":{"type":"string","description":"Default selected value (uncontrolled)"},"onValueChange":{"type":"function","description":"Called when selection changes"},"placeholder":{"type":"string","description":"Placeholder text when no value selected"},"disabled":{"type":"boolean","description":"Disable the select","default":"false"}},"relations":[{"component":"Menu","relationship":"alternative","note":"Use Menu for action-based dropdowns"},{"component":"Input","relationship":"sibling","note":"Use Input for free-form text entry"},{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox group for multiple selections"}],"variants":[{"name":"Default","description":"Basic select dropdown","code":"<StatefulSelect placeholder=\"Select a fruit\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"apple\">Apple</Select.Item>\n <Select.Item value=\"banana\">Banana</Select.Item>\n <Select.Item value=\"orange\">Orange</Select.Item>\n <Select.Item value=\"grape\">Grape</Select.Item>\n </Select.Content>\n</StatefulSelect>"},{"name":"With Groups","description":"Options organized into groups","code":"<StatefulSelect placeholder=\"Select a country\">\n <Select.Trigger />\n <Select.Content>\n <Select.Group>\n <Select.GroupLabel>North America</Select.GroupLabel>\n <Select.Item value=\"us\">United States</Select.Item>\n <Select.Item value=\"ca\">Canada</Select.Item>\n <Select.Item value=\"mx\">Mexico</Select.Item>\n </Select.Group>\n <Select.Group>\n <Select.GroupLabel>Europe</Select.GroupLabel>\n <Select.Item value=\"uk\">United Kingdom</Select.Item>\n <Select.Item value=\"de\">Germany</Select.Item>\n <Select.Item value=\"fr\">France</Select.Item>\n </Select.Group>\n </Select.Content>\n</StatefulSelect>"},{"name":"With Disabled Options","description":"Some options are disabled","code":"<StatefulSelect placeholder=\"Select a plan\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"free\">Free</Select.Item>\n <Select.Item value=\"pro\">Pro</Select.Item>\n <Select.Item value=\"enterprise\" disabled>Enterprise (Contact Sales)</Select.Item>\n </Select.Content>\n</StatefulSelect>"},{"name":"Disabled","description":"Disabled select","code":"<Select disabled placeholder=\"Select an option\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"1\">Option 1</Select.Item>\n </Select.Content>\n</Select>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Item","Group","GroupLabel"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Select placeholder=\"Select option\"><Select.Trigger /><Select.Content><Select.Item value=\"opt1\">{label1}</Select.Item><Select.Item value=\"opt2\">{label2}</Select.Item></Select.Content></Select>"]}},"Separator":{"filePath":"src/components/Separator/Separator.fragment.tsx","meta":{"name":"Separator","description":"Visual divider between content sections. Use to create clear visual boundaries and improve content organization.","category":"layout","status":"stable","tags":["separator","divider","hr","line","layout"],"since":"0.1.0"},"usage":{"when":["Dividing content sections","Separating groups of related items","Creating visual breathing room","Labeled section breaks"],"whenNot":["Creating grid layouts (use CSS Grid)","Decorative borders (use CSS)","Spacing alone is sufficient"],"guidelines":["Use sparingly - too many separators create visual noise","Consider if spacing alone would work","Use soft variant for subtle separation","Labeled separators work well for major section breaks"],"accessibility":["Uses role=\"separator\" for semantic meaning","Decorative separators should be aria-hidden"]},"props":{"orientation":{"type":"enum","description":"Direction of the separator","default":"horizontal","values":["horizontal","vertical"]},"spacing":{"type":"enum","description":"Margin around the separator","default":"none","values":["none","sm","md","lg"]},"soft":{"type":"boolean","description":"Softer, lighter appearance","default":"false"},"label":{"type":"string","description":"Optional text label (horizontal only)"}},"relations":[{"component":"Card","relationship":"sibling","note":"Cards provide stronger visual grouping"}],"variants":[{"name":"Default","description":"Basic horizontal separator","code":"<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator spacing=\"md\" />\n <p>Content below</p>\n</div>"},{"name":"With Label","description":"Labeled section divider","code":"<div style={{ width: '300px' }}>\n <p>First section</p>\n <Separator label=\"Or\" spacing=\"md\" />\n <p>Second section</p>\n</div>"},{"name":"Soft","description":"Subtle separator","code":"<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator soft spacing=\"md\" />\n <p>Content below</p>\n</div>"},{"name":"Vertical","description":"Vertical separator between elements","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '16px', height: '40px' }}>\n <span>Item 1</span>\n <Separator orientation=\"vertical\" />\n <span>Item 2</span>\n <Separator orientation=\"vertical\" />\n <span>Item 3</span>\n</div>"},{"name":"Spacing Options","description":"Different spacing sizes","code":"<div style={{ width: '300px' }}>\n <p>No spacing</p>\n <Separator spacing=\"none\" />\n <p>Small spacing</p>\n <Separator spacing=\"sm\" />\n <p>Medium spacing</p>\n <Separator spacing=\"md\" />\n <p>Large spacing</p>\n <Separator spacing=\"lg\" />\n <p>End</p>\n</div>"}]},"Sidebar":{"filePath":"src/components/Sidebar/Sidebar.fragment.tsx","meta":{"name":"Sidebar","description":"Responsive navigation sidebar with collapsible desktop mode and mobile drawer behavior.","category":"navigation","status":"stable","tags":["sidebar","navigation","drawer","menu","layout"],"since":"0.3.0"},"usage":{"when":["Primary app navigation with multiple sections","Dashboard layouts requiring persistent navigation","Admin interfaces with hierarchical menu structure","Apps that need both mobile drawer and desktop sidebar"],"whenNot":["Simple websites with few pages (use header nav)","Content-focused sites where navigation is secondary","Single-page applications with no navigation needs","Mobile-only apps where bottom navigation is preferred"],"guidelines":["Group related items into sections with clear labels","Use icons for all items to support collapsed mode","Limit nesting to 2 levels maximum","Place most frequently used items at the top","Use badges sparingly for notifications or counts","The `active` prop on items should be controlled by your app based on current route","Use `collapsedContent` on Header to show just a logo icon when collapsed","Submenus are hidden when collapsed - use tooltips for navigation hints instead","Use SidebarProvider to enable external triggers and keyboard shortcuts","Use asChild with routing libraries (Next.js Link, React Router NavLink)","Use Sidebar.MenuSkeleton while loading navigation data"],"accessibility":["Uses semantic <nav> element with aria-label","aria-current=\"page\" on active items","aria-expanded on items with submenus","Escape key closes mobile drawer","Cmd/Ctrl+B keyboard shortcut toggles sidebar (when using SidebarProvider)","Focus trap in mobile drawer mode","Minimum 44px touch targets"]},"props":{"children":{"type":"node","description":"Sidebar content (use Sidebar.Header, Sidebar.Nav, Sidebar.Section, etc.)","required":true},"collapsed":{"type":"boolean","description":"Icon-only mode for desktop (controlled)"},"defaultCollapsed":{"type":"boolean","description":"Initial collapsed state (uncontrolled)","default":false},"onCollapsedChange":{"type":"function","description":"Called when collapsed state changes"},"open":{"type":"boolean","description":"Mobile drawer open state (controlled)"},"defaultOpen":{"type":"boolean","description":"Initial open state (uncontrolled)","default":false},"onOpenChange":{"type":"function","description":"Called when open state changes"},"width":{"type":"string","description":"Width of expanded sidebar","default":"240px"},"collapsedWidth":{"type":"string","description":"Width when collapsed","default":"64px"},"position":{"type":"enum","description":"Sidebar position","default":"left","values":["left","right"]},"collapsible":{"type":"enum","description":"Collapse behavior mode","default":"icon","values":["icon","offcanvas","none"]},"asChild":{"type":"boolean","description":"(Sidebar.Item) Render as child element for polymorphic composition","default":false}},"relations":[{"component":"Tabs","relationship":"alternative","note":"Use Tabs for in-page section navigation"},{"component":"Menu","relationship":"composition","note":"Use Menu for contextual actions within sidebar"}],"variants":[{"name":"Default","description":"Standard sidebar with navigation sections. The `active` prop highlights the current page.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />}>Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n <Sidebar.Section label=\"Settings\">\n <Sidebar.Item icon={<GearIcon />}>Preferences</Sidebar.Item>\n <Sidebar.Item icon={<HelpIcon />}>Help</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Dashboard content goes here\n </main>\n</div>"},{"name":"Collapsed","description":"Icon-only collapsed state. Header shows only logo, tooltips appear on hover.","code":"<CollapsedDemo />"},{"name":"With Badges","description":"Navigation items with notification badges for counts or alerts.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} badge=\"3\">Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} badge=\"12\">Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Badges indicate unread items or notifications\n </main>\n</div>"},{"name":"With Submenu","description":"Nested navigation with expandable sections. Use defaultExpanded for initial state without manual state tracking.","code":"<SubmenuDemo />"},{"name":"With Disabled Items","description":"Some navigation items are disabled for permissions or feature flags.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} disabled>Team (Coming Soon)</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />} disabled>Projects (Upgrade)</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Disabled items cannot be clicked\n </main>\n</div>"},{"name":"With Provider & External Trigger","description":"SidebarProvider enables external triggers and keyboard shortcuts (Cmd/Ctrl+B).","code":"<ProviderDemo />"},{"name":"With asChild (Polymorphic)","description":"Use asChild to render items as custom elements like Next.js Link or React Router NavLink.","code":"<AsChildDemo />"},{"name":"With Section Action","description":"Section headers can include action buttons for quick actions like \"Add Project\".","code":"<SectionActionDemo />"},{"name":"With Loading Skeleton","description":"Show skeleton placeholders while navigation data is loading.","code":"<SkeletonDemo />"},{"name":"With Rail Toggle","description":"Add a Rail component for a subtle drag-handle style toggle at the sidebar edge. Hover to reveal, click to toggle.","code":"<RailDemo />"}],"ai":{"compositionPattern":"compound","subComponents":["Header","Nav","Section","Item","SubItem","Submenu","Footer","CollapseToggle","Rail","MenuSkeleton","SectionAction"],"requiredChildren":["Nav"],"commonPatterns":["<Sidebar><Sidebar.Header>{logo}</Sidebar.Header><Sidebar.Nav><Sidebar.Section><Sidebar.Item icon={icon} active>{label}</Sidebar.Item></Sidebar.Section></Sidebar.Nav><Sidebar.Footer><Sidebar.CollapseToggle /></Sidebar.Footer></Sidebar>"]}},"Skeleton":{"filePath":"src/components/Skeleton/Skeleton.fragment.tsx","meta":{"name":"Skeleton","description":"Placeholder loading state for content","category":"feedback","status":"stable","tags":["loading","placeholder","skeleton","shimmer"]},"usage":{"when":["Content is loading asynchronously","Preventing layout shift during data fetching","Providing visual feedback that content is coming","Improving perceived performance"],"whenNot":["Short loading times (< 300ms)","When spinner is more appropriate","Background operations without visible impact"],"guidelines":["Match skeleton shape to expected content","Use semantic variants (text, heading, avatar) for consistency","Maintain similar dimensions to loaded content","Avoid too many skeleton elements - simplify complex layouts"],"accessibility":["Skeletons are decorative - use aria-hidden","Announce loading state separately if needed","Ensure sufficient contrast for the animation"]},"props":{"variant":{"type":"enum","description":"Semantic variant that auto-sizes","default":"rect","values":["text","heading","avatar","button","input","rect"]},"size":{"type":"enum","description":"Size for avatar/button variants","default":"md","values":["sm","md","lg"]},"width":{"type":"union","description":"Custom width (string or number)"},"height":{"type":"union","description":"Custom height (string or number)"},"fill":{"type":"boolean","description":"Fill parent container","default":false},"radius":{"type":"enum","description":"Border radius override","values":["none","sm","md","lg","full"]}},"relations":[{"component":"Progress","relationship":"alternative","note":"Use Progress for determinate loading"}],"variants":[{"name":"Default","description":"Basic rectangle skeleton","code":"<Skeleton width={200} height={20} />"},{"name":"Text Lines","description":"Multi-line text placeholder","code":"<Skeleton.Text lines={3} />"},{"name":"Semantic Variants","description":"Pre-configured shapes for common elements","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width={200} />\n <Skeleton variant=\"text\" width=\"100%\" />\n <Skeleton variant=\"text\" width=\"80%\" />\n</div>"},{"name":"Avatar Skeleton","description":"Circular placeholder for avatars","code":"<div style={{ display: 'flex', gap: 'var(--fui-space-1)', alignItems: 'center' }}>\n <Skeleton.Circle size=\"sm\" />\n <Skeleton.Circle size=\"md\" />\n <Skeleton.Circle size=\"lg\" />\n</div>"},{"name":"Card Skeleton","description":"Composed skeleton for a card layout","code":"<div style={{ width: 300, padding: 'var(--fui-space-2)', border: '1px solid var(--fui-border)', borderRadius: 'var(--fui-radius-lg)' }}>\n <Skeleton variant=\"rect\" height={120} radius=\"md\" />\n <div style={{ marginTop: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width=\"60%\" />\n </div>\n <div style={{ marginTop: 'var(--fui-space-1)' }}>\n <Skeleton.Text lines={2} />\n </div>\n</div>"}]},"Slider":{"filePath":"src/components/Slider/Slider.fragment.tsx","meta":{"name":"Slider","description":"Range input control for selecting a numeric value within a defined range. Supports labels, value display, and custom step intervals.","category":"forms","status":"stable","tags":["slider","range","input","number","control"],"since":"0.2.0"},"usage":{"when":["Selecting a value from a continuous range","Volume or brightness controls","Price range filters","Settings that benefit from visual feedback"],"whenNot":["Precise numeric input (use Input type=\"number\")","Discrete options (use RadioGroup or Select)","Yes/no choices (use Toggle)"],"guidelines":["Always provide a label describing what the slider controls","Show the current value when precision matters","Use appropriate min/max values for the context","Consider step size for usability"],"accessibility":["Label is associated with the slider","Keyboard accessible with arrow keys","Current value is announced to screen readers","Uses native slider semantics"]},"props":{"value":{"type":"number","description":"Controlled value"},"defaultValue":{"type":"number","description":"Default value for uncontrolled usage"},"onChange":{"type":"function","description":"Called with new value when changed"},"min":{"type":"number","description":"Minimum value","default":"0"},"max":{"type":"number","description":"Maximum value","default":"100"},"step":{"type":"number","description":"Step interval","default":"1"},"label":{"type":"string","description":"Label text"},"showValue":{"type":"boolean","description":"Display current value","default":"false"},"valueSuffix":{"type":"string","description":"Suffix after value (e.g., \"%\", \"px\")"},"disabled":{"type":"boolean","description":"Disable the slider","default":"false"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for precise numeric entry"},{"component":"Progress","relationship":"sibling","note":"Similar visual, but Progress is read-only"}],"variants":[{"name":"Default","description":"Basic slider with label","code":"<div style={{ width: '300px' }}>\n <Slider label=\"Volume\" defaultValue={50} />\n</div>"},{"name":"With Value Display","description":"Shows current value alongside the slider","code":"<div style={{ width: '300px' }}>\n <Slider\n label=\"Brightness\"\n defaultValue={75}\n showValue\n valueSuffix=\"%\"\n />\n</div>"},{"name":"Custom Range","description":"Custom min, max, and step values","code":"<div style={{ width: '300px', display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <Slider\n label=\"Temperature\"\n min={60}\n max={80}\n step={1}\n defaultValue={72}\n showValue\n valueSuffix=\"°F\"\n />\n <Slider\n label=\"Font Size\"\n min={12}\n max={32}\n step={2}\n defaultValue={16}\n showValue\n valueSuffix=\"px\"\n />\n</div>"},{"name":"Controlled","description":"Controlled slider with external state","code":"{\n const [value, setValue] = React.useState(50);\n return (\n <div style={{ width: '300px', display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Slider\n label=\"Opacity\"\n value={value}\n onChange={setValue}\n showValue\n valueSuffix=\"%\"\n />\n <div style={{ fontSize: '14px', color: 'var(--fui-text-secondary)' }}>\n Current value: {value}%\n </div>\n </div>\n );\n}"},{"name":"Disabled","description":"Disabled slider","code":"<div style={{ width: '300px' }}>\n <Slider\n label=\"Locked Setting\"\n defaultValue={30}\n showValue\n disabled\n />\n</div>"}]},"Stack":{"filePath":"src/components/Stack/Stack.fragment.tsx","meta":{"name":"Stack","description":"Flexible layout component for arranging children in rows or columns with consistent spacing. Supports responsive direction and gap.","category":"layout","status":"stable","tags":["stack","layout","flex","spacing","responsive"],"since":"0.2.0"},"usage":{"when":["Arranging elements in a row or column","Creating consistent spacing between items","Building responsive layouts","Simple flexbox-based arrangements"],"whenNot":["Complex grid layouts (use Grid)","Button-specific grouping (use ButtonGroup)","Page-level layout (use AppShell)"],"guidelines":["Use semantic elements via the \"as\" prop when appropriate","Leverage responsive props for mobile-first layouts","Keep spacing consistent within related sections","Consider alignment for visual balance"],"accessibility":["Use semantic elements (nav, section, etc.) via \"as\" prop","Maintains source order for screen readers","No accessibility concerns with visual arrangement"]},"props":{"children":{"type":"node","description":"Elements to arrange","required":true},"direction":{"type":"string | object","description":"Stack direction: \"row\", \"column\", or responsive object","default":"column"},"gap":{"type":"string | object","description":"Spacing between items: \"none\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\", or responsive object","default":"md"},"align":{"type":"enum","description":"Cross-axis alignment","values":["start","center","end","stretch","baseline"]},"justify":{"type":"enum","description":"Main-axis alignment","values":["start","center","end","between"]},"wrap":{"type":"boolean","description":"Allow items to wrap","default":"false"},"as":{"type":"enum","description":"HTML element to render","default":"div","values":["div","section","nav","article","aside","header","footer","main","ul","ol"]}},"relations":[{"component":"Grid","relationship":"alternative","note":"Use Grid for complex 2D layouts"},{"component":"ButtonGroup","relationship":"sibling","note":"ButtonGroup is specialized for buttons"},{"component":"Box","relationship":"sibling","note":"Box for single-element styling"}],"variants":[{"name":"Vertical Stack","description":"Default column layout","code":"<Stack gap=\"sm\">\n <Badge>Item 1</Badge>\n <Badge>Item 2</Badge>\n <Badge>Item 3</Badge>\n</Stack>"},{"name":"Horizontal Stack","description":"Row layout","code":"<Stack direction=\"row\" gap=\"sm\">\n <Badge>Item 1</Badge>\n <Badge>Item 2</Badge>\n <Badge>Item 3</Badge>\n</Stack>"},{"name":"Gap Sizes","description":"Different spacing options","code":"<Stack gap=\"lg\">\n <Stack direction=\"row\" gap=\"xs\">\n <Badge variant=\"info\">XS</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"sm\">\n <Badge variant=\"info\">SM</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"md\">\n <Badge variant=\"info\">MD</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"lg\">\n <Badge variant=\"info\">LG</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n</Stack>"},{"name":"Alignment","description":"Cross-axis and main-axis alignment","code":"<Stack gap=\"md\">\n <Stack direction=\"row\" gap=\"sm\" justify=\"between\" style={{ width: '200px', padding: '8px', background: 'var(--fui-bg-secondary)', borderRadius: '4px' }}>\n <Badge>Start</Badge>\n <Badge>End</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"sm\" justify=\"center\" style={{ width: '200px', padding: '8px', background: 'var(--fui-bg-secondary)', borderRadius: '4px' }}>\n <Badge>Centered</Badge>\n </Stack>\n</Stack>"},{"name":"Responsive","description":"Direction changes at breakpoints","code":"<Stack\n direction={{ base: 'column', md: 'row' }}\n gap={{ base: 'sm', md: 'lg' }}\n>\n <Button variant=\"secondary\">First</Button>\n <Button variant=\"secondary\">Second</Button>\n <Button variant=\"secondary\">Third</Button>\n</Stack>"},{"name":"Semantic Element","description":"Using nav element for navigation","code":"<Stack as=\"nav\" direction=\"row\" gap=\"md\">\n <Button variant=\"ghost\" size=\"sm\">Home</Button>\n <Button variant=\"ghost\" size=\"sm\">About</Button>\n <Button variant=\"ghost\" size=\"sm\">Contact</Button>\n</Stack>"}]},"Table":{"filePath":"src/components/Table/Table.fragment.tsx","meta":{"name":"Table","description":"Data table with sorting and row selection. Use for displaying structured data that needs to be scanned, compared, or acted upon.","category":"display","status":"stable","tags":["table","data","grid","list","sorting"],"since":"0.1.0"},"usage":{"when":["Displaying structured, tabular data","Data that users need to scan and compare","Lists with multiple attributes per item","Data that needs sorting or selection"],"whenNot":["Simple lists (use List component)","Card-based layouts (use CardGrid)","Heavily interactive data (consider DataGrid)","Small screens (consider card or list view)"],"guidelines":["Keep columns to a reasonable number (5-7 max)","Use consistent alignment (numbers right, text left)","Provide meaningful empty states","Consider mobile responsiveness"],"accessibility":["Proper table semantics with headers","Sortable columns are keyboard accessible","Row selection is properly announced"]},"props":{"columns":{"type":"array","description":"Column definitions","required":true},"data":{"type":"array","description":"Data rows to display","required":true},"sortable":{"type":"boolean","description":"Enable column sorting","default":"false"},"selectable":{"type":"boolean","description":"Enable row selection","default":"false"},"onRowClick":{"type":"function","description":"Handler for row clicks"},"emptyMessage":{"type":"string","description":"Message when no data","default":"No data available"},"size":{"type":"enum","description":"Table density","default":"md","values":["sm","md"]}},"relations":[{"component":"EmptyState","relationship":"sibling","note":"Use EmptyState for empty table states"},{"component":"Badge","relationship":"sibling","note":"Use Badge for status columns"}],"variants":[{"name":"Default","description":"Basic data table","code":"<Table\n columns={columns}\n data={sampleUsers}\n/>"},{"name":"Sortable","description":"Table with sortable columns","code":"<Table\n columns={columns}\n data={sampleUsers}\n sortable\n/>"},{"name":"Clickable Rows","description":"Table with clickable rows","code":"<Table\n columns={columns}\n data={sampleUsers}\n onRowClick={(row) => alert(`Clicked: ${row.name}`)}\n/>"},{"name":"Compact","description":"Smaller, denser table","code":"<Table\n columns={columns}\n data={sampleUsers}\n size=\"sm\"\n/>"},{"name":"Empty State","description":"Table with no data","code":"<Table\n columns={columns}\n data={[]}\n emptyMessage=\"No users found\"\n/>"}],"ai":{"compositionPattern":"simple","commonPatterns":["<Table columns={[{header:\"Name\",accessorKey:\"name\"},{header:\"Status\",accessorKey:\"status\"}]} data={[{name:\"Item 1\",status:\"Active\"}]} />"]}},"Tabs":{"filePath":"src/components/Tabs/Tabs.fragment.tsx","meta":{"name":"Tabs","description":"Organize content into switchable panels. Use for related content that benefits from a compact, navigable layout.","category":"navigation","status":"stable","tags":["tabs","navigation","panels","content-switcher"],"since":"0.1.0"},"usage":{"when":["Organizing related content into sections","Reducing page scrolling by grouping content","Settings pages with multiple categories","Dashboard views with different data perspectives"],"whenNot":["Primary navigation (use sidebar or header nav)","Sequential steps (use Stepper or wizard)","Comparing content side-by-side","Very long lists of options (use Select or Menu)"],"guidelines":["Keep tab labels short (1-2 words)","Order tabs by usage frequency or logical sequence","Avoid more than 5-6 tabs; consider sub-navigation for more","Tab content should be roughly equivalent in scope","Use pills variant for contained sections, underline for page-level tabs"],"accessibility":["Keyboard navigation with arrow keys","Tab panels are properly labeled","Focus management follows WAI-ARIA tabs pattern"]},"props":{"children":{"type":"node","description":"Tab list and panels (use Tabs.List, Tabs.Tab, Tabs.Panel)","required":true},"defaultValue":{"type":"string","description":"Initially active tab (uncontrolled)"},"value":{"type":"string","description":"Controlled active tab value"},"onValueChange":{"type":"function","description":"Called when active tab changes"},"orientation":{"type":"enum","description":"Tab list orientation","default":"horizontal","values":["horizontal","vertical"]}},"relations":[{"component":"Select","relationship":"alternative","note":"Use Select for many options in compact space"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action-based navigation"}],"variants":[{"name":"Underline","description":"Default underline style tabs","code":"<Tabs defaultValue=\"overview\">\n <Tabs.List variant=\"underline\">\n <Tabs.Tab value=\"overview\">Overview</Tabs.Tab>\n <Tabs.Tab value=\"analytics\">Analytics</Tabs.Tab>\n <Tabs.Tab value=\"settings\">Settings</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"overview\">\n <p>Overview content goes here.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"analytics\">\n <p>Analytics content goes here.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"settings\">\n <p>Settings content goes here.</p>\n </Tabs.Panel>\n</Tabs>"},{"name":"Pills","description":"Pill-style tabs for contained sections","code":"<Tabs defaultValue=\"all\">\n <Tabs.List variant=\"pills\">\n <Tabs.Tab value=\"all\">All</Tabs.Tab>\n <Tabs.Tab value=\"active\">Active</Tabs.Tab>\n <Tabs.Tab value=\"archived\">Archived</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"all\">\n <p>Showing all items.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"active\">\n <p>Showing active items only.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"archived\">\n <p>Showing archived items.</p>\n </Tabs.Panel>\n</Tabs>"},{"name":"With Disabled","description":"Tabs with a disabled option","code":"<Tabs defaultValue=\"general\">\n <Tabs.List variant=\"underline\">\n <Tabs.Tab value=\"general\">General</Tabs.Tab>\n <Tabs.Tab value=\"security\">Security</Tabs.Tab>\n <Tabs.Tab value=\"billing\" disabled>Billing</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"general\">\n <p>General settings panel.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"security\">\n <p>Security settings panel.</p>\n </Tabs.Panel>\n</Tabs>"}],"ai":{"compositionPattern":"compound","subComponents":["List","Tab","Panel"],"requiredChildren":["List","Panel"],"commonPatterns":["<Tabs defaultValue=\"tab1\"><Tabs.List><Tabs.Tab value=\"tab1\">{label1}</Tabs.Tab><Tabs.Tab value=\"tab2\">{label2}</Tabs.Tab></Tabs.List><Tabs.Panel value=\"tab1\">{content1}</Tabs.Panel><Tabs.Panel value=\"tab2\">{content2}</Tabs.Panel></Tabs>"]}},"Text":{"filePath":"src/components/Text/Text.fragment.tsx","meta":{"name":"Text","description":"Typography component for rendering text with consistent styling. Supports various sizes, weights, colors, and semantic elements.","category":"display","status":"stable","tags":["text","typography","heading","paragraph","font"],"since":"0.2.0"},"usage":{"when":["Displaying text with specific typography styles","Creating headings, paragraphs, or labels","Text that needs truncation or line clamping","Consistent typography across the application"],"whenNot":["Complex rich text (use a rich text editor)","Code display (use CodeBlock)","Interactive text (use Link or Button)"],"guidelines":["Use semantic elements (h1-h6, p) via the \"as\" prop","Maintain heading hierarchy for accessibility","Use color variants sparingly for visual hierarchy","Consider truncation for user-generated content"],"accessibility":["Use proper heading levels (h1-h6) for document structure","Semantic elements convey meaning to screen readers","Truncated text should have full content in title/tooltip"]},"props":{"children":{"type":"node","description":"Text content","required":true},"as":{"type":"enum","description":"HTML element to render","default":"span","values":["h1","h2","h3","h4","h5","h6","p","span","label","div","strong","em","small","code"]},"size":{"type":"enum","description":"Font size","values":["2xs","xs","sm","base","lg","xl","2xl"]},"weight":{"type":"enum","description":"Font weight","values":["normal","medium","semibold"]},"color":{"type":"enum","description":"Text color","values":["primary","secondary","tertiary"]},"font":{"type":"enum","description":"Font family","default":"sans","values":["sans","mono"]},"truncate":{"type":"boolean","description":"Truncate with ellipsis on overflow"},"lineClamp":{"type":"number","description":"Number of lines before truncating (requires truncate)"}},"relations":[{"component":"Link","relationship":"sibling","note":"Use Link for clickable text"},{"component":"CodeBlock","relationship":"alternative","note":"Use CodeBlock for code display"},{"component":"Badge","relationship":"sibling","note":"Use Badge for labels/tags"}],"variants":[{"name":"Sizes","description":"Different text sizes","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text size=\"2xs\">Extra extra small (2xs)</Text>\n <Text size=\"xs\">Extra small (xs)</Text>\n <Text size=\"sm\">Small (sm)</Text>\n <Text size=\"base\">Base size</Text>\n <Text size=\"lg\">Large (lg)</Text>\n <Text size=\"xl\">Extra large (xl)</Text>\n <Text size=\"2xl\">Extra extra large (2xl)</Text>\n</div>"},{"name":"Weights","description":"Different font weights","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text weight=\"normal\">Normal weight</Text>\n <Text weight=\"medium\">Medium weight</Text>\n <Text weight=\"semibold\">Semibold weight</Text>\n</div>"},{"name":"Colors","description":"Different text colors","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text color=\"primary\">Primary color (default)</Text>\n <Text color=\"secondary\">Secondary color</Text>\n <Text color=\"tertiary\">Tertiary color</Text>\n</div>"},{"name":"Semantic Elements","description":"Using appropriate HTML elements","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Text as=\"h1\" size=\"2xl\" weight=\"semibold\">Heading 1</Text>\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Heading 2</Text>\n <Text as=\"h3\" size=\"lg\" weight=\"medium\">Heading 3</Text>\n <Text as=\"p\" color=\"secondary\">\n This is a paragraph of text that demonstrates the Text component\n with semantic paragraph element.\n </Text>\n</div>"},{"name":"Monospace","description":"Monospace font for code-like text","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text font=\"mono\" size=\"sm\">const greeting = \"Hello, World!\";</Text>\n <Text font=\"mono\" size=\"sm\" color=\"secondary\">npm install @fragments-sdk/ui</Text>\n</div>"},{"name":"Truncation","description":"Text truncation with ellipsis","code":"<div style={{ width: '200px', display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Text truncate>\n This is a very long text that will be truncated with an ellipsis when it overflows.\n </Text>\n <Text truncate lineClamp={2}>\n This text will be clamped to two lines. Any content beyond two lines\n will be hidden and replaced with an ellipsis at the end.\n </Text>\n</div>"}]},"Textarea":{"filePath":"src/components/Textarea/Textarea.fragment.tsx","meta":{"name":"Textarea","description":"Multi-line text input for longer form content","category":"forms","status":"stable","tags":["input","text","form","multiline"]},"usage":{"when":["Collecting multi-line text (comments, descriptions)","Free-form text input that may span multiple lines","Message composition fields","Code or content editing"],"whenNot":["Single-line input (use Input)","Rich text editing (use rich text editor)","Selecting from predefined options (use Select)"],"guidelines":["Set appropriate rows for expected content length","Use placeholder to show example format","Show character count when maxLength is set","Consider auto-resize for better UX"],"accessibility":["Always provide a visible label","Use helperText for format hints","Error messages should be descriptive"]},"props":{"value":{"type":"string","description":"Controlled value"},"placeholder":{"type":"string","description":"Placeholder text"},"rows":{"type":"number","description":"Number of visible text rows","default":3},"label":{"type":"string","description":"Label text above the textarea"},"helperText":{"type":"string","description":"Helper text below the textarea"},"error":{"type":"boolean","description":"Error state","default":false},"disabled":{"type":"boolean","description":"Disabled state","default":false},"resize":{"type":"enum","description":"Resize behavior","default":"vertical","values":["none","vertical","horizontal","both"]},"maxLength":{"type":"number","description":"Maximum character length"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for single-line text"}],"variants":[{"name":"Default","description":"Basic textarea with label","code":"<Textarea\n label=\"Description\"\n placeholder=\"Enter a description...\"\n/>"},{"name":"With Helper Text","description":"Textarea with additional guidance","code":"<Textarea\n label=\"Bio\"\n placeholder=\"Tell us about yourself...\"\n helperText=\"Max 500 characters\"\n maxLength={500}\n/>"},{"name":"Error State","description":"Textarea showing validation error","code":"<Textarea\n label=\"Comments\"\n placeholder=\"Add your comments...\"\n error\n helperText=\"This field is required\"\n/>"},{"name":"Disabled","description":"Non-interactive textarea","code":"<Textarea\n label=\"Notes\"\n placeholder=\"Cannot edit...\"\n disabled\n/>"},{"name":"Custom Rows","description":"Textarea with more visible rows","code":"<Textarea\n label=\"Long Description\"\n placeholder=\"Enter detailed information...\"\n rows={6}\n/>"}]},"Theme":{"filePath":"src/components/Theme/Theme.fragment.tsx","meta":{"name":"Theme","description":"Theme management system with provider, toggle, and hook pattern. Supports light, dark, and system modes with localStorage persistence.","category":"navigation","status":"stable","tags":["theme","dark-mode","light-mode","provider","toggle"],"since":"0.5.0"},"usage":{"when":["Providing theme context to an application","Toggling between light and dark modes","Respecting system color scheme preference","Persisting theme preference across sessions"],"whenNot":["Simple one-off color changes (use CSS variables)","Component-level theming (use component props)"],"guidelines":["Wrap your app with ThemeProvider at the root level","Use useTheme hook to access theme state in components","ThemeToggle cycles through light → dark → system","Use storageKey to customize localStorage key","Set attribute=\"class\" if your CSS uses .dark class instead of data-theme"],"accessibility":["ThemeToggle button has accessible label indicating current mode","Theme changes are applied via CSS custom properties for smooth transitions","System preference is detected via prefers-color-scheme media query"]},"props":{"children":{"type":"node","description":"Application content","required":true},"defaultMode":{"type":"enum","description":"Default theme mode for uncontrolled usage","default":"system","values":["light","dark","system"]},"mode":{"type":"enum","description":"Controlled theme mode","values":["light","dark","system"]},"onModeChange":{"type":"function","description":"Callback when mode changes"},"storageKey":{"type":"string","description":"localStorage key for persistence","default":"fui-theme"},"attribute":{"type":"enum","description":"How to apply theme to DOM","default":"data-theme","values":["data-theme","class"]}},"relations":[{"component":"AppShell","relationship":"sibling","note":"ThemeProvider typically wraps AppShell"}],"variants":[{"name":"Default","description":"ThemeProvider with system default","code":"<ThemeProvider defaultMode=\"system\">\n <ThemeDemo />\n</ThemeProvider>"},{"name":"With Toggle","description":"ThemeProvider with toggle button","code":"<ThemeProvider defaultMode=\"light\">\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n <ThemeToggle />\n <span>Click to cycle themes</span>\n </div>\n</ThemeProvider>"},{"name":"Toggle Sizes","description":"ThemeToggle in different sizes","code":"<ThemeProvider defaultMode=\"light\">\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n <ThemeToggle size=\"sm\" />\n <ThemeToggle size=\"md\" />\n <ThemeToggle size=\"lg\" />\n </div>\n</ThemeProvider>"}]},"ThinkingIndicator":{"filePath":"src/components/ThinkingIndicator/ThinkingIndicator.fragment.tsx","meta":{"name":"ThinkingIndicator","description":"Animated indicator showing AI is processing","category":"ai","status":"stable","tags":["thinking","loading","ai","processing","indicator","animation"]},"usage":{"when":["AI is processing a request and generating a response","Need visual feedback during async AI operations","Want to show multi-step progress for complex AI tasks","Indicating streaming is about to begin"],"whenNot":["Simple loading states (use Progress or Skeleton)","Form submission loading (use Button loading state)","Page-level loading (use Progress or Skeleton)"],"guidelines":["Use active prop to control visibility","Choose variant based on context (dots for chat, spinner for actions)","Enable showElapsed for longer operations","Use steps for multi-step AI workflows (tool calls, research)"],"accessibility":["Uses role=\"status\" and aria-live=\"polite\"","Provides aria-label for screen readers","Animations respect prefers-reduced-motion","Elapsed time uses tabular numbers for stability"]},"props":{"active":{"type":"boolean","description":"Whether thinking is active","default":"true"},"label":{"type":"string","description":"Status text","default":"\"Thinking...\""},"variant":{"type":"\"dots\" | \"pulse\" | \"spinner\"","description":"Animation style","default":"\"dots\""},"showElapsed":{"type":"boolean","description":"Show elapsed time","default":"false"},"steps":{"type":"ThinkingStep[]","description":"Multi-step progress array"}},"relations":[{"component":"Message","relationship":"sibling","note":"Show ThinkingIndicator while waiting for assistant message"},{"component":"ConversationList","relationship":"parent","note":"Typically placed at bottom of ConversationList"},{"component":"Progress","relationship":"alternative","note":"Use Progress for determinate progress"}],"variants":[{"name":"Dots (Default)","description":"Bouncing dots animation","code":"<ThinkingIndicator variant=\"dots\" label=\"Thinking...\" />"},{"name":"Pulse","description":"Pulsing ring animation","code":"<ThinkingIndicator variant=\"pulse\" label=\"Processing...\" />"},{"name":"Spinner","description":"Rotating spinner animation","code":"<ThinkingIndicator variant=\"spinner\" label=\"Loading...\" />"},{"name":"With Elapsed Time","description":"Shows time since started","code":"<ThinkingIndicator\n variant=\"dots\"\n label=\"Generating response...\"\n showElapsed\n/>"},{"name":"Multi-Step Progress","description":"Shows progress through multiple steps","code":"<ThinkingIndicator\n variant=\"spinner\"\n label=\"Working...\"\n steps={[\n { id: '1', label: 'Analyzing request', status: 'complete' },\n { id: '2', label: 'Searching knowledge base', status: 'active' },\n { id: '3', label: 'Generating response', status: 'pending' },\n ]}\n/>"},{"name":"With Error Step","description":"Shows a step that encountered an error","code":"<ThinkingIndicator\n variant=\"spinner\"\n label=\"Retrying...\"\n steps={[\n { id: '1', label: 'Connecting to API', status: 'complete' },\n { id: '2', label: 'Fetching data', status: 'error' },\n { id: '3', label: 'Retrying with fallback', status: 'active' },\n ]}\n/>"},{"name":"Custom Label","description":"Custom status text","code":"<ThinkingIndicator\n variant=\"dots\"\n label=\"Claude is writing code...\"\n/>"}]},"Toast":{"filePath":"src/components/Toast/Toast.fragment.tsx","meta":{"name":"Toast","description":"Brief, non-blocking notification messages","category":"feedback","status":"stable","tags":["notification","alert","message","feedback"]},"usage":{"when":["Providing feedback after an action","Showing success/error status of operations","Non-critical information that doesn't require action","Temporary messages that auto-dismiss"],"whenNot":["Critical errors requiring user action (use Dialog)","Persistent information (use Alert)","Inline validation (use form error states)","System-wide announcements (use Banner)"],"guidelines":["Keep messages brief and actionable","Use appropriate variant for the message type","Auto-dismiss after reasonable duration (3-5s)","Allow manual dismissal for longer messages","Limit number of simultaneous toasts"],"accessibility":["Use role=\"alert\" for important messages","Ensure sufficient display time for reading","Don't rely solely on color for meaning","Provide dismiss button with accessible label"]},"props":{"title":{"type":"string","description":"Toast title"},"description":{"type":"string","description":"Additional message content"},"variant":{"type":"enum","description":"Visual variant indicating message type","default":"default","values":["default","success","error","warning","info"]},"duration":{"type":"number","description":"Auto-dismiss duration in ms (0 = no auto-dismiss)","default":5000},"action":{"type":"object","description":"Optional action button { label, onClick }"}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for persistent inline messages"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for messages requiring user action"}],"variants":[{"name":"Default","description":"Interactive toast demo - click buttons to trigger toasts","code":"<ToastDemoWrapper />"},{"name":"Success","description":"Success message variant","code":"<Toast\n title=\"Success!\"\n description=\"Your changes have been saved.\"\n variant=\"success\"\n/>"},{"name":"Error","description":"Error message variant","code":"<Toast\n title=\"Error\"\n description=\"Failed to save changes. Please try again.\"\n variant=\"error\"\n/>"},{"name":"Warning","description":"Warning message variant","code":"<Toast\n title=\"Warning\"\n description=\"This action cannot be undone.\"\n variant=\"warning\"\n/>"},{"name":"Info","description":"Informational message variant","code":"<Toast\n title=\"New Update\"\n description=\"Version 2.0 is now available.\"\n variant=\"info\"\n/>"},{"name":"With Action","description":"Toast with an action button","code":"<Toast\n title=\"File deleted\"\n description=\"The file has been moved to trash.\"\n action={{\n label: 'Undo',\n onClick: () => console.log('Undo clicked'),\n }}\n/>"}]},"Toggle":{"filePath":"src/components/Toggle/Toggle.fragment.tsx","meta":{"name":"Toggle","description":"Binary on/off switch for settings and preferences. Provides immediate visual feedback and is ideal for options that take effect instantly.","category":"forms","status":"stable","tags":["switch","toggle","boolean","settings","preference"],"since":"0.1.0"},"usage":{"when":["Binary settings that take effect immediately (e.g., dark mode, notifications)","Enabling/disabling features in a settings panel","Options where the result is immediately visible","Mobile-friendly boolean inputs"],"whenNot":["Multiple options in a group (use checkbox group)","Selection requires form submission to take effect (use checkbox)","Yes/No questions in forms (use radio buttons)","Complex multi-state options (use select or radio)"],"guidelines":["Toggle should always have a visible label explaining what it controls","The \"on\" state should be the positive/enabling action","Changes should take effect immediately - no save button needed","Include a description for toggles whose effect isn't obvious from the label","Group related toggles visually in settings panels"],"accessibility":["Uses role=\"switch\" with aria-checked for proper semantics","Must have an accessible label (visible or aria-label)","Focus indicator must be clearly visible","State change must be announced by screen readers"]},"props":{"checked":{"type":"boolean","description":"Whether the toggle is in the on state","default":"false"},"onChange":{"type":"function","description":"Callback with new checked state: (checked: boolean) => void"},"label":{"type":"string","description":"Visible label text"},"description":{"type":"string","description":"Helper text shown below the label"},"disabled":{"type":"boolean","description":"Whether the toggle is non-interactive","default":"false"},"size":{"type":"enum","description":"Toggle track size","default":"md","values":["sm","md"]}},"relations":[{"component":"Input","relationship":"sibling","note":"Input handles text/number entry; Toggle handles boolean state"},{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox when change requires form submission"}],"variants":[{"name":"Default Off","description":"Toggle in the off state","code":"<StatefulToggle label=\"Email notifications\" />","args":{"label":"Email notifications"}},{"name":"Checked","description":"Toggle in the on state","code":"<StatefulToggle checked label=\"Dark mode\" />","args":{"checked":true,"label":"Dark mode"}},{"name":"With Description","description":"Toggle with explanatory helper text","code":"<StatefulToggle\n checked\n label=\"Auto-save\"\n description=\"Automatically save changes as you type\"\n/>","args":{"checked":true,"label":"Auto-save","description":"Automatically save changes as you type"}},{"name":"Small Size","description":"Compact toggle for dense settings panels","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <StatefulToggle size=\"sm\" checked label=\"Show line numbers\" />\n <StatefulToggle size=\"sm\" label=\"Word wrap\" />\n <StatefulToggle size=\"sm\" checked label=\"Minimap\" />\n</div>"},{"name":"Disabled States","description":"Non-interactive toggles showing both states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Toggle disabled label=\"Premium feature (upgrade required)\" />\n <Toggle disabled checked label=\"System managed (read-only)\" />\n</div>"},{"name":"Settings Panel","description":"Multiple toggles in a realistic settings layout","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '320px' }}>\n <StatefulToggle\n checked\n label=\"Push notifications\"\n description=\"Receive push notifications on your device\"\n />\n <StatefulToggle\n checked\n label=\"Email digest\"\n description=\"Weekly summary of your activity\"\n />\n <StatefulToggle\n label=\"Marketing emails\"\n description=\"Product updates and promotional offers\"\n />\n</div>"}]},"ToggleGroup":{"filePath":"src/components/ToggleGroup/ToggleGroup.fragment.tsx","meta":{"name":"ToggleGroup","description":"A group of toggle buttons where only one can be selected at a time. Useful for switching between views, modes, or options.","category":"forms","status":"stable","tags":["toggle","group","segmented","control","tabs","switch"],"since":"0.2.0"},"usage":{"when":["Switching between mutually exclusive views or modes","Selecting one option from a small set (2-5 options)","Segmented controls like view switchers","Filter or sort options"],"whenNot":["Multiple selections allowed (use Checkbox group)","Many options (use Select or RadioGroup)","Navigation between pages (use Tabs)","On/off toggle (use Toggle component)"],"guidelines":["Keep options to 2-5 items for clarity","Use clear, concise labels","Consider icons for common actions (grid/list view)","Ensure adequate touch targets on mobile"],"accessibility":["Uses role=\"group\" for semantic grouping","Each item has role=\"radio\" with aria-checked","Keyboard navigable with Tab and arrow keys","Focus visible on active item"]},"props":{"value":{"type":"string","description":"Currently selected value","required":true},"onChange":{"type":"function","description":"Called with new value when selection changes","required":true},"children":{"type":"node","description":"ToggleGroup.Item components","required":true},"variant":{"type":"enum","description":"Visual style","default":"default","values":["default","pills","outline"]},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md"]},"gap":{"type":"enum","description":"Gap between items (pills/outline variants)","default":"xs","values":["none","xs","sm"]}},"relations":[{"component":"RadioGroup","relationship":"alternative","note":"RadioGroup for form-style single selection"},{"component":"Tabs","relationship":"alternative","note":"Tabs for content panel switching"},{"component":"Toggle","relationship":"sibling","note":"Toggle for single on/off control"}],"variants":[{"name":"Default","description":"Basic toggle group","code":"{\n const [value, setValue] = React.useState('left');\n return (\n <ToggleGroup value={value} onChange={setValue}>\n <ToggleGroup.Item value=\"left\">Left</ToggleGroup.Item>\n <ToggleGroup.Item value=\"center\">Center</ToggleGroup.Item>\n <ToggleGroup.Item value=\"right\">Right</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Pills Variant","description":"Pill-shaped toggle buttons","code":"{\n const [value, setValue] = React.useState('all');\n return (\n <ToggleGroup value={value} onChange={setValue} variant=\"pills\">\n <ToggleGroup.Item value=\"all\">All</ToggleGroup.Item>\n <ToggleGroup.Item value=\"active\">Active</ToggleGroup.Item>\n <ToggleGroup.Item value=\"completed\">Completed</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Outline Variant","description":"Outlined toggle buttons","code":"{\n const [value, setValue] = React.useState('day');\n return (\n <ToggleGroup value={value} onChange={setValue} variant=\"outline\">\n <ToggleGroup.Item value=\"day\">Day</ToggleGroup.Item>\n <ToggleGroup.Item value=\"week\">Week</ToggleGroup.Item>\n <ToggleGroup.Item value=\"month\">Month</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Sizes","description":"Different size variants","code":"{\n const [value1, setValue1] = React.useState('a');\n const [value2, setValue2] = React.useState('a');\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <ToggleGroup value={value1} onChange={setValue1} size=\"sm\">\n <ToggleGroup.Item value=\"a\">Small</ToggleGroup.Item>\n <ToggleGroup.Item value=\"b\">Size</ToggleGroup.Item>\n </ToggleGroup>\n <ToggleGroup value={value2} onChange={setValue2} size=\"md\">\n <ToggleGroup.Item value=\"a\">Medium</ToggleGroup.Item>\n <ToggleGroup.Item value=\"b\">Size</ToggleGroup.Item>\n </ToggleGroup>\n </div>\n );\n}"},{"name":"View Switcher","description":"Common pattern for switching between views","code":"{\n const [view, setView] = React.useState('grid');\n return (\n <ToggleGroup value={view} onChange={setView} size=\"sm\">\n <ToggleGroup.Item value=\"grid\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" />\n </svg>\n </ToggleGroup.Item>\n <ToggleGroup.Item value=\"list\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"With Disabled Item","description":"Toggle group with a disabled option","code":"{\n const [value, setValue] = React.useState('basic');\n return (\n <ToggleGroup value={value} onChange={setValue}>\n <ToggleGroup.Item value=\"basic\">Basic</ToggleGroup.Item>\n <ToggleGroup.Item value=\"pro\">Pro</ToggleGroup.Item>\n <ToggleGroup.Item value=\"enterprise\" disabled>Enterprise</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"}]},"Tooltip":{"filePath":"src/components/Tooltip/Tooltip.fragment.tsx","meta":{"name":"Tooltip","description":"Contextual help text that appears on hover or focus. Perfect for explaining icons, truncated text, or providing additional context.","category":"feedback","status":"stable","tags":["tooltip","hint","help","hover","contextual"],"since":"0.1.0"},"usage":{"when":["Explaining icon-only buttons","Showing full text for truncated content","Providing keyboard shortcuts","Brief contextual help that fits in one line"],"whenNot":["Long-form help content (use Popover)","Critical information users must see (use Alert)","Interactive content (use Popover or Menu)","Mobile-primary interfaces (tooltips require hover)"],"guidelines":["Keep tooltip text concise (under 80 characters)","Use sentence case, no period for single sentences","Avoid duplicating visible label text","Consider mobile users who cannot hover"],"accessibility":["Accessible via focus as well as hover","Uses role=\"tooltip\" with proper aria association","Delay prevents tooltips from appearing during navigation"]},"props":{"children":{"type":"element","description":"The element that triggers the tooltip","required":true},"content":{"type":"node","description":"Content to display in the tooltip","required":true},"side":{"type":"enum","description":"Which side to show the tooltip","default":"top","values":["top","bottom","left","right"]},"align":{"type":"enum","description":"Alignment along the side","default":"center","values":["start","center","end"]},"sideOffset":{"type":"number","description":"Distance from trigger in pixels","default":"6"},"delay":{"type":"number","description":"Delay before showing (ms)","default":"400"},"arrow":{"type":"boolean","description":"Show arrow pointing to trigger","default":"true"},"disabled":{"type":"boolean","description":"Disable the tooltip","default":"false"}},"relations":[{"component":"Popover","relationship":"alternative","note":"Use Popover for interactive or longer content"},{"component":"Alert","relationship":"alternative","note":"Use Alert for critical information that must be visible"}],"variants":[{"name":"Default","description":"Basic tooltip on hover","code":"<Tooltip content=\"Save your changes\">\n <Button>Save</Button>\n</Tooltip>"},{"name":"Positions","description":"Tooltips on different sides","code":"<div style={{ display: 'flex', gap: '16px', padding: '40px' }}>\n <Tooltip content=\"Top tooltip\" side=\"top\">\n <Button variant=\"secondary\">Top</Button>\n </Tooltip>\n <Tooltip content=\"Bottom tooltip\" side=\"bottom\">\n <Button variant=\"secondary\">Bottom</Button>\n </Tooltip>\n <Tooltip content=\"Left tooltip\" side=\"left\">\n <Button variant=\"secondary\">Left</Button>\n </Tooltip>\n <Tooltip content=\"Right tooltip\" side=\"right\">\n <Button variant=\"secondary\">Right</Button>\n </Tooltip>\n</div>"},{"name":"With Shortcut","description":"Tooltip showing keyboard shortcut","code":"<Tooltip content=\"Undo (Ctrl+Z)\">\n <Button variant=\"ghost\">Undo</Button>\n</Tooltip>"},{"name":"No Arrow","description":"Tooltip without arrow","code":"<Tooltip content=\"Clean tooltip\" arrow={false}>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>"}]},"VisuallyHidden":{"filePath":"src/components/VisuallyHidden/VisuallyHidden.fragment.tsx","meta":{"name":"VisuallyHidden","description":"Hides content visually while keeping it accessible to screen readers. Essential for accessible icon-only buttons and supplementary text.","category":"navigation","status":"stable","tags":["accessibility","a11y","screen-reader","hidden","sr-only"],"since":"0.1.0"},"usage":{"when":["Providing accessible labels for icon-only buttons","Adding context that screen readers need but sighted users don't","Hiding decorative content while providing text alternatives","Skip links for keyboard navigation"],"whenNot":["Hiding content from everyone (use display: none or conditional render)","Content that should be visible on focus (use focus-visible styles)","Temporarily hidden content (use proper ARIA attributes)","Lazy-loaded content (use suspense or loading states)"],"guidelines":["Always use with icon-only interactive elements","Keep hidden text concise but descriptive","Test with screen readers to verify announcements","Don't overuse; visible text is often better"],"accessibility":["Content is announced by screen readers","Content is focusable if interactive elements are inside","Essential for WCAG 2.1 compliance with icon-only controls","Must convey equivalent information to visual content"]},"props":{"children":{"type":"node","description":"Content to hide visually","required":true},"as":{"type":"enum","description":"HTML element to render","default":"span","values":["span","div"]}},"relations":[{"component":"Button","relationship":"child","note":"Use inside icon-only buttons for accessible labels"},{"component":"Icon","relationship":"sibling","note":"Pair with icons to provide text alternatives"}],"variants":[{"name":"Icon Button Label","description":"Accessible label for icon-only button","code":"<button style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '40px',\n height: '40px',\n border: '1px solid var(--fui-border-default)',\n borderRadius: '8px',\n background: 'var(--fui-color-surface-primary)',\n cursor: 'pointer'\n}}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <VisuallyHidden>Search</VisuallyHidden>\n</button>"},{"name":"Supplementary Text","description":"Additional context for screen readers","code":"<a href=\"#\" style={{ color: 'var(--fui-color-accent)' }}>\n Read more\n <VisuallyHidden> about our accessibility features</VisuallyHidden>\n</a>"},{"name":"Skip Link","description":"Navigation aid that becomes visible on focus","code":"<div>\n <VisuallyHidden as=\"div\">\n <a\n href=\"#main-content\"\n style={{\n position: 'absolute',\n padding: '8px 16px',\n background: 'var(--fui-color-accent)',\n color: 'white'\n }}\n >\n Skip to main content\n </a>\n </VisuallyHidden>\n <p style={{ color: 'var(--fui-color-text-tertiary)', fontSize: '14px' }}>\n (Screen reader only: \"Skip to main content\" link)\n </p>\n</div>"}]}},"recipes":{"AI Chat":{"filePath":"src/recipes/AIChat.recipe.ts","name":"AI Chat","description":"Complete AI chat interface with Message, ConversationList, Prompt, and ThinkingIndicator","category":"ai","components":["Message","ConversationList","ThinkingIndicator","Prompt","Stack"],"code":"import { useState, useCallback } from 'react';\nimport {\n Message,\n ConversationList,\n ThinkingIndicator,\n Prompt,\n Stack,\n} from '@fragments/ui';\n\ninterface ChatMessage {\n id: string;\n role: 'user' | 'assistant' | 'system';\n content: string;\n timestamp: Date;\n status?: 'sending' | 'streaming' | 'complete' | 'error';\n}\n\ninterface ThinkingStep {\n id: string;\n label: string;\n status: 'pending' | 'active' | 'complete' | 'error';\n}\n\nfunction AIChat() {\n const [messages, setMessages] = useState<ChatMessage[]>([\n {\n id: 'system-1',\n role: 'system',\n content: 'Conversation started. Model: Claude 3.5 Sonnet',\n timestamp: new Date(),\n status: 'complete',\n },\n ]);\n const [isThinking, setIsThinking] = useState(false);\n const [thinkingSteps, setThinkingSteps] = useState<ThinkingStep[]>([]);\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\n\n const handleSubmit = useCallback(async (value: string) => {\n // Add user message\n const userMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'user',\n content: value,\n timestamp: new Date(),\n status: 'complete',\n };\n setMessages((prev) => [...prev, userMessage]);\n\n // Start thinking state with steps\n setIsThinking(true);\n setThinkingSteps([\n { id: '1', label: 'Understanding your request', status: 'active' },\n { id: '2', label: 'Searching knowledge base', status: 'pending' },\n { id: '3', label: 'Generating response', status: 'pending' },\n ]);\n\n try {\n // Simulate step 1 completion\n await new Promise((resolve) => setTimeout(resolve, 800));\n setThinkingSteps((prev) =>\n prev.map((s) =>\n s.id === '1'\n ? { ...s, status: 'complete' }\n : s.id === '2'\n ? { ...s, status: 'active' }\n : s\n )\n );\n\n // Simulate step 2 completion\n await new Promise((resolve) => setTimeout(resolve, 600));\n setThinkingSteps((prev) =>\n prev.map((s) =>\n s.id === '2'\n ? { ...s, status: 'complete' }\n : s.id === '3'\n ? { ...s, status: 'active' }\n : s\n )\n );\n\n // Simulate step 3 (response generation)\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Add assistant response\n const assistantMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: generateMockResponse(value),\n timestamp: new Date(),\n status: 'complete',\n };\n setMessages((prev) => [...prev, assistantMessage]);\n } catch (error) {\n // Handle error\n const errorMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n status: 'error',\n };\n setMessages((prev) => [...prev, errorMessage]);\n } finally {\n setIsThinking(false);\n setThinkingSteps([]);\n }\n }, []);\n\n const handleLoadHistory = useCallback(async () => {\n if (isLoadingHistory) return;\n\n setIsLoadingHistory(true);\n await new Promise((resolve) => setTimeout(resolve, 1500));\n\n // Simulate loading older messages\n const olderMessages: ChatMessage[] = [\n {\n id: crypto.randomUUID(),\n role: 'user',\n content: 'What can you help me with?',\n timestamp: new Date(Date.now() - 86400000), // Yesterday\n status: 'complete',\n },\n {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'I can help with coding, writing, analysis, and more!',\n timestamp: new Date(Date.now() - 86400000 + 1000),\n status: 'complete',\n },\n ];\n\n setMessages((prev) => [...olderMessages, ...prev]);\n setIsLoadingHistory(false);\n }, [isLoadingHistory]);\n\n const handleCopy = useCallback((content: string) => {\n navigator.clipboard.writeText(content);\n // You might want to show a toast here\n }, []);\n\n return (\n <Stack\n style={{\n height: '100vh',\n maxWidth: '800px',\n margin: '0 auto',\n background: 'var(--fui-bg-primary)',\n }}\n >\n <ConversationList\n autoScroll=\"smart\"\n onScrollTop={handleLoadHistory}\n loadingHistory={isLoadingHistory}\n emptyState={\n <Stack align=\"center\" justify=\"center\" style={{ flex: 1, padding: '2rem' }}>\n <p style={{ color: 'var(--fui-text-secondary)' }}>\n Start a conversation with the AI assistant\n </p>\n </Stack>\n }\n >\n {messages.map((msg, index) => {\n // Add date separator if day changed\n const prevMsg = messages[index - 1];\n const showDateSeparator =\n !prevMsg ||\n new Date(msg.timestamp).toDateString() !==\n new Date(prevMsg.timestamp).toDateString();\n\n return (\n <React.Fragment key={msg.id}>\n {showDateSeparator && (\n <ConversationList.DateSeparator date={msg.timestamp} />\n )}\n <Message\n role={msg.role}\n status={msg.status}\n timestamp={msg.timestamp}\n actions={\n msg.role === 'assistant' && msg.status === 'complete' ? (\n <>\n <button\n onClick={() => handleCopy(msg.content)}\n style={{\n padding: '4px 8px',\n fontSize: '12px',\n background: 'var(--fui-bg-tertiary)',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n }}\n >\n Copy\n </button>\n </>\n ) : undefined\n }\n >\n <Message.Content>{msg.content}</Message.Content>\n {msg.timestamp && <Message.Timestamp />}\n </Message>\n </React.Fragment>\n );\n })}\n\n {isThinking && (\n <ThinkingIndicator\n variant=\"dots\"\n label=\"Claude is thinking...\"\n showElapsed\n steps={thinkingSteps}\n />\n )}\n </ConversationList>\n\n <div style={{ padding: '1rem', borderTop: '1px solid var(--fui-border)' }}>\n <Prompt\n onSubmit={handleSubmit}\n loading={isThinking}\n placeholder=\"Message Claude...\"\n >\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Attach file\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton active>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n </Prompt>\n </div>\n </Stack>\n );\n}\n\n// Mock response generator\nfunction generateMockResponse(input: string): string {\n const responses = [\n \"That's a great question! Let me help you with that.\",\n \"I understand what you're looking for. Here's what I can tell you...\",\n \"Based on my knowledge, I can provide some insights on this topic.\",\n \"Let me break this down for you step by step.\",\n ];\n return responses[Math.floor(Math.random() * responses.length)] +\n \" This is a simulated response. In a real implementation, this would be replaced with actual AI-generated content based on your query about: \" +\n input.substring(0, 50) + (input.length > 50 ? '...' : '');\n}\n\nexport default AIChat;","tags":["chat","ai","assistant","conversation","llm","chatbot"]},"App Shell":{"filePath":"src/recipes/AppShell.recipe.ts","name":"App Shell","description":"Full application layout with sidebar, header, and main content. Supports two layout modes: stacked (header full-width) and sidebar-inset (sidebar full-height).","category":"layout","components":["AppShell","Header","Sidebar","ThemeToggle"],"code":"// App Shell - Stacked Layout (header spans full width)\n// Best for apps where the brand should be prominent in the header\n\nimport { AppShell, Header, Sidebar, ThemeToggle } from '@fragments/ui';\n\nfunction StackedLayout({ children }) {\n return (\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Brand href=\"/\">MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/\" active>Dashboard</Header.NavItem>\n <Header.NavItem href=\"/settings\">Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"240px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} href=\"/\" active>\n Home\n </Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} href=\"/analytics\">\n Analytics\n </Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />} href=\"/settings\">\n Settings\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell - Sidebar Inset Layout (sidebar is full height)\n// Best for documentation sites or when sidebar branding is preferred\n\nfunction SidebarInsetLayout({ children }) {\n return (\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Search>\n <Input placeholder=\"Search...\" />\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"260px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <a href=\"/\">MyApp</a>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Getting Started\">\n <Sidebar.Item href=\"/docs\" active>Introduction</Sidebar.Item>\n <Sidebar.Item href=\"/docs/install\">Installation</Sidebar.Item>\n </Sidebar.Section>\n <Sidebar.Section label=\"Components\">\n <Sidebar.Item href=\"/components\">Overview</Sidebar.Item>\n <Sidebar.Item href=\"/components/button\">Button</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell with Collapsible Icon Sidebar\n// Sidebar collapses to icons only - great for dashboards\n\nfunction CollapsibleLayout({ children }) {\n return (\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar collapsible=\"icon\" width=\"240px\" collapsedWidth=\"64px\">\n <Sidebar.Header collapsedContent={<Logo />}>\n <Logo /> <span>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell with Aside Panel\n// Optional right panel for additional context\n\nfunction LayoutWithAside({ children, aside }) {\n return (\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Brand>MyApp</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n\n <AppShell.Aside width=\"280px\">\n {aside}\n </AppShell.Aside>\n </AppShell>\n );\n}","tags":["layout","app-shell","sidebar","navigation","dashboard"]},"Card Grid":{"filePath":"src/recipes/CardGrid.recipe.ts","name":"Card Grid","description":"Responsive grid of cards that reflows based on available space","category":"layout","components":["Grid","Card"],"code":"<Grid columns=\"auto\" minChildWidth=\"16rem\" gap=\"md\">\n {items.map(item => (\n <Card key={item.id}>\n <Card.Header>\n <Card.Title>{item.title}</Card.Title>\n <Card.Description>{item.description}</Card.Description>\n </Card.Header>\n <Card.Body>{item.content}</Card.Body>\n </Card>\n ))}\n</Grid>","tags":["grid","cards","responsive","dashboard","tiles"]},"Chat Interface":{"filePath":"src/recipes/ChatInterface.recipe.ts","name":"Chat Interface","description":"AI chat interface with message history and prompt input","category":"layout","components":["Prompt","Card","Avatar","Stack"],"code":"import { useState } from 'react';\nimport { Prompt, Card, Avatar, Stack } from '@fragments-sdk/ui';\n\ninterface Message {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n}\n\nfunction ChatInterface() {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSubmit = async (value: string) => {\n // Add user message\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content: value,\n };\n setMessages((prev) => [...prev, userMessage]);\n setIsLoading(true);\n\n try {\n // Simulate API call\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Add assistant response\n const assistantMessage: Message = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'This is a simulated response. Replace with your AI API call.',\n };\n setMessages((prev) => [...prev, assistantMessage]);\n } finally {\n setIsLoading(false);\n }\n };\n\n return (\n <Stack gap=\"4\" style={{ height: '100vh', padding: '1rem' }}>\n {/* Messages */}\n <Stack gap=\"3\" style={{ flex: 1, overflow: 'auto' }}>\n {messages.map((msg) => (\n <Card key={msg.id} padding=\"md\">\n <Card.Body>\n <Stack direction=\"row\" gap=\"3\" align=\"start\">\n <Avatar size=\"sm\">\n {msg.role === 'user' ? 'U' : 'AI'}\n </Avatar>\n <div style={{ flex: 1 }}>{msg.content}</div>\n </Stack>\n </Card.Body>\n </Card>\n ))}\n </Stack>\n\n {/* Prompt */}\n <Prompt onSubmit={handleSubmit} loading={isLoading}>\n <Prompt.Textarea placeholder=\"Ask anything...\" />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Attach file\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n </Prompt>\n </Stack>\n );\n}","tags":["chat","ai","assistant","conversation"]},"Code Examples":{"filePath":"src/recipes/CodeExamples.recipe.ts","name":"Code Examples","description":"Patterns for displaying code in documentation with syntax highlighting","category":"documentation","components":["CodeBlock","Tabs","Card"],"code":"// Installation commands with package manager tabs\n<Tabs defaultValue=\"npm\">\n <Tabs.List>\n <Tabs.Tab value=\"npm\">npm</Tabs.Tab>\n <Tabs.Tab value=\"pnpm\">pnpm</Tabs.Tab>\n <Tabs.Tab value=\"yarn\">yarn</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"npm\">\n <CodeBlock code=\"npm install @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n <Tabs.Panel value=\"pnpm\">\n <CodeBlock code=\"pnpm add @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n <Tabs.Panel value=\"yarn\">\n <CodeBlock code=\"yarn add @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n</Tabs>\n\n// Usage example with preview\n<Card>\n <Card.Header>\n <Card.Title>Button Example</Card.Title>\n </Card.Header>\n <Card.Body>\n <div className=\"preview\">\n <Button variant=\"primary\">Click me</Button>\n </div>\n <CodeBlock\n code={`<Button variant=\"primary\">Click me</Button>`}\n language=\"tsx\"\n />\n </Card.Body>\n</Card>\n\n// Multi-file example with titles\n<CodeBlock\n title=\"Button.tsx\"\n code={buttonCode}\n language=\"tsx\"\n showLineNumbers\n/>\n<CodeBlock\n title=\"Button.module.scss\"\n code={stylesCode}\n language=\"scss\"\n showLineNumbers\n/>\n\n// Highlighted important lines\n<CodeBlock\n code={exampleCode}\n language=\"tsx\"\n showLineNumbers\n highlightLines={[3, \"7-10\"]}\n/>","tags":["code","documentation","syntax","examples"]},"Confirm Dialog":{"filePath":"src/recipes/ConfirmDialog.recipe.ts","name":"Confirm Dialog","description":"Confirmation dialog with destructive action warning","category":"overlays","components":["Dialog","Button"],"code":"<Dialog open={isOpen} onClose={onClose}>\n <Dialog.Title>{title}</Dialog.Title>\n <Dialog.Description>{description}</Dialog.Description>\n <Dialog.Actions>\n <Button variant=\"secondary\" onClick={onClose}>Cancel</Button>\n <Button variant=\"danger\" onClick={onConfirm}>Confirm</Button>\n </Dialog.Actions>\n</Dialog>","tags":["confirm","dialog","modal","destructive"]},"Dashboard Layout":{"filePath":"src/recipes/DashboardLayout.recipe.ts","name":"Dashboard Layout","description":"Dashboard grid with a featured full-width card and smaller metric cards below","category":"layout","components":["Grid","Card","Badge","Separator"],"code":"<Grid columns={4} gap=\"lg\">\n <Grid.Item colSpan=\"full\">\n <Card>\n <Card.Header>\n <Card.Title>Overview</Card.Title>\n <Card.Description>Key metrics for this period</Card.Description>\n </Card.Header>\n <Card.Body>{summaryContent}</Card.Body>\n </Card>\n </Grid.Item>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Users</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"success\">{stats.users}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Revenue</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"info\">{stats.revenue}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Orders</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"warning\">{stats.orders}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Errors</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"danger\">{stats.errors}</Badge>\n </Card.Body>\n </Card>\n <Grid.Item colSpan=\"full\">\n <Separator spacing=\"md\" />\n </Grid.Item>\n <Grid.Item colSpan={2}>\n <Card>\n <Card.Header>\n <Card.Title>Recent Activity</Card.Title>\n </Card.Header>\n <Card.Body>{activityList}</Card.Body>\n </Card>\n </Grid.Item>\n <Grid.Item colSpan={2}>\n <Card>\n <Card.Header>\n <Card.Title>Notifications</Card.Title>\n </Card.Header>\n <Card.Body>{notificationList}</Card.Body>\n </Card>\n </Grid.Item>\n</Grid>","tags":["dashboard","layout","metrics","widgets","overview"]},"Dashboard Navigation":{"filePath":"src/recipes/DashboardNav.recipe.ts","name":"Dashboard Navigation","description":"Sidebar navigation pattern for dashboard applications with user profile, sections, and nested menus","category":"navigation","components":["Sidebar","Avatar"],"code":"// Dashboard Navigation with User Profile\n// A complete sidebar navigation for admin/dashboard interfaces\n\nfunction DashboardNav({ user, currentPath }) {\n const [collapsed, setCollapsed] = React.useState(false);\n const [projectsExpanded, setProjectsExpanded] = React.useState(false);\n\n return (\n <Sidebar\n collapsed={collapsed}\n onCollapsedChange={setCollapsed}\n >\n {/* Brand header */}\n <Sidebar.Header>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 256 256\" fill=\"var(--fui-color-accent)\">\n <path d=\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H48V48H208V208Z\" />\n </svg>\n {!collapsed && (\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Dashboard</span>\n )}\n <Sidebar.CollapseToggle />\n </Sidebar.Header>\n\n {/* Main navigation */}\n <Sidebar.Nav aria-label=\"Dashboard navigation\">\n {/* Primary section */}\n <Sidebar.Section>\n <Sidebar.Item\n icon={<HomeIcon />}\n href=\"/dashboard\"\n active={currentPath === '/dashboard'}\n >\n Overview\n </Sidebar.Item>\n <Sidebar.Item\n icon={<ChartIcon />}\n href=\"/analytics\"\n active={currentPath === '/analytics'}\n badge=\"New\"\n >\n Analytics\n </Sidebar.Item>\n <Sidebar.Item\n icon={<InboxIcon />}\n href=\"/inbox\"\n active={currentPath === '/inbox'}\n badge=\"5\"\n >\n Inbox\n </Sidebar.Item>\n </Sidebar.Section>\n\n {/* Projects section with nested items */}\n <Sidebar.Section label=\"Workspace\">\n <Sidebar.Item\n icon={<FolderIcon />}\n hasSubmenu\n expanded={projectsExpanded}\n onExpandedChange={setProjectsExpanded}\n >\n Projects\n </Sidebar.Item>\n <Sidebar.Submenu>\n <Sidebar.SubItem\n href=\"/projects/website\"\n active={currentPath === '/projects/website'}\n >\n Website Redesign\n </Sidebar.SubItem>\n <Sidebar.SubItem\n href=\"/projects/mobile\"\n active={currentPath === '/projects/mobile'}\n >\n Mobile App\n </Sidebar.SubItem>\n <Sidebar.SubItem\n href=\"/projects/api\"\n active={currentPath === '/projects/api'}\n >\n API Integration\n </Sidebar.SubItem>\n </Sidebar.Submenu>\n <Sidebar.Item\n icon={<UsersIcon />}\n href=\"/team\"\n active={currentPath === '/team'}\n >\n Team Members\n </Sidebar.Item>\n <Sidebar.Item\n icon={<CalendarIcon />}\n href=\"/calendar\"\n active={currentPath === '/calendar'}\n >\n Calendar\n </Sidebar.Item>\n </Sidebar.Section>\n\n {/* Settings section */}\n <Sidebar.Section label=\"Account\">\n <Sidebar.Item\n icon={<GearIcon />}\n href=\"/settings\"\n active={currentPath === '/settings'}\n >\n Settings\n </Sidebar.Item>\n <Sidebar.Item\n icon={<HelpIcon />}\n href=\"/help\"\n active={currentPath === '/help'}\n >\n Help & Support\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n\n {/* Footer with user profile */}\n <Sidebar.Footer>\n <div style={{\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: collapsed ? '0' : '8px',\n borderRadius: '8px',\n cursor: 'pointer',\n }}>\n <Avatar\n src={user.avatar}\n name={user.name}\n size=\"sm\"\n />\n {!collapsed && (\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{\n fontWeight: 500,\n fontSize: '14px',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {user.name}\n </div>\n <div style={{\n fontSize: '12px',\n color: 'var(--fui-text-secondary)',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {user.email}\n </div>\n </div>\n )}\n </div>\n </Sidebar.Footer>\n </Sidebar>\n );\n}\n\n// Usage example:\n// <DashboardNav\n// user={{ name: 'Jane Doe', email: 'jane@example.com', avatar: '/avatar.jpg' }}\n// currentPath=\"/dashboard\"\n// />\n\n// Icon components (use your preferred icon library)\nconst HomeIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 256 256\" fill=\"currentColor\">\n <path d=\"M219.31,108.68l-80-80a16,16,0,0,0-22.62,0l-80,80A15.87,15.87,0,0,0,32,120v96a8,8,0,0,0,8,8H96a8,8,0,0,0,8-8V160h48v56a8,8,0,0,0,8,8h56a8,8,0,0,0,8-8V120A15.87,15.87,0,0,0,219.31,108.68Z\" />\n </svg>\n);","tags":["navigation","sidebar","dashboard","admin","menu"]},"Form Layout":{"filePath":"src/recipes/FormLayout.recipe.ts","name":"Form Layout","description":"Two-column form with full-width fields where needed, using Grid for alignment","category":"forms","components":["Grid","Input","Textarea","Select","Button"],"code":"<Grid columns={2} gap=\"md\">\n <Input label=\"First Name\" placeholder=\"Jane\" />\n <Input label=\"Last Name\" placeholder=\"Doe\" />\n <Grid.Item colSpan=\"full\">\n <Input label=\"Email\" type=\"email\" placeholder=\"jane@example.com\" />\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Select label=\"Role\">\n <Select.Item value=\"admin\">Admin</Select.Item>\n <Select.Item value=\"editor\">Editor</Select.Item>\n <Select.Item value=\"viewer\">Viewer</Select.Item>\n </Select>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Textarea label=\"Bio\" placeholder=\"Tell us about yourself\" />\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Save</Button>\n </Grid.Item>\n</Grid>","tags":["form","layout","grid","inputs","settings"]},"Login Form":{"filePath":"src/recipes/LoginForm.recipe.ts","name":"Login Form","description":"Email/password authentication form with validation states","category":"forms","components":["FormField","Input","Button","Alert"],"code":"<FormField label=\"Email\" error={errors.email}>\n <Input type=\"email\" placeholder=\"you@example.com\" />\n</FormField>\n<FormField label=\"Password\" error={errors.password}>\n <Input type=\"password\" />\n</FormField>\n<Button type=\"submit\" variant=\"primary\">Sign in</Button>\n{error && (\n <Alert severity=\"error\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>{error}</Alert.Content>\n </Alert.Body>\n </Alert>\n)}","tags":["auth","login","form"]},"Settings Page":{"filePath":"src/recipes/SettingsPage.recipe.ts","name":"Settings Page","description":"Settings page with labeled sections using cards, toggles, and a save action","category":"forms","components":["Grid","Card","Toggle","Input","Select","Separator","Button"],"code":"<Grid columns={1} gap=\"lg\">\n <Card>\n <Card.Header>\n <Card.Title>Profile</Card.Title>\n <Card.Description>Your public profile information</Card.Description>\n </Card.Header>\n <Card.Body>\n <Grid columns={2} gap=\"md\">\n <Input label=\"Display Name\" defaultValue={user.name} />\n <Input label=\"Email\" type=\"email\" defaultValue={user.email} />\n <Grid.Item colSpan=\"full\">\n <Input label=\"Website\" type=\"url\" defaultValue={user.website} />\n </Grid.Item>\n </Grid>\n </Card.Body>\n </Card>\n\n <Card>\n <Card.Header>\n <Card.Title>Notifications</Card.Title>\n <Card.Description>Choose what you get notified about</Card.Description>\n </Card.Header>\n <Card.Body>\n <Grid columns={1} gap=\"sm\">\n <Toggle label=\"Email notifications\" checked={prefs.emailNotifs} onChange={onToggle('emailNotifs')} />\n <Toggle label=\"Push notifications\" checked={prefs.pushNotifs} onChange={onToggle('pushNotifs')} />\n <Toggle label=\"Weekly digest\" checked={prefs.digest} onChange={onToggle('digest')} />\n </Grid>\n </Card.Body>\n </Card>\n\n <Card>\n <Card.Header>\n <Card.Title>Appearance</Card.Title>\n </Card.Header>\n <Card.Body>\n <Select label=\"Theme\" value={prefs.theme} onChange={onThemeChange}>\n <Select.Item value=\"light\">Light</Select.Item>\n <Select.Item value=\"dark\">Dark</Select.Item>\n <Select.Item value=\"system\">System</Select.Item>\n </Select>\n </Card.Body>\n </Card>\n\n <Separator />\n <Button variant=\"primary\" type=\"submit\">Save Changes</Button>\n</Grid>","tags":["settings","preferences","form","toggle","layout"]}}}
|
|
1
|
+
{"version":"1.0.0","generatedAt":"2026-02-06T15:08:06.624Z","packageName":"@fragments-sdk/ui","segments":{"Accordion":{"filePath":"src/components/Accordion/Accordion.fragment.tsx","meta":{"name":"Accordion","description":"Vertically stacked, collapsible content sections. Use for organizing related content that can be progressively disclosed.","category":"layout","status":"stable","tags":["accordion","collapse","expand","disclosure","faq"],"since":"0.2.0"},"usage":{"when":["FAQ pages with multiple questions and answers","Settings panels with grouped options","Long forms that benefit from progressive disclosure","Navigation menus with nested items"],"whenNot":["Primary content that all users need to see","Very short content (just display inline)","Sequential steps (use Stepper or wizard)","Tab-like navigation (use Tabs instead)"],"guidelines":["Keep section headers concise and descriptive","Use single mode when only one section should be open at a time","Use multiple mode when users may need to compare sections","Consider defaulting important sections to open","Avoid nesting accordions more than one level deep"],"accessibility":["Keyboard navigation with Enter/Space to toggle","Arrow keys navigate between accordion headers","Uses proper ARIA expanded/controls attributes","Focus is visible on accordion triggers"]},"props":{"children":{"type":"node","description":"Accordion items (use Accordion.Item with Accordion.Trigger and Accordion.Content)","required":true},"type":{"type":"enum","description":"Whether one or multiple items can be open","default":"single","values":["single","multiple"]},"value":{"type":"string | string[]","description":"Controlled open item(s)"},"defaultValue":{"type":"string | string[]","description":"Initially open item(s) for uncontrolled usage"},"onValueChange":{"type":"function","description":"Called when open items change"},"collapsible":{"type":"boolean","description":"Whether all items can be closed (single mode only)","default":"false"}},"relations":[{"component":"Tabs","relationship":"alternative","note":"Use Tabs for horizontal switching between related views"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for focused content that interrupts the flow"},{"component":"Card","relationship":"complementary","note":"Accordion items can contain Card-like content"}],"variants":[{"name":"Basic","description":"Single accordion with collapsible sections","code":"<Accordion type=\"single\" collapsible defaultValue=\"item-1\">\n <Accordion.Item value=\"item-1\">\n <Accordion.Trigger>What is Fragments UI?</Accordion.Trigger>\n <Accordion.Content>\n Fragments UI is a modern React component library built on Base UI primitives, providing accessible and customizable components.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-2\">\n <Accordion.Trigger>How do I install it?</Accordion.Trigger>\n <Accordion.Content>\n Install via npm or pnpm: <code>pnpm add @fragments-sdk/ui</code>\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-3\">\n <Accordion.Trigger>Is it accessible?</Accordion.Trigger>\n <Accordion.Content>\n Yes! All components follow WAI-ARIA guidelines and support keyboard navigation.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"},{"name":"Multiple Open","description":"Allows multiple sections to be open simultaneously","code":"<Accordion type=\"multiple\" defaultValue={['features', 'pricing']}>\n <Accordion.Item value=\"features\">\n <Accordion.Trigger>Features</Accordion.Trigger>\n <Accordion.Content>\n Comprehensive component library with theming support, accessibility built-in, and TypeScript-first development.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"pricing\">\n <Accordion.Trigger>Pricing</Accordion.Trigger>\n <Accordion.Content>\n Free and open source. MIT licensed for both personal and commercial use.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"support\">\n <Accordion.Trigger>Support</Accordion.Trigger>\n <Accordion.Content>\n Community support via GitHub issues and discussions.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"},{"name":"With Disabled","description":"Accordion with a disabled item","code":"<Accordion type=\"single\" collapsible>\n <Accordion.Item value=\"available\">\n <Accordion.Trigger>Available Section</Accordion.Trigger>\n <Accordion.Content>\n This section can be expanded and collapsed.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"disabled\" disabled>\n <Accordion.Trigger>Disabled Section</Accordion.Trigger>\n <Accordion.Content>\n This content is not accessible because the item is disabled.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"another\">\n <Accordion.Trigger>Another Section</Accordion.Trigger>\n <Accordion.Content>\n This section is also available for interaction.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"}],"ai":{"compositionPattern":"compound","subComponents":["Item","Trigger","Content"],"requiredChildren":["Item"],"commonPatterns":["<Accordion type=\"single\" collapsible><Accordion.Item value=\"item-1\"><Accordion.Trigger>{title}</Accordion.Trigger><Accordion.Content>{content}</Accordion.Content></Accordion.Item></Accordion>"]}},"Alert":{"filePath":"src/components/Alert/Alert.fragment.tsx","meta":{"name":"Alert","description":"Contextual feedback messages for user actions or system status. Supports multiple severity levels with optional actions and dismissibility.","category":"feedback","status":"stable","tags":["notification","message","feedback","banner","toast"],"since":"0.1.0"},"usage":{"when":["Communicating the result of a user action (success, error)","Warning about potential issues before they occur","Providing important contextual information inline","System status notifications that require attention"],"whenNot":["Brief status labels (use Badge instead)","Transient notifications (use Toast/Snackbar)","Form-field-level errors (use Input error prop)","Confirmation before destructive actions (use Dialog)"],"guidelines":["Match severity to the actual importance: info for context, warning for potential issues, error for failures","Always provide actionable guidance in error alerts","Use Alert.Title for complex messages; skip titles for brief one-liners","Limit to one action per alert to avoid decision paralysis","Use Alert.Close only for non-critical information"],"accessibility":["Uses role=\"alert\" for screen reader announcement","Error and warning alerts are announced immediately by assistive technology","Alert.Close must have an accessible label","Color alone must not convey meaning - icons and text reinforce severity"]},"props":{"children":{"type":"node","description":"Alert content - use Alert.Icon, Alert.Body, Alert.Title, Alert.Content, Alert.Actions, Alert.Close sub-components","required":true},"severity":{"type":"enum","description":"Visual severity level","default":"info","values":["info","success","warning","error"]}},"relations":[{"component":"Badge","relationship":"alternative","note":"Use Badge for compact, inline status labels"},{"component":"Toast","relationship":"alternative","note":"Use Toast for transient notifications that auto-dismiss"},{"component":"Dialog","relationship":"sibling","note":"Use Dialog for blocking confirmations"}],"variants":[{"name":"Info","description":"Informational context for the user","code":"<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n Your session will expire in 15 minutes. Save your work to avoid losing changes.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Success","description":"Positive confirmation of completed action","code":"<Alert severity=\"success\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Payment processed</Alert.Title>\n <Alert.Content>\n Your order #12345 has been confirmed. You will receive a confirmation email shortly.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Warning","description":"Caution about potential issues","code":"<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Storage almost full</Alert.Title>\n <Alert.Content>\n You have used 90% of your storage quota. Consider deleting unused files.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"Error","description":"Error state requiring user attention","code":"<Alert severity=\"error\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Upload failed</Alert.Title>\n <Alert.Content>\n The file could not be uploaded. Check your connection and try again.\n </Alert.Content>\n </Alert.Body>\n</Alert>"},{"name":"With Action","description":"Alert with an actionable button","code":"<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Update available</Alert.Title>\n <Alert.Content>\n A new version is available with important security fixes.\n </Alert.Content>\n <Alert.Actions>\n <Alert.Action onClick={() => {}}>Update now</Alert.Action>\n </Alert.Actions>\n </Alert.Body>\n</Alert>"},{"name":"Dismissible","description":"Alert that can be closed by the user","code":"<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n You can customize your notification preferences in Settings.\n </Alert.Content>\n </Alert.Body>\n <Alert.Close />\n</Alert>"}],"ai":{"compositionPattern":"compound","subComponents":["Icon","Body","Title","Content","Actions","Action","Close"],"requiredChildren":["Body"],"commonPatterns":["<Alert severity=\"info\"><Alert.Icon /><Alert.Body><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>","<Alert severity=\"warning\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>","<Alert severity=\"error\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body><Alert.Close /></Alert>"]}},"AppShell":{"filePath":"src/components/AppShell/AppShell.fragment.tsx","meta":{"name":"AppShell","description":"Full layout wrapper integrating sidebar, header, main content, and optional aside panel. Supports two layout modes: stacked (header on top) and sidebar-inset (sidebar full height).","category":"layout","status":"stable","tags":["layout","shell","scaffold","dashboard","app-layout"],"since":"0.5.0"},"usage":{"when":["Building dashboard-style applications","Apps with persistent sidebar navigation","Layouts requiring header, sidebar, and main content areas","Responsive layouts that need mobile drawer behavior"],"whenNot":["Simple marketing pages (use standard layout)","Content-first sites without navigation (use simpler layout)","Single-page apps with minimal UI (use minimal layout)"],"guidelines":["Use layout=\"stacked\" when header should span full width (logo in header)","Use layout=\"sidebar-inset\" when sidebar should be full height (logo in sidebar)","AppShell automatically wraps with SidebarProvider","Use AppShell.Sidebar to configure sidebar width and collapse behavior","Main content responds to sidebar collapsed state","Aside panel is hidden on mobile automatically"],"accessibility":["Main content area has id=\"main-content\" for skip links","Use Header.SkipLink for keyboard navigation","Sidebar drawer has proper focus trap on mobile","Keyboard navigation supported throughout"]},"props":{"children":{"type":"node","description":"Layout content (use AppShell.Header, AppShell.Sidebar, AppShell.Main, AppShell.Aside)","required":true},"layout":{"type":"enum","description":"Layout mode for header/sidebar positioning","default":"stacked","values":["stacked","sidebar-inset","inset"]}},"relations":[{"component":"ThemeProvider","relationship":"parent","note":"AppShell should be wrapped in ThemeProvider"},{"component":"Header","relationship":"child","note":"Header is placed inside AppShell.Header"},{"component":"Sidebar","relationship":"child","note":"Sidebar content goes inside AppShell.Sidebar"}],"variants":[{"name":"Stacked Layout","description":"Header spans full width above sidebar (default). Best when brand/logo should be prominent in header.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Brand>MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem active>Dashboard</Header.NavItem>\n <Header.NavItem>Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Stacked Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Header spans full width. Logo is in the header.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"Sidebar Inset Layout","description":"Sidebar is full height, header sits next to it. Best for documentation sites or when sidebar branding is preferred.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 12px', background: 'var(--fui-bg-secondary)', borderRadius: '6px', color: 'var(--fui-text-tertiary)', fontSize: '14px' }}>\n <SearchIcon /> Search...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Sidebar Inset Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Sidebar is full height. Logo is in the sidebar header.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"With Aside Panel","description":"App shell with optional right panel for additional context or actions","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Brand>App</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"180px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Stats</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Main Content</h2>\n <p style={{ margin: 0 }}>Content with aside panel on the right.</p>\n </AppShell.Main>\n\n <AppShell.Aside width=\"180px\">\n <div style={{ padding: '16px' }}>\n <h3 style={{ margin: '0 0 8px', fontSize: '14px' }}>Aside Panel</h3>\n <p style={{ margin: 0, fontSize: '13px', color: 'var(--fui-text-secondary)' }}>\n Additional context, filters, or quick actions.\n </p>\n </div>\n </AppShell.Aside>\n </AppShell>\n</div>"},{"name":"Collapsible Icon Sidebar","description":"Sidebar that collapses to icons only on desktop","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar collapsible=\"icon\" width=\"200px\" collapsedWidth=\"56px\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <p style={{ margin: 0 }}>Click the collapse button in the sidebar footer to toggle between expanded and icon-only modes.</p>\n </AppShell.Main>\n </AppShell>\n</div>"},{"name":"Inset Layout","description":"Modern shadcn-style layout with rounded main content area and visual separation from sidebar.","code":"<div style={{ height: '400px', position: 'relative', overflow: 'hidden', border: '1px solid var(--fui-border)', borderRadius: '8px' }}>\n <AppShell layout=\"inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 12px', background: 'var(--fui-bg-primary)', borderRadius: '6px', color: 'var(--fui-text-tertiary)', fontSize: '14px', border: '1px solid var(--fui-border)' }}>\n <SearchIcon /> Search...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <span style={{ fontWeight: 600 }}>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <h2 style={{ margin: '0 0 8px' }}>Inset Layout</h2>\n <p style={{ margin: 0, color: 'var(--fui-text-secondary)' }}>\n Main content has rounded corners and visual separation from the sidebar.\n </p>\n </AppShell.Main>\n </AppShell>\n</div>"}]},"Avatar":{"filePath":"src/components/Avatar/Avatar.fragment.tsx","meta":{"name":"Avatar","description":"Visual representation of a user or entity","category":"display","status":"stable","tags":["user","profile","image","identity"]},"usage":{"when":["Displaying user profile pictures","Showing team member lists","Representing entities in lists or cards","User identification in comments or messages"],"whenNot":["Decorative images (use Image)","Logo display (use Logo component)","Large profile headers (use custom layout)"],"guidelines":["Always provide alt text or name for accessibility","Use consistent sizes within the same context","Provide fallback initials when image may not load","Use Avatar.Group for multiple avatars in a row"],"accessibility":["Include meaningful alt text describing the user","Initials should be derived from name for screen readers","Decorative avatars should have empty alt"]},"props":{"src":{"type":"string","description":"Image source URL"},"alt":{"type":"string","description":"Alt text for the image"},"name":{"type":"string","description":"Full name - used to generate initials"},"initials":{"type":"string","description":"Fallback initials (1-2 characters)"},"size":{"type":"enum","description":"Size variant","default":"md","values":["xs","sm","md","lg","xl"]},"shape":{"type":"enum","description":"Shape variant","default":"circle","values":["circle","square"]}},"relations":[{"component":"AvatarGroup","relationship":"parent","note":"Use Avatar.Group for stacked avatar displays"}],"variants":[{"name":"Default","description":"Avatar with image","code":"<Avatar\n src=\"https://i.pravatar.cc/150?u=jane\"\n alt=\"Jane Doe\"\n name=\"Jane Doe\"\n/>"},{"name":"With Initials","description":"Fallback when no image is provided","code":"<Avatar name=\"John Smith\" />"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Avatar name=\"XS\" size=\"xs\" />\n <Avatar name=\"SM\" size=\"sm\" />\n <Avatar name=\"MD\" size=\"md\" />\n <Avatar name=\"LG\" size=\"lg\" />\n <Avatar name=\"XL\" size=\"xl\" />\n</div>"},{"name":"Square Shape","description":"Square variant for app icons or brands","code":"<Avatar name=\"App\" shape=\"square\" />"},{"name":"Group","description":"Multiple avatars stacked together","code":"<Avatar.Group max={3} size=\"md\">\n <Avatar name=\"Alice Johnson\" />\n <Avatar name=\"Bob Smith\" />\n <Avatar name=\"Carol Williams\" />\n <Avatar name=\"David Brown\" />\n <Avatar name=\"Eve Davis\" />\n</Avatar.Group>"}]},"Badge":{"filePath":"src/components/Badge/Badge.fragment.tsx","meta":{"name":"Badge","description":"Compact label for status, counts, or categorization. Draws attention to metadata without dominating the layout.","category":"display","status":"stable","tags":["status","label","tag","count","chip"],"since":"0.1.0"},"usage":{"when":["Showing item status (active, pending, archived)","Displaying counts or quantities inline","Categorizing or tagging content","Highlighting new or updated items"],"whenNot":["Conveying critical errors (use Alert instead)","Long-form status messages (use Alert)","Interactive filtering (use chip/toggle group)","Navigation labels (use tabs or links)"],"guidelines":["Keep badge text under 20 characters","Use dot variant for live status indicators","Pair success/error variants with meaningful labels, not just colors","Use onRemove for user-created tags only, not system-generated badges"],"accessibility":["Badge text must be meaningful without relying on color alone","Removable badges must have accessible dismiss button labels","Avoid using badges as the sole indicator of important state changes"]},"props":{"children":{"type":"node","description":"Badge label text","required":true},"variant":{"type":"enum","description":"Visual style indicating severity or category","default":"default","values":["default","success","warning","error","info"]},"size":{"type":"enum","description":"Badge size","default":"md","values":["sm","md"]},"dot":{"type":"boolean","description":"Show a colored dot indicator before the label","default":"false"},"icon":{"type":"node","description":"Optional icon element before the text"},"onRemove":{"type":"function","description":"Makes the badge removable. Called when X is clicked."}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for prominent, longer messages with actions"},{"component":"Tag","relationship":"sibling","note":"Tag is interactive (clickable/filterable); Badge is display-only"}],"variants":[{"name":"Default","description":"Neutral badge for general labels","code":"<Badge>Default</Badge>"},{"name":"Status Variants","description":"All severity variants for different contexts","code":"<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>\n <Badge variant=\"default\">Default</Badge>\n <Badge variant=\"success\">Active</Badge>\n <Badge variant=\"warning\">Pending</Badge>\n <Badge variant=\"error\">Failed</Badge>\n <Badge variant=\"info\">New</Badge>\n</div>"},{"name":"With Dot","description":"Live status indicators using dot prefix","code":"<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>\n <Badge variant=\"success\" dot>Online</Badge>\n <Badge variant=\"warning\" dot>Away</Badge>\n <Badge variant=\"error\" dot>Offline</Badge>\n</div>"},{"name":"Small Size","description":"Compact badges for dense UIs","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Badge size=\"sm\" variant=\"info\">v2.1</Badge>\n <Badge size=\"sm\" variant=\"success\">Stable</Badge>\n <Badge size=\"md\" variant=\"info\">Standard</Badge>\n</div>"},{"name":"Removable","description":"User-created tags that can be dismissed","code":"<div style={{ display: 'flex', gap: '8px' }}>\n <Badge variant=\"info\" onRemove={() => {}}>React</Badge>\n <Badge variant=\"info\" onRemove={() => {}}>TypeScript</Badge>\n <Badge variant=\"info\" onRemove={() => {}}>CSS</Badge>\n</div>"}]},"Box":{"filePath":"src/components/Box/Box.fragment.tsx","meta":{"name":"Box","description":"Primitive layout component for applying spacing, backgrounds, and borders. A flexible container for building custom layouts.","category":"layout","status":"stable","tags":["layout","container","spacing","primitive","box"],"since":"0.1.0"},"usage":{"when":["Applying consistent padding or margin to content sections","Creating bordered or elevated containers","Wrapping content with semantic HTML elements","Building custom layouts not covered by Stack or Grid"],"whenNot":["Horizontal or vertical stacking (use Stack)","Grid-based layouts (use Grid)","Card-like containers with header/body/footer (use Card)","Simple text styling (use Text)"],"guidelines":["Use padding props instead of inline styles for consistency","Choose semantic HTML elements (section, article) where appropriate","Combine with Stack or Grid for complex layouts","Use background variants from the design system, not custom colors"],"accessibility":["Choose semantic as prop values for proper document structure","Avoid div-soup; use meaningful elements like section, article","Ensure proper heading hierarchy within Box containers"]},"props":{"children":{"type":"node","description":"Content to render inside the box"},"as":{"type":"enum","description":"HTML element to render","default":"div","values":["div","section","article","aside","main","header","footer","nav","span"]},"padding":{"type":"enum","description":"Padding on all sides","values":["none","xs","sm","md","lg","xl"]},"paddingX":{"type":"enum","description":"Horizontal padding","values":["none","xs","sm","md","lg","xl"]},"paddingY":{"type":"enum","description":"Vertical padding","values":["none","xs","sm","md","lg","xl"]},"margin":{"type":"enum","description":"Margin on all sides","values":["none","xs","sm","md","lg","xl","auto"]},"marginX":{"type":"enum","description":"Horizontal margin","values":["none","xs","sm","md","lg","xl","auto"]},"marginY":{"type":"enum","description":"Vertical margin","values":["none","xs","sm","md","lg","xl","auto"]},"background":{"type":"enum","description":"Background color","values":["none","primary","secondary","tertiary","elevated"]},"rounded":{"type":"enum","description":"Border radius","values":["none","sm","md","lg","full"]},"border":{"type":"boolean","description":"Show border","default":"false"},"display":{"type":"enum","description":"Display type","values":["block","inline","inline-block","flex","inline-flex","grid","none"]}},"relations":[{"component":"Stack","relationship":"alternative","note":"Use Stack for directional layouts with gap"},{"component":"Grid","relationship":"alternative","note":"Use Grid for column-based layouts"},{"component":"Card","relationship":"alternative","note":"Use Card for content containers with structure"}],"variants":[{"name":"Default","description":"Basic box with padding","code":"<Box padding=\"md\" background=\"secondary\" rounded=\"md\">\n Content with padding and background\n</Box>"},{"name":"With Border","description":"Bordered container","code":"<Box padding=\"lg\" border rounded=\"md\">\n Bordered content area\n</Box>"},{"name":"Directional Padding","description":"Different horizontal and vertical padding","code":"<Box paddingX=\"xl\" paddingY=\"sm\" background=\"tertiary\" rounded=\"sm\">\n Wide horizontal padding, short vertical\n</Box>"},{"name":"Centered with Auto Margin","description":"Centered content using margin auto","code":"<Box padding=\"md\" marginX=\"auto\" background=\"elevated\" rounded=\"lg\" style={{ maxWidth: '300px' }}>\n Centered content\n</Box>"}]},"Button":{"filePath":"src/components/Button/Button.fragment.tsx","meta":{"name":"Button","description":"Interactive element for user actions and form submissions","category":"forms","status":"stable","tags":["action","button","form","interactive"]},"usage":{"when":["Triggering an action (save, submit, delete, etc.)","Form submission","Opening dialogs or menus","Navigation when action context is needed"],"whenNot":["Simple navigation (use Link)","Toggling state (use Switch or Checkbox)","Selecting from options (use Select or RadioGroup)"],"guidelines":["Use Primary for the main action in a context","Only one Primary button per section/form","Use Danger variant for destructive actions","Loading state should disable the button"],"accessibility":["Button text should describe the action","Avoid generic labels like \"Click here\"","Icon-only buttons need aria-label"]},"props":{"children":{"type":"node","description":"Button label content","required":true},"variant":{"type":"enum","description":"Visual style variant","default":"primary","values":["primary","secondary","ghost","danger"],"constraints":["Only one primary button per context"]},"size":{"type":"enum","description":"Button size","default":"md","values":["sm","md","lg"]},"disabled":{"type":"boolean","description":"Whether the button is disabled","default":false},"onClick":{"type":"function","description":"Click handler"},"type":{"type":"enum","description":"HTML button type attribute","default":"button","values":["button","submit","reset"]}},"relations":[{"component":"Link","relationship":"alternative","note":"Use Link for navigation without action context"},{"component":"IconButton","relationship":"alternative","note":"Use IconButton for icon-only actions"},{"component":"ButtonGroup","relationship":"parent","note":"Use ButtonGroup for related action sets"}],"variants":[{"name":"Primary","description":"Default action button for primary actions","code":"<Button variant=\"primary\">Save Changes</Button>"},{"name":"Secondary","description":"Less prominent action button","code":"<Button variant=\"secondary\">Cancel</Button>"},{"name":"Ghost","description":"Minimal visual weight for subtle actions","code":"<Button variant=\"ghost\">Learn More</Button>"},{"name":"Danger","description":"Destructive action requiring attention","code":"<Button variant=\"danger\">Delete Item</Button>"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n</div>"},{"name":"Disabled","description":"Non-interactive state","code":"<Button disabled>Cannot Click</Button>"}]},"ButtonGroup":{"filePath":"src/components/ButtonGroup/ButtonGroup.fragment.tsx","meta":{"name":"ButtonGroup","description":"Groups related buttons together with consistent spacing and alignment. Useful for action bars, toolbars, and related button sets.","category":"forms","status":"stable","tags":["button","group","toolbar","actions","layout"],"since":"0.2.0"},"usage":{"when":["Grouping related actions together","Creating toolbars or action bars","Form submit/cancel button pairs","Pagination controls"],"whenNot":["Unrelated buttons (use Stack instead)","Navigation links (use nav element)","Single button (no grouping needed)"],"guidelines":["Keep button groups focused on related actions","Use consistent button variants within a group","Consider visual hierarchy - primary action should stand out","Limit to 2-4 buttons per group for clarity"],"accessibility":["Group provides semantic relationship between buttons","Each button remains individually focusable","Consider using role=\"group\" with aria-label for screen readers"]},"props":{"children":{"type":"node","description":"Button elements to group together","required":true},"gap":{"type":"enum","description":"Spacing between buttons","default":"sm","values":["none","xs","sm","md"]},"wrap":{"type":"boolean","description":"Allow buttons to wrap to next line","default":"false"},"align":{"type":"enum","description":"Alignment of buttons","values":["start","center","end"]}},"relations":[{"component":"Button","relationship":"child","note":"ButtonGroup contains Button components"},{"component":"Stack","relationship":"alternative","note":"Use Stack for more general layout needs"}],"variants":[{"name":"Default","description":"Basic button group with default spacing","code":"<ButtonGroup>\n <Button variant=\"secondary\">Cancel</Button>\n <Button variant=\"primary\">Save</Button>\n</ButtonGroup>"},{"name":"Gap Variants","description":"Different spacing options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <ButtonGroup gap=\"none\">\n <Button variant=\"secondary\" size=\"sm\">None</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"xs\">\n <Button variant=\"secondary\" size=\"sm\">XS</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"sm\">\n <Button variant=\"secondary\" size=\"sm\">SM</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"md\">\n <Button variant=\"secondary\" size=\"sm\">MD</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n</div>"},{"name":"Alignment","description":"Different alignment options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <ButtonGroup align=\"start\">\n <Button variant=\"secondary\" size=\"sm\">Start</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"center\">\n <Button variant=\"secondary\" size=\"sm\">Center</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"end\">\n <Button variant=\"secondary\" size=\"sm\">End</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n</div>"},{"name":"Form Actions","description":"Common pattern for form submit/cancel","code":"<ButtonGroup align=\"end\">\n <Button variant=\"ghost\">Cancel</Button>\n <Button variant=\"primary\">Submit</Button>\n</ButtonGroup>"}]},"Card":{"filePath":"src/components/Card/Card.fragment.tsx","meta":{"name":"Card","description":"Container for grouping related content","category":"layout","status":"stable","tags":["container","layout","surface"]},"usage":{"when":["Grouping related pieces of content together","Creating visual separation between content sections","Displaying a preview or summary of an item","Building dashboard widgets or tiles"],"whenNot":["Simple text content that does not need grouping","Modal or dialog content (use Dialog component)","Navigation items (use NavItem or similar)"],"guidelines":["Use consistent card variants within the same context","Cards in a grid should have uniform sizing","Use elevated variant sparingly for emphasis","Interactive cards should have clear hover states"],"accessibility":["Interactive cards should use button or link semantics","Card titles should be appropriate heading levels"]},"props":{"children":{"type":"node","description":"Card content - use Card.Header, Card.Body, Card.Footer sub-components"},"variant":{"type":"enum","description":"Visual style of the card surface","default":"default","values":["default","outlined","elevated"],"constraints":["Use \"elevated\" sparingly to maintain visual hierarchy"]},"padding":{"type":"enum","description":"Internal padding size","default":"md","values":["none","sm","md","lg"]},"onClick":{"type":"function","description":"Click handler - makes card interactive"}},"relations":[{"component":"CardGrid","relationship":"parent","note":"Use CardGrid for responsive card layouts"},{"component":"ListItem","relationship":"alternative","note":"Use ListItem for linear list layouts"}],"variants":[{"name":"Default","description":"Standard card with subtle shadow","code":"<Card>\n <Card.Header>\n <Card.Title>Card Title</Card.Title>\n <Card.Description>A brief description</Card.Description>\n </Card.Header>\n <Card.Body>Card content goes here.</Card.Body>\n</Card>"},{"name":"Outlined","description":"Card with border instead of shadow","code":"<Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Outlined Card</Card.Title>\n </Card.Header>\n <Card.Body>Content with border.</Card.Body>\n</Card>"},{"name":"Elevated","description":"Card with prominent shadow for emphasis","code":"<Card variant=\"elevated\">\n <Card.Header>\n <Card.Title>Featured Item</Card.Title>\n </Card.Header>\n <Card.Body>Important content.</Card.Body>\n</Card>"},{"name":"Interactive","description":"Clickable card","code":"<Card onClick={() => alert('Card clicked!')}>\n <Card.Header>\n <Card.Title>Click Me</Card.Title>\n <Card.Description>This card is interactive</Card.Description>\n </Card.Header>\n <Card.Body>Click anywhere on this card.</Card.Body>\n</Card>"},{"name":"With Footer","description":"Card with header, body, and footer","code":"<Card>\n <Card.Header>\n <Card.Title>Card with Footer</Card.Title>\n <Card.Description>Complete card layout</Card.Description>\n </Card.Header>\n <Card.Body>Main content area.</Card.Body>\n <Card.Footer>Footer actions go here</Card.Footer>\n</Card>"},{"name":"Content Only","description":"Card with just body content","code":"<Card>\n <Card.Body>Just content, no header or footer.</Card.Body>\n</Card>"}],"ai":{"compositionPattern":"compound","subComponents":["Header","Title","Description","Body","Footer"],"requiredChildren":["Body"],"commonPatterns":["<Card><Card.Body>{content}</Card.Body></Card>","<Card><Card.Header><Card.Title>{title}</Card.Title></Card.Header><Card.Body>{content}</Card.Body></Card>","<Card><Card.Header><Card.Title>{title}</Card.Title><Card.Description>{desc}</Card.Description></Card.Header><Card.Body>{content}</Card.Body><Card.Footer>{actions}</Card.Footer></Card>"]}},"Chart":{"filePath":"src/components/Chart/Chart.fragment.tsx","meta":{"name":"Chart","description":"Composable chart wrapper for recharts with theme-aware tooltips, legends, and color integration.","category":"display","status":"stable","tags":["chart","graph","data-visualization","recharts"],"since":"0.3.0"},"usage":{"when":["Displaying data trends over time","Comparing categorical data","Showing distribution or composition","Dashboard data visualizations"],"whenNot":["Simple numeric values (use Text or Badge)","Progress toward a goal (use Progress)","Tabular data without visualization (use Table)"],"guidelines":["Use ChartContainer to wrap recharts chart components","Define a ChartConfig to map data keys to labels and colors","Use FUI CSS variables for colors so charts adapt to theme changes","Use ChartTooltip and ChartLegend for consistent themed overlays"],"accessibility":["Charts include recharts accessibilityLayer by default","Provide meaningful labels in ChartConfig for screen readers","Consider providing a data table alternative for complex charts"]},"props":{"config":{"type":"object","description":"ChartConfig mapping data keys to labels and colors"},"children":{"type":"ReactElement","description":"A recharts chart component (LineChart, BarChart, etc.)"}},"relations":[{"component":"Card","relationship":"parent","note":"Charts are typically placed inside Cards"},{"component":"Progress","relationship":"alternative","note":"Use Progress for single-value completion"},{"component":"Table","relationship":"sibling","note":"Combine with Table for full data views"}],"variants":[{"name":"Line Chart","description":"Multi-series line chart showing trends over time","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n users: { label: 'Users', color: 'var(--fui-color-info)' },\n }}\n >\n <LineChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <ChartLegend />\n <Line type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" strokeWidth={2} dot={false} />\n <Line type=\"monotone\" dataKey=\"users\" stroke=\"var(--fui-color-info)\" strokeWidth={2} dot={false} />\n </LineChart>\n </ChartContainer>\n</div>"},{"name":"Bar Chart","description":"Categorical bar chart comparing device sessions","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n sessions: { label: 'Sessions', color: 'var(--fui-color-accent)' },\n }}\n >\n <BarChart data={deviceData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"device\" />\n <YAxis />\n <ChartTooltip />\n <Bar dataKey=\"sessions\" fill=\"var(--fui-color-accent)\" radius={[4, 4, 0, 0]} />\n </BarChart>\n </ChartContainer>\n</div>"},{"name":"Area Chart","description":"Filled area chart showing revenue trend","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n }}\n >\n <AreaChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <Area type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" fill=\"var(--fui-color-accent)\" fillOpacity={0.15} strokeWidth={2} />\n </AreaChart>\n </ChartContainer>\n</div>"},{"name":"Pie Chart","description":"Donut chart showing browser share distribution","code":"<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n Chrome: { label: 'Chrome', color: 'var(--fui-color-accent)' },\n Firefox: { label: 'Firefox', color: 'var(--fui-color-info)' },\n Safari: { label: 'Safari', color: 'var(--fui-color-success)' },\n Edge: { label: 'Edge', color: 'var(--fui-color-warning)' },\n }}\n >\n <PieChart>\n <ChartTooltip />\n <ChartLegend />\n <Pie\n data={browserData}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={60}\n outerRadius={90}\n strokeWidth={2}\n >\n {browserData.map((entry) => (\n <Cell key={entry.name} fill={entry.color} />\n ))}\n </Pie>\n </PieChart>\n </ChartContainer>\n</div>"}]},"Checkbox":{"filePath":"src/components/Checkbox/Checkbox.fragment.tsx","meta":{"name":"Checkbox","description":"Binary toggle for form fields. Use for options that require explicit submission, unlike Toggle which takes effect immediately.","category":"forms","status":"stable","tags":["checkbox","form","boolean","selection","input"],"since":"0.1.0"},"usage":{"when":["Form fields requiring explicit submission","Multi-select from a list of options","Terms and conditions acceptance","Filter or preference checklists"],"whenNot":["Immediate effect settings (use Toggle)","Single selection from options (use RadioGroup)","Selecting from many options (use Select)"],"guidelines":["Always include a visible label","Use description for additional context when needed","Group related checkboxes visually","Use indeterminate state for parent/child relationships"],"accessibility":["Proper label association","Keyboard accessible (Space to toggle)","Visible focus indicator","Indeterminate state properly announced"]},"props":{"checked":{"type":"boolean","description":"Controlled checked state"},"defaultChecked":{"type":"boolean","description":"Default checked state (uncontrolled)"},"onCheckedChange":{"type":"function","description":"Called when checked state changes"},"indeterminate":{"type":"boolean","description":"Indeterminate state (partial selection)","default":"false"},"disabled":{"type":"boolean","description":"Disable the checkbox","default":"false"},"label":{"type":"string","description":"Label text"},"description":{"type":"string","description":"Description text below the label"},"size":{"type":"enum","description":"Checkbox size","default":"md","values":["sm","md","lg"]}},"relations":[{"component":"Toggle","relationship":"alternative","note":"Use Toggle for immediate-effect settings"},{"component":"Input","relationship":"sibling","note":"Checkbox handles boolean; Input handles text"}],"variants":[{"name":"Default","description":"Basic checkbox with label","code":"<StatefulCheckbox label=\"Accept terms and conditions\" />"},{"name":"With Description","description":"Checkbox with helper text","code":"<StatefulCheckbox\n label=\"Email notifications\"\n description=\"Receive email updates about your account activity\"\n/>"},{"name":"Checked","description":"Pre-checked checkbox","code":"<StatefulCheckbox defaultChecked label=\"Subscribe to newsletter\" />"},{"name":"Indeterminate","description":"Partial selection state","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Checkbox indeterminate label=\"Select all\" />\n <div style={{ marginLeft: '24px', display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <StatefulCheckbox defaultChecked label=\"Option 1\" />\n <StatefulCheckbox label=\"Option 2\" />\n <StatefulCheckbox defaultChecked label=\"Option 3\" />\n </div>\n</div>"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <StatefulCheckbox size=\"sm\" label=\"Small checkbox\" />\n <StatefulCheckbox size=\"md\" label=\"Medium checkbox\" />\n <StatefulCheckbox size=\"lg\" label=\"Large checkbox\" />\n</div>"},{"name":"Disabled","description":"Non-interactive states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Checkbox disabled label=\"Disabled unchecked\" />\n <Checkbox disabled checked label=\"Disabled checked\" />\n</div>"}]},"CodeBlock":{"filePath":"src/components/CodeBlock/CodeBlock.fragment.tsx","meta":{"name":"CodeBlock","description":"Syntax-highlighted code display with copy functionality, theming, diff view, and collapsible sections","category":"display","status":"stable","tags":["code","syntax","highlighting","documentation","developer","diff"]},"usage":{"when":["Displaying code examples in documentation","Showing installation commands","Presenting configuration snippets","Teaching programming concepts","Showing code diffs or changes","Displaying long code files with collapse functionality"],"whenNot":["User-editable code (use code editor)","Very short inline code (use <code> element)","Non-code content (use Text or Card)"],"guidelines":["Always specify the correct language for accurate highlighting","Use filename prop to show source file name in header bar","Use title prop for external labels above the code block","Enable line numbers for longer code samples","Use highlightLines to draw attention to key lines","Use addedLines/removedLines for diff highlighting","Set maxHeight for very long code blocks to prevent layout issues","Use collapsible for code samples that users may want to skim","Choose a theme that matches your documentation style","Keep code examples concise and focused"],"accessibility":["Code is presented in a semantic pre/code structure","Copy button has appropriate aria-label","Keyboard accessible copy functionality","Collapse button has aria-expanded state"]},"props":{"code":{"type":"string","description":"The code string to display","required":true},"language":{"type":"enum","description":"Programming language for syntax highlighting","default":"tsx","values":["tsx","typescript","javascript","jsx","bash","shell","css","scss","sass","json","html","xml","markdown","md","yaml","yml","python","py","ruby","go","rust","java","kotlin","swift","c","cpp","csharp","php","sql","graphql","diff","plaintext"]},"theme":{"type":"enum","description":"Syntax highlighting theme","default":"synthwave-84","values":["synthwave-84","github-dark","github-light","one-dark-pro","dracula","nord","monokai","vitesse-dark","vitesse-light","min-dark","min-light"]},"showCopy":{"type":"boolean","description":"Whether to show the copy button","default":true},"title":{"type":"string","description":"Optional title displayed above the code block (external label)"},"filename":{"type":"string","description":"Optional filename shown in header bar inside code block"},"caption":{"type":"string","description":"Optional caption displayed below the code block"},"showLineNumbers":{"type":"boolean","description":"Whether to display line numbers","default":false},"startLineNumber":{"type":"number","description":"Starting line number (useful for code excerpts)","default":1},"highlightLines":{"type":"array","description":"Lines to highlight (e.g., [1, 3, \"5-7\"])"},"addedLines":{"type":"array","description":"Lines marked as added in diff view (e.g., [2, \"4-6\"])"},"removedLines":{"type":"array","description":"Lines marked as removed in diff view (e.g., [1, 3])"},"wordWrap":{"type":"boolean","description":"Enable word wrapping for long lines","default":false},"maxHeight":{"type":"number","description":"Maximum height in pixels (enables scrolling)"},"collapsible":{"type":"boolean","description":"Allow collapsing/expanding the code block","default":false},"defaultCollapsed":{"type":"boolean","description":"Initial collapsed state (only applies when collapsible is true)","default":false},"collapsedLines":{"type":"number","description":"Number of lines to show when collapsed","default":5},"className":{"type":"string","description":"Additional CSS class name"}},"relations":[{"component":"Card","relationship":"parent","note":"Can be wrapped in Card for additional context"},{"component":"Tabs","relationship":"child","note":"Use in Tabs for showing code in multiple languages"}],"variants":[{"name":"Default","description":"Basic code block with syntax highlighting","code":"<CodeBlock code={`import { Button } from '@fragments-sdk/ui';\n\nfunction App() {\n return <Button>Click me</Button>;\n}`} language=\"tsx\" />"},{"name":"With Filename","description":"Code block with filename in header bar","code":"<CodeBlock filename=\"app.tsx\" code={`import { Button, Card } from '@fragments-sdk/ui';\n\nfunction App() {\n return (\n <Card>\n <Card.Header>Welcome</Card.Header>\n <Card.Content>\n <Button>Get Started</Button>\n </Card.Content>\n </Card>\n );\n}`} language=\"tsx\" />"},{"name":"With Title","description":"Code block with external title label","code":"<CodeBlock title=\"Installation\" code=\"npm install @fragments-sdk/ui\" language=\"bash\" />"},{"name":"With Caption","description":"Code block with footer caption","code":"<CodeBlock\n code={`const API_URL = process.env.NEXT_PUBLIC_API_URL;`}\n language=\"typescript\"\n caption=\"Environment variables must be prefixed with NEXT_PUBLIC_ to be available in the browser.\"\n/>"},{"name":"With Line Numbers","description":"Shows line numbers for reference","code":"<CodeBlock code={`const greeting = \"Hello\";\nconst name = \"World\";\nconsole.log(\\`\\${greeting}, \\${name}!\\`);`} language=\"typescript\" showLineNumbers />"},{"name":"Custom Start Line","description":"Shows code excerpt starting from a specific line number","code":"<CodeBlock\n code={` return (\n <button onClick={() => setCount(c => c + 1)}>\n Count: {count}\n </button>\n );\n}`}\n language=\"tsx\"\n showLineNumbers\n startLineNumber={15}\n caption=\"Lines 15-20 from Counter.tsx\"\n/>"},{"name":"With Highlighted Lines","description":"Emphasizes specific lines of code","code":"<CodeBlock code={`import { useState } from 'react';\n\nfunction Counter() {\n const [count, setCount] = useState(0);\n\n return (\n <button onClick={() => setCount(c => c + 1)}>\n Count: {count}\n </button>\n );\n}`} language=\"tsx\" showLineNumbers highlightLines={[4, '7-9']} />"},{"name":"Diff View","description":"Shows added and removed lines in a diff-like format","code":"<CodeBlock\n code={`import { useState } from 'react';\nimport { useCallback } from 'react';\n\nfunction Counter() {\n const [count, setCount] = useState(0);\n const increment = () => setCount(c => c + 1);\n const increment = useCallback(() => setCount(c => c + 1), []);\n\n return <button onClick={increment}>Count: {count}</button>;\n}`}\n language=\"tsx\"\n showLineNumbers\n removedLines={[6]}\n addedLines={[2, 7]}\n/>"},{"name":"GitHub Dark Theme","description":"Using the GitHub Dark theme","code":"<CodeBlock\n code={`async function fetchUser(id: string) {\n const response = await fetch(\\`/api/users/\\${id}\\`);\n return response.json();\n}`}\n language=\"typescript\"\n theme=\"github-dark\"\n/>"},{"name":"GitHub Light Theme","description":"Using the GitHub Light theme for light backgrounds","code":"<CodeBlock\n code={`def fibonacci(n):\n if n <= 1:\n return n\n return fibonacci(n - 1) + fibonacci(n - 2)`}\n language=\"python\"\n theme=\"github-light\"\n/>"},{"name":"Dracula Theme","description":"Using the popular Dracula theme","code":"<CodeBlock\n code={`fn main() {\n println!(\"Hello, Rust!\");\n}`}\n language=\"rust\"\n theme=\"dracula\"\n/>"},{"name":"Word Wrap","description":"Long lines wrap instead of scrolling horizontally","code":"<CodeBlock\n code={`const longString = \"This is a very long string that would normally cause horizontal scrolling, but with word wrap enabled it will break to the next line instead.\";`}\n language=\"typescript\"\n wordWrap\n/>"},{"name":"Max Height with Scroll","description":"Constrains height with scrollable content","code":"<CodeBlock\n code={`// This code block has a maximum height\nfunction processItems(items: string[]) {\n const results = [];\n for (const item of items) {\n if (item.startsWith('_')) {\n continue;\n }\n const processed = item.trim().toLowerCase();\n if (processed.length > 0) {\n results.push(processed);\n }\n }\n return results;\n}\n\nexport default processItems;`}\n language=\"typescript\"\n maxHeight={150}\n showLineNumbers\n/>"},{"name":"Collapsible","description":"Long code that can be expanded/collapsed","code":"<CodeBlock\n code={`import React, { useState, useEffect } from 'react';\n\ninterface User {\n id: string;\n name: string;\n email: string;\n avatar?: string;\n}\n\nexport function UserProfile({ userId }: { userId: string }) {\n const [user, setUser] = useState<User | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n async function fetchUser() {\n try {\n setLoading(true);\n const response = await fetch(\\`/api/users/\\${userId}\\`);\n if (!response.ok) throw new Error('Failed to fetch');\n const data = await response.json();\n setUser(data);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n }\n fetchUser();\n }, [userId]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div>Error: {error}</div>;\n if (!user) return null;\n\n return (\n <div>\n <h1>{user.name}</h1>\n <p>{user.email}</p>\n </div>\n );\n}`}\n language=\"tsx\"\n showLineNumbers\n collapsible\n defaultCollapsed\n collapsedLines={8}\n/>"},{"name":"JSON","description":"Configuration file example","code":"<CodeBlock title=\"package.json\" code={`{\n \"name\": \"my-app\",\n \"dependencies\": {\n \"@fragments-sdk/ui\": \"^0.3.0\"\n }\n}`} language=\"json\" />"},{"name":"Without Copy Button","description":"Minimal display without copy functionality","code":"<CodeBlock code=\"const simple = true;\" language=\"typescript\" showCopy={false} />"}]},"Collapsible":{"filePath":"src/components/Collapsible/Collapsible.fragment.tsx","meta":{"name":"Collapsible","description":"An interactive component that expands/collapses to show or hide content","category":"layout","status":"stable","tags":["collapsible","expandable","accordion","disclosure","toggle"]},"usage":{"when":["Showing/hiding additional content on demand","Building accordions or expandable sections","Collapsible navigation sections","FAQ sections with expandable answers","Settings panels with grouped options"],"whenNot":["Single item disclosure (use Accordion instead)","Navigation menus with complex interactions (use Menu)","Modal or overlay content (use Dialog or Popover)"],"guidelines":["Use clear trigger labels that indicate expandable content","Consider defaultOpen for primary content users often need","Keep trigger text concise but descriptive","Use chevron icons consistently to indicate collapsible state"],"accessibility":["Trigger must have aria-expanded to indicate state","Content region needs aria-labelledby pointing to trigger","Keyboard: Enter/Space toggles open state","Focus should remain on trigger after toggle"]},"props":{"defaultOpen":{"type":"boolean","description":"Whether the collapsible is initially open (uncontrolled)","default":false},"open":{"type":"boolean","description":"Controlled open state"},"onOpenChange":{"type":"function","description":"Callback when open state changes - (open: boolean) => void"},"disabled":{"type":"boolean","description":"Whether the collapsible is disabled","default":false},"children":{"type":"node","description":"Collapsible.Trigger and Collapsible.Content components","required":true}},"relations":[{"component":"Accordion","relationship":"alternative","note":"Use Accordion for multiple exclusive collapsible sections"},{"component":"Sidebar","relationship":"used-by","note":"Sidebar uses Collapsible for section expand/collapse"},{"component":"Menu","relationship":"alternative","note":"Use Menu for dropdown navigation with actions"}],"variants":[{"name":"Default","description":"Basic collapsible with trigger and content","code":"<Collapsible>\n <Collapsible.Trigger>Click to expand</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content is hidden by default and revealed when the trigger is clicked.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Default Open","description":"Collapsible that starts in the expanded state","code":"<Collapsible defaultOpen>\n <Collapsible.Trigger>Section Title</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content is visible by default. Click the trigger to collapse.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Chevron Start","description":"Collapsible with chevron icon on the left","code":"<Collapsible>\n <Collapsible.Trigger chevronPosition=\"start\">Navigation</Collapsible.Trigger>\n <Collapsible.Content>\n <ul style={{ margin: 0, paddingLeft: '1.5rem' }}>\n <li>Dashboard</li>\n <li>Settings</li>\n <li>Profile</li>\n </ul>\n </Collapsible.Content>\n</Collapsible>"},{"name":"No Chevron","description":"Collapsible without chevron indicator","code":"<Collapsible>\n <Collapsible.Trigger showChevron={false}>Show more details</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Hidden details that appear when triggered.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Disabled","description":"Collapsible in disabled state","code":"<Collapsible disabled>\n <Collapsible.Trigger>Cannot toggle (disabled)</Collapsible.Trigger>\n <Collapsible.Content>\n <p>This content cannot be shown because the collapsible is disabled.</p>\n </Collapsible.Content>\n</Collapsible>"},{"name":"Multiple Sections","description":"Multiple independent collapsible sections","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <Collapsible defaultOpen>\n <Collapsible.Trigger>Getting Started</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Introduction and setup instructions.</p>\n </Collapsible.Content>\n </Collapsible>\n <Collapsible>\n <Collapsible.Trigger>Advanced Usage</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Advanced configuration options.</p>\n </Collapsible.Content>\n </Collapsible>\n <Collapsible>\n <Collapsible.Trigger>API Reference</Collapsible.Trigger>\n <Collapsible.Content>\n <p>Complete API documentation.</p>\n </Collapsible.Content>\n </Collapsible>\n</div>"}]},"ColorPicker":{"filePath":"src/components/ColorPicker/ColorPicker.fragment.tsx","meta":{"name":"ColorPicker","description":"Color selection control with hex input and visual picker. Displays a swatch that opens a full color picker on click.","category":"forms","status":"stable","tags":["color","picker","input","hex","swatch","theme"],"since":"0.2.0"},"usage":{"when":["Theme customization interfaces","Brand color selection","Design tool color inputs","User preference settings for colors"],"whenNot":["Predefined color options only (use RadioGroup with swatches)","Simple color display without editing (use a colored Badge)","Color indication only (use semantic color tokens)"],"guidelines":["Always provide a label to describe what the color is for","Use description to explain color usage or constraints","Consider providing color presets alongside the picker for common choices","Validate hex format (#RRGGBB) on input"],"accessibility":["Label is associated with the color input","Swatch button has appropriate aria-label","Color picker popup is keyboard accessible","Hex input allows direct text entry"]},"props":{"value":{"type":"string","description":"Controlled color value in hex format (#RRGGBB)"},"defaultValue":{"type":"string","description":"Default color for uncontrolled usage","default":"#000000"},"onChange":{"type":"function","description":"Called with new color value when changed"},"label":{"type":"string","description":"Label text above the picker"},"description":{"type":"string","description":"Helper text below the picker"},"disabled":{"type":"boolean","description":"Disable the color picker","default":"false"},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md"]},"showInput":{"type":"boolean","description":"Show the hex input field","default":"true"}},"relations":[{"component":"Input","relationship":"sibling","note":"ColorPicker is a specialized input for colors"},{"component":"RadioGroup","relationship":"alternative","note":"Use RadioGroup for predefined color choices"},{"component":"Field","relationship":"parent","note":"ColorPicker uses Field internally for structure"}],"variants":[{"name":"Default","description":"Basic color picker with label","code":"<ColorPicker\n label=\"Brand Color\"\n defaultValue=\"#3b82f6\"\n/>"},{"name":"With Description","description":"Color picker with helper text","code":"<ColorPicker\n label=\"Primary Color\"\n defaultValue=\"#10b981\"\n description=\"This color will be used for buttons and links\"\n/>"},{"name":"Controlled","description":"Controlled color picker that logs changes","code":"{\n const [color, setColor] = React.useState('#ef4444');\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <ColorPicker\n label=\"Accent Color\"\n value={color}\n onChange={setColor}\n />\n <div style={{ fontSize: '14px', color: 'var(--fui-text-secondary)' }}>\n Selected: {color}\n </div>\n </div>\n );\n}"},{"name":"Multiple Pickers","description":"Multiple color pickers for theme configuration","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '240px' }}>\n <ColorPicker label=\"Primary\" defaultValue=\"#3b82f6\" />\n <ColorPicker label=\"Success\" defaultValue=\"#22c55e\" />\n <ColorPicker label=\"Warning\" defaultValue=\"#f59e0b\" />\n <ColorPicker label=\"Danger\" defaultValue=\"#ef4444\" />\n</div>"},{"name":"Compact","description":"Small size with swatch only (no input)","code":"<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <ColorPicker defaultValue=\"#ef4444\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#f59e0b\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#22c55e\" size=\"sm\" showInput={false} />\n <ColorPicker defaultValue=\"#3b82f6\" size=\"sm\" showInput={false} />\n</div>"},{"name":"Sizes","description":"Different size variants","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '240px' }}>\n <ColorPicker label=\"Small\" defaultValue=\"#3b82f6\" size=\"sm\" />\n <ColorPicker label=\"Medium (default)\" defaultValue=\"#3b82f6\" size=\"md\" />\n</div>"},{"name":"Disabled","description":"Disabled color picker","code":"<ColorPicker\n label=\"Locked Color\"\n defaultValue=\"#64748b\"\n description=\"This color cannot be changed\"\n disabled\n/>"}]},"Combobox":{"filePath":"src/components/Combobox/Combobox.fragment.tsx","meta":{"name":"Combobox","description":"Searchable select input that filters a dropdown list of options as you type. Supports single and multiple selection with chips.","category":"forms","status":"stable","tags":["combobox","autocomplete","search","select","typeahead","form","multiselect"],"since":"0.1.0"},"usage":{"when":["Users need to search/filter through many options","Large option lists where scrolling is impractical","When users might know what they are looking for","Autocomplete or typeahead functionality","Multiple selections from a searchable list"],"whenNot":["Few options (under 5) - use Select or RadioGroup","Free-form text with no predefined options - use Input","Non-searchable single selection - use Select","Actions, not selection - use Menu"],"guidelines":["Include a placeholder that explains what to search for","Provide an empty state message when no results match","Group related options with Combobox.Group for large lists","Keep option text concise and searchable","Use multiple prop for multi-select with chip display"],"accessibility":["Full keyboard navigation support (arrow keys, enter, escape)","Type-ahead filtering within options","Proper ARIA combobox roles and attributes","Screen reader announcements for filtered results","Chip removal via keyboard in multi-select mode"]},"props":{"children":{"type":"node","description":"Combobox input and content","required":true},"value":{"type":"string","description":"Controlled selected value (string for single, string[] for multiple)"},"defaultValue":{"type":"string","description":"Default selected value (uncontrolled)"},"onValueChange":{"type":"function","description":"Called when selection changes"},"multiple":{"type":"boolean","description":"Allow multiple selections with chips","default":"false"},"placeholder":{"type":"string","description":"Placeholder text for the input"},"disabled":{"type":"boolean","description":"Disable the combobox","default":"false"},"autoHighlight":{"type":"boolean","description":"Auto-highlight first matching item while filtering","default":"true"}},"relations":[{"component":"Select","relationship":"alternative","note":"Use Select when search/filtering is not needed"},{"component":"Input","relationship":"sibling","note":"Use Input for free-form text entry"},{"component":"Listbox","relationship":"sibling","note":"Use Listbox for inline option lists"}],"variants":[{"name":"Default","description":"Basic searchable select","code":"<StatefulCombobox placeholder=\"Select a fruit\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"apple\">Apple</Combobox.Item>\n <Combobox.Item value=\"banana\">Banana</Combobox.Item>\n <Combobox.Item value=\"orange\">Orange</Combobox.Item>\n <Combobox.Item value=\"grape\">Grape</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"},{"name":"Multiple Selection","description":"Multi-select with chips","code":"<StatefulCombobox multiple placeholder=\"Select fruits...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"apple\">Apple</Combobox.Item>\n <Combobox.Item value=\"banana\">Banana</Combobox.Item>\n <Combobox.Item value=\"orange\">Orange</Combobox.Item>\n <Combobox.Item value=\"grape\">Grape</Combobox.Item>\n <Combobox.Item value=\"mango\">Mango</Combobox.Item>\n <Combobox.Item value=\"kiwi\">Kiwi</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"},{"name":"With Groups","description":"Options organized into groups","code":"<StatefulCombobox placeholder=\"Search countries...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Group>\n <Combobox.GroupLabel>North America</Combobox.GroupLabel>\n <Combobox.Item value=\"us\">United States</Combobox.Item>\n <Combobox.Item value=\"ca\">Canada</Combobox.Item>\n <Combobox.Item value=\"mx\">Mexico</Combobox.Item>\n </Combobox.Group>\n <Combobox.Group>\n <Combobox.GroupLabel>Europe</Combobox.GroupLabel>\n <Combobox.Item value=\"uk\">United Kingdom</Combobox.Item>\n <Combobox.Item value=\"de\">Germany</Combobox.Item>\n <Combobox.Item value=\"fr\">France</Combobox.Item>\n </Combobox.Group>\n </Combobox.Content>\n</StatefulCombobox>"},{"name":"With Empty State","description":"Shows message when no results match","code":"<StatefulCombobox placeholder=\"Search programming languages...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Empty>No results found</Combobox.Empty>\n <Combobox.Item value=\"js\">JavaScript</Combobox.Item>\n <Combobox.Item value=\"ts\">TypeScript</Combobox.Item>\n <Combobox.Item value=\"py\">Python</Combobox.Item>\n <Combobox.Item value=\"rs\">Rust</Combobox.Item>\n <Combobox.Item value=\"go\">Go</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"},{"name":"Disabled","description":"Disabled combobox","code":"<Combobox disabled placeholder=\"Search...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"1\">Option 1</Combobox.Item>\n </Combobox.Content>\n</Combobox>"}],"ai":{"compositionPattern":"compound","subComponents":["Input","Trigger","Content","Item","ItemIndicator","Empty","Group","GroupLabel"],"requiredChildren":["Input","Content"],"commonPatterns":["<Combobox placeholder=\"Search...\"><Combobox.Input /><Combobox.Content><Combobox.Item value=\"opt1\">{label1}</Combobox.Item><Combobox.Item value=\"opt2\">{label2}</Combobox.Item></Combobox.Content></Combobox>","<Combobox multiple placeholder=\"Select items...\"><Combobox.Input /><Combobox.Content><Combobox.Item value=\"opt1\">{label1}</Combobox.Item><Combobox.Item value=\"opt2\">{label2}</Combobox.Item></Combobox.Content></Combobox>"]}},"ConversationList":{"filePath":"src/components/ConversationList/ConversationList.fragment.tsx","meta":{"name":"ConversationList","description":"Scrollable message container with auto-scroll and history loading","category":"ai","status":"stable","tags":["conversation","chat","messages","scroll","ai","list"]},"usage":{"when":["Building a chat interface with multiple messages","Need auto-scroll behavior when new messages arrive","Require infinite scroll for loading message history","Want date separators between message groups"],"whenNot":["Simple list of items without chat context (use List)","Single message display (use Message directly)","Non-scrolling message layout"],"guidelines":["Use autoScroll=\"smart\" for best UX (only auto-scrolls when near bottom)","Implement onScrollTop for loading older messages","Provide an emptyState for new conversations","Use DateSeparator between messages from different days"],"accessibility":["Uses proper ARIA roles for separators","Typing indicator has aria-label","Smooth scroll respects reduced motion preferences","Keyboard navigation works within scrollable container"]},"props":{"children":{"type":"ReactNode","description":"Message components","required":true},"autoScroll":{"type":"boolean | \"smart\"","description":"Auto-scroll behavior: true (always), false (never), or \"smart\" (only when near bottom)","default":"\"smart\""},"onScrollTop":{"type":"function","description":"Callback when user scrolls to top (for loading history)"},"loadingHistory":{"type":"boolean","description":"Show loading spinner at top when loading history","default":"false"},"emptyState":{"type":"ReactNode","description":"Content to show when conversation is empty"},"scrollTopThreshold":{"type":"number","description":"Pixels from top to trigger onScrollTop","default":"50"},"scrollBottomThreshold":{"type":"number","description":"Pixels from bottom for smart auto-scroll","default":"100"}},"relations":[{"component":"Message","relationship":"child","note":"ConversationList contains Message components"},{"component":"ThinkingIndicator","relationship":"child","note":"Show ThinkingIndicator at bottom while awaiting response"},{"component":"Prompt","relationship":"sibling","note":"Typically paired with Prompt for input"}],"variants":[{"name":"Basic","description":"Simple conversation with messages","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <Message role=\"user\">\n <Message.Content>Hello!</Message.Content>\n </Message>\n <Message role=\"assistant\">\n <Message.Content>Hi there! How can I help you today?</Message.Content>\n </Message>\n <Message role=\"user\">\n <Message.Content>Can you explain React hooks?</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"With Date Separators","description":"Messages grouped by date","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <ConversationList.DateSeparator date={new Date(Date.now() - 86400000)} />\n <Message role=\"user\">\n <Message.Content>A message from yesterday</Message.Content>\n </Message>\n <ConversationList.DateSeparator date={new Date()} />\n <Message role=\"assistant\">\n <Message.Content>And a message from today!</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"With Typing Indicator","description":"Shows assistant is typing","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList>\n <Message role=\"user\">\n <Message.Content>What is TypeScript?</Message.Content>\n </Message>\n <ConversationList.TypingIndicator name=\"Assistant\" />\n </ConversationList>\n</div>"},{"name":"Loading History","description":"Loading older messages","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList loadingHistory>\n <Message role=\"user\">\n <Message.Content>This is the latest message</Message.Content>\n </Message>\n </ConversationList>\n</div>"},{"name":"Empty State","description":"No messages yet","code":"<div style={{ height: '300px', border: '1px solid #e4e4e7', borderRadius: '8px' }}>\n <ConversationList\n emptyState={\n <div style={{ textAlign: 'center', color: '#71717a', padding: '2rem' }}>\n <p>No messages yet</p>\n <p style={{ fontSize: '12px' }}>Start a conversation!</p>\n </div>\n }\n >\n {/* No messages */}\n </ConversationList>\n</div>"}]},"Dialog":{"filePath":"src/components/Dialog/Dialog.fragment.tsx","meta":{"name":"Dialog","description":"Modal overlay for focused user interactions. Use for confirmations, forms, or content requiring full attention.","category":"feedback","status":"stable","tags":["modal","dialog","overlay","popup","confirmation"],"since":"0.1.0"},"usage":{"when":["Confirming destructive actions (delete, discard changes)","Collecting focused input (forms, settings)","Displaying content that requires acknowledgment","Multi-step workflows that need isolation"],"whenNot":["Simple tooltips or hints (use Tooltip)","Contextual menus (use Menu or Popover)","Non-blocking notifications (use Toast or Alert)","Simple confirmation that can be inline (use Alert)"],"guidelines":["Keep dialog content focused on a single task","Provide clear primary and secondary actions","Use descriptive title that explains the purpose","Allow dismissal via backdrop click or close button for non-critical dialogs","Trap focus within the dialog for accessibility"],"accessibility":["Automatically traps focus within the dialog","Closes on Escape key press","Returns focus to trigger element on close","Uses role=\"dialog\" with proper aria attributes"]},"props":{"children":{"type":"node","description":"Dialog content (use Dialog.Content, Dialog.Header, etc.)","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether to render as modal (blocks interaction with rest of page)","default":"true"}},"relations":[{"component":"Popover","relationship":"alternative","note":"Use Popover for non-modal contextual content"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action lists"},{"component":"Alert","relationship":"sibling","note":"Use Alert for inline notifications"}],"variants":[{"name":"Default","description":"Basic dialog with header, body, and footer","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button>Open Dialog</Button>\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Close />\n <Dialog.Header>\n <Dialog.Title>Dialog Title</Dialog.Title>\n <Dialog.Description>\n A brief description of what this dialog is for.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <p>Dialog content goes here. You can include forms, text, or any other content.</p>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"primary\">Confirm</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"},{"name":"Confirmation","description":"Destructive action confirmation","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button variant=\"danger\">Delete Item</Button>\n </Dialog.Trigger>\n <Dialog.Content size=\"sm\">\n <Dialog.Header>\n <Dialog.Title>Delete item?</Dialog.Title>\n <Dialog.Description>\n This action cannot be undone. The item will be permanently removed.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"danger\">Delete</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"},{"name":"Large","description":"Large dialog for complex content","code":"<Dialog>\n <Dialog.Trigger asChild>\n <Button>Open Large Dialog</Button>\n </Dialog.Trigger>\n <Dialog.Content size=\"lg\">\n <Dialog.Close />\n <Dialog.Header>\n <Dialog.Title>Settings</Dialog.Title>\n <Dialog.Description>\n Configure your application preferences.\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <p>This dialog has more space for complex forms or content layouts.</p>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Dialog.Close>\n <Button variant=\"primary\">Save Changes</Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Close","Header","Title","Description","Body","Footer"],"requiredChildren":["Content"],"commonPatterns":["<Dialog><Dialog.Trigger><Button>Open</Button></Dialog.Trigger><Dialog.Content><Dialog.Header><Dialog.Title>{title}</Dialog.Title></Dialog.Header><Dialog.Body>{content}</Dialog.Body><Dialog.Footer><Dialog.Close><Button variant=\"secondary\">Cancel</Button></Dialog.Close><Button>Confirm</Button></Dialog.Footer></Dialog.Content></Dialog>"]}},"EmptyState":{"filePath":"src/components/EmptyState/EmptyState.fragment.tsx","meta":{"name":"EmptyState","description":"Placeholder for empty content areas. Provides context, guidance, and actions when no data is available.","category":"feedback","status":"stable","tags":["empty","placeholder","no-data","zero-state","blank-slate"],"since":"0.1.0"},"usage":{"when":["Empty lists, tables, or search results","New user onboarding (no content yet)","Filtered views with no matches","Error states where content failed to load"],"whenNot":["Loading states (use skeleton or spinner)","Error messages with retry (use Alert)","Temporary messages (use Toast)"],"guidelines":["Always explain why the area is empty","Provide a clear action to resolve the empty state","Use appropriate icons to reinforce the message","Keep messaging positive and actionable"],"accessibility":["Empty state content is accessible to screen readers","Action buttons follow button accessibility guidelines"]},"props":{"children":{"type":"node","description":"EmptyState content - use EmptyState.Icon, EmptyState.Title, EmptyState.Description, EmptyState.Actions sub-components"},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md","lg"]}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for error states with retry"},{"component":"Progress","relationship":"alternative","note":"Use Progress/Spinner for loading states"}],"variants":[{"name":"Default","description":"Basic empty state with action","code":"<EmptyState>\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>No projects yet</EmptyState.Title>\n <EmptyState.Description>Get started by creating your first project.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Project</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"No Results","description":"Empty search results","code":"<EmptyState>\n <EmptyState.Icon><SearchIcon /></EmptyState.Icon>\n <EmptyState.Title>No results found</EmptyState.Title>\n <EmptyState.Description>Try adjusting your search terms or filters.</EmptyState.Description>\n <EmptyState.Actions>\n <Button variant=\"secondary\">Clear Filters</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"With Secondary Action","description":"Empty state with two actions","code":"<EmptyState>\n <EmptyState.Icon><InboxIcon /></EmptyState.Icon>\n <EmptyState.Title>Inbox is empty</EmptyState.Title>\n <EmptyState.Description>You have no new messages.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Compose Message</Button>\n <Button variant=\"secondary\">View Archive</Button>\n </EmptyState.Actions>\n</EmptyState>"},{"name":"Small","description":"Compact empty state for inline use","code":"<EmptyState size=\"sm\">\n <EmptyState.Title>No items</EmptyState.Title>\n <EmptyState.Description>Add items to see them here.</EmptyState.Description>\n</EmptyState>"},{"name":"Large","description":"Prominent empty state for full-page use","code":"<EmptyState size=\"lg\">\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>Welcome to your workspace</EmptyState.Title>\n <EmptyState.Description>\n This is where your projects will appear. Create your first project to get started.\n </EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Your First Project</Button>\n </EmptyState.Actions>\n</EmptyState>"}],"ai":{"compositionPattern":"compound","subComponents":["Icon","Title","Description","Actions"],"requiredChildren":["Title"],"commonPatterns":["<EmptyState><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description></EmptyState>","<EmptyState><EmptyState.Icon>{icon}</EmptyState.Icon><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description><EmptyState.Actions><Button>{action}</Button></EmptyState.Actions></EmptyState>"]}},"Field":{"filePath":"src/components/Field/Field.fragment.tsx","meta":{"name":"Field","description":"Compositional form field wrapper providing validation, labels, descriptions, and error messages. Use for advanced form needs beyond baked-in Input/Textarea props.","category":"forms","status":"stable","tags":["form","field","validation","label","error","input","accessible"],"since":"0.4.0"},"usage":{"when":["You need granular validation with match-based error messages","Custom form controls need accessible labels and descriptions","Server-side errors need to be distributed to specific fields","You need dirty/touched tracking or custom validation logic"],"whenNot":["Simple inputs with basic label and helper text (use Input with label prop)","Standalone selects or textareas with built-in error display"],"guidelines":["Always provide a Field.Label for accessibility","Wrap any form control in Field.Control to connect it to the field context","Use match prop on Field.Error for granular native validation messages","Wrap in Form to enable server-side error distribution by field name"],"accessibility":["Label automatically linked to control via aria-labelledby","Description linked via aria-describedby","Error messages announced to screen readers","Supports data-disabled and data-invalid attributes for styling"]},"props":{"name":{"type":"string","description":"Field name, used for error distribution from Form"},"disabled":{"type":"boolean","description":"Disables the field and its control"},"invalid":{"type":"boolean","description":"Marks the field as invalid"},"validate":{"type":"function","description":"Custom validation function returning error string(s) or null"},"validationMode":{"type":"enum","description":"When to trigger validation","values":["onSubmit","onBlur","onChange"]},"validationDebounceTime":{"type":"number","description":"Debounce time in ms for onChange validation"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for simple fields with built-in label/error"},{"component":"Form","relationship":"parent","note":"Wrap in Form for server-side error distribution"},{"component":"Fieldset","relationship":"sibling","note":"Use Fieldset to group related fields"}],"variants":[{"name":"Single field","description":"A single field with label, control, and description","code":"<Field name=\"email\">\n <Field.Label>Email address</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Description>We will never share your email.</Field.Description>\n</Field>"},{"name":"Two-column layout","description":"Fields arranged in a two-column grid","code":"<Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"typeMismatch\">Enter a valid email address</Field.Error>\n </Field>\n </Grid.Item>\n</Grid>"},{"name":"Custom validation","description":"Field with custom validate function","code":"<Field\n name=\"age\"\n validate={(value) => {\n const num = Number(value);\n if (isNaN(num) || num < 18) return 'Must be 18 or older';\n return null;\n }}\n validationMode=\"onChange\"\n validationDebounceTime={500}\n>\n <Field.Label>Age</Field.Label>\n <Field.Control>\n <Input type=\"number\" placeholder=\"18\" />\n </Field.Control>\n <Field.Description>You must be at least 18 years old.</Field.Description>\n <Field.Error match=\"customError\" />\n</Field>"}]},"Fieldset":{"filePath":"src/components/Fieldset/Fieldset.fragment.tsx","meta":{"name":"Fieldset","description":"Groups related form fields with an accessible legend. Use to organize forms into logical sections.","category":"forms","status":"stable","tags":["form","fieldset","group","legend","accessible"],"since":"0.4.0"},"usage":{"when":["Grouping related fields in a form (e.g., address, personal info)","Disabling a group of fields together","Providing an accessible group label for screen readers"],"whenNot":["Generic visual grouping (use Card)","Single field wrapping (use Field)"],"guidelines":["Always include a Fieldset.Legend for accessibility","Use disabled prop to disable all fields within the group","Use Grid inside Fieldset for multi-column layouts"],"accessibility":["Renders semantic fieldset element","Legend provides accessible group label","Disabled state propagates to all child fields"]},"props":{"disabled":{"type":"boolean","description":"Disables all fields within the fieldset"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Field","relationship":"sibling","note":"Contains Field components"},{"component":"Form","relationship":"parent","note":"Used within a Form"},{"component":"Card","relationship":"alternative","note":"Use Card for non-form visual grouping"}],"variants":[{"name":"Two-column layout","description":"Fieldset with Grid for side-by-side fields","code":"<Fieldset>\n <Fieldset.Legend>Personal Information</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n </Grid>\n</Fieldset>"},{"name":"Mixed controls","description":"Fieldset with textarea, select, and checkbox","code":"<Fieldset>\n <Fieldset.Legend>Preferences</Fieldset.Legend>\n <Field name=\"bio\">\n <Field.Label>Bio</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"Tell us about yourself\" rows={3} />\n </Field.Control>\n <Field.Description>Brief description for your profile.</Field.Description>\n </Field>\n <Field name=\"role\">\n <Field.Label>Role</Field.Label>\n <Field.Control>\n <Select placeholder=\"Select a role\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"admin\">Admin</Select.Item>\n <Select.Item value=\"editor\">Editor</Select.Item>\n <Select.Item value=\"viewer\">Viewer</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n <Field name=\"newsletter\">\n <Field.Control>\n <Checkbox label=\"Subscribe to newsletter\" />\n </Field.Control>\n </Field>\n</Fieldset>"},{"name":"Disabled","description":"Disabled fieldset prevents interaction with all children","code":"<Fieldset disabled>\n <Fieldset.Legend>Locked Section</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"lockedFirst\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lockedLast\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Doe\" />\n </Field.Control>\n </Field>\n </Grid>\n <Field name=\"lockedCheck\">\n <Field.Control>\n <Checkbox label=\"Cannot toggle\" defaultChecked />\n </Field.Control>\n </Field>\n</Fieldset>"}]},"Form":{"filePath":"src/components/Form/Form.fragment.tsx","meta":{"name":"Form","description":"Form wrapper that handles server-side error distribution to Field components. Pairs with Field for complete form validation.","category":"forms","status":"stable","tags":["form","validation","errors","submit","server"],"since":"0.4.0"},"usage":{"when":["Building forms that need server-side error handling","Distributing validation errors to specific fields by name","Combining client and server validation in one form"],"whenNot":["Simple forms with only client-side validation (use native form or Field alone)","Non-form layouts (use Grid or Card)"],"guidelines":["Pass errors as Record<string, string | string[]> keyed by field name","Use onClearErrors to clear errors when fields are modified","Use onFormSubmit for form submission handling","Field components with matching name prop display errors automatically","Use Grid inside Form or Fieldset for multi-column layouts"],"accessibility":["Renders semantic form element","Error messages linked to fields via aria-describedby"]},"props":{"errors":{"type":"object","description":"Server-side errors keyed by field name"},"onFormSubmit":{"type":"function","description":"Form submission handler"},"onClearErrors":{"type":"function","description":"Called with field name when errors should be cleared"},"className":{"type":"string","description":"Additional CSS class"}},"relations":[{"component":"Field","relationship":"sibling","note":"Contains Field components for error distribution"},{"component":"Fieldset","relationship":"sibling","note":"Use Fieldset to group fields within a Form"},{"component":"Button","relationship":"sibling","note":"Use Button type=\"submit\" for form submission"}],"variants":[{"name":"Sign up","description":"Registration form with two-column name fields","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"typeMismatch\">Enter a valid email address</Field.Error>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"password\">\n <Field.Label>Password</Field.Label>\n <Field.Control>\n <Input type=\"password\" placeholder=\"At least 8 characters\" />\n </Field.Control>\n <Field.Description>Must be at least 8 characters</Field.Description>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"terms\">\n <Field.Control>\n <Checkbox label=\"I agree to the terms and conditions\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Create Account</Button>\n </Grid.Item>\n </Grid>\n</Form>"},{"name":"Profile settings","description":"Multi-section form with Fieldsets, toggles, and radio group","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Fieldset>\n <Fieldset.Legend>Profile</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"displayName\">\n <Field.Label>Display Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"How others see you\" />\n </Field.Control>\n </Field>\n <Field name=\"timezone\">\n <Field.Label>Timezone</Field.Label>\n <Field.Control>\n <Select placeholder=\"Select timezone\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"utc\">UTC</Select.Item>\n <Select.Item value=\"est\">Eastern (EST)</Select.Item>\n <Select.Item value=\"pst\">Pacific (PST)</Select.Item>\n <Select.Item value=\"gmt\">GMT</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"bio\">\n <Field.Label>Bio</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"Tell us about yourself\" rows={3} maxLength={280} />\n </Field.Control>\n <Field.Description>Max 280 characters</Field.Description>\n </Field>\n </Grid.Item>\n </Grid>\n </Fieldset>\n <Fieldset>\n <Fieldset.Legend>Notifications</Fieldset.Legend>\n <Field name=\"emailNotifs\">\n <Field.Control>\n <Toggle label=\"Email notifications\" />\n </Field.Control>\n </Field>\n <Field name=\"marketingEmails\">\n <Field.Control>\n <Toggle label=\"Marketing emails\" />\n </Field.Control>\n </Field>\n <Field name=\"frequency\">\n <Field.Label>Digest frequency</Field.Label>\n <Field.Control>\n <RadioGroup name=\"frequency\" orientation=\"vertical\">\n <RadioGroup.Item value=\"daily\" label=\"Daily\" />\n <RadioGroup.Item value=\"weekly\" label=\"Weekly\" />\n <RadioGroup.Item value=\"monthly\" label=\"Monthly\" />\n </RadioGroup>\n </Field.Control>\n </Field>\n </Fieldset>\n <Button type=\"submit\" variant=\"primary\">Save Changes</Button>\n</Form>"},{"name":"Contact form","description":"Contact form with select, textarea, and checkbox","code":"<Form onFormSubmit={(e) => { e.preventDefault(); }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"name\">\n <Field.Label>Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Your name\" />\n </Field.Control>\n </Field>\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"you@example.com\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"subject\">\n <Field.Label>Subject</Field.Label>\n <Field.Control>\n <Select placeholder=\"What is this about?\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"general\">General Inquiry</Select.Item>\n <Select.Item value=\"support\">Technical Support</Select.Item>\n <Select.Item value=\"billing\">Billing</Select.Item>\n <Select.Item value=\"feedback\">Feedback</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"message\">\n <Field.Label>Message</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"How can we help?\" rows={5} />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Field name=\"copy\">\n <Field.Control>\n <Checkbox label=\"Send me a copy\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Send Message</Button>\n </Grid.Item>\n </Grid>\n</Form>"},{"name":"With server errors","description":"Form displaying server-side validation errors","code":"<Form errors={{ username: 'Username is already taken', email: 'Email is already registered' }}>\n <Grid columns={2} gap=\"md\">\n <Field name=\"username\">\n <Field.Label>Username</Field.Label>\n <Field.Control>\n <Input defaultValue=\"janedoe\" />\n </Field.Control>\n <Field.Error match=\"customError\" />\n </Field>\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" defaultValue=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"customError\" />\n </Field>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Submit</Button>\n </Grid.Item>\n </Grid>\n</Form>"}]},"Grid":{"filePath":"src/components/Grid/Grid.fragment.tsx","meta":{"name":"Grid","description":"Responsive grid layout for arranging items in columns with consistent spacing","category":"layout","status":"stable","tags":["grid","layout","columns","responsive"]},"usage":{"when":["Arranging cards, tiles, or media in a responsive grid","Building form layouts with multi-column fields","Creating dashboard layouts with widgets","Any content that should reflow across breakpoints"],"whenNot":["Single-column stacked content (use a simple flex column or Stack)","Navigation bars or toolbars (use a dedicated nav component)","Content that must not wrap (use inline layout)"],"guidelines":["Use columns=\"auto\" with minChildWidth for grids that adapt without breakpoints","Use responsive object { base: 1, md: 2, lg: 3 } when you need explicit control per breakpoint","Use fixed column counts when exact column control is needed and responsiveness is not required","Use Grid.Item with colSpan to create asymmetric layouts within a fixed grid","Keep gap consistent within a context — md is the default and works for most cases"],"accessibility":["Grid is purely visual — it does not affect reading order or semantics","Ensure logical source order matches visual order for screen readers"]},"props":{"columns":{"type":"union","description":"Number of columns: a number (1-12), a responsive object { base, sm, md, lg, xl }, or \"auto\" for auto-fill","default":1,"constraints":["Use \"auto\" with minChildWidth for fully fluid layouts","Use responsive object for explicit breakpoint control: { base: 1, md: 2, lg: 3 }"]},"minChildWidth":{"type":"string","description":"Minimum width for auto-fill columns (e.g., \"16rem\", \"250px\")","constraints":["Only applies when columns=\"auto\""]},"gap":{"type":"enum","description":"Gap between grid items, mapped to spacing tokens","default":"md","values":["none","xs","sm","md","lg","xl"]},"alignItems":{"type":"enum","description":"Vertical alignment of items within their cells","values":["start","center","end","stretch"]},"justifyItems":{"type":"enum","description":"Horizontal alignment of items within their cells","values":["start","center","end","stretch"]},"padding":{"type":"enum","description":"Internal padding of the grid container","default":"none","values":["none","sm","md","lg"]}},"relations":[{"component":"Card","relationship":"child","note":"Grid commonly contains Card components for dashboard and tile layouts"},{"component":"Separator","relationship":"sibling","note":"Use Separator between grid sections"}],"variants":[{"name":"Default","description":"Basic 3-column grid","code":"<Grid columns={3} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Item 3</div>\n</Grid>"},{"name":"Responsive","description":"1 column on mobile, 2 on tablet, 3 on desktop","code":"<Grid columns={{ base: 1, md: 2, lg: 3 }} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 3</div>\n</Grid>"},{"name":"Auto-fill","description":"Responsive grid that auto-fills based on minimum child width","code":"<Grid columns=\"auto\" minChildWidth=\"12rem\" gap=\"md\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 1</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 2</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 3</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Card 4</div>\n</Grid>"},{"name":"With Spanning","description":"Grid items spanning multiple columns","code":"<Grid columns={4} gap=\"md\">\n <Grid.Item colSpan={2}>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Spans 2 cols</div>\n </Grid.Item>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>1 col</div>\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>1 col</div>\n <Grid.Item colSpan=\"full\">\n <div style={{ padding: 'var(--fui-space-2)', background: 'var(--fui-bg-secondary)' }}>Full width</div>\n </Grid.Item>\n</Grid>"},{"name":"Form Layout","description":"Two-column form that collapses to single column on mobile","code":"<Grid columns={{ base: 1, md: 2 }} gap=\"md\">\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>First Name</div>\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>Last Name</div>\n <Grid.Item colSpan=\"full\">\n <div style={{ padding: 'var(--fui-space-1)', background: 'var(--fui-bg-secondary)' }}>Email Address</div>\n </Grid.Item>\n</Grid>"}]},"Header":{"filePath":"src/components/Header/Header.fragment.tsx","meta":{"name":"Header","description":"Composable header with slots for brand, navigation, search, and actions. Designed for use within AppShell with responsive mobile support.","category":"navigation","status":"stable","tags":["header","navigation","navbar","brand","layout"],"since":"0.5.0"},"usage":{"when":["Primary site or app header inside AppShell","Navigation bar with branding (stacked layout)","Search and actions bar (sidebar-inset layout)","Header with responsive mobile menu trigger"],"whenNot":["Simple page titles (use heading elements)","Footer navigation (use Footer component)","Standalone sidebar navigation (use Sidebar directly)"],"guidelines":["Use Header.SkipLink for accessibility (skip to main content)","In stacked layout: include Header.Brand for logo","In sidebar-inset layout: omit Header.Brand (logo in sidebar)","Header.Trigger integrates with SidebarProvider for mobile menus","Header.Nav is hidden on mobile; use sidebar for mobile navigation","Use Header.Spacer to push items apart"],"accessibility":["Include Header.SkipLink for keyboard users","Navigation has aria-label for screen readers","Active nav items use aria-current=\"page\"","Mobile trigger has aria-expanded state"]},"props":{"children":{"type":"node","description":"Header content (use Header.Brand, Header.Nav, etc.)","required":true},"height":{"type":"string","description":"Header height","default":"56px"},"position":{"type":"enum","description":"Position behavior (usually controlled by AppShell)","default":"static","values":["static","fixed","sticky"]}},"relations":[{"component":"AppShell","relationship":"parent","note":"Header is typically used inside AppShell.Header"},{"component":"Sidebar","relationship":"sibling","note":"Header.Trigger toggles Sidebar on mobile"},{"component":"ThemeToggle","relationship":"child","note":"ThemeToggle is commonly placed in Header.Actions"}],"variants":[{"name":"For Stacked Layout","description":"Header with brand, nav, and actions. Use with AppShell layout=\"stacked\".","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Brand href=\"/\">MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/dashboard\" active>Dashboard</Header.NavItem>\n <Header.NavItem href=\"/projects\">Projects</Header.NavItem>\n <Header.NavItem href=\"/settings\">Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n <Button variant=\"secondary\" size=\"sm\">Sign In</Button>\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"For Sidebar Inset Layout","description":"Header without brand (logo is in sidebar). Use with AppShell layout=\"sidebar-inset\".","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Search>\n <Input placeholder=\"Search...\" style={{ width: '240px' }} />\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"Minimal","description":"Clean header with just trigger and actions","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"With Search","description":"Header featuring a prominent search input","code":"<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.Brand>Docs</Header.Brand>\n <Header.Search>\n <div style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n background: 'var(--fui-bg-secondary)',\n borderRadius: '6px',\n color: 'var(--fui-text-tertiary)',\n fontSize: '14px',\n width: '280px'\n }}>\n <SearchIcon /> Search documentation...\n </div>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n </Header.Actions>\n </Header>\n</ThemeProvider>"},{"name":"With Skip Link","description":"Accessible header with skip link for keyboard navigation","code":"<Header>\n <Header.SkipLink href=\"#main-content\">Skip to content</Header.SkipLink>\n <Header.Brand>Accessible App</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/\" active>Home</Header.NavItem>\n <Header.NavItem href=\"/about\">About</Header.NavItem>\n </Header.Nav>\n</Header>"}],"ai":{"compositionPattern":"compound","subComponents":["SkipLink","Trigger","Brand","Nav","NavItem","Search","Spacer","Actions"],"commonPatterns":["<Header><Header.Brand href=\"/\">{appName}</Header.Brand><Header.Nav><Header.NavItem href=\"/home\" active>Home</Header.NavItem></Header.Nav><Header.Spacer /><Header.Actions>{actions}</Header.Actions></Header>"]}},"Image":{"filePath":"src/components/Image/Image.fragment.tsx","meta":{"name":"Image","description":"Responsive image component with aspect ratio control, loading states, and error fallbacks. Handles image display with consistent styling.","category":"display","status":"stable","tags":["image","media","photo","picture","visual"],"since":"0.1.0"},"usage":{"when":["Displaying product images in cards or grids","Hero images with specific aspect ratios","User-uploaded content that may fail to load","Thumbnails in lists or galleries"],"whenNot":["User avatars (use Avatar component)","Icons or symbols (use Icon component)","Background images (use CSS background-image)","SVG illustrations (use inline SVG or Image component)"],"guidelines":["Always provide meaningful alt text for accessibility","Use appropriate aspect ratios for consistent layouts","Provide fallback content for failed loads","Use objectFit=\"contain\" for logos to preserve aspect ratio"],"accessibility":["Alt text is required and must describe the image content","Decorative images should have empty alt=\"\"","Avoid text in images; if necessary, describe the text in alt","Ensure sufficient contrast between image and surrounding content"]},"props":{"src":{"type":"string","description":"Image source URL","required":true},"alt":{"type":"string","description":"Alt text for accessibility (required)","required":true},"aspectRatio":{"type":"enum","description":"Aspect ratio of the image container","default":"auto","values":["1:1","4:3","16:9","21:9","auto"]},"objectFit":{"type":"enum","description":"How the image fits within its container","default":"cover","values":["cover","contain","fill","none"]},"width":{"type":"string | number","description":"Width of the image container"},"height":{"type":"string | number","description":"Height of the image container"},"rounded":{"type":"enum","description":"Border radius","default":"none","values":["none","sm","md","lg","full"]},"fallback":{"type":"node","description":"Content to show while loading or on error"}},"relations":[{"component":"Card","relationship":"child","note":"Common pattern to use Image at top of product cards"},{"component":"Avatar","relationship":"alternative","note":"Use Avatar for user profile pictures"}],"variants":[{"name":"Default","description":"Basic image display","code":"<Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=400&h=300&fit=crop\"\n alt=\"Code on a screen\"\n width={300}\n/>"},{"name":"Aspect Ratios","description":"Different aspect ratio options","code":"<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=200&h=200&fit=crop\"\n alt=\"Square image\"\n aspectRatio=\"1:1\"\n width={100}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=200&h=150&fit=crop\"\n alt=\"4:3 image\"\n aspectRatio=\"4:3\"\n width={120}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=320&h=180&fit=crop\"\n alt=\"16:9 image\"\n aspectRatio=\"16:9\"\n width={160}\n />\n</div>"},{"name":"Rounded Corners","description":"Border radius options","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"No rounding\"\n rounded=\"none\"\n width={80}\n height={80}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"Medium rounding\"\n rounded=\"md\"\n width={80}\n height={80}\n />\n <Image\n src=\"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=100&h=100&fit=crop\"\n alt=\"Full rounding\"\n rounded=\"full\"\n width={80}\n height={80}\n />\n</div>"},{"name":"With Fallback","description":"Fallback content for loading/error states","code":"<Image\n src=\"https://invalid-url.example/image.jpg\"\n alt=\"Image that will fail\"\n width={200}\n height={150}\n rounded=\"md\"\n fallback={\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', background: 'var(--fui-color-surface-secondary)' }}>\n <span style={{ color: 'var(--fui-color-text-tertiary)' }}>No image</span>\n </div>\n }\n/>"}]},"Input":{"filePath":"src/components/Input/Input.fragment.tsx","meta":{"name":"Input","description":"Text input field for single-line user data entry","category":"forms","status":"stable","tags":["form","input","text"]},"usage":{"when":["Collecting single-line text data from users","Email, password, phone number, or URL input","Search fields","Short form fields (name, title, etc.)"],"whenNot":["Multi-line text (use Textarea)","Selecting from predefined options (use Select)","Boolean input (use Checkbox or Switch)","Date/time input (use DatePicker)"],"guidelines":["Always provide a label for accessibility","Use appropriate input type for data validation","Show validation errors with error prop and helperText","Use placeholder for format hints, not labels"],"accessibility":["Labels must be associated with inputs","Error messages should be announced to screen readers","Required fields should be indicated"]},"props":{"value":{"type":"string","description":"Current input value (controlled)"},"placeholder":{"type":"string","description":"Placeholder text shown when empty","constraints":["Use for format hints only, not as a replacement for labels"]},"type":{"type":"enum","description":"HTML input type for validation and keyboard","default":"text","values":["text","email","password","number","tel","url"]},"disabled":{"type":"boolean","description":"Whether the input is interactive","default":false},"error":{"type":"boolean","description":"Whether to show error styling","default":false},"label":{"type":"string","description":"Label text displayed above input"},"helperText":{"type":"string","description":"Helper or error message below input"},"onChange":{"type":"function","description":"Called with new value on change"}},"relations":[{"component":"Textarea","relationship":"alternative","note":"Use Textarea for multi-line text input"},{"component":"Select","relationship":"alternative","note":"Use Select when choosing from predefined options"},{"component":"FormField","relationship":"parent","note":"Wrap in FormField for consistent form layout"}],"variants":[{"name":"Default","description":"Basic text input","code":"<Input label=\"Name\" placeholder=\"Enter your name\" />"},{"name":"With Value","description":"Input with pre-filled value","code":"<Input label=\"Email\" type=\"email\" value=\"user@example.com\" />"},{"name":"With Helper","description":"Input with helper text","code":"<Input\n label=\"Password\"\n type=\"password\"\n placeholder=\"Create a password\"\n helperText=\"Must be at least 8 characters\"\n/>"},{"name":"Error State","description":"Input showing validation error","code":"<Input\n label=\"Email\"\n type=\"email\"\n value=\"invalid-email\"\n error\n helperText=\"Please enter a valid email address\"\n/>"},{"name":"Disabled","description":"Non-interactive input","code":"<Input label=\"Username\" value=\"readonly-user\" disabled />"}]},"Icon":{"filePath":"src/components/Icon/Icon.fragment.tsx","meta":{"name":"Icon","description":"Wrapper for Phosphor icons with consistent sizing and semantic colors. Provides standardized icon rendering across the design system.","category":"display","status":"stable","tags":["icon","phosphor","visual","symbol","graphic"],"since":"0.1.0"},"usage":{"when":["Displaying UI icons alongside text or in buttons","Indicating status or state visually","Adding visual hierarchy to feature lists","Decorating cards or stats with relevant symbols"],"whenNot":["Large decorative illustrations (use Image or custom SVG)","Logo display (use dedicated Logo component)","Complex graphics with multiple colors","Animated icons (use custom implementation)"],"guidelines":["Use semantic color variants (success, error, warning) for status indication","Pair icons with text labels for accessibility","Match icon weight to surrounding text weight for visual consistency","Use consistent sizes within the same context"],"accessibility":["Icons are decorative by default (aria-hidden)","Always pair with visible or visually-hidden text for meaning","Do not rely on color alone to convey information","Consider using VisuallyHidden for icon-only buttons"]},"props":{"icon":{"type":"component","description":"Phosphor icon component to render","required":true},"size":{"type":"enum","description":"Icon size","default":"md","values":["xs","sm","md","lg","xl"]},"weight":{"type":"enum","description":"Icon stroke weight/style","default":"regular","values":["thin","light","regular","bold","fill","duotone"]},"variant":{"type":"enum","description":"Semantic color variant","default":"default","values":["default","primary","secondary","tertiary","accent","success","warning","error"]}},"relations":[{"component":"Button","relationship":"child","note":"Use inside icon-only buttons with VisuallyHidden label"},{"component":"VisuallyHidden","relationship":"sibling","note":"Pair with VisuallyHidden for accessible icon-only elements"},{"component":"Badge","relationship":"child","note":"Can be used as badge icon prop"}],"variants":[{"name":"Default","description":"Basic icon with default styling","code":"<Icon icon={Heart} />"},{"name":"Sizes","description":"Available size options","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Star} size=\"xs\" />\n <Icon icon={Star} size=\"sm\" />\n <Icon icon={Star} size=\"md\" />\n <Icon icon={Star} size=\"lg\" />\n <Icon icon={Star} size=\"xl\" />\n</div>"},{"name":"Semantic Colors","description":"Status and semantic color variants","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Check} variant=\"success\" />\n <Icon icon={Warning} variant=\"warning\" />\n <Icon icon={Warning} variant=\"error\" />\n <Icon icon={Info} variant=\"accent\" />\n</div>"},{"name":"Weights","description":"Icon weight/style options","code":"<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <Icon icon={Heart} weight=\"thin\" />\n <Icon icon={Heart} weight=\"light\" />\n <Icon icon={Heart} weight=\"regular\" />\n <Icon icon={Heart} weight=\"bold\" />\n <Icon icon={Heart} weight=\"fill\" />\n <Icon icon={Heart} weight=\"duotone\" />\n</div>"}]},"Link":{"filePath":"src/components/Link/Link.fragment.tsx","meta":{"name":"Link","description":"Styled anchor element for navigation. Supports internal and external links with consistent visual treatment.","category":"navigation","status":"stable","tags":["link","anchor","navigation","href","url"],"since":"0.1.0"},"usage":{"when":["Inline text links within paragraphs","Navigation links in footers or sidebars","\"Forgot password?\" or \"Sign up\" links in forms","External links to documentation or resources"],"whenNot":["Primary call-to-action (use Button instead)","Navigation tabs (use Tabs component)","Menu items in dropdowns (use Menu component)","Cards that link to detail pages (use Card with onClick)"],"guidelines":["Link text should describe the destination, not \"click here\"","Use external prop for links that open in new tabs","Use subtle variant for secondary/contextual links","Ensure links are distinguishable from regular text"],"accessibility":["Link text must be descriptive of the destination","External links should indicate they open in new window","Links must have visible focus indicators","Avoid using links that look like buttons without button semantics"]},"props":{"children":{"type":"node","description":"Link text content","required":true},"href":{"type":"string","description":"URL destination"},"variant":{"type":"enum","description":"Visual style variant","default":"default","values":["default","subtle","muted"]},"underline":{"type":"enum","description":"Underline behavior","default":"hover","values":["always","hover","none"]},"external":{"type":"boolean","description":"Opens in new tab with noopener noreferrer","default":"false"}},"relations":[{"component":"Button","relationship":"alternative","note":"Use Button for primary actions, Link for navigation"},{"component":"Text","relationship":"parent","note":"Links often appear within Text components"}],"variants":[{"name":"Default","description":"Standard link with hover underline","code":"<Link href=\"#\">Learn more about our services</Link>"},{"name":"Variants","description":"Visual style options","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Link href=\"#\" variant=\"default\">Default</Link>\n <Link href=\"#\" variant=\"subtle\">Subtle</Link>\n <Link href=\"#\" variant=\"muted\">Muted</Link>\n</div>"},{"name":"Underline Styles","description":"Different underline behaviors","code":"<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>\n <Link href=\"#\" underline=\"always\">Always underlined</Link>\n <Link href=\"#\" underline=\"hover\">Underline on hover</Link>\n <Link href=\"#\" underline=\"none\">No underline</Link>\n</div>"},{"name":"External Link","description":"Link that opens in new tab","code":"<Link href=\"https://example.com\" external>\n View documentation ↗\n</Link>"}]},"List":{"filePath":"src/components/List/List.fragment.tsx","meta":{"name":"List","description":"Compound component for rendering ordered or unordered lists with consistent styling. Supports bullet, numbered, and icon-prefixed items.","category":"display","status":"stable","tags":["list","items","bullet","ordered","unordered"],"since":"0.1.0"},"usage":{"when":["Feature lists with checkmarks or icons","Ordered steps or instructions","Navigation lists in sidebars","Pricing plan feature comparisons"],"whenNot":["Interactive selection lists (use Menu or Select)","Data tables with columns (use Table)","Cards in a grid (use Grid with Card)","Navigation tabs (use Tabs)"],"guidelines":["Use as=\"ol\" for sequential or numbered content","Use variant=\"icon\" with meaningful icons for feature lists","Keep list items concise and parallel in structure","Use consistent icons within a single list"],"accessibility":["Use semantic list elements (ul, ol) for screen reader support","List items are automatically announced with count","Icons are decorative; ensure text conveys meaning","Avoid deeply nested lists (3+ levels)"]},"props":{"children":{"type":"node","description":"List.Item components","required":true},"as":{"type":"enum","description":"List type","default":"ul","values":["ul","ol"]},"variant":{"type":"enum","description":"List style variant","default":"disc","values":["none","disc","decimal","icon"]},"gap":{"type":"enum","description":"Spacing between items","default":"sm","values":["none","xs","sm","md","lg"]}},"relations":[{"component":"Icon","relationship":"child","note":"Use Icon as List.Item icon prop"},{"component":"Stack","relationship":"alternative","note":"Use Stack for non-semantic vertical lists"}],"variants":[{"name":"Bullet List","description":"Default unordered list with bullets","code":"<List variant=\"disc\">\n <List.Item>First item</List.Item>\n <List.Item>Second item</List.Item>\n <List.Item>Third item</List.Item>\n</List>"},{"name":"Numbered List","description":"Ordered list with numbers","code":"<List as=\"ol\" variant=\"decimal\">\n <List.Item>Create your account</List.Item>\n <List.Item>Configure your settings</List.Item>\n <List.Item>Start building</List.Item>\n</List>"},{"name":"Icon List","description":"List with custom icons per item","code":"<List variant=\"icon\">\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Unlimited projects\n </List.Item>\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Priority support\n </List.Item>\n <List.Item icon={<Check weight=\"bold\" color=\"var(--fui-color-success)\" />}>\n Advanced analytics\n </List.Item>\n</List>"},{"name":"No Style","description":"Plain list without markers","code":"<List variant=\"none\" gap=\"md\">\n <List.Item>Dashboard</List.Item>\n <List.Item>Settings</List.Item>\n <List.Item>Profile</List.Item>\n</List>"}]},"Listbox":{"filePath":"src/components/Listbox/Listbox.fragment.tsx","meta":{"name":"Listbox","description":"Controlled listbox for search results, autocomplete dropdowns, and command menus. Provides Menu-like styling without requiring a trigger.","category":"forms","status":"stable","tags":["listbox","search","autocomplete","combobox","command","dropdown"],"since":"0.3.0"},"usage":{"when":["Search result dropdowns","Autocomplete suggestions","Command palette results","Keyboard-navigable option lists"],"whenNot":["Static lists without selection (use List)","Action menus with trigger button (use Menu)","Form field selection (use Select)","Navigation menus (use Sidebar or Tabs)"],"guidelines":["Control open/close state externally based on input focus or query","Implement keyboard navigation (arrow keys, enter, escape) in parent","Use Listbox.Empty for no results state","Group related items with Listbox.Group when appropriate"],"accessibility":["Uses listbox and option ARIA roles","aria-selected indicates current selection","aria-disabled for non-interactive items","Connect to input with aria-controls for full combobox pattern"]},"props":{"children":{"type":"node","description":"Listbox.Item, Listbox.Group, or Listbox.Empty components","required":true},"className":{"type":"string","description":"Additional CSS class"},"style":{"type":"object","description":"Inline styles"}},"relations":[{"component":"Input","relationship":"sibling","note":"Pair with Input for search/autocomplete patterns"},{"component":"Menu","relationship":"alternative","note":"Use Menu when you need a trigger button"},{"component":"Select","relationship":"alternative","note":"Use Select for form field selection"},{"component":"List","relationship":"alternative","note":"Use List for static, non-interactive lists"}],"variants":[{"name":"Default","description":"Basic listbox with selectable items","code":"<Listbox aria-label=\"Options\">\n <Listbox.Item selected>First option</Listbox.Item>\n <Listbox.Item>Second option</Listbox.Item>\n <Listbox.Item>Third option</Listbox.Item>\n</Listbox>"},{"name":"Search Results","description":"Typical search results pattern with label and metadata","code":"<Listbox aria-label=\"Search results\">\n <Listbox.Item selected>\n <span style={{ fontWeight: 500 }}>Button</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Components</span>\n </Listbox.Item>\n <Listbox.Item>\n <span style={{ fontWeight: 500 }}>Badge</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Components</span>\n </Listbox.Item>\n <Listbox.Item>\n <span style={{ fontWeight: 500 }}>Box</span>\n <span style={{ marginLeft: 'auto', fontSize: '0.75rem', color: 'var(--fui-text-tertiary)' }}>Layout</span>\n </Listbox.Item>\n</Listbox>"},{"name":"With Groups","description":"Grouped items with labels","code":"<Listbox aria-label=\"Commands\">\n <Listbox.Group label=\"Recent\">\n <Listbox.Item selected>Open file...</Listbox.Item>\n <Listbox.Item>Save as...</Listbox.Item>\n </Listbox.Group>\n <Listbox.Group label=\"Actions\">\n <Listbox.Item>Copy</Listbox.Item>\n <Listbox.Item>Paste</Listbox.Item>\n <Listbox.Item disabled>Cut</Listbox.Item>\n </Listbox.Group>\n</Listbox>"},{"name":"Empty State","description":"No results found message","code":"<Listbox aria-label=\"Search results\">\n <Listbox.Empty>No results found</Listbox.Empty>\n</Listbox>"},{"name":"With Disabled Items","description":"Mix of enabled and disabled items","code":"<Listbox aria-label=\"Options\">\n <Listbox.Item>Available option</Listbox.Item>\n <Listbox.Item disabled>Disabled option</Listbox.Item>\n <Listbox.Item>Another option</Listbox.Item>\n</Listbox>"}],"ai":{"compositionPattern":"compound","subComponents":["Item","Group","Empty"],"requiredChildren":["Item"],"commonPatterns":["<Listbox aria-label=\"Search results\">{results.map(item => <Listbox.Item key={item.id} selected={item.id === selectedId} onClick={() => onSelect(item)}>{item.label}</Listbox.Item>)}</Listbox>"]}},"Loading":{"filePath":"src/components/Loading/Loading.fragment.tsx","meta":{"name":"Loading","description":"Versatile loading indicator with multiple variants for showing progress or waiting states","category":"feedback","status":"stable","tags":["loading","spinner","progress","feedback","indicator","async"]},"usage":{"when":["Indicating content is being fetched or processed","Showing a pending state while waiting for an async operation","Displaying loading state for buttons, forms, or page sections","Full-screen loading during initial app/page load"],"whenNot":["For showing determinate progress - use Progress component instead","For showing skeleton placeholders - use Skeleton component instead","For AI-specific thinking states - use ThinkingIndicator instead"],"guidelines":["Use spinner variant for general loading states","Use dots variant for chat/messaging contexts","Use pulse variant for subtle, ambient loading","Always provide a meaningful label for screen readers","Consider using Loading.Screen for initial page loads","Use Loading.Inline when loading indicator should flow with text"],"accessibility":["Component uses role=\"status\" and aria-live=\"polite\"","Always provide descriptive label prop for screen readers","Animations respect prefers-reduced-motion preference"]},"props":{"size":{"type":"enum","description":"Size of the loading indicator","default":"md","values":["sm","md","lg","xl"]},"variant":{"type":"enum","description":"Visual style of the loading animation","default":"spinner","values":["spinner","dots","pulse"]},"label":{"type":"string","description":"Accessible label for screen readers","default":"Loading..."},"centered":{"type":"boolean","description":"Whether to center the loading indicator in its container","default":false},"fill":{"type":"boolean","description":"Whether to fill the parent container","default":false},"overlay":{"type":"boolean","description":"Whether to show with a backdrop overlay","default":false},"color":{"type":"enum","description":"Color variant - accent uses theme color, current inherits text color","default":"accent","values":["accent","current","muted"]}},"relations":[],"variants":[{"name":"Default","description":"Default spinner loading indicator","code":"<Loading />"},{"name":"Sizes","description":"Loading indicators in different sizes","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '24px' }}>\n <Loading size=\"sm\" />\n <Loading size=\"md\" />\n <Loading size=\"lg\" />\n <Loading size=\"xl\" />\n</div>"},{"name":"Dots","description":"Bouncing dots animation","code":"<Loading variant=\"dots\" />"},{"name":"Pulse","description":"Pulsing circle animation","code":"<Loading variant=\"pulse\" />"},{"name":"Colors","description":"Different color variants","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '24px' }}>\n <Loading color=\"accent\" />\n <Loading color=\"muted\" />\n <span style={{ color: '#3b82f6' }}>\n <Loading color=\"current\" />\n </span>\n</div>"},{"name":"Inline","description":"Inline loading indicator that flows with text","code":"<p style={{ margin: 0 }}>\n Processing your request <Loading.Inline /> please wait...\n</p>"},{"name":"Centered","description":"Centered in container","code":"<div style={{ width: '200px', height: '100px', border: '1px dashed #ccc', borderRadius: '8px' }}>\n <Loading centered fill />\n</div>"},{"name":"Screen","description":"Full-screen loading state with optional label","code":"<div style={{ position: 'relative', width: '300px', height: '200px', border: '1px solid #ccc', borderRadius: '8px', overflow: 'hidden' }}>\n <Loading.Screen size=\"lg\" label=\"Loading application...\" showLabel />\n</div>"}]},"Menu":{"filePath":"src/components/Menu/Menu.fragment.tsx","meta":{"name":"Menu","description":"Dropdown menu for actions and commands. Use for contextual actions, overflow menus, or grouped commands.","category":"feedback","status":"stable","tags":["menu","dropdown","actions","context-menu","commands"],"since":"0.1.0"},"usage":{"when":["Overflow actions that dont fit in the toolbar","Context menus (right-click)","User account menus","Grouped actions with separators"],"whenNot":["Selecting from options (use Select)","Navigation (use Tabs or navigation components)","Form selection (use Select or RadioGroup)"],"guidelines":["Group related actions with Menu.Group","Use separators to divide action categories","Include keyboard shortcuts where applicable","Use danger variant for destructive actions","Keep menu items under 10-12 for usability"],"accessibility":["Full keyboard navigation with arrow keys","Type-ahead search for items","Focus returns to trigger on close","Proper ARIA menu roles"]},"props":{"children":{"type":"node","description":"Menu trigger and content","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether menu is modal","default":"true"}},"relations":[{"component":"Select","relationship":"alternative","note":"Use Select for form field selection"},{"component":"Popover","relationship":"alternative","note":"Use Popover for rich non-action content"}],"variants":[{"name":"Default","description":"Basic dropdown menu","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Actions</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item onSelect={() => {}}>Edit</Menu.Item>\n <Menu.Item onSelect={() => {}}>Duplicate</Menu.Item>\n <Menu.Separator />\n <Menu.Item danger onSelect={() => {}}>Delete</Menu.Item>\n </Menu.Content>\n</Menu>"},{"name":"With Shortcuts","description":"Menu items with keyboard shortcuts","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Edit</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item shortcut=\"Ctrl+Z\" onSelect={() => {}}>Undo</Menu.Item>\n <Menu.Item shortcut=\"Ctrl+Y\" onSelect={() => {}}>Redo</Menu.Item>\n <Menu.Separator />\n <Menu.Item shortcut=\"Ctrl+C\" onSelect={() => {}}>Copy</Menu.Item>\n <Menu.Item shortcut=\"Ctrl+V\" onSelect={() => {}}>Paste</Menu.Item>\n </Menu.Content>\n</Menu>"},{"name":"With Groups","description":"Menu with labeled groups","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Options</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Group>\n <Menu.GroupLabel>View</Menu.GroupLabel>\n <Menu.Item onSelect={() => {}}>Zoom In</Menu.Item>\n <Menu.Item onSelect={() => {}}>Zoom Out</Menu.Item>\n </Menu.Group>\n <Menu.Separator />\n <Menu.Group>\n <Menu.GroupLabel>Layout</Menu.GroupLabel>\n <Menu.Item onSelect={() => {}}>Grid View</Menu.Item>\n <Menu.Item onSelect={() => {}}>List View</Menu.Item>\n </Menu.Group>\n </Menu.Content>\n</Menu>"},{"name":"With Checkboxes","description":"Menu with toggleable options","code":"<Menu>\n <Menu.Trigger asChild>\n <Button variant=\"secondary\">Display</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.CheckboxItem defaultChecked>Show Grid</Menu.CheckboxItem>\n <Menu.CheckboxItem defaultChecked>Show Rulers</Menu.CheckboxItem>\n <Menu.CheckboxItem>Show Guides</Menu.CheckboxItem>\n </Menu.Content>\n</Menu>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Item","CheckboxItem","RadioGroup","RadioItem","Group","GroupLabel","Separator"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Menu><Menu.Trigger asChild><Button>Actions</Button></Menu.Trigger><Menu.Content><Menu.Item>{action1}</Menu.Item><Menu.Separator /><Menu.Item danger>{delete}</Menu.Item></Menu.Content></Menu>"]}},"Message":{"filePath":"src/components/Message/Message.fragment.tsx","meta":{"name":"Message","description":"Individual chat message display with role-based styling","category":"ai","status":"stable","tags":["message","chat","ai","conversation","bubble"]},"usage":{"when":["Displaying individual messages in a chat interface","Building AI assistant or chatbot UIs","Need role-based message styling (user vs assistant)","Messages need actions like copy, regenerate, or feedback"],"whenNot":["Simple text display without chat context (use Text)","Notification-style messages (use Alert or Toast)","Comment threads with nested replies (use Card with custom layout)"],"guidelines":["Always provide a role prop to determine styling","Use status prop to show message state (sending, streaming, error)","Consider showing timestamps for longer conversations","Provide hover actions for assistant messages (copy, regenerate)"],"accessibility":["Uses semantic HTML for message structure","Role-based styling has sufficient color contrast","Actions are keyboard accessible","Streaming indicator respects reduced motion preferences"]},"props":{"role":{"type":"\"user\" | \"assistant\" | \"system\"","description":"Message role determines styling and alignment","required":true},"children":{"type":"ReactNode","description":"Message content","required":true},"status":{"type":"\"sending\" | \"streaming\" | \"complete\" | \"error\"","description":"Message state","default":"\"complete\""},"timestamp":{"type":"Date","description":"When the message was sent"},"avatar":{"type":"ReactNode","description":"Custom avatar override (null to hide)"},"actions":{"type":"ReactNode","description":"Hover actions (copy, regenerate)"}},"relations":[{"component":"ConversationList","relationship":"parent","note":"Messages are typically used within ConversationList"},{"component":"Avatar","relationship":"child","note":"Use Avatar component for custom avatar content"},{"component":"ThinkingIndicator","relationship":"sibling","note":"Show ThinkingIndicator while awaiting assistant response"}],"variants":[{"name":"User Message","description":"Message from the user (right-aligned)","code":"<Message role=\"user\">\n <Message.Content>\n Hello! Can you help me with a coding question?\n </Message.Content>\n</Message>"},{"name":"Assistant Message","description":"Response from the AI assistant","code":"<Message role=\"assistant\">\n <Message.Content>\n Of course! I'd be happy to help. What would you like to know?\n </Message.Content>\n</Message>"},{"name":"System Message","description":"System notification or context","code":"<Message role=\"system\">\n <Message.Content>\n Conversation started. Model: GPT-4\n </Message.Content>\n</Message>"},{"name":"Streaming","description":"Message being streamed (with cursor)","code":"<Message role=\"assistant\" status=\"streaming\">\n <Message.Content>\n I'm currently generating a response for you\n </Message.Content>\n</Message>"},{"name":"With Timestamp","description":"Message with timestamp display","code":"<Message role=\"assistant\" timestamp={new Date(Date.now() - 300000)}>\n <Message.Content>\n This message was sent 5 minutes ago.\n </Message.Content>\n <Message.Timestamp />\n</Message>"},{"name":"Error State","description":"Message that failed to send","code":"<Message role=\"user\" status=\"error\">\n <Message.Content>\n This message failed to send.\n </Message.Content>\n</Message>"},{"name":"With Actions","description":"Message with hover actions","code":"<Message\n role=\"assistant\"\n actions={\n <>\n <button style={{ padding: '4px 8px', fontSize: '12px' }}>Copy</button>\n <button style={{ padding: '4px 8px', fontSize: '12px' }}>Regenerate</button>\n </>\n }\n>\n <Message.Content>\n Hover over this message to see the actions.\n </Message.Content>\n</Message>"}]},"Popover":{"filePath":"src/components/Popover/Popover.fragment.tsx","meta":{"name":"Popover","description":"Rich content overlay anchored to a trigger element. Use for forms, detailed information, or interactive content that should stay in context.","category":"feedback","status":"stable","tags":["popover","overlay","dropdown","floating","contextual"],"since":"0.1.0"},"usage":{"when":["Inline editing forms","Rich preview content","Filter panels","Date/color pickers","Content that needs more space than a tooltip"],"whenNot":["Simple hints (use Tooltip)","Action lists (use Menu)","Blocking user interaction (use Dialog)","System notifications (use Toast or Alert)"],"guidelines":["Keep popover content focused and minimal","Include a clear way to close (X button or action buttons)","Position to avoid covering important content","Use arrow to visually connect popover to trigger"],"accessibility":["Focus is moved to popover content on open","Closes on Escape key","Focus returns to trigger on close"]},"props":{"children":{"type":"node","description":"Popover trigger and content","required":true},"open":{"type":"boolean","description":"Controlled open state"},"defaultOpen":{"type":"boolean","description":"Default open state (uncontrolled)","default":"false"},"onOpenChange":{"type":"function","description":"Called when open state changes"},"modal":{"type":"boolean","description":"Whether to block page interaction","default":"false"}},"relations":[{"component":"Tooltip","relationship":"alternative","note":"Use Tooltip for brief, non-interactive hints"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action lists"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for blocking interactions"}],"variants":[{"name":"Default","description":"Basic popover with content","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Open Popover</Button>\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Close />\n <Popover.Title>Popover Title</Popover.Title>\n <Popover.Description>\n This is a popover with some content. It can contain text, forms, or other elements.\n </Popover.Description>\n </Popover.Content>\n</Popover>"},{"name":"With Form","description":"Popover containing a form","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Edit Name</Button>\n </Popover.Trigger>\n <Popover.Content size=\"sm\">\n <Popover.Close />\n <Popover.Title>Edit Name</Popover.Title>\n <Popover.Body>\n <Input label=\"Display Name\" placeholder=\"Enter name\" />\n </Popover.Body>\n <Popover.Footer>\n <Popover.Close asChild>\n <Button variant=\"secondary\" size=\"sm\">Cancel</Button>\n </Popover.Close>\n <Button variant=\"primary\" size=\"sm\">Save</Button>\n </Popover.Footer>\n </Popover.Content>\n</Popover>"},{"name":"With Arrow","description":"Popover with pointing arrow","code":"<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Info</Button>\n </Popover.Trigger>\n <Popover.Content arrow>\n <Popover.Title>Quick Tip</Popover.Title>\n <Popover.Description>\n This popover has an arrow pointing to its trigger element.\n </Popover.Description>\n </Popover.Content>\n</Popover>"},{"name":"Positions","description":"Popover on different sides","code":"<div style={{ display: 'flex', gap: '16px', padding: '60px' }}>\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Top</Button>\n </Popover.Trigger>\n <Popover.Content side=\"top\" size=\"sm\">\n <Popover.Description>Popover on top</Popover.Description>\n </Popover.Content>\n </Popover>\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Bottom</Button>\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" size=\"sm\">\n <Popover.Description>Popover on bottom</Popover.Description>\n </Popover.Content>\n </Popover>\n</div>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Close","Title","Description","Body","Footer"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Popover><Popover.Trigger asChild><Button>Open</Button></Popover.Trigger><Popover.Content><Popover.Close /><Popover.Title>{title}</Popover.Title><Popover.Description>{description}</Popover.Description></Popover.Content></Popover>"]}},"Progress":{"filePath":"src/components/Progress/Progress.fragment.tsx","meta":{"name":"Progress","description":"Visual indicator of task completion or loading state. Available in linear and circular variants.","category":"feedback","status":"stable","tags":["progress","loading","indicator","percentage","status"],"since":"0.1.0"},"usage":{"when":["Showing upload/download progress","Displaying task completion percentage","Form completion indicators","Loading states with known duration"],"whenNot":["Unknown loading duration (use Spinner)","Step-based progress (use Stepper)","Status without percentage (use Badge)"],"guidelines":["Use determinate progress when you know the completion percentage","Use indeterminate for unknown durations","Include a label for context when the purpose isnt obvious","Use appropriate color variants for success/warning/danger states"],"accessibility":["Uses role=\"progressbar\" with aria-valuenow","Label is associated with the progress bar","State changes are announced to screen readers"]},"props":{"value":{"type":"number","description":"Current progress value (0-100). Null for indeterminate."},"size":{"type":"enum","description":"Size of the progress bar","default":"md","values":["sm","md","lg"]},"variant":{"type":"enum","description":"Color variant","default":"default","values":["default","success","warning","danger"]},"label":{"type":"string","description":"Label text above the progress bar"},"showValue":{"type":"boolean","description":"Show percentage value","default":"false"}},"relations":[{"component":"Badge","relationship":"alternative","note":"Use Badge for status without percentage"},{"component":"Alert","relationship":"sibling","note":"Use Alert for completion messages"}],"variants":[{"name":"Default","description":"Basic progress bar with percentage","code":"<Progress value={60} label=\"Uploading...\" showValue />"},{"name":"Variants","description":"Different color variants for different states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <Progress value={75} variant=\"default\" label=\"Processing\" showValue />\n <Progress value={100} variant=\"success\" label=\"Complete\" showValue />\n <Progress value={80} variant=\"warning\" label=\"Almost full\" showValue />\n <Progress value={95} variant=\"danger\" label=\"Storage critical\" showValue />\n</div>"},{"name":"Sizes","description":"Different progress bar sizes","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <Progress value={50} size=\"sm\" label=\"Small\" />\n <Progress value={50} size=\"md\" label=\"Medium\" />\n <Progress value={50} size=\"lg\" label=\"Large\" />\n</div>"},{"name":"Indeterminate","description":"Loading state with unknown duration","code":"<Progress value={null} label=\"Loading...\" />"},{"name":"Circular","description":"Circular progress indicator","code":"<div style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>\n <CircularProgress value={25} size=\"sm\" />\n <CircularProgress value={50} size=\"md\" showValue />\n <CircularProgress value={75} size=\"lg\" showValue variant=\"success\" />\n <CircularProgress value={null} size=\"md\" />\n</div>"}]},"Prompt":{"filePath":"src/components/Prompt/Prompt.fragment.tsx","meta":{"name":"Prompt","description":"Multi-line input with toolbar for AI/chat interfaces","category":"ai","status":"stable","tags":["prompt","chat","ai","input","textarea","form"]},"usage":{"when":["Building chat or AI assistant interfaces","Need multi-line input with submit action","Require toolbar with actions like attachments or model selection"],"whenNot":["Simple single-line text input (use Input)","Basic multi-line without toolbar (use Textarea)","Search-only interface (use Input with search variant)"],"guidelines":["Always provide an onSubmit handler","Use loading state during API calls","Consider showing usage/token limits for AI contexts"],"accessibility":["Enter submits, Shift+Enter for newline","Submit button is keyboard accessible","Loading state prevents duplicate submissions"]},"props":{"value":{"type":"string","description":"Controlled input value"},"defaultValue":{"type":"string","description":"Uncontrolled default value"},"onChange":{"type":"function","description":"Called when value changes"},"onSubmit":{"type":"function","description":"Called on form submission"},"placeholder":{"type":"string","description":"Placeholder text for the textarea","default":"\"Ask, Search or Chat...\""},"disabled":{"type":"boolean","description":"Disable the entire prompt","default":"false"},"loading":{"type":"boolean","description":"Show loading state","default":"false"},"minRows":{"type":"number","description":"Minimum number of visible rows","default":"1"},"maxRows":{"type":"number","description":"Maximum number of visible rows","default":"8"},"autoResize":{"type":"boolean","description":"Enable auto-resize based on content","default":"true"},"submitOnEnter":{"type":"boolean","description":"Submit on Enter (Shift+Enter for newline)","default":"true"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for simple single-line text input"},{"component":"Textarea","relationship":"alternative","note":"Use Textarea for multi-line without toolbar"}],"variants":[{"name":"Basic","description":"Simple prompt with submit button","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions />\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"With Actions","description":"Prompt with attachment and mode buttons","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"With Usage","description":"Shows token usage indicator","code":"<Prompt onSubmit={(value) => console.log(value)}>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton active>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"Loading State","description":"During API submission","code":"<Prompt\n onSubmit={(value) => console.log(value)}\n loading\n defaultValue=\"Tell me about the weather...\"\n>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"},{"name":"Disabled","description":"Non-interactive prompt","code":"<Prompt onSubmit={(value) => console.log(value)} disabled>\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Add attachment\">\n +\n </Prompt.ActionButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n</Prompt>"}]},"RadioGroup":{"filePath":"src/components/RadioGroup/RadioGroup.fragment.tsx","meta":{"name":"RadioGroup","description":"Single selection from a list of mutually exclusive options","category":"forms","status":"stable","tags":["form","radio","selection","options"]},"usage":{"when":["User must select exactly one option from a small set","Options are mutually exclusive","All options should be visible at once","2-5 options available"],"whenNot":["Multiple selections allowed (use Checkbox group)","Many options (use Select)","Binary on/off choice (use Toggle/Switch)","Options need to be searchable (use Combobox)"],"guidelines":["Always have one option pre-selected when possible","Order options logically (alphabetical, frequency, etc.)","Keep option labels concise","Use descriptions for complex options"],"accessibility":["Group must have an accessible label","Use arrow keys to navigate between options","Selected option should be clearly indicated"]},"props":{"value":{"type":"string","description":"Controlled selected value"},"defaultValue":{"type":"string","description":"Default value (uncontrolled)"},"onValueChange":{"type":"function","description":"Callback when selection changes"},"orientation":{"type":"enum","description":"Layout orientation","default":"vertical","values":["horizontal","vertical"]},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md","lg"]},"disabled":{"type":"boolean","description":"Disable all options","default":false},"label":{"type":"string","description":"Group label"},"error":{"type":"string","description":"Error message"}},"relations":[{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox for multiple selections"},{"component":"Select","relationship":"alternative","note":"Use Select for many options or limited space"},{"component":"Toggle","relationship":"alternative","note":"Use Toggle for binary on/off choices"}],"variants":[{"name":"Default","description":"Basic radio group with labels","code":"<RadioGroup defaultValue=\"option1\" label=\"Select an option\">\n <RadioGroup.Item value=\"option1\" label=\"Option 1\" />\n <RadioGroup.Item value=\"option2\" label=\"Option 2\" />\n <RadioGroup.Item value=\"option3\" label=\"Option 3\" />\n</RadioGroup>"},{"name":"With Descriptions","description":"Radio items with additional context","code":"<RadioGroup defaultValue=\"standard\" label=\"Shipping Method\">\n <RadioGroup.Item\n value=\"standard\"\n label=\"Standard\"\n description=\"5-7 business days\"\n />\n <RadioGroup.Item\n value=\"express\"\n label=\"Express\"\n description=\"2-3 business days\"\n />\n <RadioGroup.Item\n value=\"overnight\"\n label=\"Overnight\"\n description=\"Next business day\"\n />\n</RadioGroup>"},{"name":"Horizontal","description":"Side-by-side layout","code":"<RadioGroup orientation=\"horizontal\" defaultValue=\"small\" label=\"Size\">\n <RadioGroup.Item value=\"small\" label=\"S\" />\n <RadioGroup.Item value=\"medium\" label=\"M\" />\n <RadioGroup.Item value=\"large\" label=\"L\" />\n <RadioGroup.Item value=\"xlarge\" label=\"XL\" />\n</RadioGroup>"},{"name":"With Error","description":"Validation error state","code":"<RadioGroup label=\"Required selection\" error=\"Please select an option\">\n <RadioGroup.Item value=\"a\" label=\"Option A\" />\n <RadioGroup.Item value=\"b\" label=\"Option B\" />\n</RadioGroup>"},{"name":"Disabled","description":"Non-interactive state","code":"<RadioGroup disabled defaultValue=\"locked\" label=\"Locked selection\">\n <RadioGroup.Item value=\"locked\" label=\"This is locked\" />\n <RadioGroup.Item value=\"other\" label=\"Cannot select\" />\n</RadioGroup>"}]},"Select":{"filePath":"src/components/Select/Select.fragment.tsx","meta":{"name":"Select","description":"Dropdown for choosing from a list of options. Use when there are more than 4-5 choices that would clutter the UI.","category":"forms","status":"stable","tags":["select","dropdown","form","options","picker"],"since":"0.1.0"},"usage":{"when":["Choosing from a predefined list of options","More than 4-5 options that would clutter UI as radio buttons","Space-constrained forms","When users need to see all options at once"],"whenNot":["Very few options (2-3) - use radio buttons","Users might type custom values - use Combobox","Multiple selections needed - use Checkbox group or MultiSelect","Actions, not selection - use Menu"],"guidelines":["Include a placeholder that explains what to select","Group related options with SelectGroup","Keep option text concise","Order options logically (alphabetical, by frequency, or by category)"],"accessibility":["Full keyboard navigation support","Type-ahead search within options","Proper ARIA roles and attributes"]},"props":{"children":{"type":"node","description":"Select trigger and content","required":true},"value":{"type":"string","description":"Controlled selected value"},"defaultValue":{"type":"string","description":"Default selected value (uncontrolled)"},"onValueChange":{"type":"function","description":"Called when selection changes"},"placeholder":{"type":"string","description":"Placeholder text when no value selected"},"disabled":{"type":"boolean","description":"Disable the select","default":"false"}},"relations":[{"component":"Menu","relationship":"alternative","note":"Use Menu for action-based dropdowns"},{"component":"Input","relationship":"sibling","note":"Use Input for free-form text entry"},{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox group for multiple selections"}],"variants":[{"name":"Default","description":"Basic select dropdown","code":"<StatefulSelect placeholder=\"Select a fruit\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"apple\">Apple</Select.Item>\n <Select.Item value=\"banana\">Banana</Select.Item>\n <Select.Item value=\"orange\">Orange</Select.Item>\n <Select.Item value=\"grape\">Grape</Select.Item>\n </Select.Content>\n</StatefulSelect>"},{"name":"With Groups","description":"Options organized into groups","code":"<StatefulSelect placeholder=\"Select a country\">\n <Select.Trigger />\n <Select.Content>\n <Select.Group>\n <Select.GroupLabel>North America</Select.GroupLabel>\n <Select.Item value=\"us\">United States</Select.Item>\n <Select.Item value=\"ca\">Canada</Select.Item>\n <Select.Item value=\"mx\">Mexico</Select.Item>\n </Select.Group>\n <Select.Group>\n <Select.GroupLabel>Europe</Select.GroupLabel>\n <Select.Item value=\"uk\">United Kingdom</Select.Item>\n <Select.Item value=\"de\">Germany</Select.Item>\n <Select.Item value=\"fr\">France</Select.Item>\n </Select.Group>\n </Select.Content>\n</StatefulSelect>"},{"name":"With Disabled Options","description":"Some options are disabled","code":"<StatefulSelect placeholder=\"Select a plan\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"free\">Free</Select.Item>\n <Select.Item value=\"pro\">Pro</Select.Item>\n <Select.Item value=\"enterprise\" disabled>Enterprise (Contact Sales)</Select.Item>\n </Select.Content>\n</StatefulSelect>"},{"name":"Disabled","description":"Disabled select","code":"<Select disabled placeholder=\"Select an option\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"1\">Option 1</Select.Item>\n </Select.Content>\n</Select>"}],"ai":{"compositionPattern":"compound","subComponents":["Trigger","Content","Item","Group","GroupLabel"],"requiredChildren":["Trigger","Content"],"commonPatterns":["<Select placeholder=\"Select option\"><Select.Trigger /><Select.Content><Select.Item value=\"opt1\">{label1}</Select.Item><Select.Item value=\"opt2\">{label2}</Select.Item></Select.Content></Select>"]}},"Separator":{"filePath":"src/components/Separator/Separator.fragment.tsx","meta":{"name":"Separator","description":"Visual divider between content sections. Use to create clear visual boundaries and improve content organization.","category":"layout","status":"stable","tags":["separator","divider","hr","line","layout"],"since":"0.1.0"},"usage":{"when":["Dividing content sections","Separating groups of related items","Creating visual breathing room","Labeled section breaks"],"whenNot":["Creating grid layouts (use CSS Grid)","Decorative borders (use CSS)","Spacing alone is sufficient"],"guidelines":["Use sparingly - too many separators create visual noise","Consider if spacing alone would work","Use soft variant for subtle separation","Labeled separators work well for major section breaks"],"accessibility":["Uses role=\"separator\" for semantic meaning","Decorative separators should be aria-hidden"]},"props":{"orientation":{"type":"enum","description":"Direction of the separator","default":"horizontal","values":["horizontal","vertical"]},"spacing":{"type":"enum","description":"Margin around the separator","default":"none","values":["none","sm","md","lg"]},"soft":{"type":"boolean","description":"Softer, lighter appearance","default":"false"},"label":{"type":"string","description":"Optional text label (horizontal only)"}},"relations":[{"component":"Card","relationship":"sibling","note":"Cards provide stronger visual grouping"}],"variants":[{"name":"Default","description":"Basic horizontal separator","code":"<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator spacing=\"md\" />\n <p>Content below</p>\n</div>"},{"name":"With Label","description":"Labeled section divider","code":"<div style={{ width: '300px' }}>\n <p>First section</p>\n <Separator label=\"Or\" spacing=\"md\" />\n <p>Second section</p>\n</div>"},{"name":"Soft","description":"Subtle separator","code":"<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator soft spacing=\"md\" />\n <p>Content below</p>\n</div>"},{"name":"Vertical","description":"Vertical separator between elements","code":"<div style={{ display: 'flex', alignItems: 'center', gap: '16px', height: '40px' }}>\n <span>Item 1</span>\n <Separator orientation=\"vertical\" />\n <span>Item 2</span>\n <Separator orientation=\"vertical\" />\n <span>Item 3</span>\n</div>"},{"name":"Spacing Options","description":"Different spacing sizes","code":"<div style={{ width: '300px' }}>\n <p>No spacing</p>\n <Separator spacing=\"none\" />\n <p>Small spacing</p>\n <Separator spacing=\"sm\" />\n <p>Medium spacing</p>\n <Separator spacing=\"md\" />\n <p>Large spacing</p>\n <Separator spacing=\"lg\" />\n <p>End</p>\n</div>"}]},"Sidebar":{"filePath":"src/components/Sidebar/Sidebar.fragment.tsx","meta":{"name":"Sidebar","description":"Responsive navigation sidebar with collapsible desktop mode and mobile drawer behavior.","category":"navigation","status":"stable","tags":["sidebar","navigation","drawer","menu","layout"],"since":"0.3.0"},"usage":{"when":["Primary app navigation with multiple sections","Dashboard layouts requiring persistent navigation","Admin interfaces with hierarchical menu structure","Apps that need both mobile drawer and desktop sidebar"],"whenNot":["Simple websites with few pages (use header nav)","Content-focused sites where navigation is secondary","Single-page applications with no navigation needs","Mobile-only apps where bottom navigation is preferred"],"guidelines":["Group related items into sections with clear labels","Use icons for all items to support collapsed mode","Limit nesting to 2 levels maximum","Place most frequently used items at the top","Use badges sparingly for notifications or counts","The `active` prop on items should be controlled by your app based on current route","Use `collapsedContent` on Header to show just a logo icon when collapsed","Submenus are hidden when collapsed - use tooltips for navigation hints instead","Use SidebarProvider to enable external triggers and keyboard shortcuts","Use asChild with routing libraries (Next.js Link, React Router NavLink)","Use Sidebar.MenuSkeleton while loading navigation data"],"accessibility":["Uses semantic <nav> element with aria-label","aria-current=\"page\" on active items","aria-expanded on items with submenus","Escape key closes mobile drawer","Cmd/Ctrl+B keyboard shortcut toggles sidebar (when using SidebarProvider)","Focus trap in mobile drawer mode","Minimum 44px touch targets"]},"props":{"children":{"type":"node","description":"Sidebar content (use Sidebar.Header, Sidebar.Nav, Sidebar.Section, etc.)","required":true},"collapsed":{"type":"boolean","description":"Icon-only mode for desktop (controlled)"},"defaultCollapsed":{"type":"boolean","description":"Initial collapsed state (uncontrolled)","default":false},"onCollapsedChange":{"type":"function","description":"Called when collapsed state changes"},"open":{"type":"boolean","description":"Mobile drawer open state (controlled)"},"defaultOpen":{"type":"boolean","description":"Initial open state (uncontrolled)","default":false},"onOpenChange":{"type":"function","description":"Called when open state changes"},"width":{"type":"string","description":"Width of expanded sidebar","default":"240px"},"collapsedWidth":{"type":"string","description":"Width when collapsed","default":"64px"},"position":{"type":"enum","description":"Sidebar position","default":"left","values":["left","right"]},"collapsible":{"type":"enum","description":"Collapse behavior mode","default":"icon","values":["icon","offcanvas","none"]},"asChild":{"type":"boolean","description":"(Sidebar.Item) Render as child element for polymorphic composition","default":false}},"relations":[{"component":"Tabs","relationship":"alternative","note":"Use Tabs for in-page section navigation"},{"component":"Menu","relationship":"composition","note":"Use Menu for contextual actions within sidebar"}],"variants":[{"name":"Default","description":"Standard sidebar with navigation sections. The `active` prop highlights the current page.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />}>Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n <Sidebar.Section label=\"Settings\">\n <Sidebar.Item icon={<GearIcon />}>Preferences</Sidebar.Item>\n <Sidebar.Item icon={<HelpIcon />}>Help</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Dashboard content goes here\n </main>\n</div>"},{"name":"Collapsed","description":"Icon-only collapsed state. Header shows only logo, tooltips appear on hover.","code":"<CollapsedDemo />"},{"name":"With Badges","description":"Navigation items with notification badges for counts or alerts.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} badge=\"3\">Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} badge=\"12\">Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Badges indicate unread items or notifications\n </main>\n</div>"},{"name":"With Submenu","description":"Nested navigation with expandable sections. Use defaultExpanded for initial state without manual state tracking.","code":"<SubmenuDemo />"},{"name":"With Disabled Items","description":"Some navigation items are disabled for permissions or feature flags.","code":"<div style={demoContainerStyle}>\n <Sidebar>\n <Sidebar.Header collapsedContent={<LogoIcon size={32} />}>\n <LogoIcon size={32} />\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} disabled>Team (Coming Soon)</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />} disabled>Projects (Upgrade)</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n <main style={mainContentStyle}>\n Disabled items cannot be clicked\n </main>\n</div>"},{"name":"With Provider & External Trigger","description":"SidebarProvider enables external triggers and keyboard shortcuts (Cmd/Ctrl+B).","code":"<ProviderDemo />"},{"name":"With asChild (Polymorphic)","description":"Use asChild to render items as custom elements like Next.js Link or React Router NavLink.","code":"<AsChildDemo />"},{"name":"With Section Action","description":"Section headers can include action buttons for quick actions like \"Add Project\".","code":"<SectionActionDemo />"},{"name":"With Loading Skeleton","description":"Show skeleton placeholders while navigation data is loading.","code":"<SkeletonDemo />"},{"name":"With Rail Toggle","description":"Add a Rail component for a subtle drag-handle style toggle at the sidebar edge. Hover to reveal, click to toggle.","code":"<RailDemo />"}],"ai":{"compositionPattern":"compound","subComponents":["Header","Nav","Section","Item","SubItem","Submenu","Footer","CollapseToggle","Rail","MenuSkeleton","SectionAction"],"requiredChildren":["Nav"],"commonPatterns":["<Sidebar><Sidebar.Header>{logo}</Sidebar.Header><Sidebar.Nav><Sidebar.Section><Sidebar.Item icon={icon} active>{label}</Sidebar.Item></Sidebar.Section></Sidebar.Nav><Sidebar.Footer><Sidebar.CollapseToggle /></Sidebar.Footer></Sidebar>"]}},"Skeleton":{"filePath":"src/components/Skeleton/Skeleton.fragment.tsx","meta":{"name":"Skeleton","description":"Placeholder loading state for content","category":"feedback","status":"stable","tags":["loading","placeholder","skeleton","shimmer"]},"usage":{"when":["Content is loading asynchronously","Preventing layout shift during data fetching","Providing visual feedback that content is coming","Improving perceived performance"],"whenNot":["Short loading times (< 300ms)","When spinner is more appropriate","Background operations without visible impact"],"guidelines":["Match skeleton shape to expected content","Use semantic variants (text, heading, avatar) for consistency","Maintain similar dimensions to loaded content","Avoid too many skeleton elements - simplify complex layouts"],"accessibility":["Skeletons are decorative - use aria-hidden","Announce loading state separately if needed","Ensure sufficient contrast for the animation"]},"props":{"variant":{"type":"enum","description":"Semantic variant that auto-sizes","default":"rect","values":["text","heading","avatar","button","input","rect"]},"size":{"type":"enum","description":"Size for avatar/button variants","default":"md","values":["sm","md","lg"]},"width":{"type":"union","description":"Custom width (string or number)"},"height":{"type":"union","description":"Custom height (string or number)"},"fill":{"type":"boolean","description":"Fill parent container","default":false},"radius":{"type":"enum","description":"Border radius override","values":["none","sm","md","lg","full"]}},"relations":[{"component":"Progress","relationship":"alternative","note":"Use Progress for determinate loading"}],"variants":[{"name":"Default","description":"Basic rectangle skeleton","code":"<Skeleton width={200} height={20} />"},{"name":"Text Lines","description":"Multi-line text placeholder","code":"<Skeleton.Text lines={3} />"},{"name":"Semantic Variants","description":"Pre-configured shapes for common elements","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width={200} />\n <Skeleton variant=\"text\" width=\"100%\" />\n <Skeleton variant=\"text\" width=\"80%\" />\n</div>"},{"name":"Avatar Skeleton","description":"Circular placeholder for avatars","code":"<div style={{ display: 'flex', gap: 'var(--fui-space-1)', alignItems: 'center' }}>\n <Skeleton.Circle size=\"sm\" />\n <Skeleton.Circle size=\"md\" />\n <Skeleton.Circle size=\"lg\" />\n</div>"},{"name":"Card Skeleton","description":"Composed skeleton for a card layout","code":"<div style={{ width: 300, padding: 'var(--fui-space-2)', border: '1px solid var(--fui-border)', borderRadius: 'var(--fui-radius-lg)' }}>\n <Skeleton variant=\"rect\" height={120} radius=\"md\" />\n <div style={{ marginTop: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width=\"60%\" />\n </div>\n <div style={{ marginTop: 'var(--fui-space-1)' }}>\n <Skeleton.Text lines={2} />\n </div>\n</div>"}]},"Slider":{"filePath":"src/components/Slider/Slider.fragment.tsx","meta":{"name":"Slider","description":"Range input control for selecting a numeric value within a defined range. Supports labels, value display, and custom step intervals.","category":"forms","status":"stable","tags":["slider","range","input","number","control"],"since":"0.2.0"},"usage":{"when":["Selecting a value from a continuous range","Volume or brightness controls","Price range filters","Settings that benefit from visual feedback"],"whenNot":["Precise numeric input (use Input type=\"number\")","Discrete options (use RadioGroup or Select)","Yes/no choices (use Toggle)"],"guidelines":["Always provide a label describing what the slider controls","Show the current value when precision matters","Use appropriate min/max values for the context","Consider step size for usability"],"accessibility":["Label is associated with the slider","Keyboard accessible with arrow keys","Current value is announced to screen readers","Uses native slider semantics"]},"props":{"value":{"type":"number","description":"Controlled value"},"defaultValue":{"type":"number","description":"Default value for uncontrolled usage"},"onChange":{"type":"function","description":"Called with new value when changed"},"min":{"type":"number","description":"Minimum value","default":"0"},"max":{"type":"number","description":"Maximum value","default":"100"},"step":{"type":"number","description":"Step interval","default":"1"},"label":{"type":"string","description":"Label text"},"showValue":{"type":"boolean","description":"Display current value","default":"false"},"valueSuffix":{"type":"string","description":"Suffix after value (e.g., \"%\", \"px\")"},"disabled":{"type":"boolean","description":"Disable the slider","default":"false"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for precise numeric entry"},{"component":"Progress","relationship":"sibling","note":"Similar visual, but Progress is read-only"}],"variants":[{"name":"Default","description":"Basic slider with label","code":"<div style={{ width: '300px' }}>\n <Slider label=\"Volume\" defaultValue={50} />\n</div>"},{"name":"With Value Display","description":"Shows current value alongside the slider","code":"<div style={{ width: '300px' }}>\n <Slider\n label=\"Brightness\"\n defaultValue={75}\n showValue\n valueSuffix=\"%\"\n />\n</div>"},{"name":"Custom Range","description":"Custom min, max, and step values","code":"<div style={{ width: '300px', display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <Slider\n label=\"Temperature\"\n min={60}\n max={80}\n step={1}\n defaultValue={72}\n showValue\n valueSuffix=\"°F\"\n />\n <Slider\n label=\"Font Size\"\n min={12}\n max={32}\n step={2}\n defaultValue={16}\n showValue\n valueSuffix=\"px\"\n />\n</div>"},{"name":"Controlled","description":"Controlled slider with external state","code":"{\n const [value, setValue] = React.useState(50);\n return (\n <div style={{ width: '300px', display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Slider\n label=\"Opacity\"\n value={value}\n onChange={setValue}\n showValue\n valueSuffix=\"%\"\n />\n <div style={{ fontSize: '14px', color: 'var(--fui-text-secondary)' }}>\n Current value: {value}%\n </div>\n </div>\n );\n}"},{"name":"Disabled","description":"Disabled slider","code":"<div style={{ width: '300px' }}>\n <Slider\n label=\"Locked Setting\"\n defaultValue={30}\n showValue\n disabled\n />\n</div>"}]},"Stack":{"filePath":"src/components/Stack/Stack.fragment.tsx","meta":{"name":"Stack","description":"Flexible layout component for arranging children in rows or columns with consistent spacing. Supports responsive direction and gap.","category":"layout","status":"stable","tags":["stack","layout","flex","spacing","responsive"],"since":"0.2.0"},"usage":{"when":["Arranging elements in a row or column","Creating consistent spacing between items","Building responsive layouts","Simple flexbox-based arrangements"],"whenNot":["Complex grid layouts (use Grid)","Button-specific grouping (use ButtonGroup)","Page-level layout (use AppShell)"],"guidelines":["Use semantic elements via the \"as\" prop when appropriate","Leverage responsive props for mobile-first layouts","Keep spacing consistent within related sections","Consider alignment for visual balance"],"accessibility":["Use semantic elements (nav, section, etc.) via \"as\" prop","Maintains source order for screen readers","No accessibility concerns with visual arrangement"]},"props":{"children":{"type":"node","description":"Elements to arrange","required":true},"direction":{"type":"string | object","description":"Stack direction: \"row\", \"column\", or responsive object","default":"column"},"gap":{"type":"string | object","description":"Spacing between items: \"none\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\", or responsive object","default":"md"},"align":{"type":"enum","description":"Cross-axis alignment","values":["start","center","end","stretch","baseline"]},"justify":{"type":"enum","description":"Main-axis alignment","values":["start","center","end","between"]},"wrap":{"type":"boolean","description":"Allow items to wrap","default":"false"},"as":{"type":"enum","description":"HTML element to render","default":"div","values":["div","section","nav","article","aside","header","footer","main","ul","ol"]}},"relations":[{"component":"Grid","relationship":"alternative","note":"Use Grid for complex 2D layouts"},{"component":"ButtonGroup","relationship":"sibling","note":"ButtonGroup is specialized for buttons"},{"component":"Box","relationship":"sibling","note":"Box for single-element styling"}],"variants":[{"name":"Vertical Stack","description":"Default column layout","code":"<Stack gap=\"sm\">\n <Badge>Item 1</Badge>\n <Badge>Item 2</Badge>\n <Badge>Item 3</Badge>\n</Stack>"},{"name":"Horizontal Stack","description":"Row layout","code":"<Stack direction=\"row\" gap=\"sm\">\n <Badge>Item 1</Badge>\n <Badge>Item 2</Badge>\n <Badge>Item 3</Badge>\n</Stack>"},{"name":"Gap Sizes","description":"Different spacing options","code":"<Stack gap=\"lg\">\n <Stack direction=\"row\" gap=\"xs\">\n <Badge variant=\"info\">XS</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"sm\">\n <Badge variant=\"info\">SM</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"md\">\n <Badge variant=\"info\">MD</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"lg\">\n <Badge variant=\"info\">LG</Badge>\n <Badge variant=\"info\">Gap</Badge>\n </Stack>\n</Stack>"},{"name":"Alignment","description":"Cross-axis and main-axis alignment","code":"<Stack gap=\"md\">\n <Stack direction=\"row\" gap=\"sm\" justify=\"between\" style={{ width: '200px', padding: '8px', background: 'var(--fui-bg-secondary)', borderRadius: '4px' }}>\n <Badge>Start</Badge>\n <Badge>End</Badge>\n </Stack>\n <Stack direction=\"row\" gap=\"sm\" justify=\"center\" style={{ width: '200px', padding: '8px', background: 'var(--fui-bg-secondary)', borderRadius: '4px' }}>\n <Badge>Centered</Badge>\n </Stack>\n</Stack>"},{"name":"Responsive","description":"Direction changes at breakpoints","code":"<Stack\n direction={{ base: 'column', md: 'row' }}\n gap={{ base: 'sm', md: 'lg' }}\n>\n <Button variant=\"secondary\">First</Button>\n <Button variant=\"secondary\">Second</Button>\n <Button variant=\"secondary\">Third</Button>\n</Stack>"},{"name":"Semantic Element","description":"Using nav element for navigation","code":"<Stack as=\"nav\" direction=\"row\" gap=\"md\">\n <Button variant=\"ghost\" size=\"sm\">Home</Button>\n <Button variant=\"ghost\" size=\"sm\">About</Button>\n <Button variant=\"ghost\" size=\"sm\">Contact</Button>\n</Stack>"}]},"Table":{"filePath":"src/components/Table/Table.fragment.tsx","meta":{"name":"Table","description":"Data table with sorting and row selection. Use for displaying structured data that needs to be scanned, compared, or acted upon.","category":"display","status":"stable","tags":["table","data","grid","list","sorting"],"since":"0.1.0"},"usage":{"when":["Displaying structured, tabular data","Data that users need to scan and compare","Lists with multiple attributes per item","Data that needs sorting or selection"],"whenNot":["Simple lists (use List component)","Card-based layouts (use CardGrid)","Heavily interactive data (consider DataGrid)","Small screens (consider card or list view)"],"guidelines":["Keep columns to a reasonable number (5-7 max)","Use consistent alignment (numbers right, text left)","Provide meaningful empty states","Consider mobile responsiveness"],"accessibility":["Proper table semantics with headers","Sortable columns are keyboard accessible","Row selection is properly announced"]},"props":{"columns":{"type":"array","description":"Column definitions","required":true},"data":{"type":"array","description":"Data rows to display","required":true},"sortable":{"type":"boolean","description":"Enable column sorting","default":"false"},"selectable":{"type":"boolean","description":"Enable row selection","default":"false"},"onRowClick":{"type":"function","description":"Handler for row clicks"},"emptyMessage":{"type":"string","description":"Message when no data","default":"No data available"},"size":{"type":"enum","description":"Table density","default":"md","values":["sm","md"]}},"relations":[{"component":"EmptyState","relationship":"sibling","note":"Use EmptyState for empty table states"},{"component":"Badge","relationship":"sibling","note":"Use Badge for status columns"}],"variants":[{"name":"Default","description":"Basic data table","code":"<Table\n columns={columns}\n data={sampleUsers}\n/>"},{"name":"Sortable","description":"Table with sortable columns","code":"<Table\n columns={columns}\n data={sampleUsers}\n sortable\n/>"},{"name":"Clickable Rows","description":"Table with clickable rows","code":"<Table\n columns={columns}\n data={sampleUsers}\n onRowClick={(row) => alert(`Clicked: ${row.name}`)}\n/>"},{"name":"Compact","description":"Smaller, denser table","code":"<Table\n columns={columns}\n data={sampleUsers}\n size=\"sm\"\n/>"},{"name":"Empty State","description":"Table with no data","code":"<Table\n columns={columns}\n data={[]}\n emptyMessage=\"No users found\"\n/>"}],"ai":{"compositionPattern":"simple","commonPatterns":["<Table columns={[{header:\"Name\",accessorKey:\"name\"},{header:\"Status\",accessorKey:\"status\"}]} data={[{name:\"Item 1\",status:\"Active\"}]} />"]}},"Tabs":{"filePath":"src/components/Tabs/Tabs.fragment.tsx","meta":{"name":"Tabs","description":"Organize content into switchable panels. Use for related content that benefits from a compact, navigable layout.","category":"navigation","status":"stable","tags":["tabs","navigation","panels","content-switcher"],"since":"0.1.0"},"usage":{"when":["Organizing related content into sections","Reducing page scrolling by grouping content","Settings pages with multiple categories","Dashboard views with different data perspectives"],"whenNot":["Primary navigation (use sidebar or header nav)","Sequential steps (use Stepper or wizard)","Comparing content side-by-side","Very long lists of options (use Select or Menu)"],"guidelines":["Keep tab labels short (1-2 words)","Order tabs by usage frequency or logical sequence","Avoid more than 5-6 tabs; consider sub-navigation for more","Tab content should be roughly equivalent in scope","Use pills variant for contained sections, underline for page-level tabs"],"accessibility":["Keyboard navigation with arrow keys","Tab panels are properly labeled","Focus management follows WAI-ARIA tabs pattern"]},"props":{"children":{"type":"node","description":"Tab list and panels (use Tabs.List, Tabs.Tab, Tabs.Panel)","required":true},"defaultValue":{"type":"string","description":"Initially active tab (uncontrolled)"},"value":{"type":"string","description":"Controlled active tab value"},"onValueChange":{"type":"function","description":"Called when active tab changes"},"orientation":{"type":"enum","description":"Tab list orientation","default":"horizontal","values":["horizontal","vertical"]}},"relations":[{"component":"Select","relationship":"alternative","note":"Use Select for many options in compact space"},{"component":"Menu","relationship":"alternative","note":"Use Menu for action-based navigation"}],"variants":[{"name":"Underline","description":"Default underline style tabs","code":"<Tabs defaultValue=\"overview\">\n <Tabs.List variant=\"underline\">\n <Tabs.Tab value=\"overview\">Overview</Tabs.Tab>\n <Tabs.Tab value=\"analytics\">Analytics</Tabs.Tab>\n <Tabs.Tab value=\"settings\">Settings</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"overview\">\n <p>Overview content goes here.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"analytics\">\n <p>Analytics content goes here.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"settings\">\n <p>Settings content goes here.</p>\n </Tabs.Panel>\n</Tabs>"},{"name":"Pills","description":"Pill-style tabs for contained sections","code":"<Tabs defaultValue=\"all\">\n <Tabs.List variant=\"pills\">\n <Tabs.Tab value=\"all\">All</Tabs.Tab>\n <Tabs.Tab value=\"active\">Active</Tabs.Tab>\n <Tabs.Tab value=\"archived\">Archived</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"all\">\n <p>Showing all items.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"active\">\n <p>Showing active items only.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"archived\">\n <p>Showing archived items.</p>\n </Tabs.Panel>\n</Tabs>"},{"name":"With Disabled","description":"Tabs with a disabled option","code":"<Tabs defaultValue=\"general\">\n <Tabs.List variant=\"underline\">\n <Tabs.Tab value=\"general\">General</Tabs.Tab>\n <Tabs.Tab value=\"security\">Security</Tabs.Tab>\n <Tabs.Tab value=\"billing\" disabled>Billing</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"general\">\n <p>General settings panel.</p>\n </Tabs.Panel>\n <Tabs.Panel value=\"security\">\n <p>Security settings panel.</p>\n </Tabs.Panel>\n</Tabs>"}],"ai":{"compositionPattern":"compound","subComponents":["List","Tab","Panel"],"requiredChildren":["List","Panel"],"commonPatterns":["<Tabs defaultValue=\"tab1\"><Tabs.List><Tabs.Tab value=\"tab1\">{label1}</Tabs.Tab><Tabs.Tab value=\"tab2\">{label2}</Tabs.Tab></Tabs.List><Tabs.Panel value=\"tab1\">{content1}</Tabs.Panel><Tabs.Panel value=\"tab2\">{content2}</Tabs.Panel></Tabs>"]}},"Text":{"filePath":"src/components/Text/Text.fragment.tsx","meta":{"name":"Text","description":"Typography component for rendering text with consistent styling. Supports various sizes, weights, colors, and semantic elements.","category":"display","status":"stable","tags":["text","typography","heading","paragraph","font"],"since":"0.2.0"},"usage":{"when":["Displaying text with specific typography styles","Creating headings, paragraphs, or labels","Text that needs truncation or line clamping","Consistent typography across the application"],"whenNot":["Complex rich text (use a rich text editor)","Code display (use CodeBlock)","Interactive text (use Link or Button)"],"guidelines":["Use semantic elements (h1-h6, p) via the \"as\" prop","Maintain heading hierarchy for accessibility","Use color variants sparingly for visual hierarchy","Consider truncation for user-generated content"],"accessibility":["Use proper heading levels (h1-h6) for document structure","Semantic elements convey meaning to screen readers","Truncated text should have full content in title/tooltip"]},"props":{"children":{"type":"node","description":"Text content","required":true},"as":{"type":"enum","description":"HTML element to render","default":"span","values":["h1","h2","h3","h4","h5","h6","p","span","label","div","strong","em","small","code"]},"size":{"type":"enum","description":"Font size","values":["2xs","xs","sm","base","lg","xl","2xl"]},"weight":{"type":"enum","description":"Font weight","values":["normal","medium","semibold"]},"color":{"type":"enum","description":"Text color","values":["primary","secondary","tertiary"]},"font":{"type":"enum","description":"Font family","default":"sans","values":["sans","mono"]},"truncate":{"type":"boolean","description":"Truncate with ellipsis on overflow"},"lineClamp":{"type":"number","description":"Number of lines before truncating (requires truncate)"}},"relations":[{"component":"Link","relationship":"sibling","note":"Use Link for clickable text"},{"component":"CodeBlock","relationship":"alternative","note":"Use CodeBlock for code display"},{"component":"Badge","relationship":"sibling","note":"Use Badge for labels/tags"}],"variants":[{"name":"Sizes","description":"Different text sizes","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text size=\"2xs\">Extra extra small (2xs)</Text>\n <Text size=\"xs\">Extra small (xs)</Text>\n <Text size=\"sm\">Small (sm)</Text>\n <Text size=\"base\">Base size</Text>\n <Text size=\"lg\">Large (lg)</Text>\n <Text size=\"xl\">Extra large (xl)</Text>\n <Text size=\"2xl\">Extra extra large (2xl)</Text>\n</div>"},{"name":"Weights","description":"Different font weights","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text weight=\"normal\">Normal weight</Text>\n <Text weight=\"medium\">Medium weight</Text>\n <Text weight=\"semibold\">Semibold weight</Text>\n</div>"},{"name":"Colors","description":"Different text colors","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text color=\"primary\">Primary color (default)</Text>\n <Text color=\"secondary\">Secondary color</Text>\n <Text color=\"tertiary\">Tertiary color</Text>\n</div>"},{"name":"Semantic Elements","description":"Using appropriate HTML elements","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Text as=\"h1\" size=\"2xl\" weight=\"semibold\">Heading 1</Text>\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Heading 2</Text>\n <Text as=\"h3\" size=\"lg\" weight=\"medium\">Heading 3</Text>\n <Text as=\"p\" color=\"secondary\">\n This is a paragraph of text that demonstrates the Text component\n with semantic paragraph element.\n </Text>\n</div>"},{"name":"Monospace","description":"Monospace font for code-like text","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <Text font=\"mono\" size=\"sm\">const greeting = \"Hello, World!\";</Text>\n <Text font=\"mono\" size=\"sm\" color=\"secondary\">npm install @fragments-sdk/ui</Text>\n</div>"},{"name":"Truncation","description":"Text truncation with ellipsis","code":"<div style={{ width: '200px', display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Text truncate>\n This is a very long text that will be truncated with an ellipsis when it overflows.\n </Text>\n <Text truncate lineClamp={2}>\n This text will be clamped to two lines. Any content beyond two lines\n will be hidden and replaced with an ellipsis at the end.\n </Text>\n</div>"}]},"Textarea":{"filePath":"src/components/Textarea/Textarea.fragment.tsx","meta":{"name":"Textarea","description":"Multi-line text input for longer form content","category":"forms","status":"stable","tags":["input","text","form","multiline"]},"usage":{"when":["Collecting multi-line text (comments, descriptions)","Free-form text input that may span multiple lines","Message composition fields","Code or content editing"],"whenNot":["Single-line input (use Input)","Rich text editing (use rich text editor)","Selecting from predefined options (use Select)"],"guidelines":["Set appropriate rows for expected content length","Use placeholder to show example format","Show character count when maxLength is set","Consider auto-resize for better UX"],"accessibility":["Always provide a visible label","Use helperText for format hints","Error messages should be descriptive"]},"props":{"value":{"type":"string","description":"Controlled value"},"placeholder":{"type":"string","description":"Placeholder text"},"rows":{"type":"number","description":"Number of visible text rows","default":3},"label":{"type":"string","description":"Label text above the textarea"},"helperText":{"type":"string","description":"Helper text below the textarea"},"error":{"type":"boolean","description":"Error state","default":false},"disabled":{"type":"boolean","description":"Disabled state","default":false},"resize":{"type":"enum","description":"Resize behavior","default":"vertical","values":["none","vertical","horizontal","both"]},"maxLength":{"type":"number","description":"Maximum character length"}},"relations":[{"component":"Input","relationship":"alternative","note":"Use Input for single-line text"}],"variants":[{"name":"Default","description":"Basic textarea with label","code":"<Textarea\n label=\"Description\"\n placeholder=\"Enter a description...\"\n/>"},{"name":"With Helper Text","description":"Textarea with additional guidance","code":"<Textarea\n label=\"Bio\"\n placeholder=\"Tell us about yourself...\"\n helperText=\"Max 500 characters\"\n maxLength={500}\n/>"},{"name":"Error State","description":"Textarea showing validation error","code":"<Textarea\n label=\"Comments\"\n placeholder=\"Add your comments...\"\n error\n helperText=\"This field is required\"\n/>"},{"name":"Disabled","description":"Non-interactive textarea","code":"<Textarea\n label=\"Notes\"\n placeholder=\"Cannot edit...\"\n disabled\n/>"},{"name":"Custom Rows","description":"Textarea with more visible rows","code":"<Textarea\n label=\"Long Description\"\n placeholder=\"Enter detailed information...\"\n rows={6}\n/>"}]},"Theme":{"filePath":"src/components/Theme/Theme.fragment.tsx","meta":{"name":"Theme","description":"Theme management system with provider, toggle, and hook pattern. Supports light, dark, and system modes with localStorage persistence.","category":"navigation","status":"stable","tags":["theme","dark-mode","light-mode","provider","toggle"],"since":"0.5.0"},"usage":{"when":["Providing theme context to an application","Toggling between light and dark modes","Respecting system color scheme preference","Persisting theme preference across sessions"],"whenNot":["Simple one-off color changes (use CSS variables)","Component-level theming (use component props)"],"guidelines":["Wrap your app with ThemeProvider at the root level","Use useTheme hook to access theme state in components","ThemeToggle cycles through light → dark → system","Use storageKey to customize localStorage key","Set attribute=\"class\" if your CSS uses .dark class instead of data-theme"],"accessibility":["ThemeToggle button has accessible label indicating current mode","Theme changes are applied via CSS custom properties for smooth transitions","System preference is detected via prefers-color-scheme media query"]},"props":{"children":{"type":"node","description":"Application content","required":true},"defaultMode":{"type":"enum","description":"Default theme mode for uncontrolled usage","default":"system","values":["light","dark","system"]},"mode":{"type":"enum","description":"Controlled theme mode","values":["light","dark","system"]},"onModeChange":{"type":"function","description":"Callback when mode changes"},"storageKey":{"type":"string","description":"localStorage key for persistence","default":"fui-theme"},"attribute":{"type":"enum","description":"How to apply theme to DOM","default":"data-theme","values":["data-theme","class"]}},"relations":[{"component":"AppShell","relationship":"sibling","note":"ThemeProvider typically wraps AppShell"}],"variants":[{"name":"Default","description":"ThemeProvider with system default","code":"<ThemeProvider defaultMode=\"system\">\n <ThemeDemo />\n</ThemeProvider>"},{"name":"With Toggle","description":"ThemeProvider with toggle button","code":"<ThemeProvider defaultMode=\"light\">\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n <ThemeToggle />\n <span>Click to cycle themes</span>\n </div>\n</ThemeProvider>"},{"name":"Toggle Sizes","description":"ThemeToggle in different sizes","code":"<ThemeProvider defaultMode=\"light\">\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n <ThemeToggle size=\"sm\" />\n <ThemeToggle size=\"md\" />\n <ThemeToggle size=\"lg\" />\n </div>\n</ThemeProvider>"}]},"ThinkingIndicator":{"filePath":"src/components/ThinkingIndicator/ThinkingIndicator.fragment.tsx","meta":{"name":"ThinkingIndicator","description":"Animated indicator showing AI is processing","category":"ai","status":"stable","tags":["thinking","loading","ai","processing","indicator","animation"]},"usage":{"when":["AI is processing a request and generating a response","Need visual feedback during async AI operations","Want to show multi-step progress for complex AI tasks","Indicating streaming is about to begin"],"whenNot":["Simple loading states (use Progress or Skeleton)","Form submission loading (use Button loading state)","Page-level loading (use Progress or Skeleton)"],"guidelines":["Use active prop to control visibility","Choose variant based on context (dots for chat, spinner for actions)","Enable showElapsed for longer operations","Use steps for multi-step AI workflows (tool calls, research)"],"accessibility":["Uses role=\"status\" and aria-live=\"polite\"","Provides aria-label for screen readers","Animations respect prefers-reduced-motion","Elapsed time uses tabular numbers for stability"]},"props":{"active":{"type":"boolean","description":"Whether thinking is active","default":"true"},"label":{"type":"string","description":"Status text","default":"\"Thinking...\""},"variant":{"type":"\"dots\" | \"pulse\" | \"spinner\"","description":"Animation style","default":"\"dots\""},"showElapsed":{"type":"boolean","description":"Show elapsed time","default":"false"},"steps":{"type":"ThinkingStep[]","description":"Multi-step progress array"}},"relations":[{"component":"Message","relationship":"sibling","note":"Show ThinkingIndicator while waiting for assistant message"},{"component":"ConversationList","relationship":"parent","note":"Typically placed at bottom of ConversationList"},{"component":"Progress","relationship":"alternative","note":"Use Progress for determinate progress"}],"variants":[{"name":"Dots (Default)","description":"Bouncing dots animation","code":"<ThinkingIndicator variant=\"dots\" label=\"Thinking...\" />"},{"name":"Pulse","description":"Pulsing ring animation","code":"<ThinkingIndicator variant=\"pulse\" label=\"Processing...\" />"},{"name":"Spinner","description":"Rotating spinner animation","code":"<ThinkingIndicator variant=\"spinner\" label=\"Loading...\" />"},{"name":"With Elapsed Time","description":"Shows time since started","code":"<ThinkingIndicator\n variant=\"dots\"\n label=\"Generating response...\"\n showElapsed\n/>"},{"name":"Multi-Step Progress","description":"Shows progress through multiple steps","code":"<ThinkingIndicator\n variant=\"spinner\"\n label=\"Working...\"\n steps={[\n { id: '1', label: 'Analyzing request', status: 'complete' },\n { id: '2', label: 'Searching knowledge base', status: 'active' },\n { id: '3', label: 'Generating response', status: 'pending' },\n ]}\n/>"},{"name":"With Error Step","description":"Shows a step that encountered an error","code":"<ThinkingIndicator\n variant=\"spinner\"\n label=\"Retrying...\"\n steps={[\n { id: '1', label: 'Connecting to API', status: 'complete' },\n { id: '2', label: 'Fetching data', status: 'error' },\n { id: '3', label: 'Retrying with fallback', status: 'active' },\n ]}\n/>"},{"name":"Custom Label","description":"Custom status text","code":"<ThinkingIndicator\n variant=\"dots\"\n label=\"Claude is writing code...\"\n/>"}]},"Toast":{"filePath":"src/components/Toast/Toast.fragment.tsx","meta":{"name":"Toast","description":"Brief, non-blocking notification messages","category":"feedback","status":"stable","tags":["notification","alert","message","feedback"]},"usage":{"when":["Providing feedback after an action","Showing success/error status of operations","Non-critical information that doesn't require action","Temporary messages that auto-dismiss"],"whenNot":["Critical errors requiring user action (use Dialog)","Persistent information (use Alert)","Inline validation (use form error states)","System-wide announcements (use Banner)"],"guidelines":["Keep messages brief and actionable","Use appropriate variant for the message type","Auto-dismiss after reasonable duration (3-5s)","Allow manual dismissal for longer messages","Limit number of simultaneous toasts"],"accessibility":["Use role=\"alert\" for important messages","Ensure sufficient display time for reading","Don't rely solely on color for meaning","Provide dismiss button with accessible label"]},"props":{"title":{"type":"string","description":"Toast title"},"description":{"type":"string","description":"Additional message content"},"variant":{"type":"enum","description":"Visual variant indicating message type","default":"default","values":["default","success","error","warning","info"]},"duration":{"type":"number","description":"Auto-dismiss duration in ms (0 = no auto-dismiss)","default":5000},"action":{"type":"object","description":"Optional action button { label, onClick }"}},"relations":[{"component":"Alert","relationship":"alternative","note":"Use Alert for persistent inline messages"},{"component":"Dialog","relationship":"alternative","note":"Use Dialog for messages requiring user action"}],"variants":[{"name":"Default","description":"Interactive toast demo - click buttons to trigger toasts","code":"<ToastDemoWrapper />"},{"name":"Success","description":"Success message variant","code":"<Toast\n title=\"Success!\"\n description=\"Your changes have been saved.\"\n variant=\"success\"\n/>"},{"name":"Error","description":"Error message variant","code":"<Toast\n title=\"Error\"\n description=\"Failed to save changes. Please try again.\"\n variant=\"error\"\n/>"},{"name":"Warning","description":"Warning message variant","code":"<Toast\n title=\"Warning\"\n description=\"This action cannot be undone.\"\n variant=\"warning\"\n/>"},{"name":"Info","description":"Informational message variant","code":"<Toast\n title=\"New Update\"\n description=\"Version 2.0 is now available.\"\n variant=\"info\"\n/>"},{"name":"With Action","description":"Toast with an action button","code":"<Toast\n title=\"File deleted\"\n description=\"The file has been moved to trash.\"\n action={{\n label: 'Undo',\n onClick: () => console.log('Undo clicked'),\n }}\n/>"}]},"Toggle":{"filePath":"src/components/Toggle/Toggle.fragment.tsx","meta":{"name":"Toggle","description":"Binary on/off switch for settings and preferences. Provides immediate visual feedback and is ideal for options that take effect instantly.","category":"forms","status":"stable","tags":["switch","toggle","boolean","settings","preference"],"since":"0.1.0"},"usage":{"when":["Binary settings that take effect immediately (e.g., dark mode, notifications)","Enabling/disabling features in a settings panel","Options where the result is immediately visible","Mobile-friendly boolean inputs"],"whenNot":["Multiple options in a group (use checkbox group)","Selection requires form submission to take effect (use checkbox)","Yes/No questions in forms (use radio buttons)","Complex multi-state options (use select or radio)"],"guidelines":["Toggle should always have a visible label explaining what it controls","The \"on\" state should be the positive/enabling action","Changes should take effect immediately - no save button needed","Include a description for toggles whose effect isn't obvious from the label","Group related toggles visually in settings panels"],"accessibility":["Uses role=\"switch\" with aria-checked for proper semantics","Must have an accessible label (visible or aria-label)","Focus indicator must be clearly visible","State change must be announced by screen readers"]},"props":{"checked":{"type":"boolean","description":"Whether the toggle is in the on state","default":"false"},"onChange":{"type":"function","description":"Callback with new checked state: (checked: boolean) => void"},"label":{"type":"string","description":"Visible label text"},"description":{"type":"string","description":"Helper text shown below the label"},"disabled":{"type":"boolean","description":"Whether the toggle is non-interactive","default":"false"},"size":{"type":"enum","description":"Toggle track size","default":"md","values":["sm","md"]}},"relations":[{"component":"Input","relationship":"sibling","note":"Input handles text/number entry; Toggle handles boolean state"},{"component":"Checkbox","relationship":"alternative","note":"Use Checkbox when change requires form submission"}],"variants":[{"name":"Default Off","description":"Toggle in the off state","code":"<StatefulToggle label=\"Email notifications\" />","args":{"label":"Email notifications"}},{"name":"Checked","description":"Toggle in the on state","code":"<StatefulToggle checked label=\"Dark mode\" />","args":{"checked":true,"label":"Dark mode"}},{"name":"With Description","description":"Toggle with explanatory helper text","code":"<StatefulToggle\n checked\n label=\"Auto-save\"\n description=\"Automatically save changes as you type\"\n/>","args":{"checked":true,"label":"Auto-save","description":"Automatically save changes as you type"}},{"name":"Small Size","description":"Compact toggle for dense settings panels","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <StatefulToggle size=\"sm\" checked label=\"Show line numbers\" />\n <StatefulToggle size=\"sm\" label=\"Word wrap\" />\n <StatefulToggle size=\"sm\" checked label=\"Minimap\" />\n</div>"},{"name":"Disabled States","description":"Non-interactive toggles showing both states","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <Toggle disabled label=\"Premium feature (upgrade required)\" />\n <Toggle disabled checked label=\"System managed (read-only)\" />\n</div>"},{"name":"Settings Panel","description":"Multiple toggles in a realistic settings layout","code":"<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '320px' }}>\n <StatefulToggle\n checked\n label=\"Push notifications\"\n description=\"Receive push notifications on your device\"\n />\n <StatefulToggle\n checked\n label=\"Email digest\"\n description=\"Weekly summary of your activity\"\n />\n <StatefulToggle\n label=\"Marketing emails\"\n description=\"Product updates and promotional offers\"\n />\n</div>"}]},"ToggleGroup":{"filePath":"src/components/ToggleGroup/ToggleGroup.fragment.tsx","meta":{"name":"ToggleGroup","description":"A group of toggle buttons where only one can be selected at a time. Useful for switching between views, modes, or options.","category":"forms","status":"stable","tags":["toggle","group","segmented","control","tabs","switch"],"since":"0.2.0"},"usage":{"when":["Switching between mutually exclusive views or modes","Selecting one option from a small set (2-5 options)","Segmented controls like view switchers","Filter or sort options"],"whenNot":["Multiple selections allowed (use Checkbox group)","Many options (use Select or RadioGroup)","Navigation between pages (use Tabs)","On/off toggle (use Toggle component)"],"guidelines":["Keep options to 2-5 items for clarity","Use clear, concise labels","Consider icons for common actions (grid/list view)","Ensure adequate touch targets on mobile"],"accessibility":["Uses role=\"group\" for semantic grouping","Each item has role=\"radio\" with aria-checked","Keyboard navigable with Tab and arrow keys","Focus visible on active item"]},"props":{"value":{"type":"string","description":"Currently selected value","required":true},"onChange":{"type":"function","description":"Called with new value when selection changes","required":true},"children":{"type":"node","description":"ToggleGroup.Item components","required":true},"variant":{"type":"enum","description":"Visual style","default":"default","values":["default","pills","outline"]},"size":{"type":"enum","description":"Size variant","default":"md","values":["sm","md"]},"gap":{"type":"enum","description":"Gap between items (pills/outline variants)","default":"xs","values":["none","xs","sm"]}},"relations":[{"component":"RadioGroup","relationship":"alternative","note":"RadioGroup for form-style single selection"},{"component":"Tabs","relationship":"alternative","note":"Tabs for content panel switching"},{"component":"Toggle","relationship":"sibling","note":"Toggle for single on/off control"}],"variants":[{"name":"Default","description":"Basic toggle group","code":"{\n const [value, setValue] = React.useState('left');\n return (\n <ToggleGroup value={value} onChange={setValue}>\n <ToggleGroup.Item value=\"left\">Left</ToggleGroup.Item>\n <ToggleGroup.Item value=\"center\">Center</ToggleGroup.Item>\n <ToggleGroup.Item value=\"right\">Right</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Pills Variant","description":"Pill-shaped toggle buttons","code":"{\n const [value, setValue] = React.useState('all');\n return (\n <ToggleGroup value={value} onChange={setValue} variant=\"pills\">\n <ToggleGroup.Item value=\"all\">All</ToggleGroup.Item>\n <ToggleGroup.Item value=\"active\">Active</ToggleGroup.Item>\n <ToggleGroup.Item value=\"completed\">Completed</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Outline Variant","description":"Outlined toggle buttons","code":"{\n const [value, setValue] = React.useState('day');\n return (\n <ToggleGroup value={value} onChange={setValue} variant=\"outline\">\n <ToggleGroup.Item value=\"day\">Day</ToggleGroup.Item>\n <ToggleGroup.Item value=\"week\">Week</ToggleGroup.Item>\n <ToggleGroup.Item value=\"month\">Month</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"Sizes","description":"Different size variants","code":"{\n const [value1, setValue1] = React.useState('a');\n const [value2, setValue2] = React.useState('a');\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <ToggleGroup value={value1} onChange={setValue1} size=\"sm\">\n <ToggleGroup.Item value=\"a\">Small</ToggleGroup.Item>\n <ToggleGroup.Item value=\"b\">Size</ToggleGroup.Item>\n </ToggleGroup>\n <ToggleGroup value={value2} onChange={setValue2} size=\"md\">\n <ToggleGroup.Item value=\"a\">Medium</ToggleGroup.Item>\n <ToggleGroup.Item value=\"b\">Size</ToggleGroup.Item>\n </ToggleGroup>\n </div>\n );\n}"},{"name":"View Switcher","description":"Common pattern for switching between views","code":"{\n const [view, setView] = React.useState('grid');\n return (\n <ToggleGroup value={view} onChange={setView} size=\"sm\">\n <ToggleGroup.Item value=\"grid\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" />\n </svg>\n </ToggleGroup.Item>\n <ToggleGroup.Item value=\"list\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </ToggleGroup.Item>\n </ToggleGroup>\n );\n}"},{"name":"With Disabled Item","description":"Toggle group with a disabled option","code":"{\n const [value, setValue] = React.useState('basic');\n return (\n <ToggleGroup value={value} onChange={setValue}>\n <ToggleGroup.Item value=\"basic\">Basic</ToggleGroup.Item>\n <ToggleGroup.Item value=\"pro\">Pro</ToggleGroup.Item>\n <ToggleGroup.Item value=\"enterprise\" disabled>Enterprise</ToggleGroup.Item>\n </ToggleGroup>\n );\n}"}]},"Tooltip":{"filePath":"src/components/Tooltip/Tooltip.fragment.tsx","meta":{"name":"Tooltip","description":"Contextual help text that appears on hover or focus. Perfect for explaining icons, truncated text, or providing additional context.","category":"feedback","status":"stable","tags":["tooltip","hint","help","hover","contextual"],"since":"0.1.0"},"usage":{"when":["Explaining icon-only buttons","Showing full text for truncated content","Providing keyboard shortcuts","Brief contextual help that fits in one line"],"whenNot":["Long-form help content (use Popover)","Critical information users must see (use Alert)","Interactive content (use Popover or Menu)","Mobile-primary interfaces (tooltips require hover)"],"guidelines":["Keep tooltip text concise (under 80 characters)","Use sentence case, no period for single sentences","Avoid duplicating visible label text","Consider mobile users who cannot hover"],"accessibility":["Accessible via focus as well as hover","Uses role=\"tooltip\" with proper aria association","Delay prevents tooltips from appearing during navigation"]},"props":{"children":{"type":"element","description":"The element that triggers the tooltip","required":true},"content":{"type":"node","description":"Content to display in the tooltip","required":true},"side":{"type":"enum","description":"Which side to show the tooltip","default":"top","values":["top","bottom","left","right"]},"align":{"type":"enum","description":"Alignment along the side","default":"center","values":["start","center","end"]},"sideOffset":{"type":"number","description":"Distance from trigger in pixels","default":"6"},"delay":{"type":"number","description":"Delay before showing (ms)","default":"400"},"arrow":{"type":"boolean","description":"Show arrow pointing to trigger","default":"true"},"disabled":{"type":"boolean","description":"Disable the tooltip","default":"false"}},"relations":[{"component":"Popover","relationship":"alternative","note":"Use Popover for interactive or longer content"},{"component":"Alert","relationship":"alternative","note":"Use Alert for critical information that must be visible"}],"variants":[{"name":"Default","description":"Basic tooltip on hover","code":"<Tooltip content=\"Save your changes\">\n <Button>Save</Button>\n</Tooltip>"},{"name":"Positions","description":"Tooltips on different sides","code":"<div style={{ display: 'flex', gap: '16px', padding: '40px' }}>\n <Tooltip content=\"Top tooltip\" side=\"top\">\n <Button variant=\"secondary\">Top</Button>\n </Tooltip>\n <Tooltip content=\"Bottom tooltip\" side=\"bottom\">\n <Button variant=\"secondary\">Bottom</Button>\n </Tooltip>\n <Tooltip content=\"Left tooltip\" side=\"left\">\n <Button variant=\"secondary\">Left</Button>\n </Tooltip>\n <Tooltip content=\"Right tooltip\" side=\"right\">\n <Button variant=\"secondary\">Right</Button>\n </Tooltip>\n</div>"},{"name":"With Shortcut","description":"Tooltip showing keyboard shortcut","code":"<Tooltip content=\"Undo (Ctrl+Z)\">\n <Button variant=\"ghost\">Undo</Button>\n</Tooltip>"},{"name":"No Arrow","description":"Tooltip without arrow","code":"<Tooltip content=\"Clean tooltip\" arrow={false}>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>"}]},"VisuallyHidden":{"filePath":"src/components/VisuallyHidden/VisuallyHidden.fragment.tsx","meta":{"name":"VisuallyHidden","description":"Hides content visually while keeping it accessible to screen readers. Essential for accessible icon-only buttons and supplementary text.","category":"navigation","status":"stable","tags":["accessibility","a11y","screen-reader","hidden","sr-only"],"since":"0.1.0"},"usage":{"when":["Providing accessible labels for icon-only buttons","Adding context that screen readers need but sighted users don't","Hiding decorative content while providing text alternatives","Skip links for keyboard navigation"],"whenNot":["Hiding content from everyone (use display: none or conditional render)","Content that should be visible on focus (use focus-visible styles)","Temporarily hidden content (use proper ARIA attributes)","Lazy-loaded content (use suspense or loading states)"],"guidelines":["Always use with icon-only interactive elements","Keep hidden text concise but descriptive","Test with screen readers to verify announcements","Don't overuse; visible text is often better"],"accessibility":["Content is announced by screen readers","Content is focusable if interactive elements are inside","Essential for WCAG 2.1 compliance with icon-only controls","Must convey equivalent information to visual content"]},"props":{"children":{"type":"node","description":"Content to hide visually","required":true},"as":{"type":"enum","description":"HTML element to render","default":"span","values":["span","div"]}},"relations":[{"component":"Button","relationship":"child","note":"Use inside icon-only buttons for accessible labels"},{"component":"Icon","relationship":"sibling","note":"Pair with icons to provide text alternatives"}],"variants":[{"name":"Icon Button Label","description":"Accessible label for icon-only button","code":"<button style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '40px',\n height: '40px',\n border: '1px solid var(--fui-border-default)',\n borderRadius: '8px',\n background: 'var(--fui-color-surface-primary)',\n cursor: 'pointer'\n}}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <VisuallyHidden>Search</VisuallyHidden>\n</button>"},{"name":"Supplementary Text","description":"Additional context for screen readers","code":"<a href=\"#\" style={{ color: 'var(--fui-color-accent)' }}>\n Read more\n <VisuallyHidden> about our accessibility features</VisuallyHidden>\n</a>"},{"name":"Skip Link","description":"Navigation aid that becomes visible on focus","code":"<div>\n <VisuallyHidden as=\"div\">\n <a\n href=\"#main-content\"\n style={{\n position: 'absolute',\n padding: '8px 16px',\n background: 'var(--fui-color-accent)',\n color: 'white'\n }}\n >\n Skip to main content\n </a>\n </VisuallyHidden>\n <p style={{ color: 'var(--fui-color-text-tertiary)', fontSize: '14px' }}>\n (Screen reader only: \"Skip to main content\" link)\n </p>\n</div>"}]}},"recipes":{"AI Chat":{"filePath":"src/recipes/AIChat.recipe.ts","name":"AI Chat","description":"Complete AI chat interface with Message, ConversationList, Prompt, and ThinkingIndicator","category":"ai","components":["Message","ConversationList","ThinkingIndicator","Prompt","Stack"],"code":"import { useState, useCallback } from 'react';\nimport {\n Message,\n ConversationList,\n ThinkingIndicator,\n Prompt,\n Stack,\n} from '@fragments/ui';\n\ninterface ChatMessage {\n id: string;\n role: 'user' | 'assistant' | 'system';\n content: string;\n timestamp: Date;\n status?: 'sending' | 'streaming' | 'complete' | 'error';\n}\n\ninterface ThinkingStep {\n id: string;\n label: string;\n status: 'pending' | 'active' | 'complete' | 'error';\n}\n\nfunction AIChat() {\n const [messages, setMessages] = useState<ChatMessage[]>([\n {\n id: 'system-1',\n role: 'system',\n content: 'Conversation started. Model: Claude 3.5 Sonnet',\n timestamp: new Date(),\n status: 'complete',\n },\n ]);\n const [isThinking, setIsThinking] = useState(false);\n const [thinkingSteps, setThinkingSteps] = useState<ThinkingStep[]>([]);\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\n\n const handleSubmit = useCallback(async (value: string) => {\n // Add user message\n const userMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'user',\n content: value,\n timestamp: new Date(),\n status: 'complete',\n };\n setMessages((prev) => [...prev, userMessage]);\n\n // Start thinking state with steps\n setIsThinking(true);\n setThinkingSteps([\n { id: '1', label: 'Understanding your request', status: 'active' },\n { id: '2', label: 'Searching knowledge base', status: 'pending' },\n { id: '3', label: 'Generating response', status: 'pending' },\n ]);\n\n try {\n // Simulate step 1 completion\n await new Promise((resolve) => setTimeout(resolve, 800));\n setThinkingSteps((prev) =>\n prev.map((s) =>\n s.id === '1'\n ? { ...s, status: 'complete' }\n : s.id === '2'\n ? { ...s, status: 'active' }\n : s\n )\n );\n\n // Simulate step 2 completion\n await new Promise((resolve) => setTimeout(resolve, 600));\n setThinkingSteps((prev) =>\n prev.map((s) =>\n s.id === '2'\n ? { ...s, status: 'complete' }\n : s.id === '3'\n ? { ...s, status: 'active' }\n : s\n )\n );\n\n // Simulate step 3 (response generation)\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Add assistant response\n const assistantMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: generateMockResponse(value),\n timestamp: new Date(),\n status: 'complete',\n };\n setMessages((prev) => [...prev, assistantMessage]);\n } catch (error) {\n // Handle error\n const errorMessage: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n status: 'error',\n };\n setMessages((prev) => [...prev, errorMessage]);\n } finally {\n setIsThinking(false);\n setThinkingSteps([]);\n }\n }, []);\n\n const handleLoadHistory = useCallback(async () => {\n if (isLoadingHistory) return;\n\n setIsLoadingHistory(true);\n await new Promise((resolve) => setTimeout(resolve, 1500));\n\n // Simulate loading older messages\n const olderMessages: ChatMessage[] = [\n {\n id: crypto.randomUUID(),\n role: 'user',\n content: 'What can you help me with?',\n timestamp: new Date(Date.now() - 86400000), // Yesterday\n status: 'complete',\n },\n {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'I can help with coding, writing, analysis, and more!',\n timestamp: new Date(Date.now() - 86400000 + 1000),\n status: 'complete',\n },\n ];\n\n setMessages((prev) => [...olderMessages, ...prev]);\n setIsLoadingHistory(false);\n }, [isLoadingHistory]);\n\n const handleCopy = useCallback((content: string) => {\n navigator.clipboard.writeText(content);\n // You might want to show a toast here\n }, []);\n\n return (\n <Stack\n style={{\n height: '100vh',\n maxWidth: '800px',\n margin: '0 auto',\n background: 'var(--fui-bg-primary)',\n }}\n >\n <ConversationList\n autoScroll=\"smart\"\n onScrollTop={handleLoadHistory}\n loadingHistory={isLoadingHistory}\n emptyState={\n <Stack align=\"center\" justify=\"center\" style={{ flex: 1, padding: '2rem' }}>\n <p style={{ color: 'var(--fui-text-secondary)' }}>\n Start a conversation with the AI assistant\n </p>\n </Stack>\n }\n >\n {messages.map((msg, index) => {\n // Add date separator if day changed\n const prevMsg = messages[index - 1];\n const showDateSeparator =\n !prevMsg ||\n new Date(msg.timestamp).toDateString() !==\n new Date(prevMsg.timestamp).toDateString();\n\n return (\n <React.Fragment key={msg.id}>\n {showDateSeparator && (\n <ConversationList.DateSeparator date={msg.timestamp} />\n )}\n <Message\n role={msg.role}\n status={msg.status}\n timestamp={msg.timestamp}\n actions={\n msg.role === 'assistant' && msg.status === 'complete' ? (\n <>\n <button\n onClick={() => handleCopy(msg.content)}\n style={{\n padding: '4px 8px',\n fontSize: '12px',\n background: 'var(--fui-bg-tertiary)',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n }}\n >\n Copy\n </button>\n </>\n ) : undefined\n }\n >\n <Message.Content>{msg.content}</Message.Content>\n {msg.timestamp && <Message.Timestamp />}\n </Message>\n </React.Fragment>\n );\n })}\n\n {isThinking && (\n <ThinkingIndicator\n variant=\"dots\"\n label=\"Claude is thinking...\"\n showElapsed\n steps={thinkingSteps}\n />\n )}\n </ConversationList>\n\n <div style={{ padding: '1rem', borderTop: '1px solid var(--fui-border)' }}>\n <Prompt\n onSubmit={handleSubmit}\n loading={isThinking}\n placeholder=\"Message Claude...\"\n >\n <Prompt.Textarea />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Attach file\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton active>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n </Prompt>\n </div>\n </Stack>\n );\n}\n\n// Mock response generator\nfunction generateMockResponse(input: string): string {\n const responses = [\n \"That's a great question! Let me help you with that.\",\n \"I understand what you're looking for. Here's what I can tell you...\",\n \"Based on my knowledge, I can provide some insights on this topic.\",\n \"Let me break this down for you step by step.\",\n ];\n return responses[Math.floor(Math.random() * responses.length)] +\n \" This is a simulated response. In a real implementation, this would be replaced with actual AI-generated content based on your query about: \" +\n input.substring(0, 50) + (input.length > 50 ? '...' : '');\n}\n\nexport default AIChat;","tags":["chat","ai","assistant","conversation","llm","chatbot"]},"App Shell":{"filePath":"src/recipes/AppShell.recipe.ts","name":"App Shell","description":"Full application layout with sidebar, header, and main content. Supports two layout modes: stacked (header full-width) and sidebar-inset (sidebar full-height).","category":"layout","components":["AppShell","Header","Sidebar","ThemeToggle"],"code":"// App Shell - Stacked Layout (header spans full width)\n// Best for apps where the brand should be prominent in the header\n\nimport { AppShell, Header, Sidebar, ThemeToggle } from '@fragments/ui';\n\nfunction StackedLayout({ children }) {\n return (\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Brand href=\"/\">MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/\" active>Dashboard</Header.NavItem>\n <Header.NavItem href=\"/settings\">Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"240px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<HomeIcon />} href=\"/\" active>\n Home\n </Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} href=\"/analytics\">\n Analytics\n </Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />} href=\"/settings\">\n Settings\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell - Sidebar Inset Layout (sidebar is full height)\n// Best for documentation sites or when sidebar branding is preferred\n\nfunction SidebarInsetLayout({ children }) {\n return (\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Search>\n <Input placeholder=\"Search...\" />\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"260px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <a href=\"/\">MyApp</a>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Getting Started\">\n <Sidebar.Item href=\"/docs\" active>Introduction</Sidebar.Item>\n <Sidebar.Item href=\"/docs/install\">Installation</Sidebar.Item>\n </Sidebar.Section>\n <Sidebar.Section label=\"Components\">\n <Sidebar.Item href=\"/components\">Overview</Sidebar.Item>\n <Sidebar.Item href=\"/components/button\">Button</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell with Collapsible Icon Sidebar\n// Sidebar collapses to icons only - great for dashboards\n\nfunction CollapsibleLayout({ children }) {\n return (\n <AppShell layout=\"sidebar-inset\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar collapsible=\"icon\" width=\"240px\" collapsedWidth=\"64px\">\n <Sidebar.Header collapsedContent={<Logo />}>\n <Logo /> <span>MyApp</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n </AppShell>\n );\n}\n\n// App Shell with Aside Panel\n// Optional right panel for additional context\n\nfunction LayoutWithAside({ children, aside }) {\n return (\n <AppShell layout=\"stacked\">\n <AppShell.Header>\n <Header>\n <Header.Brand>MyApp</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"lg\">\n {children}\n </AppShell.Main>\n\n <AppShell.Aside width=\"280px\">\n {aside}\n </AppShell.Aside>\n </AppShell>\n );\n}","tags":["layout","app-shell","sidebar","navigation","dashboard"]},"Card Grid":{"filePath":"src/recipes/CardGrid.recipe.ts","name":"Card Grid","description":"Responsive grid of cards that reflows based on available space","category":"layout","components":["Grid","Card"],"code":"<Grid columns=\"auto\" minChildWidth=\"16rem\" gap=\"md\">\n {items.map(item => (\n <Card key={item.id}>\n <Card.Header>\n <Card.Title>{item.title}</Card.Title>\n <Card.Description>{item.description}</Card.Description>\n </Card.Header>\n <Card.Body>{item.content}</Card.Body>\n </Card>\n ))}\n</Grid>","tags":["grid","cards","responsive","dashboard","tiles"]},"Chat Interface":{"filePath":"src/recipes/ChatInterface.recipe.ts","name":"Chat Interface","description":"AI chat interface with message history and prompt input","category":"layout","components":["Prompt","Card","Avatar","Stack"],"code":"import { useState } from 'react';\nimport { Prompt, Card, Avatar, Stack } from '@fragments-sdk/ui';\n\ninterface Message {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n}\n\nfunction ChatInterface() {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSubmit = async (value: string) => {\n // Add user message\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content: value,\n };\n setMessages((prev) => [...prev, userMessage]);\n setIsLoading(true);\n\n try {\n // Simulate API call\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Add assistant response\n const assistantMessage: Message = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: 'This is a simulated response. Replace with your AI API call.',\n };\n setMessages((prev) => [...prev, assistantMessage]);\n } finally {\n setIsLoading(false);\n }\n };\n\n return (\n <Stack gap=\"4\" style={{ height: '100vh', padding: '1rem' }}>\n {/* Messages */}\n <Stack gap=\"3\" style={{ flex: 1, overflow: 'auto' }}>\n {messages.map((msg) => (\n <Card key={msg.id} padding=\"md\">\n <Card.Body>\n <Stack direction=\"row\" gap=\"3\" align=\"start\">\n <Avatar size=\"sm\">\n {msg.role === 'user' ? 'U' : 'AI'}\n </Avatar>\n <div style={{ flex: 1 }}>{msg.content}</div>\n </Stack>\n </Card.Body>\n </Card>\n ))}\n </Stack>\n\n {/* Prompt */}\n <Prompt onSubmit={handleSubmit} loading={isLoading}>\n <Prompt.Textarea placeholder=\"Ask anything...\" />\n <Prompt.Toolbar>\n <Prompt.Actions>\n <Prompt.ActionButton aria-label=\"Attach file\">\n +\n </Prompt.ActionButton>\n <Prompt.ModeButton>Auto</Prompt.ModeButton>\n </Prompt.Actions>\n <Prompt.Info>\n <Prompt.Usage>52% used</Prompt.Usage>\n <Prompt.Submit />\n </Prompt.Info>\n </Prompt.Toolbar>\n </Prompt>\n </Stack>\n );\n}","tags":["chat","ai","assistant","conversation"]},"Code Examples":{"filePath":"src/recipes/CodeExamples.recipe.ts","name":"Code Examples","description":"Patterns for displaying code in documentation with syntax highlighting","category":"documentation","components":["CodeBlock","Tabs","Card"],"code":"// Installation commands with package manager tabs\n<Tabs defaultValue=\"npm\">\n <Tabs.List>\n <Tabs.Tab value=\"npm\">npm</Tabs.Tab>\n <Tabs.Tab value=\"pnpm\">pnpm</Tabs.Tab>\n <Tabs.Tab value=\"yarn\">yarn</Tabs.Tab>\n </Tabs.List>\n <Tabs.Panel value=\"npm\">\n <CodeBlock code=\"npm install @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n <Tabs.Panel value=\"pnpm\">\n <CodeBlock code=\"pnpm add @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n <Tabs.Panel value=\"yarn\">\n <CodeBlock code=\"yarn add @fragments-sdk/ui\" language=\"bash\" />\n </Tabs.Panel>\n</Tabs>\n\n// Usage example with preview\n<Card>\n <Card.Header>\n <Card.Title>Button Example</Card.Title>\n </Card.Header>\n <Card.Body>\n <div className=\"preview\">\n <Button variant=\"primary\">Click me</Button>\n </div>\n <CodeBlock\n code={`<Button variant=\"primary\">Click me</Button>`}\n language=\"tsx\"\n />\n </Card.Body>\n</Card>\n\n// Multi-file example with titles\n<CodeBlock\n title=\"Button.tsx\"\n code={buttonCode}\n language=\"tsx\"\n showLineNumbers\n/>\n<CodeBlock\n title=\"Button.module.scss\"\n code={stylesCode}\n language=\"scss\"\n showLineNumbers\n/>\n\n// Highlighted important lines\n<CodeBlock\n code={exampleCode}\n language=\"tsx\"\n showLineNumbers\n highlightLines={[3, \"7-10\"]}\n/>","tags":["code","documentation","syntax","examples"]},"Confirm Dialog":{"filePath":"src/recipes/ConfirmDialog.recipe.ts","name":"Confirm Dialog","description":"Confirmation dialog with destructive action warning","category":"overlays","components":["Dialog","Button"],"code":"<Dialog open={isOpen} onClose={onClose}>\n <Dialog.Title>{title}</Dialog.Title>\n <Dialog.Description>{description}</Dialog.Description>\n <Dialog.Actions>\n <Button variant=\"secondary\" onClick={onClose}>Cancel</Button>\n <Button variant=\"danger\" onClick={onConfirm}>Confirm</Button>\n </Dialog.Actions>\n</Dialog>","tags":["confirm","dialog","modal","destructive"]},"Dashboard Layout":{"filePath":"src/recipes/DashboardLayout.recipe.ts","name":"Dashboard Layout","description":"Dashboard grid with a featured full-width card and smaller metric cards below","category":"layout","components":["Grid","Card","Badge","Separator"],"code":"<Grid columns={4} gap=\"lg\">\n <Grid.Item colSpan=\"full\">\n <Card>\n <Card.Header>\n <Card.Title>Overview</Card.Title>\n <Card.Description>Key metrics for this period</Card.Description>\n </Card.Header>\n <Card.Body>{summaryContent}</Card.Body>\n </Card>\n </Grid.Item>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Users</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"success\">{stats.users}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Revenue</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"info\">{stats.revenue}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Orders</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"warning\">{stats.orders}</Badge>\n </Card.Body>\n </Card>\n <Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Errors</Card.Title>\n </Card.Header>\n <Card.Body>\n <Badge variant=\"danger\">{stats.errors}</Badge>\n </Card.Body>\n </Card>\n <Grid.Item colSpan=\"full\">\n <Separator spacing=\"md\" />\n </Grid.Item>\n <Grid.Item colSpan={2}>\n <Card>\n <Card.Header>\n <Card.Title>Recent Activity</Card.Title>\n </Card.Header>\n <Card.Body>{activityList}</Card.Body>\n </Card>\n </Grid.Item>\n <Grid.Item colSpan={2}>\n <Card>\n <Card.Header>\n <Card.Title>Notifications</Card.Title>\n </Card.Header>\n <Card.Body>{notificationList}</Card.Body>\n </Card>\n </Grid.Item>\n</Grid>","tags":["dashboard","layout","metrics","widgets","overview"]},"Dashboard Navigation":{"filePath":"src/recipes/DashboardNav.recipe.ts","name":"Dashboard Navigation","description":"Sidebar navigation pattern for dashboard applications with user profile, sections, and nested menus","category":"navigation","components":["Sidebar","Avatar"],"code":"// Dashboard Navigation with User Profile\n// A complete sidebar navigation for admin/dashboard interfaces\n\nfunction DashboardNav({ user, currentPath }) {\n const [collapsed, setCollapsed] = React.useState(false);\n const [projectsExpanded, setProjectsExpanded] = React.useState(false);\n\n return (\n <Sidebar\n collapsed={collapsed}\n onCollapsedChange={setCollapsed}\n >\n {/* Brand header */}\n <Sidebar.Header>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 256 256\" fill=\"var(--fui-color-accent)\">\n <path d=\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H48V48H208V208Z\" />\n </svg>\n {!collapsed && (\n <span style={{ fontWeight: 600, fontSize: '16px' }}>Dashboard</span>\n )}\n <Sidebar.CollapseToggle />\n </Sidebar.Header>\n\n {/* Main navigation */}\n <Sidebar.Nav aria-label=\"Dashboard navigation\">\n {/* Primary section */}\n <Sidebar.Section>\n <Sidebar.Item\n icon={<HomeIcon />}\n href=\"/dashboard\"\n active={currentPath === '/dashboard'}\n >\n Overview\n </Sidebar.Item>\n <Sidebar.Item\n icon={<ChartIcon />}\n href=\"/analytics\"\n active={currentPath === '/analytics'}\n badge=\"New\"\n >\n Analytics\n </Sidebar.Item>\n <Sidebar.Item\n icon={<InboxIcon />}\n href=\"/inbox\"\n active={currentPath === '/inbox'}\n badge=\"5\"\n >\n Inbox\n </Sidebar.Item>\n </Sidebar.Section>\n\n {/* Projects section with nested items */}\n <Sidebar.Section label=\"Workspace\">\n <Sidebar.Item\n icon={<FolderIcon />}\n hasSubmenu\n expanded={projectsExpanded}\n onExpandedChange={setProjectsExpanded}\n >\n Projects\n </Sidebar.Item>\n <Sidebar.Submenu>\n <Sidebar.SubItem\n href=\"/projects/website\"\n active={currentPath === '/projects/website'}\n >\n Website Redesign\n </Sidebar.SubItem>\n <Sidebar.SubItem\n href=\"/projects/mobile\"\n active={currentPath === '/projects/mobile'}\n >\n Mobile App\n </Sidebar.SubItem>\n <Sidebar.SubItem\n href=\"/projects/api\"\n active={currentPath === '/projects/api'}\n >\n API Integration\n </Sidebar.SubItem>\n </Sidebar.Submenu>\n <Sidebar.Item\n icon={<UsersIcon />}\n href=\"/team\"\n active={currentPath === '/team'}\n >\n Team Members\n </Sidebar.Item>\n <Sidebar.Item\n icon={<CalendarIcon />}\n href=\"/calendar\"\n active={currentPath === '/calendar'}\n >\n Calendar\n </Sidebar.Item>\n </Sidebar.Section>\n\n {/* Settings section */}\n <Sidebar.Section label=\"Account\">\n <Sidebar.Item\n icon={<GearIcon />}\n href=\"/settings\"\n active={currentPath === '/settings'}\n >\n Settings\n </Sidebar.Item>\n <Sidebar.Item\n icon={<HelpIcon />}\n href=\"/help\"\n active={currentPath === '/help'}\n >\n Help & Support\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n\n {/* Footer with user profile */}\n <Sidebar.Footer>\n <div style={{\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: collapsed ? '0' : '8px',\n borderRadius: '8px',\n cursor: 'pointer',\n }}>\n <Avatar\n src={user.avatar}\n name={user.name}\n size=\"sm\"\n />\n {!collapsed && (\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{\n fontWeight: 500,\n fontSize: '14px',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {user.name}\n </div>\n <div style={{\n fontSize: '12px',\n color: 'var(--fui-text-secondary)',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {user.email}\n </div>\n </div>\n )}\n </div>\n </Sidebar.Footer>\n </Sidebar>\n );\n}\n\n// Usage example:\n// <DashboardNav\n// user={{ name: 'Jane Doe', email: 'jane@example.com', avatar: '/avatar.jpg' }}\n// currentPath=\"/dashboard\"\n// />\n\n// Icon components (use your preferred icon library)\nconst HomeIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 256 256\" fill=\"currentColor\">\n <path d=\"M219.31,108.68l-80-80a16,16,0,0,0-22.62,0l-80,80A15.87,15.87,0,0,0,32,120v96a8,8,0,0,0,8,8H96a8,8,0,0,0,8-8V160h48v56a8,8,0,0,0,8,8h56a8,8,0,0,0,8-8V120A15.87,15.87,0,0,0,219.31,108.68Z\" />\n </svg>\n);","tags":["navigation","sidebar","dashboard","admin","menu"]},"Form Layout":{"filePath":"src/recipes/FormLayout.recipe.ts","name":"Form Layout","description":"Two-column form with full-width fields where needed, using Grid for alignment","category":"forms","components":["Grid","Input","Textarea","Select","Button"],"code":"<Grid columns={2} gap=\"md\">\n <Input label=\"First Name\" placeholder=\"Jane\" />\n <Input label=\"Last Name\" placeholder=\"Doe\" />\n <Grid.Item colSpan=\"full\">\n <Input label=\"Email\" type=\"email\" placeholder=\"jane@example.com\" />\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Select label=\"Role\">\n <Select.Item value=\"admin\">Admin</Select.Item>\n <Select.Item value=\"editor\">Editor</Select.Item>\n <Select.Item value=\"viewer\">Viewer</Select.Item>\n </Select>\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Textarea label=\"Bio\" placeholder=\"Tell us about yourself\" />\n </Grid.Item>\n <Grid.Item colSpan=\"full\">\n <Button type=\"submit\" variant=\"primary\">Save</Button>\n </Grid.Item>\n</Grid>","tags":["form","layout","grid","inputs","settings"]},"Login Form":{"filePath":"src/recipes/LoginForm.recipe.ts","name":"Login Form","description":"Email/password authentication form with validation states","category":"forms","components":["FormField","Input","Button","Alert"],"code":"<FormField label=\"Email\" error={errors.email}>\n <Input type=\"email\" placeholder=\"you@example.com\" />\n</FormField>\n<FormField label=\"Password\" error={errors.password}>\n <Input type=\"password\" />\n</FormField>\n<Button type=\"submit\" variant=\"primary\">Sign in</Button>\n{error && (\n <Alert severity=\"error\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>{error}</Alert.Content>\n </Alert.Body>\n </Alert>\n)}","tags":["auth","login","form"]},"Settings Page":{"filePath":"src/recipes/SettingsPage.recipe.ts","name":"Settings Page","description":"Settings page with labeled sections using cards, toggles, and a save action","category":"forms","components":["Grid","Card","Toggle","Input","Select","Separator","Button"],"code":"<Grid columns={1} gap=\"lg\">\n <Card>\n <Card.Header>\n <Card.Title>Profile</Card.Title>\n <Card.Description>Your public profile information</Card.Description>\n </Card.Header>\n <Card.Body>\n <Grid columns={2} gap=\"md\">\n <Input label=\"Display Name\" defaultValue={user.name} />\n <Input label=\"Email\" type=\"email\" defaultValue={user.email} />\n <Grid.Item colSpan=\"full\">\n <Input label=\"Website\" type=\"url\" defaultValue={user.website} />\n </Grid.Item>\n </Grid>\n </Card.Body>\n </Card>\n\n <Card>\n <Card.Header>\n <Card.Title>Notifications</Card.Title>\n <Card.Description>Choose what you get notified about</Card.Description>\n </Card.Header>\n <Card.Body>\n <Grid columns={1} gap=\"sm\">\n <Toggle label=\"Email notifications\" checked={prefs.emailNotifs} onChange={onToggle('emailNotifs')} />\n <Toggle label=\"Push notifications\" checked={prefs.pushNotifs} onChange={onToggle('pushNotifs')} />\n <Toggle label=\"Weekly digest\" checked={prefs.digest} onChange={onToggle('digest')} />\n </Grid>\n </Card.Body>\n </Card>\n\n <Card>\n <Card.Header>\n <Card.Title>Appearance</Card.Title>\n </Card.Header>\n <Card.Body>\n <Select label=\"Theme\" value={prefs.theme} onChange={onThemeChange}>\n <Select.Item value=\"light\">Light</Select.Item>\n <Select.Item value=\"dark\">Dark</Select.Item>\n <Select.Item value=\"system\">System</Select.Item>\n </Select>\n </Card.Body>\n </Card>\n\n <Separator />\n <Button variant=\"primary\" type=\"submit\">Save Changes</Button>\n</Grid>","tags":["settings","preferences","form","toggle","layout"]}}}
|