@agentero/design-system 0.18.2 → 0.19.0

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.
@@ -1 +1 @@
1
- {"v":0,"components":{"components-accordion":{"id":"components-accordion","name":"Accordion.Root","path":"./src/accordion/accordion.stories.tsx","stories":[{"id":"components-accordion--default","name":"Default","snippet":"const Default = () => <Accordion.Root type=\"single\" collapsible enclosed={false} disabled={false}>\n <FaqItems />\n</Accordion.Root>;","description":"Exclusive accordion: one item open at a time, `collapsible` lets it close."},{"id":"components-accordion--multiple","name":"Multiple","snippet":"const Multiple = () => (\n <Accordion.Root type=\"multiple\" defaultValue={['covered', 'payment']}>\n <FaqItems />\n </Accordion.Root>\n);","description":"`type=\"multiple\"` lets several sections stay open at once."},{"id":"components-accordion--enclosed","name":"Enclosed","snippet":"const Enclosed = () => (\n <div className=\"flex flex-col gap-8\">\n <Accordion.Root type=\"multiple\" defaultValue={['covered']}>\n <FaqItems />\n </Accordion.Root>\n <Accordion.Root type=\"multiple\" enclosed defaultValue={['claim']}>\n <FaqItems />\n </Accordion.Root>\n </div>\n);","description":"`enclosed` wraps the group in a bordered card (default borderless on top)."},{"id":"components-accordion--custom-trigger","name":"Custom Trigger","snippet":"const CustomTrigger = () => (\n <Accordion.Root type=\"single\" collapsible defaultValue=\"covered\">\n <Accordion.Item value=\"covered\">\n <Accordion.Trigger asChild>\n <button className=\"group flex w-full items-center gap-2 py-4 text-left text-base font-semibold\">\n <IconKeyboardArrowDown className=\"size-5 shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-180\" />\n What is covered?\n </button>\n </Accordion.Trigger>\n <Accordion.Content>{FAQS[0].answer}</Accordion.Content>\n </Accordion.Item>\n </Accordion.Root>\n);","description":"`asChild` delegates the trigger to a custom element; the built-in chevron is omitted."},{"id":"components-accordion--styled-titles","name":"Styled Titles","snippet":"const StyledTitles = () => <Accordion.Root type=\"single\" collapsible>\n {FAQS.map(({ value, question, answer }) => (\n <Accordion.Item key={value} value={value}>\n <Accordion.Trigger>\n <span className=\"text-lg font-bold\">{question}</span>\n </Accordion.Trigger>\n <Accordion.Content>{answer}</Accordion.Content>\n </Accordion.Item>\n ))}\n</Accordion.Root>;","description":"The consumer controls title weight/size via the children passed to `Trigger`."},{"id":"components-accordion--expand-collapse","name":"Expand Collapse","snippet":"const ExpandCollapse = () => <Accordion.Root type=\"single\" collapsible>\n <FaqItems />\n</Accordion.Root>;","description":"`collapsible` lets clicking the open item close it (reach an all-closed state)."},{"id":"components-accordion--non-collapsible","name":"Non Collapsible","snippet":"const NonCollapsible = () => <Accordion.Root type=\"single\" collapsible={false} defaultValue=\"covered\">\n <FaqItems />\n</Accordion.Root>;","description":"Without `collapsible`, clicking the already-open item keeps it open."}],"import":"import { Accordion, IconKeyboardArrowDown } from \"@agentero/design-system\";","jsDocTags":{},"description":"Stacked, collapsible sections built on Radix UI's Accordion (keyboard nav and ARIA come for free). Compose `Root` with `Item`s, each holding a `Trigger` and `Content`. `type=\"single\"` (optionally `collapsible`) opens one at a time; `type=\"multiple\"` opens sections independently. `enclosed` renders the group as a bordered card.","reactDocgenTypescript":{"tags":{},"filePath":"/home/runner/work/design-system/design-system/src/accordion/accordion.tsx","description":"Stacked, collapsible sections built on Radix UI's Accordion (keyboard nav and\nARIA come for free). Compose `Root` with `Item`s, each holding a `Trigger` and\n`Content`. `type=\"single\"` (optionally `collapsible`) opens one at a time;\n`type=\"multiple\"` opens sections independently. `enclosed` renders the group\nas a bordered card.","displayName":"Accordion","methods":[],"props":{},"exportName":"Accordion"}},"components-alert":{"id":"components-alert","name":"Alert","path":"./src/alert/alert.stories.tsx","stories":[{"id":"components-alert--default","name":"Default","snippet":"const Default = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Args-controlled playground. Toggle `color`, `size`, `ghost`, `hasIcon`, and `onDismiss` from the Controls panel to explore every visual combination.","summary":"Default args playground for Alert"},{"id":"components-alert--neutral","name":"Neutral","snippet":"const Neutral = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Neutral color is the default and carries no strong semantic signal — use it for generic inline information.","summary":"Neutral color (default)"},{"id":"components-alert--success","name":"Success","snippet":"const Success = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Success color confirms a positive outcome — saved record, completed task, healthy state.","summary":"Success color for positive outcomes"},{"id":"components-alert--danger","name":"Danger","snippet":"const Danger = () => <Alert\n color=\"danger\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Danger color flags errors and destructive outcomes that require the user's attention.","summary":"Danger color for errors and destructive outcomes"},{"id":"components-alert--warning","name":"Warning","snippet":"const Warning = () => <Alert\n color=\"warning\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Warning color signals caution — the user should review before proceeding.","summary":"Warning color for cautionary feedback"},{"id":"components-alert--info","name":"Info","snippet":"const Info = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Info color highlights tips, hints, or secondary informational content.","summary":"Info color for informational highlights"},{"id":"components-alert--creative","name":"Creative","snippet":"const Creative = () => <Alert\n color=\"creative\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Creative color uses a brand-aligned purple accent for marketing or onboarding moments.","summary":"Creative brand accent color"},{"id":"components-alert--dynamic","name":"Dynamic","snippet":"const Dynamic = () => <Alert\n color=\"dynamic\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Dynamic color uses a brand-aligned orange accent for activity or momentum-focused content.","summary":"Dynamic brand accent color"},{"id":"components-alert--playful","name":"Playful","snippet":"const Playful = () => <Alert\n color=\"playful\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Playful color uses a brand-aligned pink accent for lighter or celebratory content.","summary":"Playful brand accent color"},{"id":"components-alert--ghost","name":"Ghost","snippet":"const Ghost = () => <Alert\n color=\"danger\"\n size=\"sm\"\n ghost\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Ghost mode removes the background and padding so the alert blends inline with surrounding text (e.g., form field errors). Colors switch to the ghost token ramp for lower visual weight.","summary":"Ghost mode for inline, low-emphasis alerts"},{"id":"components-alert--small-size","name":"Small Size","snippet":"const SmallSize = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Small size (default) uses compact padding and 14/12px typography — suitable for inline alerts inside forms, tables, or cards.","summary":"Small size (default, compact)"},{"id":"components-alert--medium-size","name":"Medium Size","snippet":"const MediumSize = () => <Alert\n color=\"neutral\"\n size=\"md\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Medium size uses larger padding and 18/14px typography — suitable for standalone alerts in empty states, modals, or dedicated feedback regions.","summary":"Medium size (prominent, standalone)"},{"id":"components-alert--with-dismiss","name":"With Dismiss","snippet":"const WithDismiss = () => <Alert color=\"warning\" size=\"sm\" ghost={false} hasIcon onDismiss={fn()}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Dismissible alert. Providing `onDismiss` shows an icon-only close button with `aria-label=\"Dismiss\"` that inherits the alert's color.","summary":"Alert with a dismiss button"},{"id":"components-alert--with-actions","name":"With Actions","snippet":"const WithActions = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Update available</Alert.Title>\n <Alert.Paragraph>Reload to apply the latest version.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={() => {}}>Reload</Alert.Button>\n </Alert.Actions>\n</Alert>;","description":"Alert with a trailing action pinned to the right edge. Use `Alert.Actions` + `Alert.Button` for the common \"message + action\" pattern.","summary":"Alert with a trailing action button"},{"id":"components-alert--with-dismiss-and-action","name":"With Dismiss And Action","snippet":"const WithDismissAndAction = () => <Alert\n color=\"warning\"\n size=\"md\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Session expiring</Alert.Title>\n <Alert.Paragraph>Renew to continue editing.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={() => {}}>Renew session</Alert.Button>\n </Alert.Actions>\n</Alert>;","description":"Alert combining a dismiss button with a trailing action. Dismiss is pinned to the right edge after the actions.","summary":"Alert with both dismiss and action"},{"id":"components-alert--without-icon","name":"Without Icon","snippet":"const WithoutIcon = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon={false}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert rendered without the built-in color icon. Use `hasIcon={false}` when the surrounding context already conveys the semantic intent.","summary":"Alert without the default icon"},{"id":"components-alert--with-custom-icon","name":"With Custom Icon","snippet":"const WithCustomIcon = () => <Alert\n color=\"creative\"\n size=\"sm\"\n ghost={false}\n hasIcon\n icon={IconLightbulb}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert with a caller-supplied icon that replaces the default color icon. The custom icon receives the slot-computed className so color tokens still apply.","summary":"Alert with a custom icon override"},{"id":"components-alert--with-paragraph-html","name":"With Paragraph Html","snippet":"const WithParagraphHtml = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Formatted content</Alert.Title>\n <Alert.ParagraphHtml\n html=\"Review the <strong>terms</strong> or <a href='https://example.com'>read the docs</a>.\" />\n </Alert.Content>\n</Alert>;","description":"Alert rendering a paragraph from pre-sanitized HTML via `Alert.ParagraphHtml`. The caller is responsible for sanitizing the HTML string before passing it in.","summary":"Alert paragraph rendered from HTML"},{"id":"components-alert--with-pictograms","name":"With Pictograms","snippet":"const WithPictograms = () => <Alert\n color=\"info\"\n size=\"md\"\n ghost={false}\n hasIcon={false}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Pictograms>\n <svg viewBox=\"0 0 64 64\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden>\n <circle cx=\"32\" cy=\"32\" r=\"28\" fill=\"currentColor\" opacity=\"0.15\" />\n <circle cx=\"32\" cy=\"32\" r=\"14\" fill=\"currentColor\" />\n </svg>\n </Alert.Pictograms>\n <Alert.Content>\n <Alert.Title>Pictogram example</Alert.Title>\n <Alert.Paragraph>Pictograms scale to 64×64px regardless of the configured size.\n </Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert with a 64×64 pictogram in place of the inline icon. Use `Alert.Pictograms` when the message benefits from a richer illustration.","summary":"Alert with a pictogram illustration"},{"id":"components-alert--only-paragraph","name":"Only Paragraph","snippet":"const OnlyParagraph = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Paragraph>This field is required.</Alert.Paragraph>\n</Alert>;","description":"Alert rendered with only a paragraph — no title. The root omits `aria-labelledby` since there is no title to reference.","summary":"Alert with only a paragraph body"},{"id":"components-alert--with-actions-below","name":"With Actions Below","snippet":"const WithActionsBelow = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Upload complete</Alert.Title>\n <Alert.Paragraph>12 documents were added to the policy.</Alert.Paragraph>\n <div>\n <Alert.Button onClick={() => {}}>View documents</Alert.Button>\n </div>\n </Alert.Content>\n</Alert>;","description":"Action button rendered inline below the paragraphs, inside `Alert.Content`, rather than pinned to the right via `Alert.Actions`.","summary":"Alert with actions placed below the content"},{"id":"components-alert--all-colors","name":"All Colors","snippet":"const AllColors = () => (\n <Stack>\n {COLORS.map(color => (\n <Alert key={color} color={color}>\n <Alert.Content>\n <Alert.Title>{color}</Alert.Title>\n <Alert.Paragraph>\n This is a {color} alert variant with the default icon.\n </Alert.Paragraph>\n </Alert.Content>\n </Alert>\n ))}\n </Stack>\n);","description":"All eight colors in their primary (non-ghost) treatment, stacked for comparison. Each alert uses the built-in icon mapping for its color.","summary":"Visual comparison of all Alert colors"},{"id":"components-alert--all-ghost-colors","name":"All Ghost Colors","snippet":"const AllGhostColors = () => (\n <Stack>\n {COLORS.map(color => (\n <Alert key={color} color={color} ghost>\n <Alert.Content>\n <Alert.Title>{color} (ghost)</Alert.Title>\n <Alert.Paragraph>\n This is a {color} ghost alert variant with the ghost icon color.\n </Alert.Paragraph>\n </Alert.Content>\n </Alert>\n ))}\n </Stack>\n);","description":"All eight colors in ghost mode, stacked for comparison. Ghost alerts use a lower-weight token ramp and omit background + padding.","summary":"Visual comparison of all Alert colors in ghost mode"}],"import":"import { Alert } from \"@agentero/design-system\";","jsDocTags":{},"description":"Alert surfaces feedback about outcomes or state changes — success, danger, warning, or info. Compose it from `Alert.Content`, `Alert.Title`, `Alert.Paragraph`, `Alert.Actions`, and `Alert.Button` to build the layout your flow needs. Eight colors, two sizes, and a ghost mode cover most feedback scenarios.","reactDocgenTypescript":{"tags":{"summary":"Feedback banner with color variants, optional icon, and dismiss","example":"<Alert color=\"success\" size=\"sm\">\n <Alert.Content>\n <Alert.Title>Policy saved</Alert.Title>\n <Alert.Paragraph>Your changes are live.</Alert.Paragraph>\n </Alert.Content>\n</Alert>\n<Alert color=\"warning\" onDismiss={() => setOpen(false)}>\n <Alert.Content>\n <Alert.Title>Session expiring</Alert.Title>\n <Alert.Paragraph>Renew to continue editing.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={renew}>Renew session</Alert.Button>\n </Alert.Actions>\n</Alert>\n<Alert color=\"danger\" ghost>\n <Alert.Paragraph>This field is required.</Alert.Paragraph>\n</Alert>"},"filePath":"/home/runner/work/design-system/design-system/src/alert/alert.tsx","description":"Alert surfaces feedback about an outcome or state change — success, error,\nwarning, or informational. Compose it from the exposed sub-components to\nbuild the layout you need: `Alert.Content` groups a `Alert.Title` and any\nnumber of `Alert.Paragraph` / `Alert.ParagraphHtml`; `Alert.Actions` adds\ntrailing buttons; `Alert.Pictograms` renders a 64px illustration. Pass\n`onDismiss` to show a close button; `hasIcon={false}` to hide the default\nicon; `icon` to substitute a custom icon component.\n\nAccessibility: the root carries `role=\"alert\"`; `aria-labelledby` points at\nthe rendered `Alert.Title` (when present) and `aria-describedby` at the\nparagraph wrapper. Multiple Alerts on the same page receive unique ids via\n`useId()`. The dismiss control has an accessible name of `Dismiss`.\n\nDo **not** use Alert for transient toast notifications (use a Toast\ncomponent) or for large error pages (use a dedicated empty-state).","displayName":"Alert","methods":[],"props":{"onDismiss":{"defaultValue":null,"description":"Fires when the dismiss button is clicked. When provided, renders an `iconOnly` close button with `aria-label=\"Dismiss\"`.","name":"onDismiss","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"(() => void)"}},"hasIcon":{"defaultValue":{"value":"true"},"description":"When `true` (default), renders the built-in icon for the current `color`. Set to `false` to omit the icon entirely.","name":"hasIcon","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"icon":{"defaultValue":null,"description":"Overrides the default icon for the current `color`. Receives the slot-computed className so color tokens still apply.","name":"icon","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ComponentType<SVGProps<SVGSVGElement>>"}},"color":{"defaultValue":{"value":"neutral"},"description":"Semantic color. Defaults to `'neutral'`.\n- `neutral` — generic info; no strong signal.\n- `success` — positive confirmation.\n- `danger` — error or destructive outcome.\n- `warning` — caution; user attention needed.\n- `info` — informational highlight.\n- `creative`, `dynamic`, `playful` — brand-aligned accents.","name":"color","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"HTMLAttributes"}],"required":false,"type":{"name":"enum","raw":"\"neutral\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"creative\" | \"dynamic\" | \"playful\"","value":[{"value":"\"neutral\""},{"value":"\"success\""},{"value":"\"danger\""},{"value":"\"warning\""},{"value":"\"info\""},{"value":"\"creative\""},{"value":"\"dynamic\""},{"value":"\"playful\""}]}},"size":{"defaultValue":{"value":"sm"},"description":"Size treatment. Defaults to `'sm'`.\n- `sm` — compact inline alerts (1rem padding, 14/12px typography).\n- `md` — prominent standalone alerts (2rem padding, 18/14px typography).","name":"size","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"AlertSizeType","value":[{"value":"\"sm\""},{"value":"\"md\""}]}},"ghost":{"defaultValue":{"value":"false"},"description":"When `true`, removes background and padding so the alert blends inline\nwith surrounding text (e.g., inline form field errors). Colors switch\nto the ghost token ramp for lower visual weight.","name":"ghost","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Alert"}},"components-avatar":{"id":"components-avatar","name":"Avatar","path":"./src/avatar/avatar.stories.tsx","stories":[{"id":"components-avatar--default","name":"Default","snippet":"const Default = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"photo\" />;","description":"The default avatar with fallback initials. Renders as a medium circle when no image source is provided.","summary":"Default avatar with fallback initials"},{"id":"components-avatar--with-image","name":"With Image","snippet":"const WithImage = () => <Avatar\n fallback=\"JD\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\" />;","description":"Avatar displaying a user profile photo. The image fills the avatar shape and the fallback is hidden while the image loads successfully.","summary":"Avatar with a profile image"},{"id":"components-avatar--with-fallback-initials","name":"With Fallback Initials","snippet":"const WithFallbackInitials = () => <Avatar\n fallback=\"AM\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://broken-url.example/photo.jpg\" />;","description":"When the image fails to load, the fallback content is displayed. Pass initials, an icon, or any ReactNode as the `fallback` prop.","summary":"Fallback content shown when image is unavailable"},{"id":"components-avatar--circle","name":"Circle","snippet":"const Circle = () => <Avatar fallback=\"CR\" size=\"md\" variant=\"circle\" type=\"photo\" />;","description":"The circle variant is the default shape, ideal for user profile photos.","summary":"Circle-shaped avatar (default)"},{"id":"components-avatar--square","name":"Square","snippet":"const Square = () => <Avatar fallback=\"WS\" size=\"md\" variant=\"square\" type=\"photo\" />;","description":"The square variant uses a rounded rectangle, suitable for workspace, team, or organization icons.","summary":"Square-shaped avatar for workspaces"},{"id":"components-avatar--pillow","name":"Pillow","snippet":"const Pillow = () => <Avatar fallback=\"PL\" size=\"md\" variant=\"pillow\" type=\"photo\" />;","description":"The pillow variant uses a soft, organic squircle shape for a friendly and distinctive appearance.","summary":"Pillow-shaped avatar with organic squircle"},{"id":"components-avatar--pentagon","name":"Pentagon","snippet":"const Pentagon = () => <Avatar fallback=\"PT\" size=\"md\" variant=\"pentagon\" type=\"photo\" />;","description":"The pentagon variant uses a five-sided mask for a unique visual identity. Note: the border is hidden in this variant due to the mask shape.","summary":"Pentagon-shaped avatar for unique identity"},{"id":"components-avatar--type-photo","name":"Type Photo","snippet":"const TypePhoto = () => <Avatar\n fallback=\"AM\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\" />;","description":"The `photo` type is the default. The image fills the avatar shape edge-to-edge, which is ideal for user profile photographs.","summary":"Photo type fills the avatar shape edge-to-edge"},{"id":"components-avatar--type-initials","name":"Type Initials","snippet":"const TypeInitials = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"initials\" />;","description":"The `initials` type is intended when no image is available and the avatar stands in for a user with their initials. The fallback text is centered within the avatar shape.","summary":"Initials type for users without a profile photo"},{"id":"components-avatar--type-isotype","name":"Type Isotype","snippet":"const TypeIsotype = () => <Avatar\n fallback=\"FG\"\n size=\"md\"\n variant=\"square\"\n type=\"isotype\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\" />;","description":"The `isotype` type renders the image smaller than the avatar shape so a brand or organization icon sits centered inside the container rather than filling it. Use for workspace, team, or company avatars where a logo should remain legible inside the bounding shape.","summary":"Isotype type centers a brand icon inside the shape"},{"id":"components-avatar--all-types","name":"All Types","snippet":"const AllTypes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n <Avatar\n size=\"lg\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n <Avatar size=\"lg\" type=\"initials\" fallback=\"JD\" />\n <Avatar\n size=\"lg\"\n type=\"isotype\"\n variant=\"square\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\"\n fallback=\"FG\"\n />\n </div>\n);","description":"All content types shown side by side: `photo` fills the shape, `initials` centers text, and `isotype` shrinks a brand icon inside the bounding shape.","summary":"Visual comparison of all avatar content types"},{"id":"components-avatar--all-sizes-isotype","name":"All Sizes Isotype","snippet":"const AllSizesIsotype = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar\n key={size}\n size={size}\n type=\"isotype\"\n variant=\"square\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\"\n fallback=\"FG\"\n />\n ))}\n </div>\n);","description":"The isotype icon scales proportionally smaller than the avatar shape at every size, keeping a consistent inset around the logo from `xs` (24px) to `4xl` (128px).","summary":"Isotype scaling across all avatar sizes"},{"id":"components-avatar--size-xs","name":"Size Xs","snippet":"const SizeXs = () => <Avatar fallback=\"XS\" size=\"xs\" variant=\"circle\" type=\"photo\" />;","description":"Extra-small avatar (24px) for dense lists and inline indicators.","summary":"Extra-small 24px avatar"},{"id":"components-avatar--size-sm","name":"Size Sm","snippet":"const SizeSm = () => <Avatar fallback=\"SM\" size=\"sm\" variant=\"circle\" type=\"photo\" />;","description":"Small avatar (32px) for compact layouts and table rows.","summary":"Small 32px avatar"},{"id":"components-avatar--size-lg","name":"Size Lg","snippet":"const SizeLg = () => <Avatar fallback=\"LG\" size=\"lg\" variant=\"circle\" type=\"photo\" />;","description":"Large avatar (48px) for profile sections and detail views.","summary":"Large 48px avatar"},{"id":"components-avatar--size-xl","name":"Size Xl","snippet":"const SizeXl = () => <Avatar fallback=\"XL\" size=\"xl\" variant=\"circle\" type=\"photo\" />;","description":"Extra-large avatar (64px) for hero sections and prominent display.","summary":"Extra-large 64px avatar"},{"id":"components-avatar--colorized","name":"Colorized","snippet":"const Colorized = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"photo\" colorize=\"jane doe\" />;","description":"The `colorize` prop deterministically maps a string (typically a user name) to a color from the palette, applying a tinted background and matching text color. Useful for distinguishing users in lists without profile photos.","summary":"Colorized avatar based on user name"},{"id":"components-avatar--all-colorized","name":"All Colorized","snippet":"const AllColorized = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {['alice', 'bob', 'carol', 'dave', 'eve', 'frank', 'grace', 'henry', 'iris'].map(name => (\n <Avatar key={name} size=\"lg\" colorize={name} fallback={name.slice(0, 2).toUpperCase()} />\n ))}\n </div>\n);","description":"Multiple colorized avatars showing how different names map to different colors from the palette for visual distinction.","summary":"Multiple colorized avatars for visual distinction"},{"id":"components-avatar--all-sizes","name":"All Sizes","snippet":"const AllSizes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar key={size} size={size} fallback={size.toUpperCase()} />\n ))}\n </div>\n);","description":"All available sizes displayed together for visual comparison. Sizes range from `xs` (24px) to `4xl` (128px).","summary":"Visual comparison of all avatar sizes"},{"id":"components-avatar--all-sizes-with-image","name":"All Sizes With Image","snippet":"const AllSizesWithImage = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar\n key={size}\n size={size}\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n ))}\n </div>\n);","description":"All sizes with a profile image to verify image scaling and quality across the full size range from `xs` (24px) to `4xl` (128px).","summary":"All avatar sizes with a profile image"},{"id":"components-avatar--all-variants","name":"All Variants","snippet":"const AllVariants = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['circle', 'square', 'pillow', 'pentagon'] as const).map(variant => (\n <Avatar\n key={variant}\n size=\"lg\"\n variant={variant}\n fallback={variant.slice(0, 2).toUpperCase()}\n />\n ))}\n </div>\n);","description":"All available shape variants displayed together for visual comparison. Each variant serves a different use case: user photos, workspaces, friendly branding, and unique identity.","summary":"Visual comparison of all avatar shapes"},{"id":"components-avatar--all-variants-with-image","name":"All Variants With Image","snippet":"const AllVariantsWithImage = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['circle', 'square', 'pillow', 'pentagon'] as const).map(variant => (\n <Avatar\n key={variant}\n size=\"lg\"\n variant={variant}\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n ))}\n </div>\n);","description":"All shape variants with a profile image to show how each mask clips the photo. Particularly useful for verifying the pentagon mask and pillow shape render correctly with real imagery.","summary":"All avatar shapes with a profile image"}],"import":"import { Avatar } from \"@agentero/design-system\";","jsDocTags":{},"description":"Avatar displays a user's profile image, initials, or a fallback icon. Use for user identification in lists, headers, cards, and comment threads. Supports multiple shapes (`circle`, `square`, `pillow`, `pentagon`), content types (`photo`, `initials`, `isotype`), and sizes from `xs` (24px) to `4xl` (128px).","reactDocgenTypescript":{"tags":{"summary":"Displays a user's profile image, initials, or fallback icon","example":"<Avatar src=\"/photos/jane.jpg\" alt=\"Jane Doe\" size=\"md\" variant=\"circle\" />\n<Avatar fallback=\"JD\" size=\"lg\" variant=\"square\" />"},"filePath":"/home/runner/work/design-system/design-system/src/avatar/avatar.tsx","description":"Avatar displays a user's profile image, initials, or a fallback icon.\nUse Avatar for user identification in lists, headers, cards, and comment threads.\n\nDo **not** use Avatar for decorative images or thumbnails unrelated to a person\nor entity — use a standard `<img>` or a Thumbnail component instead.\n\nRenders an image when `src` is provided; otherwise displays `fallback` content\n(typically initials or an icon). Built on Radix UI Avatar primitives.\n\nAvailable shapes: `circle` (default), `square`, `pillow`, and `pentagon`.\nSizes range from `xs` (24px) to `4xl` (128px), defaulting to `md` (40px).","displayName":"Avatar","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"alt":{"defaultValue":null,"description":"Accessible alt text describing the avatar image. Required when `src` is provided.","name":"alt","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"src":{"defaultValue":null,"description":"Image URL to display. When unavailable or loading fails, `fallback` content is shown instead.","name":"src","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"fallback":{"defaultValue":null,"description":"Content rendered when `src` is missing or fails to load. Typically user initials (e.g., \"JD\") or an icon.","name":"fallback","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ReactNode"}},"colorize":{"defaultValue":null,"description":"When provided, deterministically maps the string (typically a user name) to a\ncolor from the palette, applying a light background, matching text color, and\nborder color. Useful for distinguishing users in lists without profile photos.","name":"colorize","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"size":{"defaultValue":null,"description":"Controls the avatar dimensions. Defaults to `'md'` (40px).\n- `xs` (24px) — inline indicators, dense lists\n- `sm` (32px) — compact layouts, table rows\n- `md` (40px) — standard usage, cards, headers\n- `lg` (48px) — profile sections, detail views\n- `xl` (64px) — hero sections, prominent display\n- `2xl` (80px), `3xl` (96px), `4xl` (128px) — large feature areas, profile pages","name":"size","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"xs\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"4xl\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""},{"value":"\"lg\""},{"value":"\"xl\""},{"value":"\"2xl\""},{"value":"\"3xl\""},{"value":"\"4xl\""}]}},"variant":{"defaultValue":null,"description":"Shape of the avatar container. Defaults to `'circle'`.\n- `circle` — standard round avatar for user photos\n- `square` — rounded rectangle, suitable for workspace or team icons\n- `pillow` — soft, organic squircle shape\n- `pentagon` — distinctive five-sided shape for unique visual identity","name":"variant","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"circle\" | \"square\" | \"pillow\" | \"pentagon\"","value":[{"value":"\"circle\""},{"value":"\"square\""},{"value":"\"pillow\""},{"value":"\"pentagon\""}]}},"type":{"defaultValue":null,"description":"Content type the avatar represents. Defaults to `'photo'`.\n- `photo` — a user's profile photograph filling the avatar shape\n- `initials` — text initials standing in for a missing photo\n- `isotype` — a brand or organization icon rendered smaller than the avatar\n so it sits centered inside the shape instead of filling it","name":"type","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"isotype\" | \"photo\" | \"initials\"","value":[{"value":"\"isotype\""},{"value":"\"photo\""},{"value":"\"initials\""}]}}},"exportName":"Avatar"}},"components-button":{"id":"components-button","name":"Button","path":"./src/button/button.stories.tsx","stories":[{"id":"components-button--default","name":"Default","snippet":"const Default = () => <Button variant=\"primary\" size=\"sm\">{TEXT}</Button>;","description":"Args-controlled playground. Toggle `variant`, `size`, `status`, `loading`, `disabled`, and `rounded` from the Controls panel to explore every visual combination of the Button.","summary":"Default args playground for Button"},{"id":"components-button--variants","name":"Variants","snippet":"const Variants = () => (\n <Row>\n {VARIANTS.map(variant => (\n <Button key={variant} variant={variant}>\n {TEXT}\n </Button>\n ))}\n </Row>\n);","description":"All five variants at the default `sm` size. Variants express visual hierarchy: `primary` for the main CTA, `secondary` / `tertiary` for supporting actions, `ghost` for low-emphasis inline actions, and `link` for text-only actions.","summary":"All Button variants at default size"},{"id":"components-button--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <Row>\n {SIZES.map(size => (\n <Button key={size} size={size}>\n {TEXT}\n </Button>\n ))}\n </Row>\n);","description":"All four sizes at the default `primary` variant. Sizes scale from `xs` (24px) for dense toolbars up to `lg` (48px) for hero CTAs.","summary":"All Button sizes at default variant"},{"id":"components-button--disabled","name":"Disabled","snippet":"const Disabled = () => (\n <Row>\n {VARIANTS.map(variant => (\n <Button asChild key={variant} variant={variant} disabled>\n <a>{TEXT}</a>\n </Button>\n ))}\n </Row>\n);","description":"Disabled state across all variants. Rendered via `asChild` with `<a>` children to show the disabled treatment applied via className — native anchors ignore the `disabled` attribute, so Button emits `aria-disabled` and `data-disabled` on the child instead.","summary":"Disabled treatment for every variant"},{"id":"components-button--with-icons","name":"With Icons","snippet":"const WithIcons = () => (\n <Stack>\n {VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size}>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Variant × size grid with leading and trailing icons.","summary":"Variant × size grid with leading + trailing icons"},{"id":"components-button--only-icon","name":"Only Icon","snippet":"const OnlyIcon = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size} aria-label=\"Close\">\n <IconClose />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Icon-only buttons across the variant × size grid. Excludes `variant=\"link\"` — combining `link` with icon-only children logs a dev-only warning because the link treatment has no padding to accommodate an icon alone.","summary":"Icon-only Button across variant × size (excluding `link`)"},{"id":"components-button--loading","name":"Loading","snippet":"const Loading = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <div key={size} style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>\n <Button variant={variant} size={size} loading aria-label=\"Loading\">\n <IconAdd />\n </Button>\n <Button variant={variant} size={size} loading>\n {TEXT}\n </Button>\n </div>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Loading state across the variant × size grid. Each row shows two buttons per size: one icon-only, one with text. Loading forces `disabled` and overlays a spinner that inherits the variant's text color. Excludes `variant=\"link\"` — combining `link` with `loading` logs a dev-only warning.","summary":"Loading state across variant × size (excluding `link`)"},{"id":"components-button--status","name":"Status","snippet":"const Status = () => (\n <Stack>\n <Row>\n {VARIANTS.map(variant => (\n <Button key={variant} variant={variant} status=\"danger\">\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n <Row>\n {VARIANTS.map(variant => (\n <Button asChild key={variant} variant={variant} status=\"danger\" disabled>\n <a>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </a>\n </Button>\n ))}\n </Row>\n </Stack>\n);","description":"Destructive treatment via `status=\"danger\"`. The top row shows every variant enabled; the bottom row shows every variant disabled. Use `status=\"danger\"` for delete, remove, or disconnect actions regardless of variant.","summary":"`status=\"danger\"` across every variant, enabled + disabled"},{"id":"components-button--rounded","name":"Rounded","snippet":"const Rounded = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size} rounded>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Fully pill-shaped buttons across the variant × size grid. Excludes `variant=\"link\"` since the link treatment has no background to round.","summary":"`rounded` pill shape across variant × size (excluding `link`)"},{"id":"components-button--as-child","name":"As Child","snippet":"const AsChild = () => (\n <Row>\n <Button asChild variant=\"primary\">\n <a href=\"/dashboard\">Go to dashboard</a>\n </Button>\n <Button asChild variant=\"secondary\">\n <a href=\"https://agentero.com\" target=\"_blank\" rel=\"noreferrer\">\n Visit Agentero\n </a>\n </Button>\n </Row>\n);","description":"`asChild` renders Button's styles on the nested child element rather than on a `<button>` — the child receives Button's `className`, `ref`, and merged props via Radix's `Slot` primitive. Use it to turn any anchor or framework `Link` into a Button without coupling the design system to a router. In app code, swap the plain `<a>` below for your framework's Link (`next/link`, `react-router`, `@tanstack/react-router`, etc.).","summary":"`asChild` composes Button's styles onto any element"}],"import":"import { Button } from \"@agentero/design-system\";","jsDocTags":{},"description":"Button is the design system's primary actionable control. Pick `variant` to express hierarchy, `size` for prominence, and `status=\"danger\"` for destructive actions. Pass `asChild` to render Button's styles on any nested element — a plain `<a>`, a framework `<Link>`, or a custom component — without Button binding to any particular framework.","reactDocgenTypescript":{"tags":{"summary":"Primary actionable control; renders a `<button>` or, with `asChild`, any nested element","example":"<Button variant=\"primary\" size=\"sm\" onClick={handleSave}>\n Save changes\n</Button>\n<Button asChild variant=\"secondary\">\n <a href=\"https://agentero.com\" target=\"_blank\" rel=\"noreferrer\">Visit Agentero</a>\n</Button>\n// Framework-agnostic: wrap any Link implementation\n<Button asChild variant=\"primary\">\n <Link href=\"/dashboard\">Go to dashboard</Link>\n</Button>\n<Button variant=\"primary\" status=\"danger\" loading={isDeleting} onClick={handleDelete}>\n Delete account\n</Button>"},"filePath":"/home/runner/work/design-system/design-system/src/button/button.tsx","description":"Button is the design system's primary actionable control. Use it for any\ninteraction that triggers behavior, submits a form, or navigates the user.\nBy default Button renders a `<button>`; pass `asChild` to render its single\nchild element as the underlying tag instead — Button merges its styles,\n`className`, `ref`, and props onto whatever the consumer nests. This keeps\nthe design system framework-agnostic: route a plain `<a>`, a Next.js\n`<Link>`, a React Router `<Link>`, or any custom element through the same\nvisual treatment.\n\nPick `variant` to express hierarchy (`primary` for the main CTA,\n`secondary` / `tertiary` for supporting actions, `ghost` for low-emphasis\ninline actions, `link` for text-only actions). Use `status=\"danger\"` for\ndestructive actions and `loading` to block interaction while async work\nresolves.\n\nDo **not** use Button for toggle states (prefer a Switch or ToggleButton),\nfor passive decorative anchors without action intent (use a plain `<a>`),\nor with `variant=\"link\"` when loading or when the button has no text\nchildren — both combinations log a dev-only warning (silent in production).","displayName":"Button","methods":[],"props":{"children":{"defaultValue":null,"description":"Content rendered inside the Button. Accepts a text label, icon elements,\nor any mix of both. Icon-only children switch the Button to a square\naspect ratio and trigger the icon-only layout.\n\nWhen `asChild` is set, the single child element is merged with Button's\nprops and styles; auto-detection of icon-only children is skipped — use\nthe `iconOnly` prop to opt into the square icon-only layout.\n\nNot supported with `variant=\"link\"` when children resolve to icons only\n— passing both logs a dev-only warning (silent in production).","name":"children","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"DOMAttributes"}],"required":false,"type":{"name":"ReactNode"}},"variant":{"defaultValue":null,"description":"Visual hierarchy. Defaults to `'primary'`.\n- `primary` — main call-to-action; use once per view.\n- `secondary` — alternative action alongside a primary button.\n- `tertiary` — low-emphasis action, subtle background.\n- `ghost` — minimal background; low-emphasis action in dense layouts.\n- `link` — inline text-style action; no padding or background.","name":"variant","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ButtonVariantType","value":[{"value":"\"link\""},{"value":"\"ghost\""},{"value":"\"primary\""},{"value":"\"secondary\""},{"value":"\"tertiary\""}]}},"size":{"defaultValue":null,"description":"Control size. Defaults to `'sm'`.\n- `xs` (24px) — dense toolbars, compact inline actions.\n- `sm` (32px) — standard usage in forms and cards.\n- `md` (40px) — prominent actions in modals or feature rows.\n- `lg` (48px) — hero CTAs and full-width mobile actions.","name":"size","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ButtonSizeType","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""},{"value":"\"lg\""}]}},"status":{"defaultValue":null,"description":"Semantic status override. Set to `'danger'` for destructive actions\n(delete, remove, disconnect) — applies the destructive color treatment\nacross all variants.","name":"status","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"danger\"","value":[{"value":"\"danger\""}]}},"loading":{"defaultValue":null,"description":"When `true`, shows a spinner overlay and forces the button into a disabled\nstate to block further interaction. Not supported with `variant=\"link\"` —\npassing both logs a dev-only warning (silent in production).","name":"loading","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"disabled":{"defaultValue":null,"description":"Disables interaction and applies the disabled color treatment. Applied\nvia className so it still affects anchors rendered via `asChild`, which\nignore the native `disabled` attribute — in that case `aria-disabled`\nand `data-disabled` are forwarded to the child element instead.","name":"disabled","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"ButtonHTMLAttributes"}],"required":false,"type":{"name":"boolean"}},"iconOnly":{"defaultValue":null,"description":"Forces the icon-only layout (square aspect ratio, no min-width). Useful\nwith `asChild` where the single wrapper child prevents auto-detection.\nFor non-`asChild` usage, prefer passing icon elements as children — the\nicon-only layout is applied automatically.","name":"iconOnly","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"rounded":{"defaultValue":null,"description":"When `true`, renders a fully pill-shaped button (rounded-full). Otherwise\nuses the variant's default corner radius.","name":"rounded","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"align":{"defaultValue":null,"description":"Justifies children along the main axis. Defaults to `'center'`.\nUse `'justify'` to push leading and trailing icons to the edges.","name":"align","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"center\" | \"start\" | \"end\" | \"justify\"","value":[{"value":"\"center\""},{"value":"\"start\""},{"value":"\"end\""},{"value":"\"justify\""}]}},"fitContent":{"defaultValue":null,"description":"When `true`, removes the per-size `min-width` floor so the button hugs\nits content. Useful for inline actions inside tight containers.","name":"fitContent","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"ref":{"defaultValue":null,"description":"Ref forwarded to the underlying element. Typed as a union covering both\n`<button>` and `<a>` because `asChild` lets consumers render either tag\n(or any forwardRef component) through Radix's `Slot`.","name":"ref","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"Ref<HTMLButtonElement | HTMLAnchorElement>"}},"asChild":{"defaultValue":null,"description":"When `true`, Button clones its single child element and merges\nButton's `className`, `ref`, and event handlers onto it rather than\nrendering a `<button>`. Use this to style any element (a plain `<a>`,\na framework `Link`, a `React.forwardRef` component) as a Button.\n\nWhen combined with `disabled`, Button emits `aria-disabled` and\n`data-disabled` on the child instead of the native `disabled`\nattribute (which is ignored by non-form-control elements).","name":"asChild","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Button"}},"components-checklist":{"id":"components-checklist","name":"CheckList.Root","path":"./src/check-list/check-list.stories.tsx","stories":[{"id":"components-checklist--default","name":"Default","snippet":"const Default = () => (\n <CheckList.Root>\n <CheckList.Item>Instant appointment</CheckList.Item>\n <CheckList.Item>Bind with Agentero</CheckList.Item>\n <CheckList.Item>Available in the Agentero rater</CheckList.Item>\n </CheckList.Root>\n);","description":"Plain text rows with a leading check."},{"id":"components-checklist--rich-content","name":"Rich Content","snippet":"const RichContent = () => (\n <div className=\"w-72\">\n <CheckList.Root>\n <CheckList.Item>\n <a href=\"#quoting\" className=\"underline\">\n Agentero rater\n </a>\n </CheckList.Item>\n <CheckList.Item>\n Longer descriptions wrap under their own text while the check stays aligned to the first\n line.\n </CheckList.Item>\n </CheckList.Root>\n </div>\n);","description":"Items accept rich content — links, wrapped text, custom markup."}],"import":"import { CheckList } from \"@agentero/design-system\";","jsDocTags":{},"description":"CheckList renders a vertical list where every row is marked with a check icon. Purely presentational — for interactive selection use a checkbox group.","reactDocgenTypescript":{"tags":{"summary":"Vertical list of check-marked rows","example":"```tsx\n<CheckList.Root>\n <CheckList.Item>Instant appointment</CheckList.Item>\n</CheckList.Root>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/check-list/check-list.tsx","description":"CheckList renders a vertical list where every row is marked with a check\nicon — feature lists, benefits, availability summaries. Purely\npresentational: for interactive selection use a checkbox group instead.","displayName":"CheckList","methods":[],"props":{},"exportName":"CheckList"}},"components-datatable":{"id":"components-datatable","name":"DataTable.Root","path":"./src/data-table/data-table.stories.tsx","stories":[{"id":"components-datatable--playground","name":"Playground","snippet":"const Playground = () => <div\n className={args.enclosed ? 'flex min-h-0 flex-1 flex-col p-4' : 'contents'}>\n <DataTable.Root data={LEADS} columns={columns}>\n <DataTable.Table size=\"md\" embed enclosed={false} sticky=\"header\" />\n </DataTable.Root>\n</div>;","description":"Playground for `DataTable.Table` display props — toggle `size`, `embed`, `enclosed`, and `sticky` from the controls panel.","summary":"Display props playground (size / embed / enclosed / sticky)"},{"id":"components-datatable--leads","name":"Leads","snippet":"const Leads = () => {\n const [sorting, setSorting] = useState<SortingState>([]);\n const [page, setPage] = useState(1);\n const [search, setSearch] = useState('');\n\n const data = useMemo(\n () => LEADS.filter(l => l.contact.toLowerCase().includes(search.toLowerCase())),\n [search]\n );\n\n return (\n <DataTable.Root\n data={data}\n columns={columns}\n state={{ sorting }}\n onSortingChange={setSorting}\n getSortedRowModel={getSortedRowModel()}\n enableSortingRemoval={false}\n rowHref={lead => `/leads/${lead.leadId}`}>\n <DataTable.ToolBar>\n <input\n value={search}\n onChange={e => setSearch(e.target.value)}\n placeholder=\"Search...\"\n aria-label=\"Search leads\"\n className=\"h-8 w-60 rounded-md border border-border-default-base-primary px-3 text-sm outline-none\"\n />\n <Button variant=\"secondary\" size=\"sm\">\n Filters\n </Button>\n </DataTable.ToolBar>\n\n <DataTable.Table />\n\n <DataTable.Footer>\n <Pagination\n totalCount={LEADS.length}\n currentPage={page}\n pageSize={10}\n onPageChange={setPage}\n />\n </DataTable.Footer>\n </DataTable.Root>\n );\n};","description":"A leads-table composition: sortable `Created` column, a status badge, row navigation via `rowHref`, hover-revealed actions, a search input + filters in the toolbar, and pagination in the footer.","summary":"Representative leads table composition"},{"id":"components-datatable--empty","name":"Empty","snippet":"const Empty = () => (\n <DataTable.Root data={[] as Lead[]} columns={columns}>\n <DataTable.Table />\n </DataTable.Root>\n);","description":"No rows: the table renders its default empty state instead of body rows.","summary":"Empty state when there are no rows"},{"id":"components-datatable--loading","name":"Loading","snippet":"const Loading = () => (\n <DataTable.Root data={[] as Lead[]} columns={columns} isLoading>\n <DataTable.Table />\n </DataTable.Root>\n);","description":"Loading: the body is dimmed and the empty state is suppressed while data is in flight.","summary":"Loading state dims the table and hides the empty state"}],"import":"import { Button, DataTable, DropdownMenu, Pagination, Table } from \"@agentero/design-system\";","jsDocTags":{},"description":"DataTable is the data-driven table compound built on TanStack Table. This story shows a representative leads table: an `Applicant` column with a name + address, contact info, insurance type with an icon, a sortable `Created` column, a status badge, and hover-revealed row actions (open + a kebab menu). The toolbar (search + filters) and the footer pagination are **separate components** composed inside `ToolBar` / `Footer`.","reactDocgenTypescript":{"tags":{"summary":"Data-driven table compound (sorting, toolbar, pagination) over TanStack","see":"{@link https://tanstack.com/table/latest TanStack Table}","namespace":"DataTable","example":"```tsx\nimport { DataTable } from '@agentero/design-system/data-table';\nimport { createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<User>();\nconst columns = [\n columnHelper.accessor('name', { header: 'Name', enableSorting: true }),\n columnHelper.accessor('email', { header: 'Email' })\n];\n\n<DataTable.Root data={users} columns={columns}>\n <DataTable.ToolBar>\n <SearchInput />\n </DataTable.ToolBar>\n <DataTable.Table />\n <DataTable.Footer>\n <DataTable.Pagination\n currentPage={page}\n pageSize={10}\n totalCount={total}\n onPageChange={setPage}\n />\n </DataTable.Footer>\n</DataTable.Root>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/data-table/data-table.tsx","description":"Data-driven table compound built on TanStack Table and the `Table` primitive.\nCompose `Root` (owns the table instance) with `ToolBar`, `Table` (headers/rows,\nsorting, navigation, empty state), and `Footer` + `Pagination`. For hand-rendered\nrows without TanStack, drop to the `Table` primitive.","displayName":"DataTable","methods":[],"props":{},"exportName":"DataTable"}},"components-table":{"id":"components-table","name":"Table.Root","path":"./src/data-table/table.stories.tsx","stories":[{"id":"components-table--default","name":"Default","snippet":"const Default = args => renderTable(args);","description":"Default args playground.","summary":"Default table"},{"id":"components-table--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div className=\"flex flex-col gap-6\">\n {(['sm', 'md', 'lg'] as const).map(size => (\n <div key={size} className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-text-default-base-tertiary\">size=&quot;{size}&quot;</span>\n {renderTable({ size })}\n </div>\n ))}\n </div>\n);","description":"The three row densities. `size` sets row min-height: sm 48 / md 64 / lg 88px.","summary":"size — sm / md / lg"},{"id":"components-table--sticky-header","name":"Sticky Header","snippet":"const StickyHeader = args => renderTable(args);","description":"`sticky=\"header\"` pins the header while the body scrolls. Needs a bounded-height parent.","summary":"sticky=\"header\" with a scrolling body"},{"id":"components-table--sticky-header-and-footer","name":"Sticky Header And Footer","snippet":"const StickyHeaderAndFooter = args => renderTable(args, { totals: true });","description":"`sticky=\"headerAndFooter\"` pins the header and the last body row (totals here).","summary":"sticky=\"headerAndFooter\" with a pinned totals row"},{"id":"components-table--embed","name":"Embed","snippet":"const Embed = args => renderTable(args);","description":"`embed` drops the per-row dividers and tightens the edge gutter to 1rem.","summary":"embed — no row dividers, 1rem edge gutter"},{"id":"components-table--enclosed","name":"Enclosed","snippet":"const Enclosed = args => renderTable(args);","description":"`enclosed` wraps the table in a bordered, rounded container — the standalone \"card\" look, as opposed to a full-bleed page table.","summary":"enclosed — bordered, rounded card container"},{"id":"components-table--with-checkbox","name":"With Checkbox","snippet":"const WithCheckbox = args => renderTable(args, { checkbox: true });","description":"A leading checkbox column; checkbox cells collapse to zero width.","summary":"Selectable rows with a collapsing checkbox column"},{"id":"components-table--with-row-actions","name":"With Row Actions","snippet":"const WithRowActions = args => renderTable(args, { actions: true });","description":"Hover-revealed row actions pinned to the trailing edge.","summary":"Hover-revealed row actions"},{"id":"components-table--expandable-rows","name":"Expandable Rows","snippet":"const ExpandableRows = args => {\n const Demo = () => {\n const [openId, setOpenId] = useState<string | null>(ROWS[0]!.id);\n return (\n <Table.Root {...args}>\n <Table.Head>\n <Table.Row>\n <Table.Header>\n <span className=\"sr-only\">Expand</span>\n </Table.Header>\n <Table.Header>Name</Table.Header>\n <Table.Header>Email</Table.Header>\n <Table.Header>Role</Table.Header>\n </Table.Row>\n </Table.Head>\n <Table.Body>\n {ROWS.slice(0, 4).map(row => (\n <Fragment key={row.id}>\n <Table.Row>\n <Table.Cell>\n <Table.ExpandButton\n isExpanded={openId === row.id}\n toggleExpanded={() => setOpenId(openId === row.id ? null : row.id)}\n aria-label={`Toggle ${row.name}`}\n />\n </Table.Cell>\n <Table.Cell className=\"font-bold\">{row.name}</Table.Cell>\n <Table.Cell className=\"text-text-default-base-secondary\">{row.email}</Table.Cell>\n <Table.Cell>{row.role}</Table.Cell>\n </Table.Row>\n {openId === row.id && (\n <Table.ExpandedRow>\n <Table.Cell colSpan={4}>\n <div className=\"py-2 text-text-default-base-secondary\">\n Extended details for {row.name} — {row.amount} lifetime value.\n </div>\n </Table.Cell>\n </Table.ExpandedRow>\n )}\n </Fragment>\n ))}\n </Table.Body>\n </Table.Root>\n );\n };\n return <Demo />;\n};","description":"`Table.ExpandButton` toggles a `Table.ExpandedRow` detail panel under its row.","summary":"Expandable rows with a detail panel"}],"import":"import { Button, Table } from \"@agentero/design-system\";\nimport { Fragment } from \"react\";","jsDocTags":{},"description":"Low-level presentational table primitive: native `<table>` markup themed for scrolling, sticky rows, cell padding, dividers, hover, and expandable rows. For sorting/toolbar/pagination, prefer `DataTable`.","reactDocgenTypescript":{"tags":{"summary":"Low-level themed table primitive (scrolling, sticky, sizing, rows)","namespace":"Table"},"filePath":"/home/runner/work/design-system/design-system/src/data-table/table.tsx","description":"Low-level presentational table primitive — a thin themed wrapper over native\n`<table>` markup (scrolling, sticky rows, row sizing, dividers, hover,\nexpandable rows). Compose from `Root` / `Head` / `Body` / `Row` / `Header` /\n`Cell`, plus `ExpandButton` / `ExpandedRow` and `RowActions`. For\nsorting/toolbar/pagination, prefer `DataTable`, built on top of this.","displayName":"Table","methods":[],"props":{},"exportName":"Table"}},"components-divider":{"id":"components-divider","name":"Divider","path":"./src/divider/divider.stories.tsx","stories":[{"id":"components-divider--default","name":"Default","snippet":"const Default = () => <div\n className={cn(\n 'flex gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6',\n args.orientation === 'vertical' ? 'h-40 w-lg items-stretch' : 'w-80 flex-col'\n )}>\n <div className=\"flex flex-1 flex-col justify-center gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">First section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Content on one side of the divider, visually separated from the other.\n </p>\n </div>\n <Divider orientation=\"horizontal\" decorative />\n <div className=\"flex flex-1 flex-col justify-center gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Second section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Content on the other side of the divider, clearly separated from the first.\n </p>\n </div>\n</div>;","description":"The default horizontal, decorative divider — a 1px line that spans the parent width. Use this form between stacked content blocks.","summary":"Default horizontal decorative divider"},{"id":"components-divider--horizontal","name":"Horizontal","snippet":"const Horizontal = () => (\n <div className=\"w-80\">\n <Divider />\n </div>\n);","description":"Horizontal divider — a 1px line spanning the parent's full width. The default orientation; use to separate stacked content.","summary":"Horizontal 1px line spanning the parent width"},{"id":"components-divider--vertical","name":"Vertical","snippet":"const Vertical = () => (\n <div className=\"flex h-24 items-stretch\">\n <Divider orientation=\"vertical\" />\n </div>\n);","description":"Vertical divider — a 1px line spanning the parent's full height. Parent must establish a height (via `h-*` or an intrinsic flex item height) for the line to be visible.","summary":"Vertical 1px line spanning the parent height"},{"id":"components-divider--with-label","name":"With Label","snippet":"const WithLabel = () => <div className=\"flex w-80 flex-col gap-2\">\n <Button variant=\"primary\">Continue with email</Button>\n <Divider orientation=\"horizontal\" decorative label=\"or\" />\n <Button variant=\"secondary\">Continue with SSO</Button>\n</div>;","description":"Labelled divider. The label sits centered between two flanking 1px lines — a common pattern for \"or\" breaks between authentication options.","summary":"Horizontal divider with a centered \"or\" label"},{"id":"components-divider--vertical-with-label","name":"Vertical With Label","snippet":"const VerticalWithLabel = () => <div\n className=\"flex h-40 items-stretch gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6\">\n <div className=\"flex flex-col justify-center gap-1\">\n <h3 className=\"text-sm font-semibold text-text-default-base-primary\">Left panel</h3>\n <p className=\"text-xs text-text-default-base-secondary\">Content on the left side</p>\n </div>\n <Divider orientation=\"vertical\" decorative label=\"OR\" />\n <div className=\"flex flex-col justify-center gap-1\">\n <h3 className=\"text-sm font-semibold text-text-default-base-primary\">Right panel</h3>\n <p className=\"text-xs text-text-default-base-secondary\">Content on the right side</p>\n </div>\n</div>;","description":"Vertical divider with a label. The label sits between two stacked 1px line segments; use sparingly — horizontal labelled dividers are more common.","summary":"Vertical divider with a centered label"},{"id":"components-divider--semantic","name":"Semantic","snippet":"const Semantic = () => <div\n className=\"flex w-80 flex-col gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6\">\n <section className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section one</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Semantically separated from the next section for screen readers.\n </p>\n </section>\n <Divider orientation=\"horizontal\" decorative={false} />\n <section className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section two</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Screen readers will announce this as a separate section.\n </p>\n </section>\n</div>;","description":"Semantic divider (`decorative={false}`). Exposes `role=\"separator\"` and `aria-orientation` to assistive technologies, marking a meaningful section break rather than a purely visual one.","summary":"Semantic separator announced to assistive technologies"},{"id":"components-divider--in-list","name":"In List","snippet":"const InList = () => (\n <div className=\"w-80 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary\">\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 1</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n You have a new message from Jane.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 2</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n Your report is ready to download.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 3</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n System maintenance is scheduled for tonight.\n </p>\n </div>\n </div>\n);","description":"Divider between list rows. Dividers delineate each item without the visual weight of a full border on every row.","summary":"Horizontal dividers between stacked list rows"},{"id":"components-divider--in-toolbar","name":"In Toolbar","snippet":"const InToolbar = () => (\n <div className=\"inline-flex h-10 items-center gap-1 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary px-2 shadow-1\">\n <Button variant=\"ghost\" size=\"xs\">\n Cut\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Copy\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Paste\n </Button>\n <Divider orientation=\"vertical\" className=\"mx-1 h-6\" />\n <Button variant=\"ghost\" size=\"xs\">\n Undo\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Redo\n </Button>\n <Divider orientation=\"vertical\" className=\"mx-1 h-6\" />\n <Button variant=\"ghost\" size=\"xs\">\n Settings\n </Button>\n </div>\n);","description":"Vertical dividers grouping related toolbar actions. Use to separate logical clusters of buttons (editing vs. history vs. settings) without visual weight.","summary":"Vertical dividers grouping toolbar actions"},{"id":"components-divider--horizontal-in-content","name":"Horizontal In Content","snippet":"const HorizontalInContent = () => (\n <div className=\"flex w-96 flex-col gap-4 p-6\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section title</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n Descriptive content for the first section. The divider below separates it from the next.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Another section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n The second section is clearly separated from the previous one.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Final section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n Dividers help establish visual hierarchy in content-heavy layouts.\n </p>\n </div>\n </div>\n);","description":"Horizontal dividers between content sections in a long-form layout. Helps create visual hierarchy in content-heavy pages.","summary":"Horizontal dividers between content sections"},{"id":"components-divider--vertical-between-elements","name":"Vertical Between Elements","snippet":"const VerticalBetweenElements = () => (\n <div className=\"flex items-stretch gap-3\">\n <Button variant=\"primary\" size=\"sm\">\n Button 1\n </Button>\n <Divider orientation=\"vertical\" />\n <Button variant=\"primary\" size=\"sm\">\n Button 2\n </Button>\n <Divider orientation=\"vertical\" />\n <Button variant=\"primary\" size=\"sm\">\n Button 3\n </Button>\n </div>\n);","description":"Vertical dividers between inline elements. Common for separating a row of related controls or inline links without visual weight.","summary":"Vertical dividers separating inline elements"}],"import":"import { Button, Divider } from \"@agentero/design-system\";","jsDocTags":{},"description":"Divider separates content visually along either a horizontal or vertical axis. Use between page or card sections, between inline items in a toolbar or list, or — with the `label` prop — to render an \"or\"-style break between options. Set `decorative={false}` when the separator carries semantic meaning so it's announced to assistive technologies.","reactDocgenTypescript":{"tags":{"summary":"Visual or semantic separator that optionally renders a centered label","param":"orientation - Axis along which the separator renders. Defaults to `'horizontal'`.\n- `horizontal` — 1px line spanning the parent width.\n- `vertical` — 1px line spanning the parent height; parent must establish a height.\ndecorative - When `true` (default), the separator is purely visual and hidden\nfrom assistive technologies. Set to `false` to expose `role=\"separator\"` plus\n`aria-orientation` for meaningful section breaks.\nlabel - Optional inline content rendered between two flanking 1px lines.\nWhen omitted, Divider renders a single line.","example":"<Divider />\n<Divider orientation=\"vertical\" />\n<Divider label=\"or\" />\n<Divider decorative={false} />"},"filePath":"/home/runner/work/design-system/design-system/src/divider/divider.tsx","description":"Divider separates content visually (or semantically, via `decorative={false}`)\nalong either a horizontal or vertical axis. Use Divider between page or card\nsections, between inline items in a toolbar or list, or to break up long\ncontent regions. Pass a `label` to render the \"or\"-style divider with text\ncentered between two line segments — useful for auth flows and step breaks.\n\nBuilt on Radix UI's Separator primitive for the unlabelled case; the\nlabelled case renders a `<div>` that still forwards the correct\n`role`/`aria-orientation` when `decorative={false}`.\n\nDo **not** use Divider as a bare horizontal rule to add vertical rhythm —\nreach for margin utilities or a layout wrapper instead. Divider should carry\nmeaning (visual or semantic section break), not whitespace.","displayName":"Divider","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"label":{"defaultValue":null,"description":"Optional label rendered inline between two flanking 1px lines. When set,\nDivider renders a styled `<div>` (rather than the underlying separator\nprimitive) so the label can sit centered between the two line segments.","name":"label","declarations":[{"fileName":"design-system/src/divider/divider.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ReactNode"}}},"exportName":"Divider"}},"components-dropdownmenu":{"id":"components-dropdownmenu","name":"DropdownMenu.Root","path":"./src/dropdown-menu/dropdown-menu.stories.tsx","stories":[{"id":"components-dropdownmenu--default","name":"Default","snippet":"const Default = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Click me\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Edit clicked')}>Edit</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Duplicate clicked')}>\n Duplicate\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Archive clicked')}>\n Archive\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Delete clicked')}>\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"A minimal DropdownMenu with four `Item`s — edit/duplicate/archive plus a separator before a destructive delete. Use this as the starting point for most overflow menus.","summary":"Basic menu with item rows and a separated destructive action"},{"id":"components-dropdownmenu--with-groups-and-dividers","name":"With Groups And Dividers","snippet":"const WithGroupsAndDividers = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n More Options\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Undo')}>Undo</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Redo')}>Redo</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Copy')}>Copy</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Cut')}>Cut</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Paste')}>Paste</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item disabled>Print (disabled)</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Export')}>Export</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Multiple clusters of `Item`s split by `Separator` rules — mirrors an \"edit history / clipboard / export\" overflow menu. Demonstrates the `disabled` state on a menu row.","summary":"Menu with multiple `Separator`-split groups and a disabled item"},{"id":"components-dropdownmenu--with-icons","name":"With Icons","snippet":"const WithIcons = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Actions\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Copy')}>\n <IconContentCopy />\n Copy\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n onSelect={() => console.log('Delete')}\n className=\"data-[highlighted]:bg-red-100\">\n <IconDelete className=\"[&>path]:fill-red-500\" />\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Menu items with leading icons and a destructive row using the `data-[highlighted]:bg-red-100` + `text-red-500` escape hatch. Use this pattern when a row should read as destructive.","summary":"Icon-leading items with a destructive delete row"},{"id":"components-dropdownmenu--with-group-titles","name":"With Group Titles","snippet":"const WithGroupTitles = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Account Menu\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Label>Profile</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('View Profile')}>\n View Profile\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Edit Profile')}>\n Edit Profile\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Settings</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Preferences')}>\n Preferences\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Privacy')}>Privacy</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Notifications')}>\n Notifications\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Account</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Billing')}>Billing</DropdownMenu.Item>\n <DropdownMenu.Item\n onSelect={() => console.log('Logout')}\n className=\"data-[highlighted]:bg-red-100\">\n <span className=\"text-red-500\">Logout</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"`Label`-segmented Profile / Settings / Account sections with a destructive Logout row. Use `Label` to name groups that would otherwise be ambiguous from the item text alone.","summary":"Menu with `Label`-titled sections and a destructive logout row"},{"id":"components-dropdownmenu--with-submenu","name":"With Submenu","snippet":"const WithSubmenu = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n File Options\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('New File')}>New File</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Open')}>Open</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconIosShare />\n Share\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Email')}>Email</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Slack')}>Slack</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Copy Link')}>\n Copy Link\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconDriveFileMove />\n Move to\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Archive')}>\n Archive\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Projects')}>\n Projects\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Drafts')}>Drafts</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n onSelect={() => console.log('Delete')}\n className=\"data-[highlighted]:bg-red-100\">\n <IconDelete className=\"[&>path]:fill-red-500\" />\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"One level of nesting: Share and Move-to submenus wired via `Sub` / `SubTrigger` / `SubContent`. Each submenu is portaled independently so it escapes the parent's stacking context.","summary":"Single-level submenus for Share and Move-to flows"},{"id":"components-dropdownmenu--nested-submenus","name":"Nested Submenus","snippet":"const NestedSubmenus = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Organization Menu\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Label>Organization</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Dashboard')}>Dashboard</DropdownMenu.Item>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconPeople />\n Teams\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('View All Teams')}>\n View All Teams\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Engineering</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Frontend')}>\n Frontend\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Backend')}>\n Backend\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('DevOps')}>\n DevOps\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Design</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Product Design')}>\n Product Design\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Brand')}>\n Brand\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Item onSelect={() => console.log('Marketing')}>\n Marketing\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Settings')}>Settings</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Two levels of nesting: Organization → Teams → (Engineering, Design). Deeper nesting is rarely a good UX — prefer splitting into separate screens once the tree grows past two levels.","summary":"Two-level nested submenus inside a parent menu"},{"id":"components-dropdownmenu--submenu-with-disabled-items","name":"Submenu With Disabled Items","snippet":"const SubmenuWithDisabledItems = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Document Actions\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('View')}>View</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Edit')}>Edit</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconContentCopy />\n Export as\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('PDF')}>PDF</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Word')}>\n Word Document\n </DropdownMenu.Item>\n <DropdownMenu.Item disabled>Excel (Premium only)</DropdownMenu.Item>\n <DropdownMenu.Item disabled>PowerPoint (Premium only)</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger disabled>\n <IconIosShare />\n Share (Sign in required)\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item>Email</DropdownMenu.Item>\n <DropdownMenu.Item>Link</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Submenu that contains `disabled` `Item`s alongside a fully-disabled `SubTrigger`. Use `disabled` sparingly — prefer hiding unavailable actions outright unless the user needs to see them and understand why.","summary":"Submenu with `disabled` items and a disabled `SubTrigger`"}],"import":"import { Button, DropdownMenu } from \"@agentero/design-system\";","jsDocTags":{},"description":"DropdownMenu is a compound overlay for secondary actions, bulk operations, or navigation shortcuts triggered off a button or icon. Compose it from `Root` / `Trigger` / `Portal` / `Content` and fill the menu with `Item`, `Separator`, `Label`, and — for nested flows — `Sub` / `SubTrigger` / `SubContent`. Built on Radix UI's DropdownMenu primitive, so keyboard navigation, focus trapping, typeahead, and collision detection come for free.","reactDocgenTypescript":{"tags":{"summary":"Compound overlay menu for secondary actions, grouped items, and submenus","see":"{@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu Radix UI DropdownMenu}","example":"```tsx\nimport { DropdownMenu } from '@agentero/design-system/dropdown-menu';\n\n<DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconMoreVert />\n </DropdownMenu.Trigger>\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content side=\"bottom\" align=\"end\">\n <DropdownMenu.Label>Actions</DropdownMenu.Label>\n\n <DropdownMenu.Item onSelect={() => handleEdit()}>\n <IconEdit />\n Edit\n </DropdownMenu.Item>\n\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Share</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item>Email</DropdownMenu.Item>\n <DropdownMenu.Item>Slack</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n\n <DropdownMenu.Separator />\n\n <DropdownMenu.Item\n onSelect={() => handleDelete()}\n disabled={!canDelete}\n >\n <IconDelete />\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n</DropdownMenu.Root>\n```","component":"","namespace":"DropdownMenu"},"filePath":"/home/runner/work/design-system/design-system/src/dropdown-menu/dropdown-menu.tsx","description":"DropdownMenu is the compound component for attaching a menu of secondary\nactions to a button or icon trigger — edit/duplicate/delete rows, account\nmenus, overflow affordances, and nested submenus. Built on Radix UI's\nDropdownMenu primitive, so keyboard navigation, focus trapping, typeahead,\nand viewport-collision detection come for free.\n\nCompose it from `Root` / `Trigger` / `Portal` / `Content` and fill the\nmenu with `Item`, `Separator`, `Label`, and — for nested flows — `Sub` /\n`SubTrigger` / `SubContent`. Wrap content in `Portal` so the menu escapes\nancestor `overflow:hidden` and z-index stacking contexts.\n\nDo **not** use DropdownMenu for primary navigation (use a real nav menu),\nfor single-choice form input (use a `Select`), or for command palettes\n(use a dedicated command component). For radio/checkbox-style toggles,\nuse Radix's `CheckboxItem` / `RadioItem` primitives directly — those\nparts are not exposed here yet.","displayName":"DropdownMenu","methods":[],"props":{},"exportName":"DropdownMenu"}},"components-loading":{"id":"components-loading","name":"Loading","path":"./src/loading/loading.stories.tsx","stories":[{"id":"components-loading--default","name":"Default","snippet":"const Default = () => <Loading size=\"sm\" />;","description":"The default spinner at `size=\"sm\"` (1em diameter), inheriting the current text color. Matches the out-of-the-box behavior when Loading is dropped into any layout.","summary":"Default spinner at the `sm` size"},{"id":"components-loading--size-sm","name":"Size Sm","snippet":"const SizeSm = () => <Loading size=\"sm\" />;","description":"Small spinner (1em diameter) — the default. Ideal for inline indicators, buttons, and compact layouts where the spinner needs to sit next to text.","summary":"Small 1em spinner for inline indicators"},{"id":"components-loading--size-md","name":"Size Md","snippet":"const SizeMd = () => <Loading size=\"md\" />;","description":"Medium spinner (1.5em diameter). Use for cards, panels, and standalone loading states where the spinner is the primary visual signal.","summary":"Medium 1.5em spinner for cards and panels"},{"id":"components-loading--size-lg","name":"Size Lg","snippet":"const SizeLg = () => <Loading size=\"lg\" />;","description":"Large spinner (2em diameter). Use for page-level or section-level loading where the spinner needs more visual weight.","summary":"Large 2em spinner for page or section loading"},{"id":"components-loading--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '2rem' }}>\n {(['sm', 'md', 'lg'] as const).map(size => (\n <Loading key={size} size={size} />\n ))}\n </div>\n);","description":"All three sizes rendered side by side for visual comparison of the `em`-based scaling. Each spinner inherits the same parent text color.","summary":"Visual comparison of all three spinner sizes"},{"id":"components-loading--inherits-color","name":"Inherits Color","snippet":"const InheritsColor = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '2rem' }}>\n <div className=\"text-text-default-base-primary\">\n <Loading size=\"md\" />\n </div>\n <div className=\"text-text-default-brand-primary\">\n <Loading size=\"md\" />\n </div>\n <div className=\"text-text-default-danger-primary\">\n <Loading size=\"md\" />\n </div>\n </div>\n);","description":"The spinner color tracks the parent `color` (text color) via `border-current`. Wrap Loading in any element with a text color utility — or set `color` on Loading itself — and the spinner adopts that color without extra props.","summary":"Spinner color inherits from the parent text color"},{"id":"components-loading--on-dark-surface","name":"On Dark Surface","snippet":"const OnDarkSurface = () => (\n <div className=\"flex items-center gap-8 rounded-lg bg-bg-button-primary-enable p-8 text-text-default-base-inverse-primary\">\n <Loading size=\"sm\" />\n <Loading size=\"md\" />\n <Loading size=\"lg\" />\n </div>\n);","description":"Spinner on a dark surface to verify `border-current` contrast. The parent sets a light text color, which the spinner inherits so it remains visible against the dark background.","summary":"Spinner on a dark-background surface"}],"import":"import { Loading } from \"@agentero/design-system\";","jsDocTags":{},"description":"Loading displays a circular spinner that indicates an in-progress operation. Use for inline fetch, form submission, or asynchronous task indicators. The spinner inherits its color from the parent `color` and scales with the parent font size via `em`-based size variants (`sm`, `md`, `lg`).","reactDocgenTypescript":{"tags":{"summary":"Circular spinner for in-progress and loading states","example":"<Loading />\n<Loading size=\"lg\" className=\"text-text-default-brand-primary\" />"},"filePath":"/home/runner/work/design-system/design-system/src/loading/loading.tsx","description":"Loading displays a circular spinner that indicates an in-progress operation.\nUse Loading to signal that content is being fetched, a form is submitting,\nor any asynchronous task is running inline with surrounding content.\n\nThe spinner inherits its color from the parent `color` (text color) via\n`border-current`, so it adapts to the surrounding context without extra\nprops. It fades in on mount and spins continuously until unmounted.\n\nAvailable sizes: `sm` (1em, default), `md` (1.5em), and `lg` (2em). Each\nsize is expressed in `em` units so the spinner scales with the parent\nfont size — wrap the Loading (or its ancestor) with the appropriate\n`text-[size]` utility to override the absolute diameter.\n\nExposes `role=\"status\"` and `aria-label=\"Loading\"` for screen readers, and\n`data-slot=\"loading\"` for styling hooks.\n\nDo **not** use Loading as the busy indicator for a button — the Button\ncomponent has its own built-in loading overlay ([Button](?path=/docs/button--docs)).\nFor full-page or skeleton loading states prefer a dedicated skeleton\nplaceholder instead of a spinner.","displayName":"Loading","methods":[],"props":{"size":{"defaultValue":null,"description":"Controls the spinner diameter in `em` units relative to the parent font size.\nDefaults to `'sm'`.\n- `sm` (1em) — inline indicators, buttons, and compact layouts\n- `md` (1.5em) — cards, panels, and standalone loading states\n- `lg` (2em) — page-level or section-level loading","name":"size","declarations":[{"fileName":"design-system/src/loading/loading.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"lg\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"lg\""}]}}},"exportName":"Loading"}},"components-modal":{"id":"components-modal","name":"Modal.Root","path":"./src/modal/modal.stories.tsx","stories":[{"id":"components-modal--default","name":"Default","snippet":"const Default = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Delete carrier</Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Title>Delete carrier</Modal.Title>\n <Modal.Body>\n <p>This will remove the carrier from your agency. This action cannot be undone.</p>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"ghost\">Cancel</Button>\n </Modal.Close>\n <Button variant=\"primary\">Delete</Button>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n);","description":"Trigger-driven modal: open it, then dismiss with the footer's Cancel."},{"id":"components-modal--controlled","name":"Controlled","snippet":"const Controlled = () => <ControlledExample />;","description":"Controlled with `open`/`onOpenChange` — the dominant pattern in both apps. Also closes on `Escape`."},{"id":"components-modal--large","name":"Large","snippet":"const Large = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Open large</Button>\n </Modal.Trigger>\n <Modal.Content size=\"lg\">\n <Modal.Title>Large modal</Modal.Title>\n <Modal.Body>\n <p>Use `lg` for wide content like tables or side-by-side forms.</p>\n </Modal.Body>\n </Modal.Content>\n </Modal.Root>\n);","description":"`size=\"lg\"` widens the surface to 720px; `md` (default) is 540px."},{"id":"components-modal--scrollable-body","name":"Scrollable Body","snippet":"const ScrollableBody = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Open scrollable</Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Title>Terms and conditions</Modal.Title>\n <Modal.Body>\n {Array.from({ length: 24 }, (_, i) => (\n <p key={i} className=\"mb-4\">\n Section {i + 1}: agents shall maintain active licensure in every state where they\n transact business, and notify the marketplace of any change in appointment status.\n </p>\n ))}\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"primary\">Accept</Button>\n </Modal.Close>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n);","description":"Long content scrolls inside `Body` while title and footer stay pinned."}],"import":"import { Button, Modal } from \"@agentero/design-system\";","jsDocTags":{},"description":"Modal is a compound dialog built on Radix UI: `Root` owns the open state, `Content` is the centered surface (`size` md/lg), and `Title`/`Body`/`Footer` structure it. Close it with `Escape`, the overlay, the X button, or a `Modal.Close asChild` around your own button.","reactDocgenTypescript":{"tags":{"summary":"Compound modal dialog over a dimmed overlay","example":"```tsx\n<Modal.Root open={isOpen} onOpenChange={setIsOpen}>\n <Modal.Content size=\"md\">\n <Modal.Title>Delete carrier</Modal.Title>\n <Modal.Body>This action cannot be undone.</Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"ghost\">Cancel</Button>\n </Modal.Close>\n <Button onClick={handleDelete}>Delete</Button>\n </Modal.Footer>\n </Modal.Content>\n</Modal.Root>\n```","component":"","namespace":"Modal"},"filePath":"/home/runner/work/design-system/design-system/src/modal/modal.tsx","description":"Modal is the compound component for dialogs that interrupt the flow —\nconfirmations, forms, and detail views. Built on Radix UI Dialog, so focus\ntrapping, scroll locking, `Escape`/overlay dismissal, and ARIA wiring come\nfor free.\n\nCompose `Root` (open state) with `Content` (surface, `size` md/lg), and\nfill it with `Title` (built-in X button), `Body` (scrollable), and `Footer`\n(right-aligned actions). Open it controlled (`open`/`onOpenChange`) or via\n`Trigger`; close from inside with `Close asChild` around your cancel button.","displayName":"Modal","methods":[],"props":{},"exportName":"Modal"}},"components-pagination":{"id":"components-pagination","name":"Pagination","path":"./src/pagination/pagination.stories.tsx","stories":[{"id":"components-pagination--default","name":"Default","snippet":"const Default = () => <Pagination currentPage={1} totalCount={1000} pageSize={10} onPageChange={fn()} />;","description":"Default args playground. The first page of a 1,000-item list paged 10 at a time — renders pages 1–5, an ellipsis, and the last page (100), with the previous-page button disabled because we're on page 1.","summary":"Default args playground for Pagination"},{"id":"components-pagination--few-pages","name":"Few Pages","snippet":"const FewPages = () => <Pagination\n currentPage={2}\n totalCount={30}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Short list whose total pages fit in the visible window — no ellipsis is rendered. Exercises the `totalPageNumbers >= totalPageCount` branch in `getPages`.","summary":"Short page list with no ellipsis collapse"},{"id":"components-pagination--dots-right","name":"Dots Right","snippet":"const DotsRight = () => <Pagination\n currentPage={2}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits near the start of the range — left ellipsis is hidden, right ellipsis is shown, and the last page button anchors the right edge.","summary":"Right-side ellipsis only (current page near start)"},{"id":"components-pagination--dots-left","name":"Dots Left","snippet":"const DotsLeft = () => <Pagination\n currentPage={99}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits near the end of the range — left ellipsis is shown, right ellipsis is hidden, and the first page button anchors the left edge.","summary":"Left-side ellipsis only (current page near end)"},{"id":"components-pagination--dots-both","name":"Dots Both","snippet":"const DotsBoth = () => <Pagination\n currentPage={50}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits in the middle of the range — both ellipses are visible, with the first and last page buttons anchoring each edge.","summary":"Both ellipses visible (current page in middle)"},{"id":"components-pagination--last-page","name":"Last Page","snippet":"const LastPage = () => <Pagination currentPage={100} totalCount={1000} pageSize={10} onPageChange={fn()} />;","description":"Last page selected — the next-page button is disabled and the active page indicator sits on the trailing number.","summary":"Last page selected with disabled next button"},{"id":"components-pagination--controlled","name":"Controlled","snippet":"const Controlled = ({ totalCount, pageSize }) => {\n const [page, setPage] = useState(1);\n\n return (\n <Pagination\n currentPage={page}\n totalCount={totalCount}\n pageSize={pageSize}\n onPageChange={setPage}\n />\n );\n};","description":"Interactive controlled example. Local `useState` owns the page; clicking a page, previous, or next button updates it so the active page indicator and entries summary follow along.","summary":"Interactive controlled example backed by `useState`"}],"import":"import { Pagination } from \"@agentero/design-system\";","jsDocTags":{},"description":"Pagination is a 1-indexed paged navigation control with previous/next icon buttons, numeric page buttons, and a leading \"X - Y of Z\" entries summary. The page list collapses long ranges with `…` ellipses so the control stays compact regardless of total page count. Use it for lists, tables, or grids that are split across pages.","reactDocgenTypescript":{"tags":{"summary":"1-indexed paged navigation control with prev/next, numeric pages, and entries summary","example":"```tsx\nimport { useState } from 'react';\nimport { Pagination } from '@agentero/design-system/pagination';\n\nconst [page, setPage] = useState(1);\n\n<Pagination\n currentPage={page}\n pageSize={10}\n totalCount={1000}\n onPageChange={setPage}\n/>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/pagination/pagination.tsx","description":"Pagination is a 1-indexed paged navigation control with previous/next icon\nbuttons, numeric page buttons, and a leading \"X - Y of Z\" entries summary.\nThe page list collapses long ranges with `…` ellipses, keeping at most a\nhandful of buttons in view regardless of total page count. Use it whenever\na list, table, or grid is split across pages and the user needs direct\naccess to specific pages (not just prev/next).\n\nThe control short-circuits to `null` when `currentPage === 0` (legacy \"off\"\nsentinel) or when there are no pages to show, so it's safe to mount\nunconditionally above a list that may be empty.\n\nDo **not** use Pagination for infinite-scroll feeds, sub-page-1 indexing\n(the `0` value is reserved as the off-switch), or as a tab/segmented\ncontrol — it's strictly a page-of-pages affordance.","displayName":"Pagination","methods":[],"props":{"onPageChange":{"defaultValue":null,"description":"","name":"onPageChange","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"(page: number) => void"}},"totalCount":{"defaultValue":null,"description":"","name":"totalCount","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"currentPage":{"defaultValue":null,"description":"","name":"currentPage","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"pageSize":{"defaultValue":null,"description":"","name":"pageSize","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"className":{"defaultValue":null,"description":"","name":"className","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Pagination"}},"components-progress":{"id":"components-progress","name":"Progress","path":"./src/progress/progress.stories.tsx","stories":[{"id":"components-progress--default","name":"Default","snippet":"const Default = () => <Progress percentage={62} />;","description":"Default near-black bar; exposes `role=\"progressbar\"` with the current value."},{"id":"components-progress--with-label","name":"With Label","snippet":"const WithLabel = () => <Progress percentage={62} label=\"Profile completion\" className=\"text-brand-400\" />;","description":"`label` renders above the bar with the percentage value on the right."},{"id":"components-progress--custom-colors","name":"Custom Colors","snippet":"const CustomColors = args => (\n <div className=\"flex flex-col gap-4\">\n {[\n ['default', undefined],\n ['text-brand-400', 'text-brand-400'],\n ['text-brand-600', 'text-brand-600'],\n ['text-purple-400', 'text-purple-400'],\n ['text-orange-400', 'text-orange-400'],\n ['text-pink-400', 'text-pink-400'],\n ['text-blue-400', 'text-blue-400']\n ].map(([name, className]) => (\n <Progress key={name} {...args} className={className} label={name} />\n ))}\n </div>\n);","description":"The fill follows `currentColor`: recolor it with any `text-*` class via `className`."},{"id":"components-progress--clamped","name":"Clamped","snippet":"const Clamped = () => <Progress percentage={150} />;","description":"Out-of-range values are clamped to 0–100."}],"import":"import { Progress } from \"@agentero/design-system\";","jsDocTags":{},"description":"Progress shows how far a bounded task has advanced. Pass `percentage` (0–100) and optionally a `label` rendered above the bar. The fill paints with `currentColor`, so recolor it with a plain text class — e.g. `className=\"text-brand-400\"`.","reactDocgenTypescript":{"tags":{"summary":"Horizontal progress bar with optional label","example":"```tsx\n<Progress percentage={62} label=\"Profile completion\" className=\"text-brand-400\" />\n```"},"filePath":"/home/runner/work/design-system/design-system/src/progress/progress.tsx","description":"Progress shows how far a bounded task has advanced — wizard steps, upload\nstatus, or a split of a total. Pass `percentage` (0–100) and optionally a\n`label`, which renders above the bar with the percentage value. Built on\nRadix UI Progress, so `role=\"progressbar\"` and `aria-value*` come wired.\n\nThe fill is near-black by default and paints with `currentColor` — recolor\nit from the consumer with a plain text color class.","displayName":"Progress","methods":[],"props":{"percentage":{"defaultValue":null,"description":"Completion percentage, 0–100. Values outside the range are clamped.","name":"percentage","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"label":{"defaultValue":null,"description":"Optional label rendered above the bar, with the percentage value on the right.","name":"label","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"aria-label":{"defaultValue":null,"description":"Accessible name when no visible `label` is provided. Defaults to `'Progress'`.","name":"aria-label","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"className":{"defaultValue":null,"description":"Extra classes for the bar, merged last. The fill paints with `currentColor`,\nso a text color recolors it (e.g. `text-brand-400`); sizing classes resize\nthe track (e.g. `h-3`).","name":"className","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Progress"}},"components-skeleton":{"id":"components-skeleton","name":"Skeleton","path":"./src/skeleton/skeleton.stories.tsx","stories":[{"id":"components-skeleton--default","name":"Default","snippet":"const Default = () => <Skeleton className=\"h-4 w-40\" />;","description":"Default placeholder box, sized via `className`; hidden from assistive technologies."},{"id":"components-skeleton--text-block","name":"Text Block","snippet":"const TextBlock = () => (\n <div className=\"flex w-80 flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n);","description":"Compose plain skeletons to sketch the loading shape of real content."},{"id":"components-skeleton--list-item","name":"List Item","snippet":"const ListItem = () => (\n <div className=\"flex w-80 items-center gap-3\">\n <Skeleton className=\"size-10 shrink-0 rounded-full\" />\n <div className=\"flex w-full flex-col gap-2\">\n <Skeleton className=\"h-4 w-1/2\" />\n <Skeleton className=\"h-3 w-3/4\" />\n </div>\n </div>\n);","description":"`rounded-full` for avatars; pair with text lines for a list-item placeholder."},{"id":"components-skeleton--card","name":"Card","snippet":"const Card = () => (\n <div className=\"flex w-80 flex-col gap-3 rounded-lg border border-border-default-base-primary p-4\">\n <Skeleton className=\"h-32 w-full rounded-md\" />\n <Skeleton className=\"h-5 w-1/2\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n);","description":"A card-shaped placeholder: media area, title, and body lines."}],"import":"import { Skeleton } from \"@agentero/design-system\";","jsDocTags":{},"description":"Skeleton renders a pulsing placeholder box while content loads. Size and shape it with Tailwind classes to mirror the content it stands in for.","reactDocgenTypescript":{"tags":{"summary":"Pulsing placeholder box for loading content","example":"```tsx\n<Skeleton className=\"h-4 w-30\" />\n```"},"filePath":"/home/runner/work/design-system/design-system/src/skeleton/skeleton.tsx","description":"Skeleton renders a pulsing placeholder box while content loads. Size and\nshape it with Tailwind classes (`h-4 w-30`, `size-10 rounded-full`) to\nmirror the content it stands in for. Hidden from assistive technologies.","displayName":"Skeleton","methods":[],"props":{},"exportName":"Skeleton"}},"components-switch":{"id":"components-switch","name":"Switch","path":"./src/switch/switch.stories.tsx","stories":[{"id":"components-switch--default","name":"Default","snippet":"const Default = () => <Switch size=\"md\" disabled={false} defaultChecked aria-label=\"Toggle setting\" />;"},{"id":"components-switch--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div className=\"flex items-center gap-6\">\n <div className=\"flex items-center gap-2\">\n <Switch id=\"size-sm\" size=\"sm\" defaultChecked />\n <label htmlFor=\"size-sm\" className=\"text-sm text-text-default-base-primary\">\n Small\n </label>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch id=\"size-md\" size=\"md\" defaultChecked />\n <label htmlFor=\"size-md\" className=\"text-sm text-text-default-base-primary\">\n Medium\n </label>\n </div>\n </div>\n);","description":"The `sm` and `md` sizes compared."},{"id":"components-switch--states","name":"States","snippet":"const States = () => <div className=\"flex items-center gap-6\">\n <Switch size=\"md\" disabled={false} defaultChecked={false} aria-label=\"Off\" />\n <Switch size=\"md\" disabled={false} defaultChecked aria-label=\"On\" />\n</div>;","description":"Unchecked and checked tracks."},{"id":"components-switch--disabled","name":"Disabled","snippet":"const Disabled = () => (\n <div className=\"flex items-center gap-6\">\n <Switch disabled aria-label=\"Disabled off\" />\n <Switch disabled defaultChecked aria-label=\"Disabled on\" />\n </div>\n);","description":"Disabled switches are dimmed and reject pointer and keyboard interaction."},{"id":"components-switch--controlled","name":"Controlled","snippet":"const Controlled = () => {\n const [enabled, setEnabled] = useState(false);\n\n return (\n <div className=\"flex items-center gap-2\">\n <Switch id=\"controlled\" checked={enabled} onCheckedChange={setEnabled} />\n <label htmlFor=\"controlled\" className=\"text-sm text-text-default-base-primary\">\n Notifications {enabled ? 'on' : 'off'}\n </label>\n </div>\n );\n};","description":"Controlled switch wired to component state via `checked` + `onCheckedChange`."},{"id":"components-switch--with-label","name":"With Label","snippet":"const WithLabel = () => (\n <div className=\"flex items-center gap-6\">\n <Switch id=\"with-label\" label=\"Email\" defaultChecked />\n <Switch id=\"with-label-reverse\" label=\"SMS\" reverse />\n </div>\n);","description":"The built-in `label` prop renders an associated text label beside the toggle (wired via `htmlFor`/`id`); `reverse` places the label before the toggle."},{"id":"components-switch--setting-row","name":"Setting Row","snippet":"const SettingRow = () => (\n <div className=\"flex w-80 items-center justify-between gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-4\">\n <div className=\"flex flex-col gap-0.5\">\n <label htmlFor=\"marketing\" className=\"text-sm font-medium text-text-default-base-primary\">\n Marketing emails\n </label>\n <p className=\"text-xs text-text-default-base-secondary\">\n Receive product updates and offers.\n </p>\n </div>\n <Switch id=\"marketing\" defaultChecked />\n </div>\n);","description":"Switch aligned in a labelled settings row."}],"import":"import { Switch } from \"@agentero/design-system\";","jsDocTags":{},"description":"Two-state toggle for a setting that takes effect immediately. Prefer it over a Checkbox for a single boolean that applies instantly, and pair it with a `<label htmlFor>` to give it an accessible name.","reactDocgenTypescript":{"tags":{"summary":"Instant-effect on/off toggle built on Radix Switch","example":"<Switch checked={enabled} onCheckedChange={setEnabled} />\n<Switch id=\"email-notifications\" label=\"Email\" checked={on} onCheckedChange={setOn} />"},"filePath":"/home/runner/work/design-system/design-system/src/switch/switch.tsx","description":"Instant-effect on/off toggle built on Radix Switch. Reach for it over a\nCheckbox when flipping a single boolean that applies immediately.\n\nRenders only the toggle by default — pair it with a `<label htmlFor>` for an\naccessible name. Pass `label` (with an `id`) to render an associated text\nlabel beside the toggle; `reverse` places the label before it.","displayName":"Switch","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"reverse":{"defaultValue":null,"description":"","name":"reverse","required":false,"type":{"name":"boolean"}},"size":{"defaultValue":null,"description":"","name":"size","required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\"","value":[{"value":"\"sm\""},{"value":"\"md\""}]}},"label":{"defaultValue":null,"description":"Optional text rendered beside the toggle and associated with it via\n`htmlFor`. Provide an `id` so the association resolves. Omit it to keep\nthe toggle headless and supply your own `<label htmlFor>`.","name":"label","declarations":[{"fileName":"design-system/src/switch/switch.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Switch"}},"components-tabs":{"id":"components-tabs","name":"Tabs.Root","path":"./src/tabs/tabs.stories.tsx","stories":[{"id":"components-tabs--default","name":"Default","snippet":"const Default = () => <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n</Tabs.Root>;","description":"`line` (default): the active tab is marked with an animated underline."},{"id":"components-tabs--enclosed","name":"Enclosed","snippet":"const Enclosed = () => (\n <Tabs.Root variant=\"enclosed\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`enclosed` renders segmented pills; the active tab sits on a raised surface."},{"id":"components-tabs--buttons","name":"Buttons","snippet":"const Buttons = () => (\n <Tabs.Root variant=\"button\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`button` renders button-like tabs, with room for a leading icon per trigger."},{"id":"components-tabs--positions","name":"Positions","snippet":"const Positions = () => (\n <div className=\"flex flex-col gap-8\">\n {(['start', 'center', 'end'] as const).map(position => (\n <Tabs.Root key={position} variant=\"enclosed\" position={position} defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n ))}\n </div>\n);","description":"`position` aligns the tab list within the row (`start` is the default)."},{"id":"components-tabs--full-width","name":"Full Width","snippet":"const FullWidth = () => (\n <Tabs.Root variant=\"enclosed\" position=\"full\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`position=\"full\"` stretches the tab list to fill the available width."},{"id":"components-tabs--as-child-links","name":"As Child Links","snippet":"const AsChildLinks = () => (\n <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n {TABS.map(({ value, label }) => (\n <Tabs.Trigger key={value} value={value} asChild>\n <a href={`#${value}`}>{label}</a>\n </Tabs.Trigger>\n ))}\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"Triggers accept `asChild` to render as another element — e.g. a router link. The trigger resets the anchor's default underline, so link-based tabs match the button-based ones."},{"id":"components-tabs--switch-tabs","name":"Switch Tabs","snippet":"const SwitchTabs = () => <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n</Tabs.Root>;","description":"Selecting a tab reveals its panel and hides the others."}],"import":"import { Tabs } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tabs built on Radix UI's Tabs (keyboard nav, roving focus and ARIA come for free). Compose `Root` with a `List` of `Trigger`s and matching `Content`s, pairing each `Trigger`/`Content` by `value`.","reactDocgenTypescript":{"tags":{},"filePath":"/home/runner/work/design-system/design-system/src/tabs/tabs.tsx","description":"Tabs built on Radix UI's Tabs (keyboard nav, roving focus and ARIA come for\nfree). Compose `Root` with a `List` of `Trigger`s and matching `Content`s,\npairing each `Trigger`/`Content` by `value`.","displayName":"Tabs","methods":[],"props":{},"exportName":"Tabs"}},"components-tag":{"id":"components-tag","name":"Tag","path":"./src/tag/tag.stories.tsx","stories":[{"id":"components-tag--default","name":"Default","snippet":"const Default = () => <Tag color=\"neutral\" variant=\"secondary\" size=\"sm\">Default</Tag>;","description":"Args-controlled playground. Toggle `color`, `variant`, `size`, `pill`, and `truncate` from the Controls panel to explore every visual combination.","summary":"Default args playground for Tag"},{"id":"components-tag--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <Stack>\n {(['xs', 'sm', 'md'] as const).map(size => (\n <Stack gap=\"0.5rem\" key={size}>\n <strong>{size}:</strong>\n <Row>\n <Tag\n size={size}\n color=\"informative\"\n variant=\"secondary\"\n role=\"img\"\n aria-label={`${size} icon only`}>\n <IconAdd />\n </Tag>\n <Tag size={size} color=\"informative\" variant=\"secondary\">\n <IconAdd />\n {size}\n </Tag>\n <Tag size={size} color=\"informative\" variant=\"secondary\">\n {size}\n </Tag>\n </Row>\n </Stack>\n ))}\n </Stack>\n);","description":"The three sizes — `xs` (20px), `sm` (24px, default), and `md` (32px) — each shown icon-only, icon + text, and text-only so the type and icon scale are visible.","summary":"All three sizes across icon-only, icon + text, and text-only"},{"id":"components-tag--styles","name":"Styles","snippet":"const Styles = () => (\n <Stack gap=\"0.5rem\">\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color=\"informative\" variant={variant}>\n {variant}\n </Tag>\n ))}\n </Row>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color=\"informative\" variant={variant} pill>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n);","description":"The `Style` axis: the default rounded corners (top row) versus `pill` fully rounded (bottom row), shown across every fill variant.","summary":"Rounded (default) vs pill"},{"id":"components-tag--interactive","name":"Interactive","snippet":"const Interactive = () => (\n <Row>\n <Tag color=\"informative\" variant=\"secondary\">\n badge\n </Tag>\n <Tag color=\"informative\" variant=\"secondary\" asChild>\n <button type=\"button\">interactive</button>\n </Tag>\n <Tag color=\"informative\" variant=\"secondary\" asChild aria-label=\"add\">\n <button type=\"button\">\n <IconAdd />\n </button>\n </Tag>\n </Row>\n);","description":"Static badge vs interactive Tag. A plain `<span>` badge has no hover; pass `asChild` with a `<button>` (or `<a>`) to make it interactive — that adds the pointer cursor and reveals the hover fill on `:hover`. Hover the middle and right Tags to see it.","summary":"Static badge vs interactive (asChild) hover"},{"id":"components-tag--secondary","name":"Secondary","snippet":"const Secondary = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"secondary\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`secondary` fills with a tinted background plus a matching border, shown across every color.","summary":"`secondary` variant across all colors"},{"id":"components-tag--tertiary","name":"Tertiary","snippet":"const Tertiary = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"tertiary\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`tertiary` (default) fills with a tinted background and no border, shown across every color.","summary":"`tertiary` variant across all colors"},{"id":"components-tag--ghost","name":"Ghost","snippet":"const Ghost = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"ghost\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`ghost` shows colored text alone with no background or border, across every color.","summary":"`ghost` variant across all colors"},{"id":"components-tag--invisible","name":"Invisible","snippet":"const Invisible = () => (\n <Stack gap=\"0.5rem\">\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"invisible\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"invisible\" color={color} asChild>\n <button type=\"button\">{color}</button>\n </Tag>\n ))}\n </Row>\n </Stack>\n);","description":"`invisible` stays fully transparent until hovered, then reveals its fill. The top row renders plain `<span>` Tags; the bottom row renders interactive Tags via `asChild` with a `<button>` child.","summary":"`invisible` variant as span and as interactive button"},{"id":"components-tag--with-icon","name":"With Icon","snippet":"const WithIcon = () => (\n <Stack>\n {COLORS.map(color => (\n <Row key={color}>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n tag\n <IconAdd />\n </Tag>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Every variant for every color rendered with a leading and trailing icon. Icons are tinted with each color's `icon-tag-*` token.","summary":"Variant × color grid with icons"},{"id":"components-tag--colors","name":"Colors","snippet":"const Colors = () => (\n <div style={{ display: 'flex', gap: '4rem', flexWrap: 'wrap' }}>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color}:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with pill:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant} pill>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} as button:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant} asChild>\n <button type=\"button\">{variant}</button>\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with icon:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with icons:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n {variant}\n <IconAdd />\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} icon only:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag\n key={variant}\n color={color}\n variant={variant}\n role=\"img\"\n aria-label={`${color} ${variant}`}>\n <IconAdd />\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n </div>\n);","description":"Full matrix: every variant for every color, repeated as default, as `pill`, as an interactive `asChild` `<button>`, with a single leading icon, with leading + trailing icons, and icon-only.","summary":"Variant × color matrix — default, pill, button, and icon layouts"}],"import":"import { Tag } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tag is a compact semantic label for statuses, categories, counts, and attributes. Pick `color` for meaning, `variant` for fill emphasis, and `size` for prominence. A plain Tag is a static badge; pass `asChild` to make it an interactive link or button, which adds the pointer cursor and hover fill.","reactDocgenTypescript":{"tags":{"summary":"Compact semantic label; renders a static badge `<span>` or, with `asChild`, an interactive element","example":"<Tag color=\"positive\">Active</Tag>\n<Tag asChild color=\"informative\">\n <a href=\"/carriers\">View carriers</a>\n</Tag>"},"filePath":"/home/runner/work/design-system/design-system/src/tag/tag.tsx","description":"Tag is a compact label for statuses, categories, counts, and attributes. As a\nplain `<span>` it reads as a static badge with no hover. Pass `asChild` to\nrender an interactive link or button instead — that adds the pointer cursor\nand the hover fill. Pick `color` for meaning and `variant` for fill emphasis.","displayName":"Tag","methods":[],"props":{"color":{"defaultValue":null,"description":"","name":"color","required":false,"type":{"name":"enum","raw":"\"neutral\" | \"danger\" | \"warning\" | \"creative\" | \"dynamic\" | \"playful\" | \"positive\" | \"informative\"","value":[{"value":"\"neutral\""},{"value":"\"danger\""},{"value":"\"warning\""},{"value":"\"creative\""},{"value":"\"dynamic\""},{"value":"\"playful\""},{"value":"\"positive\""},{"value":"\"informative\""}]}},"size":{"defaultValue":null,"description":"","name":"size","required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"xs\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""}]}},"variant":{"defaultValue":null,"description":"","name":"variant","required":false,"type":{"name":"enum","raw":"\"ghost\" | \"secondary\" | \"tertiary\" | \"invisible\"","value":[{"value":"\"ghost\""},{"value":"\"secondary\""},{"value":"\"tertiary\""},{"value":"\"invisible\""}]}},"pill":{"defaultValue":null,"description":"","name":"pill","required":false,"type":{"name":"boolean"}},"truncate":{"defaultValue":null,"description":"","name":"truncate","required":false,"type":{"name":"boolean"}},"asChild":{"defaultValue":null,"description":"Render the single child element instead of a `<span>` (via Radix `Slot`),\nkeeping Tag framework-agnostic. Marks the Tag interactive: adds the pointer\ncursor and the hover fill (a plain `<span>` Tag is a static badge).","name":"asChild","declarations":[{"fileName":"design-system/src/tag/tag.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Tag"}},"components-toast":{"id":"components-toast","name":"Toast","path":"./src/toast/toast.stories.tsx","stories":[{"id":"components-toast--default","name":"Default","snippet":"const Default = () => (\n <div style={{ minHeight: '240px' }}>\n <Button variant=\"secondary\" onClick={() => toast('Hello from Toast')}>\n Show toast\n </Button>\n </div>\n);","description":"Args-controlled playground. Click the button to fire a neutral toast; tweak `position` and `duration` from the Controls panel to preview the provider defaults.","summary":"Default playground for the Toast provider"},{"id":"components-toast--inline","name":"Inline","snippet":"const Inline = () => (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() => toast('Something happened', { description: 'Additional context.' })}>\n Neutral\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() => toast.success('Policy saved', { description: 'Your edits are live.' })}>\n Success\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Failed to save', { description: 'The file could not be processed.' })\n }>\n Error\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.warning('License expiring soon', { description: 'Renew before end of month.' })\n }>\n Warning\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', { description: 'Please wait while we sync your data.' })\n }>\n Info\n </Button>\n </div>\n);","description":"Inline layout (default). Compact treatment — title with an optional description stacked directly below it. The `type` drives the icon color. Use for short acknowledgments that don't need a colored rail.","summary":"Inline layout across all five semantic types"},{"id":"components-toast--expanded","name":"Expanded","snippet":"const Expanded = () => (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast('Something happened', {\n variant: 'expanded',\n description: 'Additional context for the user.'\n })\n }>\n Neutral\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Policy saved', {\n variant: 'expanded',\n description: 'Your changes have been saved successfully.'\n })\n }>\n Success\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Failed to save', {\n variant: 'expanded',\n description: 'The file could not be processed.'\n })\n }>\n Error\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.warning('License expiring soon', {\n variant: 'expanded',\n description: 'Renew before the end of the month to avoid interruption.'\n })\n }>\n Warning\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', {\n variant: 'expanded',\n description: 'Please wait while we sync your data.'\n })\n }>\n Info\n </Button>\n </div>\n);","description":"Expanded layout. Multi-line treatment with a 0.375rem colored left rail that tracks the toast's `type`. Use for feedback that benefits from a description on its own line or a trailing action button.","summary":"Expanded layout across all five semantic types"},{"id":"components-toast--with-action-object","name":"With Action Object","snippet":"const WithActionObject = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Upload failed', {\n variant: 'expanded',\n description: 'The file could not be processed.',\n action: { label: 'Retry', onClick: () => {} }\n })\n }>\n Show toast with action\n </Button>\n);","description":"Toast with a structured `action` object. Passing `{ label, onClick }` renders the built-in secondary Button; the handler runs and the toast auto-dismisses afterward.","summary":"Toast with a structured action button"},{"id":"components-toast--with-action-node","name":"With Action Node","snippet":"const WithActionNode = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast('File uploaded', {\n description: 'document.pdf is ready.',\n action: (\n <Button variant=\"link\" onClick={() => {}}>\n View file\n </Button>\n )\n })\n }>\n Show toast with link action\n </Button>\n);","description":"Toast with a raw-ReactNode `action`. Pass any JSX to render a custom trailing control — a link, a pair of buttons, etc. — when the default secondary Button doesn't fit.","summary":"Toast with a custom ReactNode action"},{"id":"components-toast--with-action-and-cancel","name":"With Action And Cancel","snippet":"const WithActionAndCancel = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Record archived', {\n variant: 'expanded',\n description: 'The record is hidden from the default view.',\n action: { label: 'Undo', onClick: () => {} },\n cancel: { label: 'Dismiss', onClick: () => {} }\n })\n }>\n Show toast with action + cancel\n </Button>\n);","description":"Toast with both `action` and `cancel`. Cancel renders as a ghost Button next to the action; its handler runs and the toast auto-dismisses.","summary":"Toast with an action and a cancel control"},{"id":"components-toast--non-dismissible","name":"Non Dismissible","snippet":"const NonDismissible = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', {\n dismissible: false,\n description: 'Please wait while we sync your data.'\n })\n }>\n Show non-dismissible toast\n </Button>\n);","description":"Non-dismissible toast. Setting `dismissible: false` hides the close button; the toast still auto-dismisses when its `duration` elapses, or programmatically via `toast.dismiss(id)`.","summary":"Non-dismissible toast (no close button)"},{"id":"components-toast--long-duration","name":"Long Duration","snippet":"const LongDuration = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Uploading documents', {\n description: 'This may take a moment.',\n duration: 10_000\n })\n }>\n Show 10s toast\n </Button>\n);","description":"Long-duration toast. `duration` (in ms) overrides the provider default so long-running operations stay visible until they're relevant.","summary":"Toast with a custom `duration`"},{"id":"components-toast--programmatic-dismiss","name":"Programmatic Dismiss","snippet":"const ProgrammaticDismiss = () => {\n let toastId: string | number | undefined;\n return (\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() => {\n toastId = toast.info('Uploading...', { duration: 60_000 });\n }}>\n Start\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => {\n if (toastId !== undefined) toast.dismiss(toastId);\n }}>\n Dismiss\n </Button>\n </div>\n );\n};","description":"Programmatic dismissal. `toast()` returns the toast id, which you can pass to `toast.dismiss(id)` to clear it before its duration elapses.","summary":"Dismiss a toast programmatically via its id"},{"id":"components-toast--with-promise","name":"With Promise","snippet":"const WithPromise = () => {\n const fakeFetch = () =>\n new Promise<string>((resolve, reject) => {\n window.setTimeout(\n () => (Math.random() > 0.5 ? resolve('ok') : reject(new globalThis.Error('nope'))),\n 1500\n );\n });\n return (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.promise(fakeFetch(), {\n loading: 'Saving document…',\n success: 'Document saved',\n error: 'Save failed'\n })\n }>\n Run promise\n </Button>\n );\n};","description":"`toast.promise` wires a toast to an async operation — loading while the promise is pending, success or error when it settles. Useful for save/submit flows where the outcome feeds back into the same toast.","summary":"Wire a toast to an async operation via `toast.promise`"},{"id":"components-toast--custom-icon","name":"Custom Icon","snippet":"const CustomIcon = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Sync started', {\n description: 'Data sync is in progress.',\n icon: (\n <svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\" aria-hidden>\n <path d=\"M12 4V1L8 5l4 4V6c3.3 0 6 2.7 6 6 0 1-.3 2-.7 2.8l1.5 1.5C19.5 15 20 13.6 20 12c0-4.4-3.6-8-8-8zm0 14c-3.3 0-6-2.7-6-6 0-1 .3-2 .7-2.8L5.2 7.7C4.5 9 4 10.4 4 12c0 4.4 3.6 8 8 8v3l4-4-4-4v3z\" />\n </svg>\n )\n })\n }>\n Show toast with custom icon\n </Button>\n);","description":"Custom `icon` override. Pass any ReactNode as `icon` to replace the type-based default — helpful when the toast reflects a domain-specific action (e.g., a sync icon for a sync-in-progress toast).","summary":"Override the default type-based icon"}],"import":"import { Button, Toast } from \"@agentero/design-system\";","jsDocTags":{},"description":"Toast renders transient feedback about an outcome — saved, failed, warning, info — without interrupting the user's flow. Mount `<Toast />` once near the app root to register the provider, then call the imperative `toast()` API from anywhere in the tree. Five semantic types (`neutral`, `success`, `error`, `warning`, `info`) × two layouts (`inline`, `expanded`) cover the common feedback patterns.","reactDocgenTypescript":{"tags":{"summary":"Toast provider; mount once near the app root","example":"<Toast />\n<Toast position=\"top-center\" duration={4000} />"},"filePath":"/home/runner/work/design-system/design-system/src/toast/toast.tsx","description":"Toast provider. Renders the sonner `<Toaster />` configured for the\n{@link toast} imperative API. Mount it once near the root of your React\ntree (below any context providers that the toasts need, and above the\nrest of the app) so every call to `toast()` from anywhere in the tree\nrenders into the same surface.\n\nDefaults: `position='bottom-right'`, `duration=5000`. The Toaster is sized\nto `23.75rem` (`[--width:23.75rem]`) and each list item stretches to that\nwidth (`[&>li]:w-full`) so the DS Toast fills the Toaster row rather than\nsonner's 356px default. The provider disables sonner's built-in close\nbutton (`closeButton={false}`) — dismissal is rendered inside each Toast\nby the DS component itself.\n\nDo **not** use Toast for persistent feedback — mount an `Alert` with\n`color=\"success|danger\"` instead. Do **not** use Toast for form\nvalidation errors — render those inline with the form field.","displayName":"Toast","methods":[],"props":{"position":{"defaultValue":{"value":"bottom-right"},"description":"Placement of the toaster on the screen. Defaults to `'bottom-right'`.","name":"position","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ToastPosition","value":[{"value":"\"top-left\""},{"value":"\"top-center\""},{"value":"\"top-right\""},{"value":"\"bottom-left\""},{"value":"\"bottom-center\""},{"value":"\"bottom-right\""}]}},"duration":{"defaultValue":{"value":"5000"},"description":"Default auto-dismiss duration in ms for toasts fired against this provider. Defaults to `5000`.","name":"duration","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"dir":{"defaultValue":null,"description":"Text direction. Sonner forwards this to the rendered toaster root.","name":"dir","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"auto\" | \"ltr\" | \"rtl\"","value":[{"value":"\"auto\""},{"value":"\"ltr\""},{"value":"\"rtl\""}]}},"gap":{"defaultValue":null,"description":"Gap between stacked toasts, in pixels.","name":"gap","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"offset":{"defaultValue":null,"description":"Offset from the screen edge, in pixels or as a CSS length.","name":"offset","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string | number"}},"expand":{"defaultValue":null,"description":"When `true`, stack expands on hover instead of auto-collapsing.","name":"expand","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"visibleToasts":{"defaultValue":null,"description":"Maximum number of toasts rendered at once before earlier ones dismiss.","name":"visibleToasts","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"hotkey":{"defaultValue":null,"description":"Keyboard shortcut used to focus the toaster.","name":"hotkey","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string[]"}},"richColors":{"defaultValue":null,"description":"When `true`, sonner paints colored backgrounds per type (DS uses its own icon tokens by default).","name":"richColors","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"invert":{"defaultValue":null,"description":"When `true`, flips light/dark theme on the toaster root.","name":"invert","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"className":{"defaultValue":null,"description":"Additional className merged onto the sonner `<Toaster>` root.","name":"className","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Toast"}},"components-tooltip":{"id":"components-tooltip","name":"Tooltip","path":"./src/tooltip/tooltip.stories.tsx","stories":[{"id":"components-tooltip--default","name":"Default","snippet":"const Default = () => <Tooltip content=\"Archive this carrier\" side=\"top\" asChild>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>;","description":"Default hint revealed on hover; hides again on unhover."},{"id":"components-tooltip--opens-on-focus","name":"Opens On Focus","snippet":"const OpensOnFocus = () => <Tooltip content=\"Archive this carrier\" side=\"top\" asChild>\n <Button variant=\"secondary\">Focus me</Button>\n</Tooltip>;","description":"Opens on keyboard focus too, wiring `aria-describedby` on the trigger."},{"id":"components-tooltip--sides","name":"Sides","snippet":"const Sides = () => (\n <div className=\"grid grid-cols-2 gap-6\">\n <Tooltip content=\"Tooltip on top\" side=\"top\" asChild>\n <Button variant=\"secondary\">Top</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the right\" side=\"right\" asChild>\n <Button variant=\"secondary\">Right</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the bottom\" side=\"bottom\" asChild>\n <Button variant=\"secondary\">Bottom</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the left\" side=\"left\" asChild>\n <Button variant=\"secondary\">Left</Button>\n </Tooltip>\n </div>\n);","description":"`side` sets the preferred placement; it flips on viewport collision."},{"id":"components-tooltip--as-child","name":"As Child","snippet":"const AsChild = () => <Tooltip content=\"Opens in a new tab\" side=\"bottom\" asChild>\n <a\n href=\"https://agentero.com\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-text-default-base-primary underline\">Docs\n </a>\n</Tooltip>;","description":"`asChild` decorates an already-interactive trigger instead of wrapping it in a `<button>`."},{"id":"components-tooltip--long-content","name":"Long Content","snippet":"const LongContent = () => <Tooltip\n content=\"This carrier requires a completed appointment before you can request quotes for this line of business.\"\n side=\"top\"\n asChild>\n <Button variant=\"secondary\">Why is this disabled?</Button>\n</Tooltip>;","description":"Content wraps at the `32ch` max width."}],"import":"import { Button, Tooltip } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tooltip reveals a short, non-essential hint anchored to a trigger element on hover or focus.","reactDocgenTypescript":{"tags":{"summary":"Hover/focus hint anchored to a trigger element","example":"```tsx\n<Tooltip content=\"Archive this carrier\" asChild>\n <IconButton aria-label=\"Archive\"><IconArchive /></IconButton>\n</Tooltip>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/tooltip/tooltip.tsx","description":"Tooltip reveals a short, non-essential hint anchored to a trigger element on\nhover or focus. Pass the trigger as `children` and the hint as `content`; use\n`asChild` when the trigger is already interactive (a button or link) to avoid\nnesting interactive elements. Don't put essential or interactive content\ninside it — hover-only content is inaccessible to touch and keyboard users.","displayName":"Tooltip","methods":[],"props":{"children":{"defaultValue":null,"description":"The trigger element. Hovering or focusing it reveals the tooltip.","name":"children","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"ReactNode"}},"content":{"defaultValue":null,"description":"The floating hint. Keep it short — labels or hints, not paragraphs.","name":"content","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"ReactNode"}},"side":{"defaultValue":{"value":"top"},"description":"Preferred side of the trigger; flips on collision. Defaults to `'top'`.","name":"side","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"top\" | \"right\" | \"bottom\" | \"left\"","value":[{"value":"\"top\""},{"value":"\"right\""},{"value":"\"bottom\""},{"value":"\"left\""}]}},"align":{"defaultValue":null,"description":"Preferred alignment against the trigger. Defaults to `'center'`.","name":"align","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"center\" | \"start\" | \"end\"","value":[{"value":"\"center\""},{"value":"\"start\""},{"value":"\"end\""}]}},"sideOffset":{"defaultValue":{"value":"4"},"description":"Distance in pixels between the tooltip and its trigger. Defaults to `4`.","name":"sideOffset","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"asChild":{"defaultValue":{"value":"false"},"description":"Merge Radix's behavior onto an already-interactive child instead of wrapping it in a `<button>`. Defaults to `false`.","name":"asChild","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"hideWhenDetached":{"defaultValue":null,"description":"Hide the tooltip when the trigger is clipped away (e.g. scrolled out of an `overflow` container).","name":"hideWhenDetached","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"delayDuration":{"defaultValue":{"value":"0"},"description":"Delay in ms before opening on hover. Defaults to `0`; focus always opens instantly.","name":"delayDuration","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"className":{"defaultValue":null,"description":"Extra classes for the content surface, merged last.","name":"className","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Tooltip"}}},"meta":{"docgen":"react-docgen-typescript","durationMs":3021}}
1
+ {"v":0,"components":{"components-accordion":{"id":"components-accordion","name":"Accordion.Root","path":"./src/accordion/accordion.stories.tsx","stories":[{"id":"components-accordion--default","name":"Default","snippet":"const Default = () => <Accordion.Root type=\"single\" collapsible enclosed={false} disabled={false}>\n <FaqItems />\n</Accordion.Root>;","description":"Exclusive accordion: one item open at a time, `collapsible` lets it close."},{"id":"components-accordion--multiple","name":"Multiple","snippet":"const Multiple = () => (\n <Accordion.Root type=\"multiple\" defaultValue={['covered', 'payment']}>\n <FaqItems />\n </Accordion.Root>\n);","description":"`type=\"multiple\"` lets several sections stay open at once."},{"id":"components-accordion--enclosed","name":"Enclosed","snippet":"const Enclosed = () => (\n <div className=\"flex flex-col gap-8\">\n <Accordion.Root type=\"multiple\" defaultValue={['covered']}>\n <FaqItems />\n </Accordion.Root>\n <Accordion.Root type=\"multiple\" enclosed defaultValue={['claim']}>\n <FaqItems />\n </Accordion.Root>\n </div>\n);","description":"`enclosed` wraps the group in a bordered card (default borderless on top)."},{"id":"components-accordion--custom-trigger","name":"Custom Trigger","snippet":"const CustomTrigger = () => (\n <Accordion.Root type=\"single\" collapsible defaultValue=\"covered\">\n <Accordion.Item value=\"covered\">\n <Accordion.Trigger asChild>\n <button className=\"group flex w-full items-center gap-2 py-4 text-left text-base font-semibold\">\n <IconKeyboardArrowDown className=\"size-5 shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-180\" />\n What is covered?\n </button>\n </Accordion.Trigger>\n <Accordion.Content>{FAQS[0].answer}</Accordion.Content>\n </Accordion.Item>\n </Accordion.Root>\n);","description":"`asChild` delegates the trigger to a custom element; the built-in chevron is omitted."},{"id":"components-accordion--styled-titles","name":"Styled Titles","snippet":"const StyledTitles = () => <Accordion.Root type=\"single\" collapsible>\n {FAQS.map(({ value, question, answer }) => (\n <Accordion.Item key={value} value={value}>\n <Accordion.Trigger>\n <span className=\"text-lg font-bold\">{question}</span>\n </Accordion.Trigger>\n <Accordion.Content>{answer}</Accordion.Content>\n </Accordion.Item>\n ))}\n</Accordion.Root>;","description":"The consumer controls title weight/size via the children passed to `Trigger`."},{"id":"components-accordion--expand-collapse","name":"Expand Collapse","snippet":"const ExpandCollapse = () => <Accordion.Root type=\"single\" collapsible>\n <FaqItems />\n</Accordion.Root>;","description":"`collapsible` lets clicking the open item close it (reach an all-closed state)."},{"id":"components-accordion--non-collapsible","name":"Non Collapsible","snippet":"const NonCollapsible = () => <Accordion.Root type=\"single\" collapsible={false} defaultValue=\"covered\">\n <FaqItems />\n</Accordion.Root>;","description":"Without `collapsible`, clicking the already-open item keeps it open."}],"import":"import { Accordion, IconKeyboardArrowDown } from \"@agentero/design-system\";","jsDocTags":{},"description":"Stacked, collapsible sections built on Radix UI's Accordion (keyboard nav and ARIA come for free). Compose `Root` with `Item`s, each holding a `Trigger` and `Content`. `type=\"single\"` (optionally `collapsible`) opens one at a time; `type=\"multiple\"` opens sections independently. `enclosed` renders the group as a bordered card.","reactDocgenTypescript":{"tags":{},"filePath":"/home/runner/work/design-system/design-system/src/accordion/accordion.tsx","description":"Stacked, collapsible sections built on Radix UI's Accordion (keyboard nav and\nARIA come for free). Compose `Root` with `Item`s, each holding a `Trigger` and\n`Content`. `type=\"single\"` (optionally `collapsible`) opens one at a time;\n`type=\"multiple\"` opens sections independently. `enclosed` renders the group\nas a bordered card.","displayName":"Accordion","methods":[],"props":{},"exportName":"Accordion"}},"components-alert":{"id":"components-alert","name":"Alert","path":"./src/alert/alert.stories.tsx","stories":[{"id":"components-alert--default","name":"Default","snippet":"const Default = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Args-controlled playground. Toggle `color`, `size`, `ghost`, `hasIcon`, and `onDismiss` from the Controls panel to explore every visual combination.","summary":"Default args playground for Alert"},{"id":"components-alert--neutral","name":"Neutral","snippet":"const Neutral = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Neutral color is the default and carries no strong semantic signal — use it for generic inline information.","summary":"Neutral color (default)"},{"id":"components-alert--success","name":"Success","snippet":"const Success = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Success color confirms a positive outcome — saved record, completed task, healthy state.","summary":"Success color for positive outcomes"},{"id":"components-alert--danger","name":"Danger","snippet":"const Danger = () => <Alert\n color=\"danger\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Danger color flags errors and destructive outcomes that require the user's attention.","summary":"Danger color for errors and destructive outcomes"},{"id":"components-alert--warning","name":"Warning","snippet":"const Warning = () => <Alert\n color=\"warning\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Warning color signals caution — the user should review before proceeding.","summary":"Warning color for cautionary feedback"},{"id":"components-alert--info","name":"Info","snippet":"const Info = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Info color highlights tips, hints, or secondary informational content.","summary":"Info color for informational highlights"},{"id":"components-alert--creative","name":"Creative","snippet":"const Creative = () => <Alert\n color=\"creative\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Creative color uses a brand-aligned purple accent for marketing or onboarding moments.","summary":"Creative brand accent color"},{"id":"components-alert--dynamic","name":"Dynamic","snippet":"const Dynamic = () => <Alert\n color=\"dynamic\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Dynamic color uses a brand-aligned orange accent for activity or momentum-focused content.","summary":"Dynamic brand accent color"},{"id":"components-alert--playful","name":"Playful","snippet":"const Playful = () => <Alert\n color=\"playful\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Playful color uses a brand-aligned pink accent for lighter or celebratory content.","summary":"Playful brand accent color"},{"id":"components-alert--ghost","name":"Ghost","snippet":"const Ghost = () => <Alert\n color=\"danger\"\n size=\"sm\"\n ghost\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Ghost mode removes the background and padding so the alert blends inline with surrounding text (e.g., form field errors). Colors switch to the ghost token ramp for lower visual weight.","summary":"Ghost mode for inline, low-emphasis alerts"},{"id":"components-alert--small-size","name":"Small Size","snippet":"const SmallSize = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Small size (default) uses compact padding and 14/12px typography — suitable for inline alerts inside forms, tables, or cards.","summary":"Small size (default, compact)"},{"id":"components-alert--medium-size","name":"Medium Size","snippet":"const MediumSize = () => <Alert\n color=\"neutral\"\n size=\"md\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Medium size uses larger padding and 18/14px typography — suitable for standalone alerts in empty states, modals, or dedicated feedback regions.","summary":"Medium size (prominent, standalone)"},{"id":"components-alert--with-dismiss","name":"With Dismiss","snippet":"const WithDismiss = () => <Alert color=\"warning\" size=\"sm\" ghost={false} hasIcon onDismiss={fn()}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Dismissible alert. Providing `onDismiss` shows an icon-only close button with `aria-label=\"Dismiss\"` that inherits the alert's color.","summary":"Alert with a dismiss button"},{"id":"components-alert--with-actions","name":"With Actions","snippet":"const WithActions = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Update available</Alert.Title>\n <Alert.Paragraph>Reload to apply the latest version.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={() => {}}>Reload</Alert.Button>\n </Alert.Actions>\n</Alert>;","description":"Alert with a trailing action pinned to the right edge. Use `Alert.Actions` + `Alert.Button` for the common \"message + action\" pattern.","summary":"Alert with a trailing action button"},{"id":"components-alert--with-dismiss-and-action","name":"With Dismiss And Action","snippet":"const WithDismissAndAction = () => <Alert\n color=\"warning\"\n size=\"md\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Session expiring</Alert.Title>\n <Alert.Paragraph>Renew to continue editing.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={() => {}}>Renew session</Alert.Button>\n </Alert.Actions>\n</Alert>;","description":"Alert combining a dismiss button with a trailing action. Dismiss is pinned to the right edge after the actions.","summary":"Alert with both dismiss and action"},{"id":"components-alert--without-icon","name":"Without Icon","snippet":"const WithoutIcon = () => <Alert\n color=\"info\"\n size=\"sm\"\n ghost={false}\n hasIcon={false}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert rendered without the built-in color icon. Use `hasIcon={false}` when the surrounding context already conveys the semantic intent.","summary":"Alert without the default icon"},{"id":"components-alert--with-custom-icon","name":"With Custom Icon","snippet":"const WithCustomIcon = () => <Alert\n color=\"creative\"\n size=\"sm\"\n ghost={false}\n hasIcon\n icon={IconLightbulb}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Title</Alert.Title>\n <Alert.Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert with a caller-supplied icon that replaces the default color icon. The custom icon receives the slot-computed className so color tokens still apply.","summary":"Alert with a custom icon override"},{"id":"components-alert--with-paragraph-html","name":"With Paragraph Html","snippet":"const WithParagraphHtml = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Formatted content</Alert.Title>\n <Alert.ParagraphHtml\n html=\"Review the <strong>terms</strong> or <a href='https://example.com'>read the docs</a>.\" />\n </Alert.Content>\n</Alert>;","description":"Alert rendering a paragraph from pre-sanitized HTML via `Alert.ParagraphHtml`. The caller is responsible for sanitizing the HTML string before passing it in.","summary":"Alert paragraph rendered from HTML"},{"id":"components-alert--with-pictograms","name":"With Pictograms","snippet":"const WithPictograms = () => <Alert\n color=\"info\"\n size=\"md\"\n ghost={false}\n hasIcon={false}\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Pictograms>\n <svg viewBox=\"0 0 64 64\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden>\n <circle cx=\"32\" cy=\"32\" r=\"28\" fill=\"currentColor\" opacity=\"0.15\" />\n <circle cx=\"32\" cy=\"32\" r=\"14\" fill=\"currentColor\" />\n </svg>\n </Alert.Pictograms>\n <Alert.Content>\n <Alert.Title>Pictogram example</Alert.Title>\n <Alert.Paragraph>Pictograms scale to 64×64px regardless of the configured size.\n </Alert.Paragraph>\n </Alert.Content>\n</Alert>;","description":"Alert with a 64×64 pictogram in place of the inline icon. Use `Alert.Pictograms` when the message benefits from a richer illustration.","summary":"Alert with a pictogram illustration"},{"id":"components-alert--only-paragraph","name":"Only Paragraph","snippet":"const OnlyParagraph = () => <Alert\n color=\"neutral\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Paragraph>This field is required.</Alert.Paragraph>\n</Alert>;","description":"Alert rendered with only a paragraph — no title. The root omits `aria-labelledby` since there is no title to reference.","summary":"Alert with only a paragraph body"},{"id":"components-alert--with-actions-below","name":"With Actions Below","snippet":"const WithActionsBelow = () => <Alert\n color=\"success\"\n size=\"sm\"\n ghost={false}\n hasIcon\n onDismiss={onDismiss ? () => {} : undefined}>\n <Alert.Content>\n <Alert.Title>Upload complete</Alert.Title>\n <Alert.Paragraph>12 documents were added to the policy.</Alert.Paragraph>\n <div>\n <Alert.Button onClick={() => {}}>View documents</Alert.Button>\n </div>\n </Alert.Content>\n</Alert>;","description":"Action button rendered inline below the paragraphs, inside `Alert.Content`, rather than pinned to the right via `Alert.Actions`.","summary":"Alert with actions placed below the content"},{"id":"components-alert--all-colors","name":"All Colors","snippet":"const AllColors = () => (\n <Stack>\n {COLORS.map(color => (\n <Alert key={color} color={color}>\n <Alert.Content>\n <Alert.Title>{color}</Alert.Title>\n <Alert.Paragraph>\n This is a {color} alert variant with the default icon.\n </Alert.Paragraph>\n </Alert.Content>\n </Alert>\n ))}\n </Stack>\n);","description":"All eight colors in their primary (non-ghost) treatment, stacked for comparison. Each alert uses the built-in icon mapping for its color.","summary":"Visual comparison of all Alert colors"},{"id":"components-alert--all-ghost-colors","name":"All Ghost Colors","snippet":"const AllGhostColors = () => (\n <Stack>\n {COLORS.map(color => (\n <Alert key={color} color={color} ghost>\n <Alert.Content>\n <Alert.Title>{color} (ghost)</Alert.Title>\n <Alert.Paragraph>\n This is a {color} ghost alert variant with the ghost icon color.\n </Alert.Paragraph>\n </Alert.Content>\n </Alert>\n ))}\n </Stack>\n);","description":"All eight colors in ghost mode, stacked for comparison. Ghost alerts use a lower-weight token ramp and omit background + padding.","summary":"Visual comparison of all Alert colors in ghost mode"}],"import":"import { Alert } from \"@agentero/design-system\";","jsDocTags":{},"description":"Alert surfaces feedback about outcomes or state changes — success, danger, warning, or info. Compose it from `Alert.Content`, `Alert.Title`, `Alert.Paragraph`, `Alert.Actions`, and `Alert.Button` to build the layout your flow needs. Eight colors, two sizes, and a ghost mode cover most feedback scenarios.","reactDocgenTypescript":{"tags":{"summary":"Feedback banner with color variants, optional icon, and dismiss","example":"<Alert color=\"success\" size=\"sm\">\n <Alert.Content>\n <Alert.Title>Policy saved</Alert.Title>\n <Alert.Paragraph>Your changes are live.</Alert.Paragraph>\n </Alert.Content>\n</Alert>\n<Alert color=\"warning\" onDismiss={() => setOpen(false)}>\n <Alert.Content>\n <Alert.Title>Session expiring</Alert.Title>\n <Alert.Paragraph>Renew to continue editing.</Alert.Paragraph>\n </Alert.Content>\n <Alert.Actions>\n <Alert.Button onClick={renew}>Renew session</Alert.Button>\n </Alert.Actions>\n</Alert>\n<Alert color=\"danger\" ghost>\n <Alert.Paragraph>This field is required.</Alert.Paragraph>\n</Alert>"},"filePath":"/home/runner/work/design-system/design-system/src/alert/alert.tsx","description":"Alert surfaces feedback about an outcome or state change — success, error,\nwarning, or informational. Compose it from the exposed sub-components to\nbuild the layout you need: `Alert.Content` groups a `Alert.Title` and any\nnumber of `Alert.Paragraph` / `Alert.ParagraphHtml`; `Alert.Actions` adds\ntrailing buttons; `Alert.Pictograms` renders a 64px illustration. Pass\n`onDismiss` to show a close button; `hasIcon={false}` to hide the default\nicon; `icon` to substitute a custom icon component.\n\nAccessibility: the root carries `role=\"alert\"`; `aria-labelledby` points at\nthe rendered `Alert.Title` (when present) and `aria-describedby` at the\nparagraph wrapper. Multiple Alerts on the same page receive unique ids via\n`useId()`. The dismiss control has an accessible name of `Dismiss`.\n\nDo **not** use Alert for transient toast notifications (use a Toast\ncomponent) or for large error pages (use a dedicated empty-state).","displayName":"Alert","methods":[],"props":{"onDismiss":{"defaultValue":null,"description":"Fires when the dismiss button is clicked. When provided, renders an `iconOnly` close button with `aria-label=\"Dismiss\"`.","name":"onDismiss","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"(() => void)"}},"hasIcon":{"defaultValue":{"value":"true"},"description":"When `true` (default), renders the built-in icon for the current `color`. Set to `false` to omit the icon entirely.","name":"hasIcon","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"icon":{"defaultValue":null,"description":"Overrides the default icon for the current `color`. Receives the slot-computed className so color tokens still apply.","name":"icon","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ComponentType<SVGProps<SVGSVGElement>>"}},"color":{"defaultValue":{"value":"neutral"},"description":"Semantic color. Defaults to `'neutral'`.\n- `neutral` — generic info; no strong signal.\n- `success` — positive confirmation.\n- `danger` — error or destructive outcome.\n- `warning` — caution; user attention needed.\n- `info` — informational highlight.\n- `creative`, `dynamic`, `playful` — brand-aligned accents.","name":"color","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"HTMLAttributes"}],"required":false,"type":{"name":"enum","raw":"\"neutral\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"creative\" | \"dynamic\" | \"playful\"","value":[{"value":"\"neutral\""},{"value":"\"success\""},{"value":"\"danger\""},{"value":"\"warning\""},{"value":"\"info\""},{"value":"\"creative\""},{"value":"\"dynamic\""},{"value":"\"playful\""}]}},"size":{"defaultValue":{"value":"sm"},"description":"Size treatment. Defaults to `'sm'`.\n- `sm` — compact inline alerts (1rem padding, 14/12px typography).\n- `md` — prominent standalone alerts (2rem padding, 18/14px typography).","name":"size","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"AlertSizeType","value":[{"value":"\"sm\""},{"value":"\"md\""}]}},"ghost":{"defaultValue":{"value":"false"},"description":"When `true`, removes background and padding so the alert blends inline\nwith surrounding text (e.g., inline form field errors). Colors switch\nto the ghost token ramp for lower visual weight.","name":"ghost","declarations":[{"fileName":"design-system/src/alert/alert.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Alert"}},"components-avatar":{"id":"components-avatar","name":"Avatar","path":"./src/avatar/avatar.stories.tsx","stories":[{"id":"components-avatar--default","name":"Default","snippet":"const Default = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"photo\" />;","description":"The default avatar with fallback initials. Renders as a medium circle when no image source is provided.","summary":"Default avatar with fallback initials"},{"id":"components-avatar--with-image","name":"With Image","snippet":"const WithImage = () => <Avatar\n fallback=\"JD\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\" />;","description":"Avatar displaying a user profile photo. The image fills the avatar shape and the fallback is hidden while the image loads successfully.","summary":"Avatar with a profile image"},{"id":"components-avatar--with-fallback-initials","name":"With Fallback Initials","snippet":"const WithFallbackInitials = () => <Avatar\n fallback=\"AM\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://broken-url.example/photo.jpg\" />;","description":"When the image fails to load, the fallback content is displayed. Pass initials, an icon, or any ReactNode as the `fallback` prop.","summary":"Fallback content shown when image is unavailable"},{"id":"components-avatar--circle","name":"Circle","snippet":"const Circle = () => <Avatar fallback=\"CR\" size=\"md\" variant=\"circle\" type=\"photo\" />;","description":"The circle variant is the default shape, ideal for user profile photos.","summary":"Circle-shaped avatar (default)"},{"id":"components-avatar--square","name":"Square","snippet":"const Square = () => <Avatar fallback=\"WS\" size=\"md\" variant=\"square\" type=\"photo\" />;","description":"The square variant uses a rounded rectangle, suitable for workspace, team, or organization icons.","summary":"Square-shaped avatar for workspaces"},{"id":"components-avatar--pillow","name":"Pillow","snippet":"const Pillow = () => <Avatar fallback=\"PL\" size=\"md\" variant=\"pillow\" type=\"photo\" />;","description":"The pillow variant uses a soft, organic squircle shape for a friendly and distinctive appearance.","summary":"Pillow-shaped avatar with organic squircle"},{"id":"components-avatar--pentagon","name":"Pentagon","snippet":"const Pentagon = () => <Avatar fallback=\"PT\" size=\"md\" variant=\"pentagon\" type=\"photo\" />;","description":"The pentagon variant uses a five-sided mask for a unique visual identity. Note: the border is hidden in this variant due to the mask shape.","summary":"Pentagon-shaped avatar for unique identity"},{"id":"components-avatar--type-photo","name":"Type Photo","snippet":"const TypePhoto = () => <Avatar\n fallback=\"AM\"\n size=\"md\"\n variant=\"circle\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\" />;","description":"The `photo` type is the default. The image fills the avatar shape edge-to-edge, which is ideal for user profile photographs.","summary":"Photo type fills the avatar shape edge-to-edge"},{"id":"components-avatar--type-initials","name":"Type Initials","snippet":"const TypeInitials = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"initials\" />;","description":"The `initials` type is intended when no image is available and the avatar stands in for a user with their initials. The fallback text is centered within the avatar shape.","summary":"Initials type for users without a profile photo"},{"id":"components-avatar--type-isotype","name":"Type Isotype","snippet":"const TypeIsotype = () => <Avatar\n fallback=\"FG\"\n size=\"md\"\n variant=\"square\"\n type=\"isotype\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\" />;","description":"The `isotype` type renders the image smaller than the avatar shape so a brand or organization icon sits centered inside the container rather than filling it. Use for workspace, team, or company avatars where a logo should remain legible inside the bounding shape.","summary":"Isotype type centers a brand icon inside the shape"},{"id":"components-avatar--all-types","name":"All Types","snippet":"const AllTypes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n <Avatar\n size=\"lg\"\n type=\"photo\"\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n <Avatar size=\"lg\" type=\"initials\" fallback=\"JD\" />\n <Avatar\n size=\"lg\"\n type=\"isotype\"\n variant=\"square\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\"\n fallback=\"FG\"\n />\n </div>\n);","description":"All content types shown side by side: `photo` fills the shape, `initials` centers text, and `isotype` shrinks a brand icon inside the bounding shape.","summary":"Visual comparison of all avatar content types"},{"id":"components-avatar--all-sizes-isotype","name":"All Sizes Isotype","snippet":"const AllSizesIsotype = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar\n key={size}\n size={size}\n type=\"isotype\"\n variant=\"square\"\n src=\"https://cdn.simpleicons.org/figma\"\n alt=\"Figma\"\n fallback=\"FG\"\n />\n ))}\n </div>\n);","description":"The isotype icon scales proportionally smaller than the avatar shape at every size, keeping a consistent inset around the logo from `xs` (24px) to `4xl` (128px).","summary":"Isotype scaling across all avatar sizes"},{"id":"components-avatar--size-xs","name":"Size Xs","snippet":"const SizeXs = () => <Avatar fallback=\"XS\" size=\"xs\" variant=\"circle\" type=\"photo\" />;","description":"Extra-small avatar (24px) for dense lists and inline indicators.","summary":"Extra-small 24px avatar"},{"id":"components-avatar--size-sm","name":"Size Sm","snippet":"const SizeSm = () => <Avatar fallback=\"SM\" size=\"sm\" variant=\"circle\" type=\"photo\" />;","description":"Small avatar (32px) for compact layouts and table rows.","summary":"Small 32px avatar"},{"id":"components-avatar--size-lg","name":"Size Lg","snippet":"const SizeLg = () => <Avatar fallback=\"LG\" size=\"lg\" variant=\"circle\" type=\"photo\" />;","description":"Large avatar (48px) for profile sections and detail views.","summary":"Large 48px avatar"},{"id":"components-avatar--size-xl","name":"Size Xl","snippet":"const SizeXl = () => <Avatar fallback=\"XL\" size=\"xl\" variant=\"circle\" type=\"photo\" />;","description":"Extra-large avatar (64px) for hero sections and prominent display.","summary":"Extra-large 64px avatar"},{"id":"components-avatar--colorized","name":"Colorized","snippet":"const Colorized = () => <Avatar fallback=\"JD\" size=\"md\" variant=\"circle\" type=\"photo\" colorize=\"jane doe\" />;","description":"The `colorize` prop deterministically maps a string (typically a user name) to a color from the palette, applying a tinted background and matching text color. Useful for distinguishing users in lists without profile photos.","summary":"Colorized avatar based on user name"},{"id":"components-avatar--all-colorized","name":"All Colorized","snippet":"const AllColorized = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {['alice', 'bob', 'carol', 'dave', 'eve', 'frank', 'grace', 'henry', 'iris'].map(name => (\n <Avatar key={name} size=\"lg\" colorize={name} fallback={name.slice(0, 2).toUpperCase()} />\n ))}\n </div>\n);","description":"Multiple colorized avatars showing how different names map to different colors from the palette for visual distinction.","summary":"Multiple colorized avatars for visual distinction"},{"id":"components-avatar--all-sizes","name":"All Sizes","snippet":"const AllSizes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar key={size} size={size} fallback={size.toUpperCase()} />\n ))}\n </div>\n);","description":"All available sizes displayed together for visual comparison. Sizes range from `xs` (24px) to `4xl` (128px).","summary":"Visual comparison of all avatar sizes"},{"id":"components-avatar--all-sizes-with-image","name":"All Sizes With Image","snippet":"const AllSizesWithImage = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'] as const).map(size => (\n <Avatar\n key={size}\n size={size}\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n ))}\n </div>\n);","description":"All sizes with a profile image to verify image scaling and quality across the full size range from `xs` (24px) to `4xl` (128px).","summary":"All avatar sizes with a profile image"},{"id":"components-avatar--all-variants","name":"All Variants","snippet":"const AllVariants = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['circle', 'square', 'pillow', 'pentagon'] as const).map(variant => (\n <Avatar\n key={variant}\n size=\"lg\"\n variant={variant}\n fallback={variant.slice(0, 2).toUpperCase()}\n />\n ))}\n </div>\n);","description":"All available shape variants displayed together for visual comparison. Each variant serves a different use case: user photos, workspaces, friendly branding, and unique identity.","summary":"Visual comparison of all avatar shapes"},{"id":"components-avatar--all-variants-with-image","name":"All Variants With Image","snippet":"const AllVariantsWithImage = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>\n {(['circle', 'square', 'pillow', 'pentagon'] as const).map(variant => (\n <Avatar\n key={variant}\n size=\"lg\"\n variant={variant}\n src=\"https://images.unsplash.com/photo-1502823403499-6ccfcf4fb453?&w=256&h=256&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1&fit=crop\"\n alt=\"Alex Morgan\"\n fallback=\"AM\"\n />\n ))}\n </div>\n);","description":"All shape variants with a profile image to show how each mask clips the photo. Particularly useful for verifying the pentagon mask and pillow shape render correctly with real imagery.","summary":"All avatar shapes with a profile image"}],"import":"import { Avatar } from \"@agentero/design-system\";","jsDocTags":{},"description":"Avatar displays a user's profile image, initials, or a fallback icon. Use for user identification in lists, headers, cards, and comment threads. Supports multiple shapes (`circle`, `square`, `pillow`, `pentagon`), content types (`photo`, `initials`, `isotype`), and sizes from `xs` (24px) to `4xl` (128px).","reactDocgenTypescript":{"tags":{"summary":"Displays a user's profile image, initials, or fallback icon","example":"<Avatar src=\"/photos/jane.jpg\" alt=\"Jane Doe\" size=\"md\" variant=\"circle\" />\n<Avatar fallback=\"JD\" size=\"lg\" variant=\"square\" />"},"filePath":"/home/runner/work/design-system/design-system/src/avatar/avatar.tsx","description":"Avatar displays a user's profile image, initials, or a fallback icon.\nUse Avatar for user identification in lists, headers, cards, and comment threads.\n\nDo **not** use Avatar for decorative images or thumbnails unrelated to a person\nor entity — use a standard `<img>` or a Thumbnail component instead.\n\nRenders an image when `src` is provided; otherwise displays `fallback` content\n(typically initials or an icon). Built on Radix UI Avatar primitives.\n\nAvailable shapes: `circle` (default), `square`, `pillow`, and `pentagon`.\nSizes range from `xs` (24px) to `4xl` (128px), defaulting to `md` (40px).","displayName":"Avatar","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"alt":{"defaultValue":null,"description":"Accessible alt text describing the avatar image. Required when `src` is provided.","name":"alt","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"src":{"defaultValue":null,"description":"Image URL to display. When unavailable or loading fails, `fallback` content is shown instead.","name":"src","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"fallback":{"defaultValue":null,"description":"Content rendered when `src` is missing or fails to load. Typically user initials (e.g., \"JD\") or an icon.","name":"fallback","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ReactNode"}},"colorize":{"defaultValue":null,"description":"When provided, deterministically maps the string (typically a user name) to a\ncolor from the palette, applying a light background, matching text color, and\nborder color. Useful for distinguishing users in lists without profile photos.","name":"colorize","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"size":{"defaultValue":null,"description":"Controls the avatar dimensions. Defaults to `'md'` (40px).\n- `xs` (24px) — inline indicators, dense lists\n- `sm` (32px) — compact layouts, table rows\n- `md` (40px) — standard usage, cards, headers\n- `lg` (48px) — profile sections, detail views\n- `xl` (64px) — hero sections, prominent display\n- `2xl` (80px), `3xl` (96px), `4xl` (128px) — large feature areas, profile pages","name":"size","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"xs\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"4xl\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""},{"value":"\"lg\""},{"value":"\"xl\""},{"value":"\"2xl\""},{"value":"\"3xl\""},{"value":"\"4xl\""}]}},"variant":{"defaultValue":null,"description":"Shape of the avatar container. Defaults to `'circle'`.\n- `circle` — standard round avatar for user photos\n- `square` — rounded rectangle, suitable for workspace or team icons\n- `pillow` — soft, organic squircle shape\n- `pentagon` — distinctive five-sided shape for unique visual identity","name":"variant","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"circle\" | \"square\" | \"pillow\" | \"pentagon\"","value":[{"value":"\"circle\""},{"value":"\"square\""},{"value":"\"pillow\""},{"value":"\"pentagon\""}]}},"type":{"defaultValue":null,"description":"Content type the avatar represents. Defaults to `'photo'`.\n- `photo` — a user's profile photograph filling the avatar shape\n- `initials` — text initials standing in for a missing photo\n- `isotype` — a brand or organization icon rendered smaller than the avatar\n so it sits centered inside the shape instead of filling it","name":"type","declarations":[{"fileName":"design-system/src/avatar/avatar.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"isotype\" | \"photo\" | \"initials\"","value":[{"value":"\"isotype\""},{"value":"\"photo\""},{"value":"\"initials\""}]}}},"exportName":"Avatar"}},"components-button":{"id":"components-button","name":"Button","path":"./src/button/button.stories.tsx","stories":[{"id":"components-button--default","name":"Default","snippet":"const Default = () => <Button variant=\"primary\" size=\"sm\">{TEXT}</Button>;","description":"Args-controlled playground. Toggle `variant`, `size`, `status`, `loading`, `disabled`, and `rounded` from the Controls panel to explore every visual combination of the Button.","summary":"Default args playground for Button"},{"id":"components-button--variants","name":"Variants","snippet":"const Variants = () => (\n <Row>\n {VARIANTS.map(variant => (\n <Button key={variant} variant={variant}>\n {TEXT}\n </Button>\n ))}\n </Row>\n);","description":"All five variants at the default `sm` size. Variants express visual hierarchy: `primary` for the main CTA, `secondary` / `tertiary` for supporting actions, `ghost` for low-emphasis inline actions, and `link` for text-only actions.","summary":"All Button variants at default size"},{"id":"components-button--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <Row>\n {SIZES.map(size => (\n <Button key={size} size={size}>\n {TEXT}\n </Button>\n ))}\n </Row>\n);","description":"All four sizes at the default `primary` variant. Sizes scale from `xs` (24px) for dense toolbars up to `lg` (48px) for hero CTAs.","summary":"All Button sizes at default variant"},{"id":"components-button--disabled","name":"Disabled","snippet":"const Disabled = () => (\n <Row>\n {VARIANTS.map(variant => (\n <Button asChild key={variant} variant={variant} disabled>\n <a>{TEXT}</a>\n </Button>\n ))}\n </Row>\n);","description":"Disabled state across all variants. Rendered via `asChild` with `<a>` children to show the disabled treatment applied via className — native anchors ignore the `disabled` attribute, so Button emits `aria-disabled` and `data-disabled` on the child instead.","summary":"Disabled treatment for every variant"},{"id":"components-button--with-icons","name":"With Icons","snippet":"const WithIcons = () => (\n <Stack>\n {VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size}>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Variant × size grid with leading and trailing icons.","summary":"Variant × size grid with leading + trailing icons"},{"id":"components-button--only-icon","name":"Only Icon","snippet":"const OnlyIcon = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size} aria-label=\"Close\">\n <IconClose />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Icon-only buttons across the variant × size grid. Excludes `variant=\"link\"` — combining `link` with icon-only children logs a dev-only warning because the link treatment has no padding to accommodate an icon alone.","summary":"Icon-only Button across variant × size (excluding `link`)"},{"id":"components-button--loading","name":"Loading","snippet":"const Loading = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <div key={size} style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>\n <Button variant={variant} size={size} loading aria-label=\"Loading\">\n <IconAdd />\n </Button>\n <Button variant={variant} size={size} loading>\n {TEXT}\n </Button>\n </div>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Loading state across the variant × size grid. Each row shows two buttons per size: one icon-only, one with text. Loading forces `disabled` and overlays a spinner that inherits the variant's text color. Excludes `variant=\"link\"` — combining `link` with `loading` logs a dev-only warning.","summary":"Loading state across variant × size (excluding `link`)"},{"id":"components-button--status","name":"Status","snippet":"const Status = () => (\n <Stack>\n <Row>\n {VARIANTS.map(variant => (\n <Button key={variant} variant={variant} status=\"danger\">\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n <Row>\n {VARIANTS.map(variant => (\n <Button asChild key={variant} variant={variant} status=\"danger\" disabled>\n <a>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </a>\n </Button>\n ))}\n </Row>\n </Stack>\n);","description":"Destructive treatment via `status=\"danger\"`. The top row shows every variant enabled; the bottom row shows every variant disabled. Use `status=\"danger\"` for delete, remove, or disconnect actions regardless of variant.","summary":"`status=\"danger\"` across every variant, enabled + disabled"},{"id":"components-button--rounded","name":"Rounded","snippet":"const Rounded = () => (\n <Stack>\n {NON_LINK_VARIANTS.map(variant => (\n <Row key={variant}>\n {SIZES.map(size => (\n <Button key={size} variant={variant} size={size} rounded>\n <IconAdd />\n {TEXT}\n <IconAdd />\n </Button>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Fully pill-shaped buttons across the variant × size grid. Excludes `variant=\"link\"` since the link treatment has no background to round.","summary":"`rounded` pill shape across variant × size (excluding `link`)"},{"id":"components-button--as-child","name":"As Child","snippet":"const AsChild = () => (\n <Row>\n <Button asChild variant=\"primary\">\n <a href=\"/dashboard\">Go to dashboard</a>\n </Button>\n <Button asChild variant=\"secondary\">\n <a href=\"https://agentero.com\" target=\"_blank\" rel=\"noreferrer\">\n Visit Agentero\n </a>\n </Button>\n </Row>\n);","description":"`asChild` renders Button's styles on the nested child element rather than on a `<button>` — the child receives Button's `className`, `ref`, and merged props via Radix's `Slot` primitive. Use it to turn any anchor or framework `Link` into a Button without coupling the design system to a router. In app code, swap the plain `<a>` below for your framework's Link (`next/link`, `react-router`, `@tanstack/react-router`, etc.).","summary":"`asChild` composes Button's styles onto any element"}],"import":"import { Button } from \"@agentero/design-system\";","jsDocTags":{},"description":"Button is the design system's primary actionable control. Pick `variant` to express hierarchy, `size` for prominence, and `status=\"danger\"` for destructive actions. Pass `asChild` to render Button's styles on any nested element — a plain `<a>`, a framework `<Link>`, or a custom component — without Button binding to any particular framework.","reactDocgenTypescript":{"tags":{"summary":"Primary actionable control; renders a `<button>` or, with `asChild`, any nested element","example":"<Button variant=\"primary\" size=\"sm\" onClick={handleSave}>\n Save changes\n</Button>\n<Button asChild variant=\"secondary\">\n <a href=\"https://agentero.com\" target=\"_blank\" rel=\"noreferrer\">Visit Agentero</a>\n</Button>\n// Framework-agnostic: wrap any Link implementation\n<Button asChild variant=\"primary\">\n <Link href=\"/dashboard\">Go to dashboard</Link>\n</Button>\n<Button variant=\"primary\" status=\"danger\" loading={isDeleting} onClick={handleDelete}>\n Delete account\n</Button>"},"filePath":"/home/runner/work/design-system/design-system/src/button/button.tsx","description":"Button is the design system's primary actionable control. Use it for any\ninteraction that triggers behavior, submits a form, or navigates the user.\nBy default Button renders a `<button>`; pass `asChild` to render its single\nchild element as the underlying tag instead — Button merges its styles,\n`className`, `ref`, and props onto whatever the consumer nests. This keeps\nthe design system framework-agnostic: route a plain `<a>`, a Next.js\n`<Link>`, a React Router `<Link>`, or any custom element through the same\nvisual treatment.\n\nPick `variant` to express hierarchy (`primary` for the main CTA,\n`secondary` / `tertiary` for supporting actions, `ghost` for low-emphasis\ninline actions, `link` for text-only actions). Use `status=\"danger\"` for\ndestructive actions and `loading` to block interaction while async work\nresolves.\n\nDo **not** use Button for toggle states (prefer a Switch or ToggleButton),\nfor passive decorative anchors without action intent (use a plain `<a>`),\nor with `variant=\"link\"` when loading or when the button has no text\nchildren — both combinations log a dev-only warning (silent in production).","displayName":"Button","methods":[],"props":{"children":{"defaultValue":null,"description":"Content rendered inside the Button. Accepts a text label, icon elements,\nor any mix of both. Icon-only children switch the Button to a square\naspect ratio and trigger the icon-only layout.\n\nWhen `asChild` is set, the single child element is merged with Button's\nprops and styles; auto-detection of icon-only children is skipped — use\nthe `iconOnly` prop to opt into the square icon-only layout.\n\nNot supported with `variant=\"link\"` when children resolve to icons only\n— passing both logs a dev-only warning (silent in production).","name":"children","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"DOMAttributes"}],"required":false,"type":{"name":"ReactNode"}},"variant":{"defaultValue":null,"description":"Visual hierarchy. Defaults to `'primary'`.\n- `primary` — main call-to-action; use once per view.\n- `secondary` — alternative action alongside a primary button.\n- `tertiary` — low-emphasis action, subtle background.\n- `ghost` — minimal background; low-emphasis action in dense layouts.\n- `link` — inline text-style action; no padding or background.","name":"variant","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ButtonVariantType","value":[{"value":"\"link\""},{"value":"\"ghost\""},{"value":"\"primary\""},{"value":"\"secondary\""},{"value":"\"tertiary\""}]}},"size":{"defaultValue":null,"description":"Control size. Defaults to `'sm'`.\n- `xs` (24px) — dense toolbars, compact inline actions.\n- `sm` (32px) — standard usage in forms and cards.\n- `md` (40px) — prominent actions in modals or feature rows.\n- `lg` (48px) — hero CTAs and full-width mobile actions.","name":"size","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ButtonSizeType","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""},{"value":"\"lg\""}]}},"status":{"defaultValue":null,"description":"Semantic status override. Set to `'danger'` for destructive actions\n(delete, remove, disconnect) — applies the destructive color treatment\nacross all variants.","name":"status","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"danger\"","value":[{"value":"\"danger\""}]}},"loading":{"defaultValue":null,"description":"When `true`, shows a spinner overlay and forces the button into a disabled\nstate to block further interaction. Not supported with `variant=\"link\"` —\npassing both logs a dev-only warning (silent in production).","name":"loading","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"disabled":{"defaultValue":null,"description":"Disables interaction and applies the disabled color treatment. Applied\nvia className so it still affects anchors rendered via `asChild`, which\nignore the native `disabled` attribute — in that case `aria-disabled`\nand `data-disabled` are forwarded to the child element instead.","name":"disabled","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"},{"fileName":"design-system/node_modules/@types/react/index.d.ts","name":"ButtonHTMLAttributes"}],"required":false,"type":{"name":"boolean"}},"iconOnly":{"defaultValue":null,"description":"Forces the icon-only layout (square aspect ratio, no min-width). Useful\nwith `asChild` where the single wrapper child prevents auto-detection.\nFor non-`asChild` usage, prefer passing icon elements as children — the\nicon-only layout is applied automatically.","name":"iconOnly","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"rounded":{"defaultValue":null,"description":"When `true`, renders a fully pill-shaped button (rounded-full). Otherwise\nuses the variant's default corner radius.","name":"rounded","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"align":{"defaultValue":null,"description":"Justifies children along the main axis. Defaults to `'center'`.\nUse `'justify'` to push leading and trailing icons to the edges.","name":"align","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"center\" | \"start\" | \"end\" | \"justify\"","value":[{"value":"\"center\""},{"value":"\"start\""},{"value":"\"end\""},{"value":"\"justify\""}]}},"fitContent":{"defaultValue":null,"description":"When `true`, removes the per-size `min-width` floor so the button hugs\nits content. Useful for inline actions inside tight containers.","name":"fitContent","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"ref":{"defaultValue":null,"description":"Ref forwarded to the underlying element. Typed as a union covering both\n`<button>` and `<a>` because `asChild` lets consumers render either tag\n(or any forwardRef component) through Radix's `Slot`.","name":"ref","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"Ref<HTMLButtonElement | HTMLAnchorElement>"}},"asChild":{"defaultValue":null,"description":"When `true`, Button clones its single child element and merges\nButton's `className`, `ref`, and event handlers onto it rather than\nrendering a `<button>`. Use this to style any element (a plain `<a>`,\na framework `Link`, a `React.forwardRef` component) as a Button.\n\nWhen combined with `disabled`, Button emits `aria-disabled` and\n`data-disabled` on the child instead of the native `disabled`\nattribute (which is ignored by non-form-control elements).","name":"asChild","declarations":[{"fileName":"design-system/src/button/button.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Button"}},"components-checklist":{"id":"components-checklist","name":"CheckList.Root","path":"./src/check-list/check-list.stories.tsx","stories":[{"id":"components-checklist--default","name":"Default","snippet":"const Default = () => (\n <CheckList.Root>\n <CheckList.Item>Instant appointment</CheckList.Item>\n <CheckList.Item>Bind with Agentero</CheckList.Item>\n <CheckList.Item>Available in the Agentero rater</CheckList.Item>\n </CheckList.Root>\n);","description":"Plain text rows with a leading check."},{"id":"components-checklist--rich-content","name":"Rich Content","snippet":"const RichContent = () => (\n <div className=\"w-72\">\n <CheckList.Root>\n <CheckList.Item>\n <a href=\"#quoting\" className=\"underline\">\n Agentero rater\n </a>\n </CheckList.Item>\n <CheckList.Item>\n Longer descriptions wrap under their own text while the check stays aligned to the first\n line.\n </CheckList.Item>\n </CheckList.Root>\n </div>\n);","description":"Items accept rich content — links, wrapped text, custom markup."}],"import":"import { CheckList } from \"@agentero/design-system\";","jsDocTags":{},"description":"CheckList renders a vertical list where every row is marked with a check icon. Purely presentational — for interactive selection use a checkbox group.","reactDocgenTypescript":{"tags":{"summary":"Vertical list of check-marked rows","example":"```tsx\n<CheckList.Root>\n <CheckList.Item>Instant appointment</CheckList.Item>\n</CheckList.Root>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/check-list/check-list.tsx","description":"CheckList renders a vertical list where every row is marked with a check\nicon — feature lists, benefits, availability summaries. Purely\npresentational: for interactive selection use a checkbox group instead.","displayName":"CheckList","methods":[],"props":{},"exportName":"CheckList"}},"components-datatable":{"id":"components-datatable","name":"DataTable.Root","path":"./src/data-table/data-table.stories.tsx","stories":[{"id":"components-datatable--playground","name":"Playground","snippet":"const Playground = () => <div\n className={args.enclosed ? 'flex min-h-0 flex-1 flex-col p-4' : 'contents'}>\n <DataTable.Root data={LEADS} columns={columns}>\n <DataTable.Table size=\"md\" embed enclosed={false} sticky=\"header\" />\n </DataTable.Root>\n</div>;","description":"Playground for `DataTable.Table` display props — toggle `size`, `embed`, `enclosed`, and `sticky` from the controls panel.","summary":"Display props playground (size / embed / enclosed / sticky)"},{"id":"components-datatable--leads","name":"Leads","snippet":"const Leads = () => {\n const [sorting, setSorting] = useState<SortingState>([]);\n const [page, setPage] = useState(1);\n const [search, setSearch] = useState('');\n\n const data = useMemo(\n () => LEADS.filter(l => l.contact.toLowerCase().includes(search.toLowerCase())),\n [search]\n );\n\n return (\n <DataTable.Root\n data={data}\n columns={columns}\n state={{ sorting }}\n onSortingChange={setSorting}\n getSortedRowModel={getSortedRowModel()}\n enableSortingRemoval={false}\n rowHref={lead => `/leads/${lead.leadId}`}>\n <DataTable.ToolBar>\n <input\n value={search}\n onChange={e => setSearch(e.target.value)}\n placeholder=\"Search...\"\n aria-label=\"Search leads\"\n className=\"h-8 w-60 rounded-md border border-border-default-base-primary px-3 text-sm outline-none\"\n />\n <Button variant=\"secondary\" size=\"sm\">\n Filters\n </Button>\n </DataTable.ToolBar>\n\n <DataTable.Table />\n\n <DataTable.Footer>\n <Pagination\n totalCount={LEADS.length}\n currentPage={page}\n pageSize={10}\n onPageChange={setPage}\n />\n </DataTable.Footer>\n </DataTable.Root>\n );\n};","description":"A leads-table composition: sortable `Created` column, a status badge, row navigation via `rowHref`, hover-revealed actions, a search input + filters in the toolbar, and pagination in the footer.","summary":"Representative leads table composition"},{"id":"components-datatable--empty","name":"Empty","snippet":"const Empty = () => (\n <DataTable.Root data={[] as Lead[]} columns={columns}>\n <DataTable.Table />\n </DataTable.Root>\n);","description":"No rows: the table renders its default empty state instead of body rows.","summary":"Empty state when there are no rows"},{"id":"components-datatable--loading","name":"Loading","snippet":"const Loading = () => (\n <DataTable.Root data={[] as Lead[]} columns={columns} isLoading>\n <DataTable.Table />\n </DataTable.Root>\n);","description":"Loading: the body is dimmed and the empty state is suppressed while data is in flight.","summary":"Loading state dims the table and hides the empty state"}],"import":"import { Button, DataTable, DropdownMenu, Pagination, Table } from \"@agentero/design-system\";","jsDocTags":{},"description":"DataTable is the data-driven table compound built on TanStack Table. This story shows a representative leads table: an `Applicant` column with a name + address, contact info, insurance type with an icon, a sortable `Created` column, a status badge, and hover-revealed row actions (open + a kebab menu). The toolbar (search + filters) and the footer pagination are **separate components** composed inside `ToolBar` / `Footer`.","reactDocgenTypescript":{"tags":{"summary":"Data-driven table compound (sorting, toolbar, pagination) over TanStack","see":"{@link https://tanstack.com/table/latest TanStack Table}","namespace":"DataTable","example":"```tsx\nimport { DataTable } from '@agentero/design-system/data-table';\nimport { createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<User>();\nconst columns = [\n columnHelper.accessor('name', { header: 'Name', enableSorting: true }),\n columnHelper.accessor('email', { header: 'Email' })\n];\n\n<DataTable.Root data={users} columns={columns}>\n <DataTable.ToolBar>\n <SearchInput />\n </DataTable.ToolBar>\n <DataTable.Table />\n <DataTable.Footer>\n <DataTable.Pagination\n currentPage={page}\n pageSize={10}\n totalCount={total}\n onPageChange={setPage}\n />\n </DataTable.Footer>\n</DataTable.Root>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/data-table/data-table.tsx","description":"Data-driven table compound built on TanStack Table and the `Table` primitive.\nCompose `Root` (owns the table instance) with `ToolBar`, `Table` (headers/rows,\nsorting, navigation, empty state), and `Footer` + `Pagination`. For hand-rendered\nrows without TanStack, drop to the `Table` primitive.","displayName":"DataTable","methods":[],"props":{},"exportName":"DataTable"}},"components-table":{"id":"components-table","name":"Table.Root","path":"./src/data-table/table.stories.tsx","stories":[{"id":"components-table--default","name":"Default","snippet":"const Default = args => renderTable(args);","description":"Default args playground.","summary":"Default table"},{"id":"components-table--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div className=\"flex flex-col gap-6\">\n {(['sm', 'md', 'lg'] as const).map(size => (\n <div key={size} className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-text-default-base-tertiary\">size=&quot;{size}&quot;</span>\n {renderTable({ size })}\n </div>\n ))}\n </div>\n);","description":"The three row densities. `size` sets row min-height: sm 48 / md 64 / lg 88px.","summary":"size — sm / md / lg"},{"id":"components-table--sticky-header","name":"Sticky Header","snippet":"const StickyHeader = args => renderTable(args);","description":"`sticky=\"header\"` pins the header while the body scrolls. Needs a bounded-height parent.","summary":"sticky=\"header\" with a scrolling body"},{"id":"components-table--sticky-header-and-footer","name":"Sticky Header And Footer","snippet":"const StickyHeaderAndFooter = args => renderTable(args, { totals: true });","description":"`sticky=\"headerAndFooter\"` pins the header and the last body row (totals here).","summary":"sticky=\"headerAndFooter\" with a pinned totals row"},{"id":"components-table--embed","name":"Embed","snippet":"const Embed = args => renderTable(args);","description":"`embed` drops the per-row dividers and tightens the edge gutter to 1rem.","summary":"embed — no row dividers, 1rem edge gutter"},{"id":"components-table--enclosed","name":"Enclosed","snippet":"const Enclosed = args => renderTable(args);","description":"`enclosed` wraps the table in a bordered, rounded container — the standalone \"card\" look, as opposed to a full-bleed page table.","summary":"enclosed — bordered, rounded card container"},{"id":"components-table--with-checkbox","name":"With Checkbox","snippet":"const WithCheckbox = args => renderTable(args, { checkbox: true });","description":"A leading checkbox column; checkbox cells collapse to zero width.","summary":"Selectable rows with a collapsing checkbox column"},{"id":"components-table--with-row-actions","name":"With Row Actions","snippet":"const WithRowActions = args => renderTable(args, { actions: true });","description":"Hover-revealed row actions pinned to the trailing edge.","summary":"Hover-revealed row actions"},{"id":"components-table--expandable-rows","name":"Expandable Rows","snippet":"const ExpandableRows = args => {\n const Demo = () => {\n const [openId, setOpenId] = useState<string | null>(ROWS[0]!.id);\n return (\n <Table.Root {...args}>\n <Table.Head>\n <Table.Row>\n <Table.Header>\n <span className=\"sr-only\">Expand</span>\n </Table.Header>\n <Table.Header>Name</Table.Header>\n <Table.Header>Email</Table.Header>\n <Table.Header>Role</Table.Header>\n </Table.Row>\n </Table.Head>\n <Table.Body>\n {ROWS.slice(0, 4).map(row => (\n <Fragment key={row.id}>\n <Table.Row>\n <Table.Cell>\n <Table.ExpandButton\n isExpanded={openId === row.id}\n toggleExpanded={() => setOpenId(openId === row.id ? null : row.id)}\n aria-label={`Toggle ${row.name}`}\n />\n </Table.Cell>\n <Table.Cell className=\"font-bold\">{row.name}</Table.Cell>\n <Table.Cell className=\"text-text-default-base-secondary\">{row.email}</Table.Cell>\n <Table.Cell>{row.role}</Table.Cell>\n </Table.Row>\n {openId === row.id && (\n <Table.ExpandedRow>\n <Table.Cell colSpan={4}>\n <div className=\"py-2 text-text-default-base-secondary\">\n Extended details for {row.name} — {row.amount} lifetime value.\n </div>\n </Table.Cell>\n </Table.ExpandedRow>\n )}\n </Fragment>\n ))}\n </Table.Body>\n </Table.Root>\n );\n };\n return <Demo />;\n};","description":"`Table.ExpandButton` toggles a `Table.ExpandedRow` detail panel under its row.","summary":"Expandable rows with a detail panel"}],"import":"import { Button, Table } from \"@agentero/design-system\";\nimport { Fragment } from \"react\";","jsDocTags":{},"description":"Low-level presentational table primitive: native `<table>` markup themed for scrolling, sticky rows, cell padding, dividers, hover, and expandable rows. For sorting/toolbar/pagination, prefer `DataTable`.","reactDocgenTypescript":{"tags":{"summary":"Low-level themed table primitive (scrolling, sticky, sizing, rows)","namespace":"Table"},"filePath":"/home/runner/work/design-system/design-system/src/data-table/table.tsx","description":"Low-level presentational table primitive — a thin themed wrapper over native\n`<table>` markup (scrolling, sticky rows, row sizing, dividers, hover,\nexpandable rows). Compose from `Root` / `Head` / `Body` / `Row` / `Header` /\n`Cell`, plus `ExpandButton` / `ExpandedRow` and `RowActions`. For\nsorting/toolbar/pagination, prefer `DataTable`, built on top of this.","displayName":"Table","methods":[],"props":{},"exportName":"Table"}},"components-divider":{"id":"components-divider","name":"Divider","path":"./src/divider/divider.stories.tsx","stories":[{"id":"components-divider--default","name":"Default","snippet":"const Default = () => <div\n className={cn(\n 'flex gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6',\n args.orientation === 'vertical' ? 'h-40 w-lg items-stretch' : 'w-80 flex-col'\n )}>\n <div className=\"flex flex-1 flex-col justify-center gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">First section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Content on one side of the divider, visually separated from the other.\n </p>\n </div>\n <Divider orientation=\"horizontal\" decorative />\n <div className=\"flex flex-1 flex-col justify-center gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Second section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Content on the other side of the divider, clearly separated from the first.\n </p>\n </div>\n</div>;","description":"The default horizontal, decorative divider — a 1px line that spans the parent width. Use this form between stacked content blocks.","summary":"Default horizontal decorative divider"},{"id":"components-divider--horizontal","name":"Horizontal","snippet":"const Horizontal = () => (\n <div className=\"w-80\">\n <Divider />\n </div>\n);","description":"Horizontal divider — a 1px line spanning the parent's full width. The default orientation; use to separate stacked content.","summary":"Horizontal 1px line spanning the parent width"},{"id":"components-divider--vertical","name":"Vertical","snippet":"const Vertical = () => (\n <div className=\"flex h-24 items-stretch\">\n <Divider orientation=\"vertical\" />\n </div>\n);","description":"Vertical divider — a 1px line spanning the parent's full height. Parent must establish a height (via `h-*` or an intrinsic flex item height) for the line to be visible.","summary":"Vertical 1px line spanning the parent height"},{"id":"components-divider--with-label","name":"With Label","snippet":"const WithLabel = () => <div className=\"flex w-80 flex-col gap-2\">\n <Button variant=\"primary\">Continue with email</Button>\n <Divider orientation=\"horizontal\" decorative label=\"or\" />\n <Button variant=\"secondary\">Continue with SSO</Button>\n</div>;","description":"Labelled divider. The label sits centered between two flanking 1px lines — a common pattern for \"or\" breaks between authentication options.","summary":"Horizontal divider with a centered \"or\" label"},{"id":"components-divider--vertical-with-label","name":"Vertical With Label","snippet":"const VerticalWithLabel = () => <div\n className=\"flex h-40 items-stretch gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6\">\n <div className=\"flex flex-col justify-center gap-1\">\n <h3 className=\"text-sm font-semibold text-text-default-base-primary\">Left panel</h3>\n <p className=\"text-xs text-text-default-base-secondary\">Content on the left side</p>\n </div>\n <Divider orientation=\"vertical\" decorative label=\"OR\" />\n <div className=\"flex flex-col justify-center gap-1\">\n <h3 className=\"text-sm font-semibold text-text-default-base-primary\">Right panel</h3>\n <p className=\"text-xs text-text-default-base-secondary\">Content on the right side</p>\n </div>\n</div>;","description":"Vertical divider with a label. The label sits between two stacked 1px line segments; use sparingly — horizontal labelled dividers are more common.","summary":"Vertical divider with a centered label"},{"id":"components-divider--semantic","name":"Semantic","snippet":"const Semantic = () => <div\n className=\"flex w-80 flex-col gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6\">\n <section className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section one</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Semantically separated from the next section for screen readers.\n </p>\n </section>\n <Divider orientation=\"horizontal\" decorative={false} />\n <section className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section two</h3>\n <p className=\"text-sm text-text-default-base-secondary\">Screen readers will announce this as a separate section.\n </p>\n </section>\n</div>;","description":"Semantic divider (`decorative={false}`). Exposes `role=\"separator\"` and `aria-orientation` to assistive technologies, marking a meaningful section break rather than a purely visual one.","summary":"Semantic separator announced to assistive technologies"},{"id":"components-divider--in-list","name":"In List","snippet":"const InList = () => (\n <div className=\"w-80 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary\">\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 1</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n You have a new message from Jane.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 2</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n Your report is ready to download.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1 px-4 py-3\">\n <h4 className=\"text-sm text-text-default-base-primary\">Notification 3</h4>\n <p className=\"text-xs text-text-default-base-secondary\">\n System maintenance is scheduled for tonight.\n </p>\n </div>\n </div>\n);","description":"Divider between list rows. Dividers delineate each item without the visual weight of a full border on every row.","summary":"Horizontal dividers between stacked list rows"},{"id":"components-divider--in-toolbar","name":"In Toolbar","snippet":"const InToolbar = () => (\n <div className=\"inline-flex h-10 items-center gap-1 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary px-2 shadow-1\">\n <Button variant=\"ghost\" size=\"xs\">\n Cut\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Copy\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Paste\n </Button>\n <Divider orientation=\"vertical\" className=\"mx-1 h-6\" />\n <Button variant=\"ghost\" size=\"xs\">\n Undo\n </Button>\n <Button variant=\"ghost\" size=\"xs\">\n Redo\n </Button>\n <Divider orientation=\"vertical\" className=\"mx-1 h-6\" />\n <Button variant=\"ghost\" size=\"xs\">\n Settings\n </Button>\n </div>\n);","description":"Vertical dividers grouping related toolbar actions. Use to separate logical clusters of buttons (editing vs. history vs. settings) without visual weight.","summary":"Vertical dividers grouping toolbar actions"},{"id":"components-divider--horizontal-in-content","name":"Horizontal In Content","snippet":"const HorizontalInContent = () => (\n <div className=\"flex w-96 flex-col gap-4 p-6\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Section title</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n Descriptive content for the first section. The divider below separates it from the next.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Another section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n The second section is clearly separated from the previous one.\n </p>\n </div>\n <Divider />\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-base font-semibold text-text-default-base-primary\">Final section</h3>\n <p className=\"text-sm text-text-default-base-secondary\">\n Dividers help establish visual hierarchy in content-heavy layouts.\n </p>\n </div>\n </div>\n);","description":"Horizontal dividers between content sections in a long-form layout. Helps create visual hierarchy in content-heavy pages.","summary":"Horizontal dividers between content sections"},{"id":"components-divider--vertical-between-elements","name":"Vertical Between Elements","snippet":"const VerticalBetweenElements = () => (\n <div className=\"flex items-stretch gap-3\">\n <Button variant=\"primary\" size=\"sm\">\n Button 1\n </Button>\n <Divider orientation=\"vertical\" />\n <Button variant=\"primary\" size=\"sm\">\n Button 2\n </Button>\n <Divider orientation=\"vertical\" />\n <Button variant=\"primary\" size=\"sm\">\n Button 3\n </Button>\n </div>\n);","description":"Vertical dividers between inline elements. Common for separating a row of related controls or inline links without visual weight.","summary":"Vertical dividers separating inline elements"}],"import":"import { Button, Divider } from \"@agentero/design-system\";","jsDocTags":{},"description":"Divider separates content visually along either a horizontal or vertical axis. Use between page or card sections, between inline items in a toolbar or list, or — with the `label` prop — to render an \"or\"-style break between options. Set `decorative={false}` when the separator carries semantic meaning so it's announced to assistive technologies.","reactDocgenTypescript":{"tags":{"summary":"Visual or semantic separator that optionally renders a centered label","param":"orientation - Axis along which the separator renders. Defaults to `'horizontal'`.\n- `horizontal` — 1px line spanning the parent width.\n- `vertical` — 1px line spanning the parent height; parent must establish a height.\ndecorative - When `true` (default), the separator is purely visual and hidden\nfrom assistive technologies. Set to `false` to expose `role=\"separator\"` plus\n`aria-orientation` for meaningful section breaks.\nlabel - Optional inline content rendered between two flanking 1px lines.\nWhen omitted, Divider renders a single line.","example":"<Divider />\n<Divider orientation=\"vertical\" />\n<Divider label=\"or\" />\n<Divider decorative={false} />"},"filePath":"/home/runner/work/design-system/design-system/src/divider/divider.tsx","description":"Divider separates content visually (or semantically, via `decorative={false}`)\nalong either a horizontal or vertical axis. Use Divider between page or card\nsections, between inline items in a toolbar or list, or to break up long\ncontent regions. Pass a `label` to render the \"or\"-style divider with text\ncentered between two line segments — useful for auth flows and step breaks.\n\nBuilt on Radix UI's Separator primitive for the unlabelled case; the\nlabelled case renders a `<div>` that still forwards the correct\n`role`/`aria-orientation` when `decorative={false}`.\n\nDo **not** use Divider as a bare horizontal rule to add vertical rhythm —\nreach for margin utilities or a layout wrapper instead. Divider should carry\nmeaning (visual or semantic section break), not whitespace.","displayName":"Divider","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"label":{"defaultValue":null,"description":"Optional label rendered inline between two flanking 1px lines. When set,\nDivider renders a styled `<div>` (rather than the underlying separator\nprimitive) so the label can sit centered between the two line segments.","name":"label","declarations":[{"fileName":"design-system/src/divider/divider.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"ReactNode"}}},"exportName":"Divider"}},"components-dropdownmenu":{"id":"components-dropdownmenu","name":"DropdownMenu.Root","path":"./src/dropdown-menu/dropdown-menu.stories.tsx","stories":[{"id":"components-dropdownmenu--default","name":"Default","snippet":"const Default = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Click me\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Edit clicked')}>Edit</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Duplicate clicked')}>\n Duplicate\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Archive clicked')}>\n Archive\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Delete clicked')}>\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"A minimal DropdownMenu with four `Item`s — edit/duplicate/archive plus a separator before a destructive delete. Use this as the starting point for most overflow menus.","summary":"Basic menu with item rows and a separated destructive action"},{"id":"components-dropdownmenu--with-groups-and-dividers","name":"With Groups And Dividers","snippet":"const WithGroupsAndDividers = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n More Options\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Undo')}>Undo</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Redo')}>Redo</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Copy')}>Copy</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Cut')}>Cut</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Paste')}>Paste</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item disabled>Print (disabled)</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Export')}>Export</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Multiple clusters of `Item`s split by `Separator` rules — mirrors an \"edit history / clipboard / export\" overflow menu. Demonstrates the `disabled` state on a menu row.","summary":"Menu with multiple `Separator`-split groups and a disabled item"},{"id":"components-dropdownmenu--with-icons","name":"With Icons","snippet":"const WithIcons = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Actions\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('Copy')}>\n <IconContentCopy />\n Copy\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n onSelect={() => console.log('Delete')}\n className=\"data-[highlighted]:bg-red-100\">\n <IconDelete className=\"[&>path]:fill-red-500\" />\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Menu items with leading icons and a destructive row using the `data-[highlighted]:bg-red-100` + `text-red-500` escape hatch. Use this pattern when a row should read as destructive.","summary":"Icon-leading items with a destructive delete row"},{"id":"components-dropdownmenu--with-group-titles","name":"With Group Titles","snippet":"const WithGroupTitles = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Account Menu\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Label>Profile</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('View Profile')}>\n View Profile\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Edit Profile')}>\n Edit Profile\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Settings</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Preferences')}>\n Preferences\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Privacy')}>Privacy</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Notifications')}>\n Notifications\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Account</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Billing')}>Billing</DropdownMenu.Item>\n <DropdownMenu.Item\n onSelect={() => console.log('Logout')}\n className=\"data-[highlighted]:bg-red-100\">\n <span className=\"text-red-500\">Logout</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"`Label`-segmented Profile / Settings / Account sections with a destructive Logout row. Use `Label` to name groups that would otherwise be ambiguous from the item text alone.","summary":"Menu with `Label`-titled sections and a destructive logout row"},{"id":"components-dropdownmenu--with-submenu","name":"With Submenu","snippet":"const WithSubmenu = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n File Options\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('New File')}>New File</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Open')}>Open</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconIosShare />\n Share\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Email')}>Email</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Slack')}>Slack</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Copy Link')}>\n Copy Link\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconDriveFileMove />\n Move to\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Archive')}>\n Archive\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Projects')}>\n Projects\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Drafts')}>Drafts</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n onSelect={() => console.log('Delete')}\n className=\"data-[highlighted]:bg-red-100\">\n <IconDelete className=\"[&>path]:fill-red-500\" />\n <span className=\"text-red-500\">Delete</span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"One level of nesting: Share and Move-to submenus wired via `Sub` / `SubTrigger` / `SubContent`. Each submenu is portaled independently so it escapes the parent's stacking context.","summary":"Single-level submenus for Share and Move-to flows"},{"id":"components-dropdownmenu--nested-submenus","name":"Nested Submenus","snippet":"const NestedSubmenus = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Organization Menu\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Label>Organization</DropdownMenu.Label>\n <DropdownMenu.Item onSelect={() => console.log('Dashboard')}>Dashboard</DropdownMenu.Item>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconPeople />\n Teams\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('View All Teams')}>\n View All Teams\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Engineering</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Frontend')}>\n Frontend\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Backend')}>\n Backend\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('DevOps')}>\n DevOps\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Design</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('Product Design')}>\n Product Design\n </DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Brand')}>\n Brand\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Item onSelect={() => console.log('Marketing')}>\n Marketing\n </DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={() => console.log('Settings')}>Settings</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Two levels of nesting: Organization → Teams → (Engineering, Design). Deeper nesting is rarely a good UX — prefer splitting into separate screens once the tree grows past two levels.","summary":"Two-level nested submenus inside a parent menu"},{"id":"components-dropdownmenu--submenu-with-disabled-items","name":"Submenu With Disabled Items","snippet":"const SubmenuWithDisabledItems = () => (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button size=\"md\" variant=\"secondary\">\n Document Actions\n <IconKeyboardArrowDown />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content>\n <DropdownMenu.Item onSelect={() => console.log('View')}>View</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Edit')}>Edit</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>\n <IconContentCopy />\n Export as\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item onSelect={() => console.log('PDF')}>PDF</DropdownMenu.Item>\n <DropdownMenu.Item onSelect={() => console.log('Word')}>\n Word Document\n </DropdownMenu.Item>\n <DropdownMenu.Item disabled>Excel (Premium only)</DropdownMenu.Item>\n <DropdownMenu.Item disabled>PowerPoint (Premium only)</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger disabled>\n <IconIosShare />\n Share (Sign in required)\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item>Email</DropdownMenu.Item>\n <DropdownMenu.Item>Link</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n);","description":"Submenu that contains `disabled` `Item`s alongside a fully-disabled `SubTrigger`. Use `disabled` sparingly — prefer hiding unavailable actions outright unless the user needs to see them and understand why.","summary":"Submenu with `disabled` items and a disabled `SubTrigger`"}],"import":"import { Button, DropdownMenu } from \"@agentero/design-system\";","jsDocTags":{},"description":"DropdownMenu is a compound overlay for secondary actions, bulk operations, or navigation shortcuts triggered off a button or icon. Compose it from `Root` / `Trigger` / `Portal` / `Content` and fill the menu with `Item`, `Separator`, `Label`, and — for nested flows — `Sub` / `SubTrigger` / `SubContent`. Built on Radix UI's DropdownMenu primitive, so keyboard navigation, focus trapping, typeahead, and collision detection come for free.","reactDocgenTypescript":{"tags":{"summary":"Compound overlay menu for secondary actions, grouped items, and submenus","see":"{@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu Radix UI DropdownMenu}","example":"```tsx\nimport { DropdownMenu } from '@agentero/design-system/dropdown-menu';\n\n<DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconMoreVert />\n </DropdownMenu.Trigger>\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content side=\"bottom\" align=\"end\">\n <DropdownMenu.Label>Actions</DropdownMenu.Label>\n\n <DropdownMenu.Item onSelect={() => handleEdit()}>\n <IconEdit />\n Edit\n </DropdownMenu.Item>\n\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Share</DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent>\n <DropdownMenu.Item>Email</DropdownMenu.Item>\n <DropdownMenu.Item>Slack</DropdownMenu.Item>\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n\n <DropdownMenu.Separator />\n\n <DropdownMenu.Item\n onSelect={() => handleDelete()}\n disabled={!canDelete}\n >\n <IconDelete />\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n</DropdownMenu.Root>\n```","component":"","namespace":"DropdownMenu"},"filePath":"/home/runner/work/design-system/design-system/src/dropdown-menu/dropdown-menu.tsx","description":"DropdownMenu is the compound component for attaching a menu of secondary\nactions to a button or icon trigger — edit/duplicate/delete rows, account\nmenus, overflow affordances, and nested submenus. Built on Radix UI's\nDropdownMenu primitive, so keyboard navigation, focus trapping, typeahead,\nand viewport-collision detection come for free.\n\nCompose it from `Root` / `Trigger` / `Portal` / `Content` and fill the\nmenu with `Item`, `Separator`, `Label`, and — for nested flows — `Sub` /\n`SubTrigger` / `SubContent`. Wrap content in `Portal` so the menu escapes\nancestor `overflow:hidden` and z-index stacking contexts.\n\nDo **not** use DropdownMenu for primary navigation (use a real nav menu),\nfor single-choice form input (use a `Select`), or for command palettes\n(use a dedicated command component). For radio/checkbox-style toggles,\nuse Radix's `CheckboxItem` / `RadioItem` primitives directly — those\nparts are not exposed here yet.","displayName":"DropdownMenu","methods":[],"props":{},"exportName":"DropdownMenu"}},"components-hovercard":{"id":"components-hovercard","name":"HoverCard.Root","path":"./src/hover-card/hover-card.stories.tsx","stories":[{"id":"components-hovercard--default","name":"Default","snippet":"const Default = () => <HoverCard.Root openDelay={0} closeDelay={0}>\n <HoverCard.Trigger asChild>\n <a\n href=\"https://agentero.com\"\n className=\"text-text-default-base-primary underline\">@agentero\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content>\n <PreviewCard />\n </HoverCard.Content>\n </HoverCard.Portal>\n</HoverCard.Root>;","description":"Default preview revealed on hover; hides again on unhover."},{"id":"components-hovercard--opens-on-focus","name":"Opens On Focus","snippet":"const OpensOnFocus = () => <HoverCard.Root openDelay={0} closeDelay={0}>\n <HoverCard.Trigger asChild>\n <a\n href=\"https://agentero.com\"\n className=\"text-text-default-base-primary underline\">@agentero\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content>\n <PreviewCard />\n </HoverCard.Content>\n </HoverCard.Portal>\n</HoverCard.Root>;","description":"Opens on focus as a supplementary affordance. Note this is not the same as being keyboard-accessible: focus does not move into the card and it closes on blur, so any interactive content inside stays unreachable by keyboard — never put essential actions there."},{"id":"components-hovercard--sides","name":"Sides","snippet":"const Sides = args => (\n <div className=\"grid grid-cols-2 gap-10\">\n {(['top', 'right', 'bottom', 'left'] as const).map(side => (\n <HoverCard.Root key={side} {...args}>\n <HoverCard.Trigger asChild>\n <a href=\"https://agentero.com\" className=\"text-text-default-base-primary underline\">\n {side}\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content side={side}>\n <PreviewCard />\n </HoverCard.Content>\n </HoverCard.Portal>\n </HoverCard.Root>\n ))}\n </div>\n);","description":"`side` sets the preferred placement; it flips on viewport collision."},{"id":"components-hovercard--rich-content","name":"Rich Content","snippet":"const RichContent = () => <HoverCard.Root openDelay={0} closeDelay={0}>\n <HoverCard.Trigger asChild>\n <a\n href=\"https://agentero.com\"\n className=\"text-text-default-base-primary underline\">@agentero\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content className=\"w-80\">\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex gap-3\">\n <Avatar fallback=\"AG\" colorize=\"Agentero\" type=\"initials\" size=\"lg\" />\n <div className=\"flex flex-col gap-1\">\n <p className=\"font-medium text-text-default-base-primary\">Agentero</p>\n <p className=\"text-text-default-base-tertiary\">Insurance marketplace for independent agents.\n </p>\n </div>\n </div>\n <div className=\"flex gap-4 text-text-default-base-secondary\">\n <span>\n <span className=\"font-medium text-text-default-base-primary\">128</span>carriers\n </span>\n <span>\n <span className=\"font-medium text-text-default-base-primary\">50</span>states\n </span>\n </div>\n <a\n href=\"https://agentero.com\"\n className=\"text-text-default-base-primary underline\">View profile\n </a>\n </div>\n </HoverCard.Content>\n </HoverCard.Portal>\n</HoverCard.Root>;","description":"The whole point of a HoverCard over a Tooltip: freely laid-out content that may include its own links and actions. Still supplementary — never the only path to an action."},{"id":"components-hovercard--with-arrow","name":"With Arrow","snippet":"const WithArrow = () => <HoverCard.Root openDelay={0} closeDelay={0}>\n <HoverCard.Trigger asChild>\n <a\n href=\"https://agentero.com\"\n className=\"text-text-default-base-primary underline\">@agentero\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content>\n <PreviewCard />\n <HoverCard.Arrow />\n </HoverCard.Content>\n </HoverCard.Portal>\n</HoverCard.Root>;","description":"An optional `Arrow` points back at the trigger; render it inside `Content`. The arrow is filled with the card background (white), so it only reads against a surface that contrasts with the card — shown here on a muted backdrop."},{"id":"components-hovercard--delays","name":"Delays","snippet":"const Delays = () => (\n <div className=\"flex gap-10\">\n <HoverCard.Root openDelay={700} closeDelay={300}>\n <HoverCard.Trigger asChild>\n <a href=\"https://agentero.com\" className=\"text-text-default-base-primary underline\">\n Default (700ms)\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content>\n <PreviewCard />\n </HoverCard.Content>\n </HoverCard.Portal>\n </HoverCard.Root>\n <HoverCard.Root openDelay={0} closeDelay={0}>\n <HoverCard.Trigger asChild>\n <a href=\"https://agentero.com\" className=\"text-text-default-base-primary underline\">\n Instant (0ms)\n </a>\n </HoverCard.Trigger>\n <HoverCard.Portal>\n <HoverCard.Content>\n <PreviewCard />\n </HoverCard.Content>\n </HoverCard.Portal>\n </HoverCard.Root>\n </div>\n);","description":"`openDelay` / `closeDelay` tune the hover latency. Default is a deliberate `700ms` open so cards don't flash on incidental passes; drop it to `0` for trigger-dense UIs where an instant preview reads as more responsive."}],"import":"import { Avatar, HoverCard } from \"@agentero/design-system\";","jsDocTags":{},"description":"HoverCard reveals rich, sighted-user preview content anchored to a trigger on pointer hover or keyboard focus. Compose it from `Root` / `Trigger` / `Portal` / `Content`.","reactDocgenTypescript":{"tags":{"summary":"Compound overlay card for rich hover previews of an entity","see":"{@link https://www.radix-ui.com/primitives/docs/components/hover-card Radix UI HoverCard}"},"filePath":"/home/runner/work/design-system/design-system/src/hover-card/hover-card.tsx","description":"Rich, sighted-user hover preview anchored to a trigger (profile cards, entity\npreviews) shown on hover/focus, built on Radix HoverCard. Compose from\n`Root` / `Trigger` / `Portal` / `Content`, plus an optional `Arrow`.\n\nPointer-first and NOT keyboard-accessible: focus opens it but focus never\nenters the card — never put essential info or the only path to an action\ninside. Use `Popover`/`DropdownMenu` for that, or `Tooltip` for text hints.","displayName":"HoverCard","methods":[],"props":{},"exportName":"HoverCard"}},"components-loading":{"id":"components-loading","name":"Loading","path":"./src/loading/loading.stories.tsx","stories":[{"id":"components-loading--default","name":"Default","snippet":"const Default = () => <Loading size=\"sm\" />;","description":"The default spinner at `size=\"sm\"` (1em diameter), inheriting the current text color. Matches the out-of-the-box behavior when Loading is dropped into any layout.","summary":"Default spinner at the `sm` size"},{"id":"components-loading--size-sm","name":"Size Sm","snippet":"const SizeSm = () => <Loading size=\"sm\" />;","description":"Small spinner (1em diameter) — the default. Ideal for inline indicators, buttons, and compact layouts where the spinner needs to sit next to text.","summary":"Small 1em spinner for inline indicators"},{"id":"components-loading--size-md","name":"Size Md","snippet":"const SizeMd = () => <Loading size=\"md\" />;","description":"Medium spinner (1.5em diameter). Use for cards, panels, and standalone loading states where the spinner is the primary visual signal.","summary":"Medium 1.5em spinner for cards and panels"},{"id":"components-loading--size-lg","name":"Size Lg","snippet":"const SizeLg = () => <Loading size=\"lg\" />;","description":"Large spinner (2em diameter). Use for page-level or section-level loading where the spinner needs more visual weight.","summary":"Large 2em spinner for page or section loading"},{"id":"components-loading--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '2rem' }}>\n {(['sm', 'md', 'lg'] as const).map(size => (\n <Loading key={size} size={size} />\n ))}\n </div>\n);","description":"All three sizes rendered side by side for visual comparison of the `em`-based scaling. Each spinner inherits the same parent text color.","summary":"Visual comparison of all three spinner sizes"},{"id":"components-loading--inherits-color","name":"Inherits Color","snippet":"const InheritsColor = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '2rem' }}>\n <div className=\"text-text-default-base-primary\">\n <Loading size=\"md\" />\n </div>\n <div className=\"text-text-default-brand-primary\">\n <Loading size=\"md\" />\n </div>\n <div className=\"text-text-default-danger-primary\">\n <Loading size=\"md\" />\n </div>\n </div>\n);","description":"The spinner color tracks the parent `color` (text color) via `border-current`. Wrap Loading in any element with a text color utility — or set `color` on Loading itself — and the spinner adopts that color without extra props.","summary":"Spinner color inherits from the parent text color"},{"id":"components-loading--on-dark-surface","name":"On Dark Surface","snippet":"const OnDarkSurface = () => (\n <div className=\"flex items-center gap-8 rounded-lg bg-bg-button-primary-enable p-8 text-text-default-base-inverse-primary\">\n <Loading size=\"sm\" />\n <Loading size=\"md\" />\n <Loading size=\"lg\" />\n </div>\n);","description":"Spinner on a dark surface to verify `border-current` contrast. The parent sets a light text color, which the spinner inherits so it remains visible against the dark background.","summary":"Spinner on a dark-background surface"}],"import":"import { Loading } from \"@agentero/design-system\";","jsDocTags":{},"description":"Loading displays a circular spinner that indicates an in-progress operation. Use for inline fetch, form submission, or asynchronous task indicators. The spinner inherits its color from the parent `color` and scales with the parent font size via `em`-based size variants (`sm`, `md`, `lg`).","reactDocgenTypescript":{"tags":{"summary":"Circular spinner for in-progress and loading states","example":"<Loading />\n<Loading size=\"lg\" className=\"text-text-default-brand-primary\" />"},"filePath":"/home/runner/work/design-system/design-system/src/loading/loading.tsx","description":"Loading displays a circular spinner that indicates an in-progress operation.\nUse Loading to signal that content is being fetched, a form is submitting,\nor any asynchronous task is running inline with surrounding content.\n\nThe spinner inherits its color from the parent `color` (text color) via\n`border-current`, so it adapts to the surrounding context without extra\nprops. It fades in on mount and spins continuously until unmounted.\n\nAvailable sizes: `sm` (1em, default), `md` (1.5em), and `lg` (2em). Each\nsize is expressed in `em` units so the spinner scales with the parent\nfont size — wrap the Loading (or its ancestor) with the appropriate\n`text-[size]` utility to override the absolute diameter.\n\nExposes `role=\"status\"` and `aria-label=\"Loading\"` for screen readers, and\n`data-slot=\"loading\"` for styling hooks.\n\nDo **not** use Loading as the busy indicator for a button — the Button\ncomponent has its own built-in loading overlay ([Button](?path=/docs/button--docs)).\nFor full-page or skeleton loading states prefer a dedicated skeleton\nplaceholder instead of a spinner.","displayName":"Loading","methods":[],"props":{"size":{"defaultValue":null,"description":"Controls the spinner diameter in `em` units relative to the parent font size.\nDefaults to `'sm'`.\n- `sm` (1em) — inline indicators, buttons, and compact layouts\n- `md` (1.5em) — cards, panels, and standalone loading states\n- `lg` (2em) — page-level or section-level loading","name":"size","declarations":[{"fileName":"design-system/src/loading/loading.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"lg\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"lg\""}]}}},"exportName":"Loading"}},"components-modal":{"id":"components-modal","name":"Modal.Root","path":"./src/modal/modal.stories.tsx","stories":[{"id":"components-modal--default","name":"Default","snippet":"const Default = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Delete carrier</Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Title>Delete carrier</Modal.Title>\n <Modal.Body>\n <p>This will remove the carrier from your agency. This action cannot be undone.</p>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"ghost\">Cancel</Button>\n </Modal.Close>\n <Button variant=\"primary\">Delete</Button>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n);","description":"Trigger-driven modal: open it, then dismiss with the footer's Cancel."},{"id":"components-modal--controlled","name":"Controlled","snippet":"const Controlled = () => <ControlledExample />;","description":"Controlled with `open`/`onOpenChange` — the dominant pattern in both apps. Also closes on `Escape`."},{"id":"components-modal--large","name":"Large","snippet":"const Large = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Open large</Button>\n </Modal.Trigger>\n <Modal.Content size=\"lg\">\n <Modal.Title>Large modal</Modal.Title>\n <Modal.Body>\n <p>Use `lg` for wide content like tables or side-by-side forms.</p>\n </Modal.Body>\n </Modal.Content>\n </Modal.Root>\n);","description":"`size=\"lg\"` widens the surface to 720px; `md` (default) is 540px."},{"id":"components-modal--scrollable-body","name":"Scrollable Body","snippet":"const ScrollableBody = () => (\n <Modal.Root>\n <Modal.Trigger asChild>\n <Button variant=\"secondary\">Open scrollable</Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Title>Terms and conditions</Modal.Title>\n <Modal.Body>\n {Array.from({ length: 24 }, (_, i) => (\n <p key={i} className=\"mb-4\">\n Section {i + 1}: agents shall maintain active licensure in every state where they\n transact business, and notify the marketplace of any change in appointment status.\n </p>\n ))}\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"primary\">Accept</Button>\n </Modal.Close>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n);","description":"Long content scrolls inside `Body` while title and footer stay pinned."}],"import":"import { Button, Modal } from \"@agentero/design-system\";","jsDocTags":{},"description":"Modal is a compound dialog built on Radix UI: `Root` owns the open state, `Content` is the centered surface (`size` md/lg), and `Title`/`Body`/`Footer` structure it. Close it with `Escape`, the overlay, the X button, or a `Modal.Close asChild` around your own button.","reactDocgenTypescript":{"tags":{"summary":"Compound modal dialog over a dimmed overlay","example":"```tsx\n<Modal.Root open={isOpen} onOpenChange={setIsOpen}>\n <Modal.Content size=\"md\">\n <Modal.Title>Delete carrier</Modal.Title>\n <Modal.Body>This action cannot be undone.</Modal.Body>\n <Modal.Footer>\n <Modal.Close asChild>\n <Button variant=\"ghost\">Cancel</Button>\n </Modal.Close>\n <Button onClick={handleDelete}>Delete</Button>\n </Modal.Footer>\n </Modal.Content>\n</Modal.Root>\n```","component":"","namespace":"Modal"},"filePath":"/home/runner/work/design-system/design-system/src/modal/modal.tsx","description":"Modal is the compound component for dialogs that interrupt the flow —\nconfirmations, forms, and detail views. Built on Radix UI Dialog, so focus\ntrapping, scroll locking, `Escape`/overlay dismissal, and ARIA wiring come\nfor free.\n\nCompose `Root` (open state) with `Content` (surface, `size` md/lg), and\nfill it with `Title` (built-in X button), `Body` (scrollable), and `Footer`\n(right-aligned actions). Open it controlled (`open`/`onOpenChange`) or via\n`Trigger`; close from inside with `Close asChild` around your cancel button.","displayName":"Modal","methods":[],"props":{},"exportName":"Modal"}},"components-pagination":{"id":"components-pagination","name":"Pagination","path":"./src/pagination/pagination.stories.tsx","stories":[{"id":"components-pagination--default","name":"Default","snippet":"const Default = () => <Pagination currentPage={1} totalCount={1000} pageSize={10} onPageChange={fn()} />;","description":"Default args playground. The first page of a 1,000-item list paged 10 at a time — renders pages 1–5, an ellipsis, and the last page (100), with the previous-page button disabled because we're on page 1.","summary":"Default args playground for Pagination"},{"id":"components-pagination--few-pages","name":"Few Pages","snippet":"const FewPages = () => <Pagination\n currentPage={2}\n totalCount={30}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Short list whose total pages fit in the visible window — no ellipsis is rendered. Exercises the `totalPageNumbers >= totalPageCount` branch in `getPages`.","summary":"Short page list with no ellipsis collapse"},{"id":"components-pagination--dots-right","name":"Dots Right","snippet":"const DotsRight = () => <Pagination\n currentPage={2}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits near the start of the range — left ellipsis is hidden, right ellipsis is shown, and the last page button anchors the right edge.","summary":"Right-side ellipsis only (current page near start)"},{"id":"components-pagination--dots-left","name":"Dots Left","snippet":"const DotsLeft = () => <Pagination\n currentPage={99}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits near the end of the range — left ellipsis is shown, right ellipsis is hidden, and the first page button anchors the left edge.","summary":"Left-side ellipsis only (current page near end)"},{"id":"components-pagination--dots-both","name":"Dots Both","snippet":"const DotsBoth = () => <Pagination\n currentPage={50}\n totalCount={1000}\n pageSize={10}\n onPageChange={(page: number) => console.log('onPageChange', page)} />;","description":"Current page sits in the middle of the range — both ellipses are visible, with the first and last page buttons anchoring each edge.","summary":"Both ellipses visible (current page in middle)"},{"id":"components-pagination--last-page","name":"Last Page","snippet":"const LastPage = () => <Pagination currentPage={100} totalCount={1000} pageSize={10} onPageChange={fn()} />;","description":"Last page selected — the next-page button is disabled and the active page indicator sits on the trailing number.","summary":"Last page selected with disabled next button"},{"id":"components-pagination--controlled","name":"Controlled","snippet":"const Controlled = ({ totalCount, pageSize }) => {\n const [page, setPage] = useState(1);\n\n return (\n <Pagination\n currentPage={page}\n totalCount={totalCount}\n pageSize={pageSize}\n onPageChange={setPage}\n />\n );\n};","description":"Interactive controlled example. Local `useState` owns the page; clicking a page, previous, or next button updates it so the active page indicator and entries summary follow along.","summary":"Interactive controlled example backed by `useState`"}],"import":"import { Pagination } from \"@agentero/design-system\";","jsDocTags":{},"description":"Pagination is a 1-indexed paged navigation control with previous/next icon buttons, numeric page buttons, and a leading \"X - Y of Z\" entries summary. The page list collapses long ranges with `…` ellipses so the control stays compact regardless of total page count. Use it for lists, tables, or grids that are split across pages.","reactDocgenTypescript":{"tags":{"summary":"1-indexed paged navigation control with prev/next, numeric pages, and entries summary","example":"```tsx\nimport { useState } from 'react';\nimport { Pagination } from '@agentero/design-system/pagination';\n\nconst [page, setPage] = useState(1);\n\n<Pagination\n currentPage={page}\n pageSize={10}\n totalCount={1000}\n onPageChange={setPage}\n/>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/pagination/pagination.tsx","description":"Pagination is a 1-indexed paged navigation control with previous/next icon\nbuttons, numeric page buttons, and a leading \"X - Y of Z\" entries summary.\nThe page list collapses long ranges with `…` ellipses, keeping at most a\nhandful of buttons in view regardless of total page count. Use it whenever\na list, table, or grid is split across pages and the user needs direct\naccess to specific pages (not just prev/next).\n\nThe control short-circuits to `null` when `currentPage === 0` (legacy \"off\"\nsentinel) or when there are no pages to show, so it's safe to mount\nunconditionally above a list that may be empty.\n\nDo **not** use Pagination for infinite-scroll feeds, sub-page-1 indexing\n(the `0` value is reserved as the off-switch), or as a tab/segmented\ncontrol — it's strictly a page-of-pages affordance.","displayName":"Pagination","methods":[],"props":{"onPageChange":{"defaultValue":null,"description":"","name":"onPageChange","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"(page: number) => void"}},"totalCount":{"defaultValue":null,"description":"","name":"totalCount","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"currentPage":{"defaultValue":null,"description":"","name":"currentPage","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"pageSize":{"defaultValue":null,"description":"","name":"pageSize","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"className":{"defaultValue":null,"description":"","name":"className","declarations":[{"fileName":"design-system/src/pagination/pagination.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Pagination"}},"components-progress":{"id":"components-progress","name":"Progress","path":"./src/progress/progress.stories.tsx","stories":[{"id":"components-progress--default","name":"Default","snippet":"const Default = () => <Progress percentage={62} />;","description":"Default near-black bar; exposes `role=\"progressbar\"` with the current value."},{"id":"components-progress--with-label","name":"With Label","snippet":"const WithLabel = () => <Progress percentage={62} label=\"Profile completion\" className=\"text-brand-400\" />;","description":"`label` renders above the bar with the percentage value on the right."},{"id":"components-progress--custom-colors","name":"Custom Colors","snippet":"const CustomColors = args => (\n <div className=\"flex flex-col gap-4\">\n {[\n ['default', undefined],\n ['text-brand-400', 'text-brand-400'],\n ['text-brand-600', 'text-brand-600'],\n ['text-purple-400', 'text-purple-400'],\n ['text-orange-400', 'text-orange-400'],\n ['text-pink-400', 'text-pink-400'],\n ['text-blue-400', 'text-blue-400']\n ].map(([name, className]) => (\n <Progress key={name} {...args} className={className} label={name} />\n ))}\n </div>\n);","description":"The fill follows `currentColor`: recolor it with any `text-*` class via `className`."},{"id":"components-progress--clamped","name":"Clamped","snippet":"const Clamped = () => <Progress percentage={150} />;","description":"Out-of-range values are clamped to 0–100."}],"import":"import { Progress } from \"@agentero/design-system\";","jsDocTags":{},"description":"Progress shows how far a bounded task has advanced. Pass `percentage` (0–100) and optionally a `label` rendered above the bar. The fill paints with `currentColor`, so recolor it with a plain text class — e.g. `className=\"text-brand-400\"`.","reactDocgenTypescript":{"tags":{"summary":"Horizontal progress bar with optional label","example":"```tsx\n<Progress percentage={62} label=\"Profile completion\" className=\"text-brand-400\" />\n```"},"filePath":"/home/runner/work/design-system/design-system/src/progress/progress.tsx","description":"Progress shows how far a bounded task has advanced — wizard steps, upload\nstatus, or a split of a total. Pass `percentage` (0–100) and optionally a\n`label`, which renders above the bar with the percentage value. Built on\nRadix UI Progress, so `role=\"progressbar\"` and `aria-value*` come wired.\n\nThe fill is near-black by default and paints with `currentColor` — recolor\nit from the consumer with a plain text color class.","displayName":"Progress","methods":[],"props":{"percentage":{"defaultValue":null,"description":"Completion percentage, 0–100. Values outside the range are clamped.","name":"percentage","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"number"}},"label":{"defaultValue":null,"description":"Optional label rendered above the bar, with the percentage value on the right.","name":"label","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"aria-label":{"defaultValue":null,"description":"Accessible name when no visible `label` is provided. Defaults to `'Progress'`.","name":"aria-label","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}},"className":{"defaultValue":null,"description":"Extra classes for the bar, merged last. The fill paints with `currentColor`,\nso a text color recolors it (e.g. `text-brand-400`); sizing classes resize\nthe track (e.g. `h-3`).","name":"className","declarations":[{"fileName":"design-system/src/progress/progress.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Progress"}},"components-skeleton":{"id":"components-skeleton","name":"Skeleton","path":"./src/skeleton/skeleton.stories.tsx","stories":[{"id":"components-skeleton--default","name":"Default","snippet":"const Default = () => <Skeleton className=\"h-4 w-40\" />;","description":"Default placeholder box, sized via `className`; hidden from assistive technologies."},{"id":"components-skeleton--text-block","name":"Text Block","snippet":"const TextBlock = () => (\n <div className=\"flex w-80 flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n);","description":"Compose plain skeletons to sketch the loading shape of real content."},{"id":"components-skeleton--list-item","name":"List Item","snippet":"const ListItem = () => (\n <div className=\"flex w-80 items-center gap-3\">\n <Skeleton className=\"size-10 shrink-0 rounded-full\" />\n <div className=\"flex w-full flex-col gap-2\">\n <Skeleton className=\"h-4 w-1/2\" />\n <Skeleton className=\"h-3 w-3/4\" />\n </div>\n </div>\n);","description":"`rounded-full` for avatars; pair with text lines for a list-item placeholder."},{"id":"components-skeleton--card","name":"Card","snippet":"const Card = () => (\n <div className=\"flex w-80 flex-col gap-3 rounded-lg border border-border-default-base-primary p-4\">\n <Skeleton className=\"h-32 w-full rounded-md\" />\n <Skeleton className=\"h-5 w-1/2\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n);","description":"A card-shaped placeholder: media area, title, and body lines."}],"import":"import { Skeleton } from \"@agentero/design-system\";","jsDocTags":{},"description":"Skeleton renders a pulsing placeholder box while content loads. Size and shape it with Tailwind classes to mirror the content it stands in for.","reactDocgenTypescript":{"tags":{"summary":"Pulsing placeholder box for loading content","example":"```tsx\n<Skeleton className=\"h-4 w-30\" />\n```"},"filePath":"/home/runner/work/design-system/design-system/src/skeleton/skeleton.tsx","description":"Skeleton renders a pulsing placeholder box while content loads. Size and\nshape it with Tailwind classes (`h-4 w-30`, `size-10 rounded-full`) to\nmirror the content it stands in for. Hidden from assistive technologies.","displayName":"Skeleton","methods":[],"props":{},"exportName":"Skeleton"}},"components-switch":{"id":"components-switch","name":"Switch","path":"./src/switch/switch.stories.tsx","stories":[{"id":"components-switch--default","name":"Default","snippet":"const Default = () => <Switch size=\"md\" disabled={false} defaultChecked aria-label=\"Toggle setting\" />;"},{"id":"components-switch--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <div className=\"flex items-center gap-6\">\n <div className=\"flex items-center gap-2\">\n <Switch id=\"size-sm\" size=\"sm\" defaultChecked />\n <label htmlFor=\"size-sm\" className=\"text-sm text-text-default-base-primary\">\n Small\n </label>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch id=\"size-md\" size=\"md\" defaultChecked />\n <label htmlFor=\"size-md\" className=\"text-sm text-text-default-base-primary\">\n Medium\n </label>\n </div>\n </div>\n);","description":"The `sm` and `md` sizes compared."},{"id":"components-switch--states","name":"States","snippet":"const States = () => <div className=\"flex items-center gap-6\">\n <Switch size=\"md\" disabled={false} defaultChecked={false} aria-label=\"Off\" />\n <Switch size=\"md\" disabled={false} defaultChecked aria-label=\"On\" />\n</div>;","description":"Unchecked and checked tracks."},{"id":"components-switch--disabled","name":"Disabled","snippet":"const Disabled = () => (\n <div className=\"flex items-center gap-6\">\n <Switch disabled aria-label=\"Disabled off\" />\n <Switch disabled defaultChecked aria-label=\"Disabled on\" />\n </div>\n);","description":"Disabled switches are dimmed and reject pointer and keyboard interaction."},{"id":"components-switch--controlled","name":"Controlled","snippet":"const Controlled = () => {\n const [enabled, setEnabled] = useState(false);\n\n return (\n <div className=\"flex items-center gap-2\">\n <Switch id=\"controlled\" checked={enabled} onCheckedChange={setEnabled} />\n <label htmlFor=\"controlled\" className=\"text-sm text-text-default-base-primary\">\n Notifications {enabled ? 'on' : 'off'}\n </label>\n </div>\n );\n};","description":"Controlled switch wired to component state via `checked` + `onCheckedChange`."},{"id":"components-switch--with-label","name":"With Label","snippet":"const WithLabel = () => (\n <div className=\"flex items-center gap-6\">\n <Switch id=\"with-label\" label=\"Email\" defaultChecked />\n <Switch id=\"with-label-reverse\" label=\"SMS\" reverse />\n </div>\n);","description":"The built-in `label` prop renders an associated text label beside the toggle (wired via `htmlFor`/`id`); `reverse` places the label before the toggle."},{"id":"components-switch--setting-row","name":"Setting Row","snippet":"const SettingRow = () => (\n <div className=\"flex w-80 items-center justify-between gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-4\">\n <div className=\"flex flex-col gap-0.5\">\n <label htmlFor=\"marketing\" className=\"text-sm font-medium text-text-default-base-primary\">\n Marketing emails\n </label>\n <p className=\"text-xs text-text-default-base-secondary\">\n Receive product updates and offers.\n </p>\n </div>\n <Switch id=\"marketing\" defaultChecked />\n </div>\n);","description":"Switch aligned in a labelled settings row."}],"import":"import { Switch } from \"@agentero/design-system\";","jsDocTags":{},"description":"Two-state toggle for a setting that takes effect immediately. Prefer it over a Checkbox for a single boolean that applies instantly, and pair it with a `<label htmlFor>` to give it an accessible name.","reactDocgenTypescript":{"tags":{"summary":"Instant-effect on/off toggle built on Radix Switch","example":"<Switch checked={enabled} onCheckedChange={setEnabled} />\n<Switch id=\"email-notifications\" label=\"Email\" checked={on} onCheckedChange={setOn} />"},"filePath":"/home/runner/work/design-system/design-system/src/switch/switch.tsx","description":"Instant-effect on/off toggle built on Radix Switch. Reach for it over a\nCheckbox when flipping a single boolean that applies immediately.\n\nRenders only the toggle by default — pair it with a `<label htmlFor>` for an\naccessible name. Pass `label` (with an `id`) to render an associated text\nlabel beside the toggle; `reverse` places the label before it.","displayName":"Switch","methods":[],"props":{"asChild":{"defaultValue":null,"description":"","name":"asChild","declarations":[{"fileName":"design-system/node_modules/@radix-ui/react-primitive/dist/index.d.mts","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"reverse":{"defaultValue":null,"description":"","name":"reverse","required":false,"type":{"name":"boolean"}},"size":{"defaultValue":null,"description":"","name":"size","required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\"","value":[{"value":"\"sm\""},{"value":"\"md\""}]}},"label":{"defaultValue":null,"description":"Optional text rendered beside the toggle and associated with it via\n`htmlFor`. Provide an `id` so the association resolves. Omit it to keep\nthe toggle headless and supply your own `<label htmlFor>`.","name":"label","declarations":[{"fileName":"design-system/src/switch/switch.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Switch"}},"components-tabs":{"id":"components-tabs","name":"Tabs.Root","path":"./src/tabs/tabs.stories.tsx","stories":[{"id":"components-tabs--default","name":"Default","snippet":"const Default = () => <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n</Tabs.Root>;","description":"`line` (default): the active tab is marked with an animated underline."},{"id":"components-tabs--enclosed","name":"Enclosed","snippet":"const Enclosed = () => (\n <Tabs.Root variant=\"enclosed\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`enclosed` renders segmented pills; the active tab sits on a raised surface."},{"id":"components-tabs--buttons","name":"Buttons","snippet":"const Buttons = () => (\n <Tabs.Root variant=\"button\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`button` renders button-like tabs, with room for a leading icon per trigger."},{"id":"components-tabs--positions","name":"Positions","snippet":"const Positions = () => (\n <div className=\"flex flex-col gap-8\">\n {(['start', 'center', 'end'] as const).map(position => (\n <Tabs.Root key={position} variant=\"enclosed\" position={position} defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n ))}\n </div>\n);","description":"`position` aligns the tab list within the row (`start` is the default)."},{"id":"components-tabs--full-width","name":"Full Width","snippet":"const FullWidth = () => (\n <Tabs.Root variant=\"enclosed\" position=\"full\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"`position=\"full\"` stretches the tab list to fill the available width."},{"id":"components-tabs--as-child-links","name":"As Child Links","snippet":"const AsChildLinks = () => (\n <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n {TABS.map(({ value, label }) => (\n <Tabs.Trigger key={value} value={value} asChild>\n <a href={`#${value}`}>{label}</a>\n </Tabs.Trigger>\n ))}\n </Tabs.List>\n <TabPanels />\n </Tabs.Root>\n);","description":"Triggers accept `asChild` to render as another element — e.g. a router link. The trigger resets the anchor's default underline, so link-based tabs match the button-based ones."},{"id":"components-tabs--switch-tabs","name":"Switch Tabs","snippet":"const SwitchTabs = () => <Tabs.Root variant=\"line\" defaultValue=\"overview\">\n <Tabs.List>\n <TabItems />\n </Tabs.List>\n <TabPanels />\n</Tabs.Root>;","description":"Selecting a tab reveals its panel and hides the others."}],"import":"import { Tabs } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tabs built on Radix UI's Tabs (keyboard nav, roving focus and ARIA come for free). Compose `Root` with a `List` of `Trigger`s and matching `Content`s, pairing each `Trigger`/`Content` by `value`.","reactDocgenTypescript":{"tags":{},"filePath":"/home/runner/work/design-system/design-system/src/tabs/tabs.tsx","description":"Tabs built on Radix UI's Tabs (keyboard nav, roving focus and ARIA come for\nfree). Compose `Root` with a `List` of `Trigger`s and matching `Content`s,\npairing each `Trigger`/`Content` by `value`.","displayName":"Tabs","methods":[],"props":{},"exportName":"Tabs"}},"components-tag":{"id":"components-tag","name":"Tag","path":"./src/tag/tag.stories.tsx","stories":[{"id":"components-tag--default","name":"Default","snippet":"const Default = () => <Tag color=\"neutral\" variant=\"secondary\" size=\"sm\">Default</Tag>;","description":"Args-controlled playground. Toggle `color`, `variant`, `size`, `pill`, and `truncate` from the Controls panel to explore every visual combination.","summary":"Default args playground for Tag"},{"id":"components-tag--sizes","name":"Sizes","snippet":"const Sizes = () => (\n <Stack>\n {(['xs', 'sm', 'md'] as const).map(size => (\n <Stack gap=\"0.5rem\" key={size}>\n <strong>{size}:</strong>\n <Row>\n <Tag\n size={size}\n color=\"informative\"\n variant=\"secondary\"\n role=\"img\"\n aria-label={`${size} icon only`}>\n <IconAdd />\n </Tag>\n <Tag size={size} color=\"informative\" variant=\"secondary\">\n <IconAdd />\n {size}\n </Tag>\n <Tag size={size} color=\"informative\" variant=\"secondary\">\n {size}\n </Tag>\n </Row>\n </Stack>\n ))}\n </Stack>\n);","description":"The three sizes — `xs` (20px), `sm` (24px, default), and `md` (32px) — each shown icon-only, icon + text, and text-only so the type and icon scale are visible.","summary":"All three sizes across icon-only, icon + text, and text-only"},{"id":"components-tag--styles","name":"Styles","snippet":"const Styles = () => (\n <Stack gap=\"0.5rem\">\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color=\"informative\" variant={variant}>\n {variant}\n </Tag>\n ))}\n </Row>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color=\"informative\" variant={variant} pill>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n);","description":"The `Style` axis: the default rounded corners (top row) versus `pill` fully rounded (bottom row), shown across every fill variant.","summary":"Rounded (default) vs pill"},{"id":"components-tag--interactive","name":"Interactive","snippet":"const Interactive = () => (\n <Row>\n <Tag color=\"informative\" variant=\"secondary\">\n badge\n </Tag>\n <Tag color=\"informative\" variant=\"secondary\" asChild>\n <button type=\"button\">interactive</button>\n </Tag>\n <Tag color=\"informative\" variant=\"secondary\" asChild aria-label=\"add\">\n <button type=\"button\">\n <IconAdd />\n </button>\n </Tag>\n </Row>\n);","description":"Static badge vs interactive Tag. A plain `<span>` badge has no hover; pass `asChild` with a `<button>` (or `<a>`) to make it interactive — that adds the pointer cursor and reveals the hover fill on `:hover`. Hover the middle and right Tags to see it.","summary":"Static badge vs interactive (asChild) hover"},{"id":"components-tag--secondary","name":"Secondary","snippet":"const Secondary = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"secondary\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`secondary` fills with a tinted background plus a matching border, shown across every color.","summary":"`secondary` variant across all colors"},{"id":"components-tag--tertiary","name":"Tertiary","snippet":"const Tertiary = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"tertiary\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`tertiary` (default) fills with a tinted background and no border, shown across every color.","summary":"`tertiary` variant across all colors"},{"id":"components-tag--ghost","name":"Ghost","snippet":"const Ghost = () => (\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"ghost\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n);","description":"`ghost` shows colored text alone with no background or border, across every color.","summary":"`ghost` variant across all colors"},{"id":"components-tag--invisible","name":"Invisible","snippet":"const Invisible = () => (\n <Stack gap=\"0.5rem\">\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"invisible\" color={color}>\n {color}\n </Tag>\n ))}\n </Row>\n <Row>\n {COLORS.map(color => (\n <Tag key={color} variant=\"invisible\" color={color} asChild>\n <button type=\"button\">{color}</button>\n </Tag>\n ))}\n </Row>\n </Stack>\n);","description":"`invisible` stays fully transparent until hovered, then reveals its fill. The top row renders plain `<span>` Tags; the bottom row renders interactive Tags via `asChild` with a `<button>` child.","summary":"`invisible` variant as span and as interactive button"},{"id":"components-tag--with-icon","name":"With Icon","snippet":"const WithIcon = () => (\n <Stack>\n {COLORS.map(color => (\n <Row key={color}>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n tag\n <IconAdd />\n </Tag>\n ))}\n </Row>\n ))}\n </Stack>\n);","description":"Every variant for every color rendered with a leading and trailing icon. Icons are tinted with each color's `icon-tag-*` token.","summary":"Variant × color grid with icons"},{"id":"components-tag--colors","name":"Colors","snippet":"const Colors = () => (\n <div style={{ display: 'flex', gap: '4rem', flexWrap: 'wrap' }}>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color}:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with pill:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant} pill>\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} as button:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant} asChild>\n <button type=\"button\">{variant}</button>\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with icon:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n {variant}\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} with icons:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag key={variant} color={color} variant={variant}>\n <IconAdd />\n {variant}\n <IconAdd />\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n <Stack>\n {COLORS.map(color => (\n <Stack gap=\"0.5rem\" key={color}>\n <strong>{color} icon only:</strong>\n <Row>\n {VARIANTS.map(variant => (\n <Tag\n key={variant}\n color={color}\n variant={variant}\n role=\"img\"\n aria-label={`${color} ${variant}`}>\n <IconAdd />\n </Tag>\n ))}\n </Row>\n </Stack>\n ))}\n </Stack>\n </div>\n);","description":"Full matrix: every variant for every color, repeated as default, as `pill`, as an interactive `asChild` `<button>`, with a single leading icon, with leading + trailing icons, and icon-only.","summary":"Variant × color matrix — default, pill, button, and icon layouts"}],"import":"import { Tag } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tag is a compact semantic label for statuses, categories, counts, and attributes. Pick `color` for meaning, `variant` for fill emphasis, and `size` for prominence. A plain Tag is a static badge; pass `asChild` to make it an interactive link or button, which adds the pointer cursor and hover fill.","reactDocgenTypescript":{"tags":{"summary":"Compact semantic label; renders a static badge `<span>` or, with `asChild`, an interactive element","example":"<Tag color=\"positive\">Active</Tag>\n<Tag asChild color=\"informative\">\n <a href=\"/carriers\">View carriers</a>\n</Tag>"},"filePath":"/home/runner/work/design-system/design-system/src/tag/tag.tsx","description":"Tag is a compact label for statuses, categories, counts, and attributes. As a\nplain `<span>` it reads as a static badge with no hover. Pass `asChild` to\nrender an interactive link or button instead — that adds the pointer cursor\nand the hover fill. Pick `color` for meaning and `variant` for fill emphasis.","displayName":"Tag","methods":[],"props":{"color":{"defaultValue":null,"description":"","name":"color","required":false,"type":{"name":"enum","raw":"\"neutral\" | \"danger\" | \"warning\" | \"creative\" | \"dynamic\" | \"playful\" | \"positive\" | \"informative\"","value":[{"value":"\"neutral\""},{"value":"\"danger\""},{"value":"\"warning\""},{"value":"\"creative\""},{"value":"\"dynamic\""},{"value":"\"playful\""},{"value":"\"positive\""},{"value":"\"informative\""}]}},"size":{"defaultValue":null,"description":"","name":"size","required":false,"type":{"name":"enum","raw":"\"sm\" | \"md\" | \"xs\"","value":[{"value":"\"sm\""},{"value":"\"md\""},{"value":"\"xs\""}]}},"variant":{"defaultValue":null,"description":"","name":"variant","required":false,"type":{"name":"enum","raw":"\"ghost\" | \"secondary\" | \"tertiary\" | \"invisible\"","value":[{"value":"\"ghost\""},{"value":"\"secondary\""},{"value":"\"tertiary\""},{"value":"\"invisible\""}]}},"pill":{"defaultValue":null,"description":"","name":"pill","required":false,"type":{"name":"boolean"}},"truncate":{"defaultValue":null,"description":"","name":"truncate","required":false,"type":{"name":"boolean"}},"asChild":{"defaultValue":null,"description":"Render the single child element instead of a `<span>` (via Radix `Slot`),\nkeeping Tag framework-agnostic. Marks the Tag interactive: adds the pointer\ncursor and the hover fill (a plain `<span>` Tag is a static badge).","name":"asChild","declarations":[{"fileName":"design-system/src/tag/tag.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}}},"exportName":"Tag"}},"components-toast":{"id":"components-toast","name":"Toast","path":"./src/toast/toast.stories.tsx","stories":[{"id":"components-toast--default","name":"Default","snippet":"const Default = () => (\n <div style={{ minHeight: '240px' }}>\n <Button variant=\"secondary\" onClick={() => toast('Hello from Toast')}>\n Show toast\n </Button>\n </div>\n);","description":"Args-controlled playground. Click the button to fire a neutral toast; tweak `position` and `duration` from the Controls panel to preview the provider defaults.","summary":"Default playground for the Toast provider"},{"id":"components-toast--inline","name":"Inline","snippet":"const Inline = () => (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() => toast('Something happened', { description: 'Additional context.' })}>\n Neutral\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() => toast.success('Policy saved', { description: 'Your edits are live.' })}>\n Success\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Failed to save', { description: 'The file could not be processed.' })\n }>\n Error\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.warning('License expiring soon', { description: 'Renew before end of month.' })\n }>\n Warning\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', { description: 'Please wait while we sync your data.' })\n }>\n Info\n </Button>\n </div>\n);","description":"Inline layout (default). Compact treatment — title with an optional description stacked directly below it. The `type` drives the icon color. Use for short acknowledgments that don't need a colored rail.","summary":"Inline layout across all five semantic types"},{"id":"components-toast--expanded","name":"Expanded","snippet":"const Expanded = () => (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast('Something happened', {\n variant: 'expanded',\n description: 'Additional context for the user.'\n })\n }>\n Neutral\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Policy saved', {\n variant: 'expanded',\n description: 'Your changes have been saved successfully.'\n })\n }>\n Success\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Failed to save', {\n variant: 'expanded',\n description: 'The file could not be processed.'\n })\n }>\n Error\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.warning('License expiring soon', {\n variant: 'expanded',\n description: 'Renew before the end of the month to avoid interruption.'\n })\n }>\n Warning\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', {\n variant: 'expanded',\n description: 'Please wait while we sync your data.'\n })\n }>\n Info\n </Button>\n </div>\n);","description":"Expanded layout. Multi-line treatment with a 0.375rem colored left rail that tracks the toast's `type`. Use for feedback that benefits from a description on its own line or a trailing action button.","summary":"Expanded layout across all five semantic types"},{"id":"components-toast--with-action-object","name":"With Action Object","snippet":"const WithActionObject = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.error('Upload failed', {\n variant: 'expanded',\n description: 'The file could not be processed.',\n action: { label: 'Retry', onClick: () => {} }\n })\n }>\n Show toast with action\n </Button>\n);","description":"Toast with a structured `action` object. Passing `{ label, onClick }` renders the built-in secondary Button; the handler runs and the toast auto-dismisses afterward.","summary":"Toast with a structured action button"},{"id":"components-toast--with-action-node","name":"With Action Node","snippet":"const WithActionNode = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast('File uploaded', {\n description: 'document.pdf is ready.',\n action: (\n <Button variant=\"link\" onClick={() => {}}>\n View file\n </Button>\n )\n })\n }>\n Show toast with link action\n </Button>\n);","description":"Toast with a raw-ReactNode `action`. Pass any JSX to render a custom trailing control — a link, a pair of buttons, etc. — when the default secondary Button doesn't fit.","summary":"Toast with a custom ReactNode action"},{"id":"components-toast--with-action-and-cancel","name":"With Action And Cancel","snippet":"const WithActionAndCancel = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Record archived', {\n variant: 'expanded',\n description: 'The record is hidden from the default view.',\n action: { label: 'Undo', onClick: () => {} },\n cancel: { label: 'Dismiss', onClick: () => {} }\n })\n }>\n Show toast with action + cancel\n </Button>\n);","description":"Toast with both `action` and `cancel`. Cancel renders as a ghost Button next to the action; its handler runs and the toast auto-dismisses.","summary":"Toast with an action and a cancel control"},{"id":"components-toast--non-dismissible","name":"Non Dismissible","snippet":"const NonDismissible = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Sync in progress', {\n dismissible: false,\n description: 'Please wait while we sync your data.'\n })\n }>\n Show non-dismissible toast\n </Button>\n);","description":"Non-dismissible toast. Setting `dismissible: false` hides the close button; the toast still auto-dismisses when its `duration` elapses, or programmatically via `toast.dismiss(id)`.","summary":"Non-dismissible toast (no close button)"},{"id":"components-toast--long-duration","name":"Long Duration","snippet":"const LongDuration = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.info('Uploading documents', {\n description: 'This may take a moment.',\n duration: 10_000\n })\n }>\n Show 10s toast\n </Button>\n);","description":"Long-duration toast. `duration` (in ms) overrides the provider default so long-running operations stay visible until they're relevant.","summary":"Toast with a custom `duration`"},{"id":"components-toast--programmatic-dismiss","name":"Programmatic Dismiss","snippet":"const ProgrammaticDismiss = () => {\n let toastId: string | number | undefined;\n return (\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <Button\n variant=\"secondary\"\n onClick={() => {\n toastId = toast.info('Uploading...', { duration: 60_000 });\n }}>\n Start\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => {\n if (toastId !== undefined) toast.dismiss(toastId);\n }}>\n Dismiss\n </Button>\n </div>\n );\n};","description":"Programmatic dismissal. `toast()` returns the toast id, which you can pass to `toast.dismiss(id)` to clear it before its duration elapses.","summary":"Dismiss a toast programmatically via its id"},{"id":"components-toast--with-promise","name":"With Promise","snippet":"const WithPromise = () => {\n const fakeFetch = () =>\n new Promise<string>((resolve, reject) => {\n window.setTimeout(\n () => (Math.random() > 0.5 ? resolve('ok') : reject(new globalThis.Error('nope'))),\n 1500\n );\n });\n return (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.promise(fakeFetch(), {\n loading: 'Saving document…',\n success: 'Document saved',\n error: 'Save failed'\n })\n }>\n Run promise\n </Button>\n );\n};","description":"`toast.promise` wires a toast to an async operation — loading while the promise is pending, success or error when it settles. Useful for save/submit flows where the outcome feeds back into the same toast.","summary":"Wire a toast to an async operation via `toast.promise`"},{"id":"components-toast--custom-icon","name":"Custom Icon","snippet":"const CustomIcon = () => (\n <Button\n variant=\"secondary\"\n onClick={() =>\n toast.success('Sync started', {\n description: 'Data sync is in progress.',\n icon: (\n <svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\" aria-hidden>\n <path d=\"M12 4V1L8 5l4 4V6c3.3 0 6 2.7 6 6 0 1-.3 2-.7 2.8l1.5 1.5C19.5 15 20 13.6 20 12c0-4.4-3.6-8-8-8zm0 14c-3.3 0-6-2.7-6-6 0-1 .3-2 .7-2.8L5.2 7.7C4.5 9 4 10.4 4 12c0 4.4 3.6 8 8 8v3l4-4-4-4v3z\" />\n </svg>\n )\n })\n }>\n Show toast with custom icon\n </Button>\n);","description":"Custom `icon` override. Pass any ReactNode as `icon` to replace the type-based default — helpful when the toast reflects a domain-specific action (e.g., a sync icon for a sync-in-progress toast).","summary":"Override the default type-based icon"}],"import":"import { Button, Toast } from \"@agentero/design-system\";","jsDocTags":{},"description":"Toast renders transient feedback about an outcome — saved, failed, warning, info — without interrupting the user's flow. Mount `<Toast />` once near the app root to register the provider, then call the imperative `toast()` API from anywhere in the tree. Five semantic types (`neutral`, `success`, `error`, `warning`, `info`) × two layouts (`inline`, `expanded`) cover the common feedback patterns.","reactDocgenTypescript":{"tags":{"summary":"Toast provider; mount once near the app root","example":"<Toast />\n<Toast position=\"top-center\" duration={4000} />"},"filePath":"/home/runner/work/design-system/design-system/src/toast/toast.tsx","description":"Toast provider. Renders the sonner `<Toaster />` configured for the\n{@link toast} imperative API. Mount it once near the root of your React\ntree (below any context providers that the toasts need, and above the\nrest of the app) so every call to `toast()` from anywhere in the tree\nrenders into the same surface.\n\nDefaults: `position='bottom-right'`, `duration=5000`. The Toaster is sized\nto `23.75rem` (`[--width:23.75rem]`) and each list item stretches to that\nwidth (`[&>li]:w-full`) so the DS Toast fills the Toaster row rather than\nsonner's 356px default. The provider disables sonner's built-in close\nbutton (`closeButton={false}`) — dismissal is rendered inside each Toast\nby the DS component itself.\n\nDo **not** use Toast for persistent feedback — mount an `Alert` with\n`color=\"success|danger\"` instead. Do **not** use Toast for form\nvalidation errors — render those inline with the form field.","displayName":"Toast","methods":[],"props":{"position":{"defaultValue":{"value":"bottom-right"},"description":"Placement of the toaster on the screen. Defaults to `'bottom-right'`.","name":"position","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"ToastPosition","value":[{"value":"\"top-left\""},{"value":"\"top-center\""},{"value":"\"top-right\""},{"value":"\"bottom-left\""},{"value":"\"bottom-center\""},{"value":"\"bottom-right\""}]}},"duration":{"defaultValue":{"value":"5000"},"description":"Default auto-dismiss duration in ms for toasts fired against this provider. Defaults to `5000`.","name":"duration","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"dir":{"defaultValue":null,"description":"Text direction. Sonner forwards this to the rendered toaster root.","name":"dir","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"auto\" | \"ltr\" | \"rtl\"","value":[{"value":"\"auto\""},{"value":"\"ltr\""},{"value":"\"rtl\""}]}},"gap":{"defaultValue":null,"description":"Gap between stacked toasts, in pixels.","name":"gap","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"offset":{"defaultValue":null,"description":"Offset from the screen edge, in pixels or as a CSS length.","name":"offset","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string | number"}},"expand":{"defaultValue":null,"description":"When `true`, stack expands on hover instead of auto-collapsing.","name":"expand","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"visibleToasts":{"defaultValue":null,"description":"Maximum number of toasts rendered at once before earlier ones dismiss.","name":"visibleToasts","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"hotkey":{"defaultValue":null,"description":"Keyboard shortcut used to focus the toaster.","name":"hotkey","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string[]"}},"richColors":{"defaultValue":null,"description":"When `true`, sonner paints colored backgrounds per type (DS uses its own icon tokens by default).","name":"richColors","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"invert":{"defaultValue":null,"description":"When `true`, flips light/dark theme on the toaster root.","name":"invert","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"className":{"defaultValue":null,"description":"Additional className merged onto the sonner `<Toaster>` root.","name":"className","declarations":[{"fileName":"design-system/src/toast/toast.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Toast"}},"components-tooltip":{"id":"components-tooltip","name":"Tooltip","path":"./src/tooltip/tooltip.stories.tsx","stories":[{"id":"components-tooltip--default","name":"Default","snippet":"const Default = () => <Tooltip content=\"Archive this carrier\" side=\"top\" asChild>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>;","description":"Default hint revealed on hover; hides again on unhover."},{"id":"components-tooltip--opens-on-focus","name":"Opens On Focus","snippet":"const OpensOnFocus = () => <Tooltip content=\"Archive this carrier\" side=\"top\" asChild>\n <Button variant=\"secondary\">Focus me</Button>\n</Tooltip>;","description":"Opens on keyboard focus too, wiring `aria-describedby` on the trigger."},{"id":"components-tooltip--sides","name":"Sides","snippet":"const Sides = () => (\n <div className=\"grid grid-cols-2 gap-6\">\n <Tooltip content=\"Tooltip on top\" side=\"top\" asChild>\n <Button variant=\"secondary\">Top</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the right\" side=\"right\" asChild>\n <Button variant=\"secondary\">Right</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the bottom\" side=\"bottom\" asChild>\n <Button variant=\"secondary\">Bottom</Button>\n </Tooltip>\n <Tooltip content=\"Tooltip on the left\" side=\"left\" asChild>\n <Button variant=\"secondary\">Left</Button>\n </Tooltip>\n </div>\n);","description":"`side` sets the preferred placement; it flips on viewport collision."},{"id":"components-tooltip--as-child","name":"As Child","snippet":"const AsChild = () => <Tooltip content=\"Opens in a new tab\" side=\"bottom\" asChild>\n <a\n href=\"https://agentero.com\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-text-default-base-primary underline\">Docs\n </a>\n</Tooltip>;","description":"`asChild` decorates an already-interactive trigger instead of wrapping it in a `<button>`."},{"id":"components-tooltip--long-content","name":"Long Content","snippet":"const LongContent = () => <Tooltip\n content=\"This carrier requires a completed appointment before you can request quotes for this line of business.\"\n side=\"top\"\n asChild>\n <Button variant=\"secondary\">Why is this disabled?</Button>\n</Tooltip>;","description":"Content wraps at the `32ch` max width."}],"import":"import { Button, Tooltip } from \"@agentero/design-system\";","jsDocTags":{},"description":"Tooltip reveals a short, non-essential hint anchored to a trigger element on hover or focus.","reactDocgenTypescript":{"tags":{"summary":"Hover/focus hint anchored to a trigger element","example":"```tsx\n<Tooltip content=\"Archive this carrier\" asChild>\n <IconButton aria-label=\"Archive\"><IconArchive /></IconButton>\n</Tooltip>\n```"},"filePath":"/home/runner/work/design-system/design-system/src/tooltip/tooltip.tsx","description":"Tooltip reveals a short, non-essential hint anchored to a trigger element on\nhover or focus. Pass the trigger as `children` and the hint as `content`; use\n`asChild` when the trigger is already interactive (a button or link) to avoid\nnesting interactive elements. Don't put essential or interactive content\ninside it — hover-only content is inaccessible to touch and keyboard users.","displayName":"Tooltip","methods":[],"props":{"children":{"defaultValue":null,"description":"The trigger element. Hovering or focusing it reveals the tooltip.","name":"children","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"ReactNode"}},"content":{"defaultValue":null,"description":"The floating hint. Keep it short — labels or hints, not paragraphs.","name":"content","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":true,"type":{"name":"ReactNode"}},"side":{"defaultValue":{"value":"top"},"description":"Preferred side of the trigger; flips on collision. Defaults to `'top'`.","name":"side","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"top\" | \"right\" | \"bottom\" | \"left\"","value":[{"value":"\"top\""},{"value":"\"right\""},{"value":"\"bottom\""},{"value":"\"left\""}]}},"align":{"defaultValue":null,"description":"Preferred alignment against the trigger. Defaults to `'center'`.","name":"align","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"enum","raw":"\"center\" | \"start\" | \"end\"","value":[{"value":"\"center\""},{"value":"\"start\""},{"value":"\"end\""}]}},"sideOffset":{"defaultValue":{"value":"4"},"description":"Distance in pixels between the tooltip and its trigger. Defaults to `4`.","name":"sideOffset","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"asChild":{"defaultValue":{"value":"false"},"description":"Merge Radix's behavior onto an already-interactive child instead of wrapping it in a `<button>`. Defaults to `false`.","name":"asChild","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"hideWhenDetached":{"defaultValue":null,"description":"Hide the tooltip when the trigger is clipped away (e.g. scrolled out of an `overflow` container).","name":"hideWhenDetached","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"boolean"}},"delayDuration":{"defaultValue":{"value":"0"},"description":"Delay in ms before opening on hover. Defaults to `0`; focus always opens instantly.","name":"delayDuration","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"number"}},"className":{"defaultValue":null,"description":"Extra classes for the content surface, merged last.","name":"className","declarations":[{"fileName":"design-system/src/tooltip/tooltip.tsx","name":"TypeLiteral"}],"required":false,"type":{"name":"string"}}},"exportName":"Tooltip"}}},"meta":{"docgen":"react-docgen-typescript","durationMs":3215}}