@instruments/materia-ui 0.4.0 → 0.4.2

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.
Files changed (117) hide show
  1. package/README.md +2 -4
  2. package/agent-docs.md +9 -9
  3. package/dist/components/accordion/accordion-root.d.ts +1 -0
  4. package/dist/components/accordion/accordion-root.js +1 -0
  5. package/dist/components/alert/alert-root.d.ts +1 -0
  6. package/dist/components/alert/alert-root.js +1 -0
  7. package/dist/components/alert-dialog/alert-dialog-root.d.ts +1 -0
  8. package/dist/components/alert-dialog/alert-dialog-root.js +1 -0
  9. package/dist/components/avatar/avatar-root.d.ts +1 -0
  10. package/dist/components/avatar/avatar-root.js +1 -0
  11. package/dist/components/badge/badge-root.d.ts +1 -0
  12. package/dist/components/badge/badge-root.js +1 -0
  13. package/dist/components/calendar/calendar-root.js +1 -0
  14. package/dist/components/carousel/carousel-root.d.ts +1 -0
  15. package/dist/components/carousel/carousel-root.js +1 -0
  16. package/dist/components/chart/chart-root.d.ts +1 -0
  17. package/dist/components/chart/chart-root.js +1 -0
  18. package/dist/components/collapsible/collapsible-root.d.ts +1 -0
  19. package/dist/components/collapsible/collapsible-root.js +1 -0
  20. package/dist/components/combobox/combobox-root.d.ts +1 -0
  21. package/dist/components/combobox/combobox-root.js +1 -0
  22. package/dist/components/command/command-dialog.d.ts +5 -1
  23. package/dist/components/command/command-dialog.js +1 -1
  24. package/dist/components/command/command-input.js +5 -2
  25. package/dist/components/command/command-root.d.ts +1 -0
  26. package/dist/components/command/command-root.js +1 -0
  27. package/dist/components/dialog/dialog-content.d.ts +2 -0
  28. package/dist/components/dialog/dialog-content.js +3 -2
  29. package/dist/components/dialog/dialog-footer.d.ts +2 -0
  30. package/dist/components/dialog/dialog-footer.js +8 -8
  31. package/dist/components/dialog/dialog-root.d.ts +1 -0
  32. package/dist/components/dialog/dialog-root.js +1 -0
  33. package/dist/components/dialog/dialog-title.d.ts +2 -0
  34. package/dist/components/dialog/dialog-title.js +3 -1
  35. package/dist/components/drawer/drawer-root.d.ts +1 -0
  36. package/dist/components/drawer/drawer-root.js +1 -0
  37. package/dist/components/heading/heading-root.d.ts +1 -0
  38. package/dist/components/heading/heading-root.js +1 -0
  39. package/dist/components/input/input-root.d.ts +1 -0
  40. package/dist/components/input/input-root.js +1 -0
  41. package/dist/components/kbd/kbd-root.d.ts +1 -0
  42. package/dist/components/kbd/kbd-root.js +1 -0
  43. package/dist/components/logo/logo-mark.d.ts +1 -1
  44. package/dist/components/logo/logo-mark.js +1 -1
  45. package/dist/components/logotype/logotype-paths.d.ts +1 -1
  46. package/dist/components/logotype/logotype-paths.js +1 -1
  47. package/dist/components/month-year-picker/month-year-picker-root.d.ts +1 -0
  48. package/dist/components/month-year-picker/month-year-picker-root.js +1 -0
  49. package/dist/components/native-select/native-select-root.d.ts +1 -0
  50. package/dist/components/native-select/native-select-root.js +1 -0
  51. package/dist/components/pill/pill-root.d.ts +1 -0
  52. package/dist/components/pill/pill-root.js +1 -0
  53. package/dist/components/popover/popover-root.d.ts +1 -0
  54. package/dist/components/popover/popover-root.js +1 -0
  55. package/dist/components/quantity-control/quantity-control-root.d.ts +1 -0
  56. package/dist/components/quantity-control/quantity-control-root.js +1 -0
  57. package/dist/components/segmented-control/segmented-control-root.js +6 -3
  58. package/dist/components/segmented-control/segmented-control-variants.js +4 -1
  59. package/dist/components/select/select-root.d.ts +1 -0
  60. package/dist/components/select/select-root.js +1 -0
  61. package/dist/components/separator/separator-root.d.ts +1 -0
  62. package/dist/components/separator/separator-root.js +1 -0
  63. package/dist/components/sheet/sheet-root.d.ts +1 -0
  64. package/dist/components/sheet/sheet-root.js +1 -0
  65. package/dist/components/spinner/spinner-root.d.ts +1 -0
  66. package/dist/components/spinner/spinner-root.js +1 -0
  67. package/dist/components/stepper/stepper-root.d.ts +1 -0
  68. package/dist/components/stepper/stepper-root.js +1 -0
  69. package/dist/components/success-tick-ripple/success-tick-ripple-root.d.ts +1 -0
  70. package/dist/components/success-tick-ripple/success-tick-ripple-root.js +1 -0
  71. package/dist/components/swatch-selector/swatch-selector-item.js +4 -1
  72. package/dist/components/switch/switch-root.d.ts +1 -0
  73. package/dist/components/switch/switch-root.js +1 -0
  74. package/dist/components/tag/tag-root.d.ts +1 -0
  75. package/dist/components/tag/tag-root.js +1 -0
  76. package/dist/components/textarea/textarea-root.d.ts +1 -0
  77. package/dist/components/textarea/textarea-root.js +1 -0
  78. package/dist/components/time-slot-picker/time-slot-picker-root.d.ts +1 -0
  79. package/dist/components/time-slot-picker/time-slot-picker-root.js +1 -0
  80. package/dist/components/toast/toast-root.d.ts +1 -0
  81. package/dist/components/toast/toast-root.js +1 -0
  82. package/dist/components/tooltip/tooltip-root.d.ts +1 -0
  83. package/dist/components/tooltip/tooltip-root.js +1 -0
  84. package/dist/compositions/empty-state/empty-state-root.d.ts +1 -0
  85. package/dist/compositions/empty-state/empty-state-root.js +1 -0
  86. package/dist/compositions/file-upload/file-upload-dropzone.d.ts +1 -0
  87. package/dist/compositions/file-upload/file-upload-dropzone.js +1 -0
  88. package/dist/data/decision-trees.d.ts +1 -1
  89. package/dist/data/decision-trees.js +1 -1
  90. package/dist/data/docs-manifest.d.ts +2 -0
  91. package/dist/data/docs-manifest.js +235 -68
  92. package/dist/styles/index.css +0 -1
  93. package/dist/tokens/segmented.d.ts +8 -0
  94. package/dist/tokens/segmented.js +26 -0
  95. package/dist/utils/cn-theme.js +1 -1
  96. package/lint/README.md +6 -2
  97. package/lint/doctrine-rules.mjs +4 -4
  98. package/lint/oxlint/index.d.mts +13 -5
  99. package/lint/oxlint/index.mjs +26 -0
  100. package/lint/oxlint/no-naked-element.mjs +123 -65
  101. package/lint/oxlint/no-render-layout-as.mjs +61 -56
  102. package/lint/scan-classes.d.mts +58 -5
  103. package/lint/scan-classes.mjs +274 -38
  104. package/lint/tokens.d.mts +16 -8
  105. package/lint/tokens.mjs +13 -3
  106. package/lint/type-case.d.mts +16 -8
  107. package/lint/type-case.mjs +17 -0
  108. package/package.json +27 -14
  109. package/lint/oxlint/fixtures/allowed.tsx +0 -12
  110. package/lint/oxlint/fixtures/fixture.config.mjs +0 -29
  111. package/lint/oxlint/fixtures/invalid.tsx +0 -24
  112. package/lint/oxlint/fixtures/layout-only.tsx +0 -26
  113. package/lint/oxlint/fixtures/render-as-invalid.tsx +0 -11
  114. package/lint/oxlint/fixtures/render-as-valid.tsx +0 -14
  115. package/lint/oxlint/fixtures/valid.tsx +0 -18
  116. package/lint/oxlint/no-naked-element.test.ts +0 -155
  117. package/lint/oxlint/no-render-layout-as.test.ts +0 -81
package/README.md CHANGED
@@ -127,10 +127,8 @@ Point your agent at the guidance from your own `AGENTS.md` or `CLAUDE.md`:
127
127
 
128
128
  ```md
129
129
  ## UI
130
- Build UI with @instruments/materia-ui. Before writing any UI, read
131
- node_modules/@instruments/materia-ui/agent-docs.md and follow its rules.
132
- Never invent a prop; if a component can't do what you need, say so.
133
- Run `materia-ui-lint --all <dirs>` on what you changed.
130
+
131
+ Build UI with @instruments/materia-ui. Before writing any UI, read node_modules/@instruments/materia-ui/agent-docs.md and follow its rules. Never invent a prop; if a component can't do what you need, say so. Run `materia-ui-lint --all <dirs>` on what you changed.
134
132
  ```
135
133
 
136
134
  ## Build an app
package/agent-docs.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @instruments/materia-ui - agent guidance
2
2
 
3
- <!-- GENERATED by scripts/generate-agent-docs.mjs - DO NOT EDIT.
3
+ <!-- GENERATED by scripts/generate-agent-docs.ts - DO NOT EDIT.
4
4
  Author `@bestPractice` JSDoc tags on public exports; regenerate with
5
5
  `pnpm generate:agent-docs`. -->
6
6
 
@@ -133,7 +133,7 @@ Honours `prefers-reduced-motion` (renders nothing - a static ring would be loude
133
133
 
134
134
  `@instruments/materia-ui/components/box`
135
135
 
136
- The escape hatch: a raw host element with a `className`, still checked for tokens-only classes. Box renders the chosen {@link LayoutElement} with no layout opinions of its own (no margin, width, or padding, unlike Container), so it suits decorative wrappers that a styled primitive would visually break. Reach for it only when no styled primitive fits; the `className` you pass is governed by the same tokens-only scan as everything else. RSC-safe.
136
+ The escape hatch: a raw host element with a `className`, still checked for tokens-only classes. Box renders the chosen `LayoutElement` with no layout opinions of its own (no margin, width, or padding, unlike Container), so it suits decorative wrappers that a styled primitive would visually break. Reach for it only when no styled primitive fits; the `className` you pass is governed by the same tokens-only scan as everything else. RSC-safe.
137
137
 
138
138
  - `Box` renders the chosen element with no layout opinions (no margin/width/padding, unlike `Container`); use it as a neutral wrapper when a styled primitive would interfere.
139
139
  - Use `as="span"` for a decorative inline wrapper; reach for `Box` only when no styled primitive fits - its `className` is still checked for tokens-only classes.
@@ -1514,7 +1514,7 @@ A generic section header: an optional eyebrow label, a `Heading` title, an optio
1514
1514
 
1515
1515
  A single-select, always-one-selected control that switches between a small set of visible options - a view or mode switcher rendered as a pill of segments. Built on Base UI ToggleGroup (single-select) but kept permanently selected: re-clicking the active segment never clears it.
1516
1516
 
1517
- Compose it from {@link SegmentedControlItem}s; shared `size` / `fullWidth` / active state flow to them through context. Controlled via `value`, or uncontrolled via `defaultValue`. Items scroll horizontally with a trailing fade hint when they overflow.
1517
+ Compose it from `SegmentedControlItem`s; shared `size` / `fullWidth` / active state flow to them through context. Controlled via `value`, or uncontrolled via `defaultValue`. Items scroll horizontally with a trailing fade hint when they overflow.
1518
1518
 
1519
1519
  - One value is always selected - the active segment cannot be deselected; for deselectable or multi-select sets reach for ToggleGroup.
1520
1520
  - Switching visible content panels is Tabs; navigating URLs is TabNavigation - SegmentedControl is an input that selects a value or mode.
@@ -1606,7 +1606,7 @@ Honours `prefers-reduced-motion` - renders nothing when motion is reduced (a sta
1606
1606
 
1607
1607
  `@instruments/materia-ui/compositions/sidebar`
1608
1608
 
1609
- The sidebar shell. Reads open/collapsed state from {@link useSidebar}, so it must render inside a {@link SidebarProvider}.
1609
+ The sidebar shell. Reads open/collapsed state from `useSidebar`, so it must render inside a `SidebarProvider`.
1610
1610
 
1611
1611
  Adapts by viewport and `collapsible`: an animated docked shell on desktop, a slide-in `Sheet` on mobile, or a static column when `collapsible="none"`.
1612
1612
 
@@ -1641,7 +1641,7 @@ The desktop (md+) top header beside the sidebar. Fixed by default, its left offs
1641
1641
 
1642
1642
  The primary interactive row of a sidebar menu - a leading icon plus label, optional suffix icon and keyboard-shortcut hint.
1643
1643
 
1644
- Collapses to icon-only when the sidebar collapses (swapping in `collapsedIcon` /`collapsedContent` and revealing the `tooltip`), unless `forceExpanded`. Reads collapsed state from {@link useSidebar}; pass `render` to render a `<Link>` or other element as the button.
1644
+ Collapses to icon-only when the sidebar collapses (swapping in `collapsedIcon` /`collapsedContent` and revealing the `tooltip`), unless `forceExpanded`. Reads collapsed state from `useSidebar`; pass `render` to render a `<Link>` or other element as the button.
1645
1645
 
1646
1646
  - In an icon-collapsible sidebar use `size="xl"`: the icon rail is sized for an `xl` row, so its collapsed square centres on the rail and the icon stays put as the sidebar folds.
1647
1647
 
@@ -1798,7 +1798,7 @@ Progressive streaming answer with settle-gated chrome.
1798
1798
 
1799
1799
  `@instruments/materia-ui/components/sub-navigation`
1800
1800
 
1801
- Vertical secondary navigation for page subsections and settings-like layouts; the `<nav>` landmark wrapping a {@link SubNavigationList} of links.
1801
+ Vertical secondary navigation for page subsections and settings-like layouts; the `<nav>` landmark wrapping a `SubNavigationList` of links.
1802
1802
 
1803
1803
  - Reach for `SubNavigation` for a vertical in-page section/settings menu; horizontal router tabs are `TabNavigation`, the app-chrome shell is `Sidebar`.
1804
1804
  - Fill it with a `SubNavigationList` of links - it already renders the `<nav>` landmark, so don't nest it inside another `<nav>`.
@@ -1838,7 +1838,7 @@ Chips paint the darkening overlay on every fill and draw the double-ring selecti
1838
1838
 
1839
1839
  `@instruments/materia-ui/compositions/swatch-fan`
1840
1840
 
1841
- A fanned stack of {@link Swatch} tiles: a fixed three-card editorial fan or an interactive N-tile splay.
1841
+ A fanned stack of `Swatch` tiles: a fixed three-card editorial fan or an interactive N-tile splay.
1842
1842
 
1843
1843
  Pass 3 `items` with `interaction="breathe"` for the editorial fan (Figma geometry, `variant` spread/stack, white 3px mount via `bordered`); pass N `items` with `interaction="hover-fan"` for the interactive splay-on-hover with pointer tilt. `bordered={false}` swaps the white mount for the 1px hairline tile.
1844
1844
 
@@ -1862,7 +1862,7 @@ Row of selectable circular color/image swatches with single-select behaviour, bu
1862
1862
 
1863
1863
  Row of selectable color/image swatches with controlled single selection, built on Base UI ToggleGroup: the row is one tab stop and the arrow keys move between swatches.
1864
1864
 
1865
- Shares the selected `value`, `onValueChange`, and `size` with its {@link SwatchSelectorItem} children through context.
1865
+ Shares the selected `value`, `onValueChange`, and `size` with its `SwatchSelectorItem` children through context.
1866
1866
 
1867
1867
  - Pair `SwatchSelector` with `SwatchSelectorItem` children - it shares `value`/`onValueChange`/`size` through context, so items need no individual wiring.
1868
1868
  - Prefer `SwatchGroup` when the row is a single-choice form control needing radio roles and form submission; `SwatchSelector` is a row of pressed-state toggle buttons.
@@ -2030,7 +2030,7 @@ Inside a `ToggleGroup` it is the group's item, as in Base UI: give it a `value`,
2030
2030
 
2031
2031
  `@instruments/materia-ui/components/toggle-group`
2032
2032
 
2033
- A literal group of {@link Toggle}s: several two-state pressable buttons that share one selection, laid out `joined` (a seamless segmented row), `separated`, or `wrap`ped. Built on Base UI ToggleGroup - by default one item is pressed at a time (radio-like), `multiple` makes it checkbox-like; `value` is always an array. The `Toggle`s inside take `size` / `radius` / `variant` from the group through context.
2033
+ A literal group of `Toggle`s: several two-state pressable buttons that share one selection, laid out `joined` (a seamless segmented row), `separated`, or `wrap`ped. Built on Base UI ToggleGroup - by default one item is pressed at a time (radio-like), `multiple` makes it checkbox-like; `value` is always an array. The `Toggle`s inside take `size` / `radius` / `variant` from the group through context.
2034
2034
 
2035
2035
  - An always-one-selected mode switcher is `SegmentedControl`, not `ToggleGroup` - reach here for multi-select toolbars and deselectable choice chips.
2036
2036
  - `layout="wrap"` + `required` (without `multiple`) is the wizard choice-chip recipe.
@@ -10,6 +10,7 @@ import { accordionRootVariants } from "../accordion/accordion-variants.js";
10
10
  * @bestPractice Leave `multiple` off for one-at-a-time panels or set it to allow several open at once; `value`/`defaultValue` are arrays either way, and an open item can always be closed again.
11
11
  * @bestPractice Reach for `Collapsible` instead when there is a single expandable region - `Accordion` is for a set of grouped items keyed by `value`.
12
12
  * @bestPractice Children must be `AccordionItem`s (each with `AccordionTrigger`/`AccordionContent`); the item's `value` is what `value`/`defaultValue` match against.
13
+ * @keywords disclosure, faq, expander
13
14
  * @category data
14
15
  */
15
16
  declare const AccordionRoot: <Value = string>({ className, variant, indicator, children, ...rest }: Omit<AccordionPrimitive.Root.Props<Value>, "className"> & VariantProps<typeof accordionRootVariants> & {
@@ -14,6 +14,7 @@ import { accordionRootVariants } from "../accordion/accordion-variants.js";
14
14
  * @bestPractice Leave `multiple` off for one-at-a-time panels or set it to allow several open at once; `value`/`defaultValue` are arrays either way, and an open item can always be closed again.
15
15
  * @bestPractice Reach for `Collapsible` instead when there is a single expandable region - `Accordion` is for a set of grouped items keyed by `value`.
16
16
  * @bestPractice Children must be `AccordionItem`s (each with `AccordionTrigger`/`AccordionContent`); the item's `value` is what `value`/`defaultValue` match against.
17
+ * @keywords disclosure, faq, expander
17
18
  * @category data
18
19
  */
19
20
  const AccordionRoot = ({ className, variant = "default", indicator = "arrow", children, ...rest }) => {
@@ -15,6 +15,7 @@ declare const alertVariants: (props?: ({
15
15
  * @bestPractice Use `Alert` for a persistent inline message block; a transient, auto-dismissing notification is a toast (`Toaster` and `toast()` from `components/toast`).
16
16
  * @bestPractice Compose `AlertTitle` / `AlertDescription` as children and render a direct-child `<svg>` for the auto-detected icon column; `tone="danger"` recolours for errors.
17
17
  * @bestPractice It renders `role="alert"`, so AT announces it on mount - keep it a notice, not a container for heavy interactive UI.
18
+ * @keywords callout, notice, banner, message
18
19
  * @category feedback
19
20
  */
20
21
  declare const Alert: ({ className, tone, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) => React.JSX.Element;
@@ -25,6 +25,7 @@ const alertVariants = cva("text-paragraph-sm relative grid w-full grid-cols-[0_1
25
25
  * @bestPractice Use `Alert` for a persistent inline message block; a transient, auto-dismissing notification is a toast (`Toaster` and `toast()` from `components/toast`).
26
26
  * @bestPractice Compose `AlertTitle` / `AlertDescription` as children and render a direct-child `<svg>` for the auto-detected icon column; `tone="danger"` recolours for errors.
27
27
  * @bestPractice It renders `role="alert"`, so AT announces it on mount - keep it a notice, not a container for heavy interactive UI.
28
+ * @keywords callout, notice, banner, message
28
29
  * @category feedback
29
30
  */
30
31
  const Alert = ({ className, tone, ...props }) => (_jsx("div", { className: cn(alertVariants({ tone }), className), "data-component": "alert", "data-slot": "alert", role: "alert", ...props }));
@@ -9,6 +9,7 @@ import type * as React from "react";
9
9
  * @bestPractice Use `AlertDialog` only for a confirm / warn / destructive decision (Cancel + Action); a general modal form or details view is a `Dialog`.
10
10
  * @bestPractice Route every destructive confirmation here, never a plain `Dialog` - unlike `Dialog` it won't dismiss on outside-click / Esc, so the choice stays deliberate.
11
11
  * @bestPractice Give the destructive `AlertDialogAction` `tone="danger"` and keep the safe escape as `AlertDialogCancel`.
12
+ * @keywords confirm, confirmation, modal
12
13
  * @category overlays
13
14
  */
14
15
  declare const AlertDialog: ({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) => React.JSX.Element;
@@ -10,6 +10,7 @@ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog
10
10
  * @bestPractice Use `AlertDialog` only for a confirm / warn / destructive decision (Cancel + Action); a general modal form or details view is a `Dialog`.
11
11
  * @bestPractice Route every destructive confirmation here, never a plain `Dialog` - unlike `Dialog` it won't dismiss on outside-click / Esc, so the choice stays deliberate.
12
12
  * @bestPractice Give the destructive `AlertDialogAction` `tone="danger"` and keep the safe escape as `AlertDialogCancel`.
13
+ * @keywords confirm, confirmation, modal
13
14
  * @category overlays
14
15
  */
15
16
  const AlertDialog = ({ ...props }) => (_jsx(AlertDialogPrimitive.Root, { "data-component": "alert-dialog", "data-slot": "alert-dialog", ...props }));
@@ -34,6 +34,7 @@ export type AvatarRootProps = AvatarPrimitive.Root.Props & {
34
34
  * @bestPractice Always render an `AvatarFallback` child - it is what shows while the image loads and when `src` is missing or errors; an image-only avatar renders empty on failure.
35
35
  * @bestPractice Give `AvatarImage` a meaningful `alt`; the visual is decorative only when the fallback initials already convey the identity.
36
36
  * @bestPractice Keep the default `radius="full"` for people; use a squared `radius` for brand/entity logos so they read as objects, not users.
37
+ * @keywords profile picture, user, initials
37
38
  * @category data
38
39
  */
39
40
  export declare const AvatarRoot: ({ className, size: sizeProp, radius, withRing, ringColor, ...props }: AvatarRootProps) => import("react").JSX.Element;
@@ -46,6 +46,7 @@ const RADIUS_CLASS = {
46
46
  * @bestPractice Always render an `AvatarFallback` child - it is what shows while the image loads and when `src` is missing or errors; an image-only avatar renders empty on failure.
47
47
  * @bestPractice Give `AvatarImage` a meaningful `alt`; the visual is decorative only when the fallback initials already convey the identity.
48
48
  * @bestPractice Keep the default `radius="full"` for people; use a squared `radius` for brand/entity logos so they read as objects, not users.
49
+ * @keywords profile picture, user, initials
49
50
  * @category data
50
51
  */
51
52
  export const AvatarRoot = ({ className, size: sizeProp = "base", radius = "full", withRing = false, ringColor, ...props }) => {
@@ -65,6 +65,7 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, Omit<V
65
65
  * @bestPractice For a notification count use `mode="count"` (circular, tabular figures), not `radius="full"` + manual classes.
66
66
  * @bestPractice A standalone count needs an `accessibleLabel` ("3 unread"); inside an icon-only trigger, mark the badge `aria-hidden` and fold the count into the trigger's `aria-label`.
67
67
  * @bestPractice A badge overlapping a corner of another surface takes `ring` so a 2px `background`-coloured ring separates it from what's beneath; set it only where the badge truly overlaps, and the page surface should be `background`.
68
+ * @keywords chip, status, label
68
69
  * @category feedback
69
70
  */
70
71
  export declare const Badge: ({ className, tone, size, emphasis, radius, asInput, render, disabled, testid, label, value, icon, iconPlacement, focused, hovered, loading, loadingLabel, mode, accessibleLabel, ring, children, ...props }: BadgeProps) => React.JSX.Element;
@@ -69,6 +69,7 @@ const getOptionalPillProps = ({ asInput, disabled, emphasis, tone, }) => {
69
69
  * @bestPractice For a notification count use `mode="count"` (circular, tabular figures), not `radius="full"` + manual classes.
70
70
  * @bestPractice A standalone count needs an `accessibleLabel` ("3 unread"); inside an icon-only trigger, mark the badge `aria-hidden` and fold the count into the trigger's `aria-label`.
71
71
  * @bestPractice A badge overlapping a corner of another surface takes `ring` so a 2px `background`-coloured ring separates it from what's beneath; set it only where the badge truly overlaps, and the page surface should be `background`.
72
+ * @keywords chip, status, label
72
73
  * @category feedback
73
74
  */
74
75
  export const Badge = ({ className, tone, size, emphasis, radius = "rounded", asInput, render, disabled, testid, label, value, icon, iconPlacement = "start", focused, hovered, loading = false, loadingLabel, mode = "default", accessibleLabel, ring = false, children, ...props }) => {
@@ -46,6 +46,7 @@ const CalendarDayButton = ({ modifiers, ...props }) => {
46
46
  * @bestPractice Set `mode` explicitly (`single` | `multiple` | `range`) - the selection value shape and `onSelect` signature change with it; a `range` handler never fires in `single` mode.
47
47
  * @bestPractice Restrict selectable dates with react-day-picker matchers (`disabled`/`hidden`/`startMonth`/`endMonth`), not by filtering after the user clicks.
48
48
  * @bestPractice Use `Calendar` for an inline date grid; for a compact click-to-open date field, wrap it in a `Popover` behind a `Button`/`Input` trigger.
49
+ * @keywords date picker, datepicker, date
49
50
  * @category forms
50
51
  */
51
52
  const Calendar = ({ className, classNames, showOutsideDays = true, ...props }) => (_jsx(DayPicker, { className: cn("w-fit p-3", className), classNames: {
@@ -50,6 +50,7 @@ interface CarouselProps {
50
50
  * @bestPractice Set `slidesToShow` to show multiple items at once (it drives each item's `flex-basis`); don't fake a multi-item view with CSS widths on `CarouselItem`.
51
51
  * @bestPractice Tune scroll behaviour via `opts` (Embla options like `loop`/`align`) and enable `wheelScroll`/`freeScroll` deliberately - free-scroll drops snap points, so pass `slideCount` if the dots miscount.
52
52
  * @bestPractice Give a descriptive `aria-label` when the region isn't self-evidently "Carousel" (e.g. `"Product images"`).
53
+ * @keywords slideshow, gallery, swiper
53
54
  * @category data
54
55
  */
55
56
  declare const Carousel: ({ "aria-label": ariaLabel, opts, plugins, orientation, slidesToShow, slideCount, freeScroll, wheelScroll, className, children, }: CarouselProps) => import("react").JSX.Element;
@@ -29,6 +29,7 @@ const useCarousel = () => {
29
29
  * @bestPractice Set `slidesToShow` to show multiple items at once (it drives each item's `flex-basis`); don't fake a multi-item view with CSS widths on `CarouselItem`.
30
30
  * @bestPractice Tune scroll behaviour via `opts` (Embla options like `loop`/`align`) and enable `wheelScroll`/`freeScroll` deliberately - free-scroll drops snap points, so pass `slideCount` if the dots miscount.
31
31
  * @bestPractice Give a descriptive `aria-label` when the region isn't self-evidently "Carousel" (e.g. `"Product images"`).
32
+ * @keywords slideshow, gallery, swiper
32
33
  * @category data
33
34
  */
34
35
  const Carousel = ({ "aria-label": ariaLabel = "Carousel", opts, plugins, orientation = "horizontal", slidesToShow = 1, slideCount, freeScroll = false, wheelScroll = false, className, children, }) => {
@@ -12,6 +12,7 @@ import type { ChartConfig } from "./chart-context.js";
12
12
  *
13
13
  * @bestPractice Colour every series through `config` (`{ desktop: { label, color } }`) and reference `var(--color-<key>)` on the marks - never hardcode a hex on a `Bar` / `Line`; that keeps light/dark theming and the legend/tooltip swatches in sync.
14
14
  * @bestPractice Reach for `Chart` only to render a recharts data visualization; for a static value + delta use `Stat`, and for a progress bar use `Progress`.
15
+ * @keywords graph, plot, visualisation, visualization
15
16
  * @category data
16
17
  */
17
18
  export declare const Chart: ({ id, className, children, config, initialDimension, ...props }: React.ComponentProps<"div"> & {
@@ -19,6 +19,7 @@ const INITIAL_DIMENSION = { width: 320, height: 200 };
19
19
  *
20
20
  * @bestPractice Colour every series through `config` (`{ desktop: { label, color } }`) and reference `var(--color-<key>)` on the marks - never hardcode a hex on a `Bar` / `Line`; that keeps light/dark theming and the legend/tooltip swatches in sync.
21
21
  * @bestPractice Reach for `Chart` only to render a recharts data visualization; for a static value + delta use `Stat`, and for a progress bar use `Progress`.
22
+ * @keywords graph, plot, visualisation, visualization
22
23
  * @category data
23
24
  */
24
25
  export const Chart = ({ id, className, children, config, initialDimension = INITIAL_DIMENSION, ...props }) => {
@@ -6,6 +6,7 @@ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
6
6
  * @bestPractice Use `Collapsible` for a single expand/collapse region; reach for `Accordion` when you have a set of grouped items where selecting one can close the others.
7
7
  * @bestPractice Compose `CollapsibleTrigger` + `CollapsibleContent` inside it - a bare child won't expand.
8
8
  * @bestPractice Drive it uncontrolled with `defaultOpen`; only lift to `open`/`onOpenChange` when external state must sync (e.g. persisting the open panel).
9
+ * @keywords disclosure, show more, expander
9
10
  * @category data
10
11
  */
11
12
  export declare const Collapsible: ({ ...props }: CollapsiblePrimitive.Root.Props) => import("react").JSX.Element;
@@ -8,6 +8,7 @@ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
8
8
  * @bestPractice Use `Collapsible` for a single expand/collapse region; reach for `Accordion` when you have a set of grouped items where selecting one can close the others.
9
9
  * @bestPractice Compose `CollapsibleTrigger` + `CollapsibleContent` inside it - a bare child won't expand.
10
10
  * @bestPractice Drive it uncontrolled with `defaultOpen`; only lift to `open`/`onOpenChange` when external state must sync (e.g. persisting the open panel).
11
+ * @keywords disclosure, show more, expander
11
12
  * @category data
12
13
  */
13
14
  export const Collapsible = ({ ...props }) => (_jsx(CollapsiblePrimitive.Root, { "data-component": "collapsible", "data-slot": "collapsible", ...props }));
@@ -48,6 +48,7 @@ export interface ComboboxProps {
48
48
  * @bestPractice `onValueChange` fires with `""` when the current selection is toggled off - treat empty string as "cleared", not as a real value.
49
49
  * @bestPractice For lists in the hundreds+, pass `virtualization={{ enabled: true }}` so only visible rows mount instead of every option.
50
50
  * @bestPractice Provide `items` as `{ label, value }[]` - the visible text comes from `label` while selection is tracked by `value`.
51
+ * @keywords autocomplete, typeahead, searchable select
51
52
  * @category forms
52
53
  */
53
54
  export declare const Combobox: ({ items, value, onValueChange, placeholder, buttonClassName, contentClassName, disabled, size, virtualization, "data-testid": dataTestId, }: ComboboxProps) => React.JSX.Element;
@@ -80,6 +80,7 @@ const scrollHighlightIntoView = (virtualizer, item, { reason, index }) => {
80
80
  * @bestPractice `onValueChange` fires with `""` when the current selection is toggled off - treat empty string as "cleared", not as a real value.
81
81
  * @bestPractice For lists in the hundreds+, pass `virtualization={{ enabled: true }}` so only visible rows mount instead of every option.
82
82
  * @bestPractice Provide `items` as `{ label, value }[]` - the visible text comes from `label` while selection is tracked by `value`.
83
+ * @keywords autocomplete, typeahead, searchable select
83
84
  * @category forms
84
85
  */
85
86
  export const Combobox = ({ items, value, onValueChange, placeholder = "Select…", buttonClassName, contentClassName, disabled, size = "xl", virtualization, "data-testid": dataTestId, }) => {
@@ -10,7 +10,11 @@ export type CommandDialogProps<Item> = Omit<React.ComponentProps<typeof Dialog>,
10
10
  description?: string;
11
11
  /** Extra class names applied to the `DialogContent` wrapper. */
12
12
  className?: string;
13
- /** Whether to show the dialog close button. */
13
+ /**
14
+ * Whether to show the dialog close button. Off by default: the button sits
15
+ * over the search field, and Escape or a click outside closes the palette.
16
+ * @default false
17
+ */
14
18
  showCloseButton?: boolean;
15
19
  /** Extra props applied to the rendered dialog content element. */
16
20
  contentProps?: Omit<React.ComponentProps<typeof DialogContent>, "children"> & React.HTMLAttributes<HTMLDivElement> & {
@@ -14,7 +14,7 @@ import { Command } from "../command/command-root.js";
14
14
  * @bestPractice Pass `filter={null}` to list the entries unfiltered, for example when the application filters them itself.
15
15
  */
16
16
  export const CommandDialog = (props) => {
17
- const { title = "Command Palette", description = "Search for a command to run…", children, className, showCloseButton = true, contentProps, filter, groups: _groups, items: _items, limit, mode, ...dialogProps } = props;
17
+ const { title = "Command Palette", description = "Search for a command to run…", children, className, showCloseButton = false, contentProps, filter, groups: _groups, items: _items, limit, mode, ...dialogProps } = props;
18
18
  // Narrow on `props` so the palette receives exactly one of items or groups.
19
19
  const source = props.groups === undefined
20
20
  ? { items: props.items }
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Autocomplete as AutocompletePrimitive } from "@base-ui/react/autocomplete";
4
- import { focusRing } from "@instruments/materia-ui/tokens/focus-ring";
5
4
  import { cn } from "@instruments/materia-ui/utils/cn";
6
5
  import { Search } from "lucide-react";
7
6
  import { Icon } from "../icon.js";
@@ -9,4 +8,8 @@ import { Icon } from "../icon.js";
9
8
  * CommandInput renders the search field for a Command; typing filters the list.
10
9
  * Import from "@instruments/materia-ui/components/command".
11
10
  */
12
- export const CommandInput = ({ className, ...props }) => (_jsxs(AutocompletePrimitive.InputGroup, { className: "flex h-9 items-center gap-2 border-b px-3", "data-component": "command-input-wrapper", "data-slot": "command-input-wrapper", children: [_jsx(Icon, { className: "shrink-0 opacity-50", icon: Search, size: "xs" }), _jsx(AutocompletePrimitive.Input, { className: cn(focusRing(), "placeholder:text-muted-foreground text-paragraph-sm flex h-10 w-full rounded-lg bg-transparent py-3 disabled:cursor-not-allowed disabled:opacity-50", "focus-visible:ring-inset", className), "data-component": "command-input", "data-slot": "command-input", ...props })] }));
11
+ export const CommandInput = ({ className, ...props }) => (_jsxs(AutocompletePrimitive.InputGroup, { className: "flex h-9 items-center gap-2 border-b px-3", "data-component": "command-input-wrapper", "data-slot": "command-input-wrapper", children: [_jsx(Icon, { className: "shrink-0 opacity-50", icon: Search, size: "xs" }), _jsx(AutocompletePrimitive.Input, { className: cn(
12
+ // No ring: the field is the palette's only input and always holds
13
+ // focus, so the caret marks it; a ring would collide with the
14
+ // dialog's rounded top edge.
15
+ "placeholder:text-muted-foreground text-paragraph-sm flex h-full w-full bg-transparent outline-none disabled:cursor-not-allowed disabled:opacity-50", className), "data-component": "command-input", "data-slot": "command-input", ...props })] }));
@@ -35,6 +35,7 @@ export type CommandProps<Item> = Omit<AutocompletePrimitive.Root.Props<Item>, "c
35
35
  * @bestPractice Pass the entries as `items`, or as titled `groups`, and render them with a function child of `CommandList`; filtering only sees those entries, so items written as static JSX are not filtered.
36
36
  * @bestPractice Act on a choice with `CommandItem`'s `onClick`, which fires for a pointer click and for `Enter` on the highlighted item.
37
37
  * @bestPractice A plain click-triggered action menu is `DropdownMenu`; a remembered selection is `Combobox`.
38
+ * @keywords command palette, spotlight, cmd+k, quick search
38
39
  * @category navigation
39
40
  */
40
41
  export declare const Command: <Item>(props: CommandProps<Item>) => React.JSX.Element;
@@ -14,6 +14,7 @@ import { cn } from "@instruments/materia-ui/utils/cn";
14
14
  * @bestPractice Pass the entries as `items`, or as titled `groups`, and render them with a function child of `CommandList`; filtering only sees those entries, so items written as static JSX are not filtered.
15
15
  * @bestPractice Act on a choice with `CommandItem`'s `onClick`, which fires for a pointer click and for `Enter` on the highlighted item.
16
16
  * @bestPractice A plain click-triggered action menu is `DropdownMenu`; a remembered selection is `Combobox`.
17
+ * @keywords command palette, spotlight, cmd+k, quick search
17
18
  * @category navigation
18
19
  */
19
20
  export const Command = (props) => {
@@ -10,6 +10,8 @@ type DialogContentProps = Omit<React.ComponentProps<typeof DialogPrimitive.Popup
10
10
  * such as a product's quick view.
11
11
  */
12
12
  export type DialogContentSize = "default" | "viewport";
13
+ /** Panel geometry per size. Exported for the Figma generator in `figma/`. */
14
+ export declare const DIALOG_SIZE_CLASSES: Record<DialogContentSize, string | undefined>;
13
15
  export interface DialogContentExtras {
14
16
  /** Extra classes for the overlay behind the dialog. */
15
17
  overlayClassName?: string;
@@ -6,7 +6,8 @@ import { OVERLAY_PANEL_ANIMATION, OVERLAY_PANEL_CENTERED, } from "../../tokens/o
6
6
  import { Button } from "../button.js";
7
7
  import { DialogOverlay } from "../dialog/dialog-overlay.js";
8
8
  import { DialogPortal } from "../dialog/dialog-portal.js";
9
- const SIZE_CLASSES = {
9
+ /** Panel geometry per size. Exported for the Figma generator in `figma/`. */
10
+ export const DIALOG_SIZE_CLASSES = {
10
11
  default: undefined,
11
12
  viewport: "h-dialog-viewport w-dialog-viewport max-w-dialog-viewport sm:max-w-dialog-viewport md:h-dialog-viewport-md md:max-h-dialog-viewport md:w-dialog-viewport-md",
12
13
  };
@@ -20,4 +21,4 @@ const SIZE_CLASSES = {
20
21
  *
21
22
  * @bestPractice Use `size="viewport"` for a dialog that holds a whole view (a product quick view, a large preview); it sets only the geometry, so lay the panel out as a column with a scrolling body yourself or compose `QuickView`.
22
23
  */
23
- export const DialogContent = ({ className, children, showCloseButton = true, overlayClassName, size = "default", ...props }) => (_jsxs(DialogPortal, { "data-component": "dialog-portal", "data-slot": "dialog-portal", children: [_jsx(DialogOverlay, { className: overlayClassName }), _jsxs(DialogPrimitive.Popup, { className: cn(OVERLAY_PANEL_ANIMATION, OVERLAY_PANEL_CENTERED, SIZE_CLASSES[size], className), "data-component": "dialog-content", "data-size": size, "data-slot": "dialog-content", ...props, children: [children, showCloseButton ? (_jsx(DialogPrimitive.Close, { render: _jsx(Button, { "aria-label": "Close", className: "absolute top-5 right-5", "data-component": "dialog-close", "data-slot": "dialog-close", emphasis: "soft", icon: XIcon, size: "icon-sm", tone: "neutral" }) })) : null] })] }));
24
+ export const DialogContent = ({ className, children, showCloseButton = true, overlayClassName, size = "default", ...props }) => (_jsxs(DialogPortal, { "data-component": "dialog-portal", "data-slot": "dialog-portal", children: [_jsx(DialogOverlay, { className: overlayClassName }), _jsxs(DialogPrimitive.Popup, { className: cn(OVERLAY_PANEL_ANIMATION, OVERLAY_PANEL_CENTERED, DIALOG_SIZE_CLASSES[size], className), "data-component": "dialog-content", "data-size": size, "data-slot": "dialog-content", ...props, children: [children, showCloseButton ? (_jsx(DialogPrimitive.Close, { render: _jsx(Button, { "aria-label": "Close", className: "absolute top-5 right-5", "data-component": "dialog-close", "data-slot": "dialog-close", emphasis: "soft", icon: XIcon, size: "icon-sm", tone: "neutral" }) })) : null] })] }));
@@ -3,6 +3,8 @@ interface DialogFooterProps extends React.ComponentProps<"div"> {
3
3
  /** Button alignment within the footer. @default "end" */
4
4
  justify?: "end" | "between";
5
5
  }
6
+ /** Footer classes for a `justify`. Exported for the Figma generator in `figma/`. */
7
+ export declare const dialogFooterClasses: (justify: NonNullable<DialogFooterProps["justify"]>) => string;
6
8
  /**
7
9
  * Action row at the bottom of the panel; stacks buttons vertically on mobile and
8
10
  * lays them out horizontally from `sm` up. Render inside `<DialogContent>`.
@@ -1,16 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cn } from "@instruments/materia-ui/utils/cn";
3
3
  import { Flex } from "../flex.js";
4
+ /** Footer classes for a `justify`. Exported for the Figma generator in `figma/`. */
5
+ export const dialogFooterClasses = (justify) => cn("mt-2 flex-col-reverse gap-2 sm:flex-row", justify === "between" ? "sm:-ml-1.5 sm:justify-between" : "sm:justify-end",
6
+ // Concentric nesting: pull the actions 6px onto the trailing edges so a
7
+ // default pill button (h-9, r 18px) sits 18px from the rounded-modal (36px)
8
+ // corner - 36−18 - its curve parallel to the boundary.
9
+ // `between` also pulls the leading edge so the left action nestles too.
10
+ "sm:-mr-1.5 sm:-mb-1.5");
4
11
  /**
5
12
  * Action row at the bottom of the panel; stacks buttons vertically on mobile and
6
13
  * lays them out horizontally from `sm` up. Render inside `<DialogContent>`.
7
14
  * Import from "@instruments/materia-ui/components/dialog".
8
15
  */
9
- export const DialogFooter = ({ className, justify = "end", ...props }) => (_jsx(Flex, { className: cn("mt-2 flex-col-reverse gap-2 sm:flex-row", justify === "between"
10
- ? "sm:-ml-1.5 sm:justify-between"
11
- : "sm:justify-end",
12
- // Concentric nesting: pull the actions 6px onto the trailing edges so a
13
- // default pill button (h-9, r 18px) sits 18px from the rounded-modal (36px)
14
- // corner - 36−18 - its curve parallel to the boundary.
15
- // `between` also pulls the leading edge so the left action nestles too.
16
- "sm:-mr-1.5 sm:-mb-1.5", className), "data-component": "dialog-footer", "data-slot": "dialog-footer", ...props }));
16
+ export const DialogFooter = ({ className, justify = "end", ...props }) => (_jsx(Flex, { className: cn(dialogFooterClasses(justify), className), "data-component": "dialog-footer", "data-slot": "dialog-footer", ...props }));
@@ -6,6 +6,7 @@ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
6
6
  * @bestPractice Use `Dialog` for a centred blocking modal (form, details, footer actions); a destructive confirm is `AlertDialog`, an anchored non-blocking panel is `Popover`.
7
7
  * @bestPractice A panel that slides in from a screen edge is a `Sheet` (or `Drawer` for a drag-to-dismiss bottom sheet), not a `Dialog`.
8
8
  * @bestPractice Always render a `DialogTitle` (wrap in `sr-only` if visually hidden) so the modal is announced; `DialogContent` uses the 36px `--radius-modal` corner.
9
+ * @keywords modal, popup, lightbox
9
10
  * @category overlays
10
11
  */
11
12
  export declare const Dialog: (props: DialogPrimitive.Root.Props<unknown>) => import("react").ReactElement;
@@ -7,6 +7,7 @@ import { makeOverlayRoot } from "../overlay-primitives.js";
7
7
  * @bestPractice Use `Dialog` for a centred blocking modal (form, details, footer actions); a destructive confirm is `AlertDialog`, an anchored non-blocking panel is `Popover`.
8
8
  * @bestPractice A panel that slides in from a screen edge is a `Sheet` (or `Drawer` for a drag-to-dismiss bottom sheet), not a `Dialog`.
9
9
  * @bestPractice Always render a `DialogTitle` (wrap in `sr-only` if visually hidden) so the modal is announced; `DialogContent` uses the 36px `--radius-modal` corner.
10
+ * @keywords modal, popup, lightbox
10
11
  * @category overlays
11
12
  */
12
13
  export const Dialog = makeOverlayRoot(DialogPrimitive.Root, {
@@ -1,5 +1,7 @@
1
1
  import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
2
2
  import type * as React from "react";
3
+ /** Title classes. Exported for the Figma generator in `figma/`. */
4
+ export declare const DIALOG_TITLE_CLASSES = "text-subheading font-semibold text-balance";
3
5
  /**
4
6
  * Accessible heading that labels the dialog (wired to the panel's
5
7
  * `aria-labelledby`). Render inside `<DialogHeader>`.
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
3
3
  import { cn } from "@instruments/materia-ui/utils/cn";
4
+ /** Title classes. Exported for the Figma generator in `figma/`. */
5
+ export const DIALOG_TITLE_CLASSES = "text-subheading font-semibold text-balance";
4
6
  /**
5
7
  * Accessible heading that labels the dialog (wired to the panel's
6
8
  * `aria-labelledby`). Render inside `<DialogHeader>`.
7
9
  * Import from "@instruments/materia-ui/components/dialog".
8
10
  */
9
- export const DialogTitle = ({ className, ...props }) => (_jsx(DialogPrimitive.Title, { className: cn("text-subheading font-semibold text-balance", className), "data-component": "dialog-title", "data-slot": "dialog-title", ...props }));
11
+ export const DialogTitle = ({ className, ...props }) => (_jsx(DialogPrimitive.Title, { className: cn(DIALOG_TITLE_CLASSES, className), "data-component": "dialog-title", "data-slot": "dialog-title", ...props }));
@@ -16,6 +16,7 @@ export declare const DrawerContext: import("react").Context<DrawerContextValue>;
16
16
  * @bestPractice Drawer is the touch-first slide-up panel - reach for `Sheet` for desktop side panels and `Dialog` for centred modals.
17
17
  * @bestPractice Always render a `DrawerTitle` inside `DrawerContent` (sr-only if visually hidden) - the underlying primitive uses it for `aria-labelledby`.
18
18
  * @bestPractice Pass `container` to scope the drawer and its scrim to a bounded element instead of the viewport (the mobile-nav overlay pattern).
19
+ * @keywords bottom sheet
19
20
  * @category overlays
20
21
  */
21
22
  export declare const Drawer: ({ container, ...props }: ComponentProps<typeof DrawerPrimitive.Root> & {
@@ -15,6 +15,7 @@ export const DrawerContext = createContext({});
15
15
  * @bestPractice Drawer is the touch-first slide-up panel - reach for `Sheet` for desktop side panels and `Dialog` for centred modals.
16
16
  * @bestPractice Always render a `DrawerTitle` inside `DrawerContent` (sr-only if visually hidden) - the underlying primitive uses it for `aria-labelledby`.
17
17
  * @bestPractice Pass `container` to scope the drawer and its scrim to a bounded element instead of the viewport (the mobile-nav overlay pattern).
18
+ * @keywords bottom sheet
18
19
  * @category overlays
19
20
  */
20
21
  export const Drawer = ({ container, ...props }) => {
@@ -30,6 +30,7 @@ type HeadingProps = Omit<React.ComponentProps<"h1">, "size"> & {
30
30
  *
31
31
  * @bestPractice Set `level` (`h1`–`h6`) for the document outline and `size` for visual scale independently - don't pick a tag just to get a size; a small-looking heading can still be an `h2`.
32
32
  * @bestPractice Keep one `h1` per page and don't skip levels for styling; use `size` (responsive-capable) to make a lower-level heading look larger.
33
+ * @keywords title, headline
33
34
  * @category typography
34
35
  */
35
36
  declare const Heading: ({ level, size, className, ...props }: HeadingProps) => React.JSX.Element;
@@ -41,6 +41,7 @@ const SIZE_CLASSES = {
41
41
  *
42
42
  * @bestPractice Set `level` (`h1`–`h6`) for the document outline and `size` for visual scale independently - don't pick a tag just to get a size; a small-looking heading can still be an `h2`.
43
43
  * @bestPractice Keep one `h1` per page and don't skip levels for styling; use `size` (responsive-capable) to make a lower-level heading look larger.
44
+ * @keywords title, headline
44
45
  * @category typography
45
46
  */
46
47
  const Heading = ({ level = "2", size, className, ...props }) => {
@@ -32,6 +32,7 @@ export type InputProps = WithTestId<Omit<React.ComponentProps<"input">, "size">>
32
32
  * @bestPractice Inside a `Field`, let invalid state cascade - omit `hasError`; pass `hasError` only to force error styling on a standalone `Input`. An invalid `Field` keeps `aria-invalid` on its control even with `hasError={false}`.
33
33
  * @bestPractice Give every `Input` an associated label - inside a `Field` a `FieldLabel` targets it with no ids to wire; standalone, point a `Label`'s `htmlFor` at its `id`. A placeholder is not an accessible name.
34
34
  * @bestPractice `size` defaults to `"xl"` (48px); pass a responsive object like `{ base: "sm", md: "xl" }` rather than swapping components per breakpoint.
35
+ * @keywords text field, textbox, text input
35
36
  * @category forms
36
37
  */
37
38
  export declare const Input: ({ className, testId, size, radius, hasError, focused, ...props }: InputProps) => React.JSX.Element;
@@ -25,6 +25,7 @@ import { DEFAULT_INPUT_SIZE, INPUT_SIZE_CLASSES, standaloneInputVariants, } from
25
25
  * @bestPractice Inside a `Field`, let invalid state cascade - omit `hasError`; pass `hasError` only to force error styling on a standalone `Input`. An invalid `Field` keeps `aria-invalid` on its control even with `hasError={false}`.
26
26
  * @bestPractice Give every `Input` an associated label - inside a `Field` a `FieldLabel` targets it with no ids to wire; standalone, point a `Label`'s `htmlFor` at its `id`. A placeholder is not an accessible name.
27
27
  * @bestPractice `size` defaults to `"xl"` (48px); pass a responsive object like `{ base: "sm", md: "xl" }` rather than swapping components per breakpoint.
28
+ * @keywords text field, textbox, text input
28
29
  * @category forms
29
30
  */
30
31
  export const Input = ({ className, testId, size, radius, hasError, focused, ...props }) => {
@@ -65,6 +65,7 @@ type KbdProps = Omit<React.ComponentProps<"kbd">, "size"> & VariantProps<typeof
65
65
  *
66
66
  * @bestPractice Wrap multi-key chords in `KbdGroup` and set `size` on the group - children inherit it via context, so you size the combo once.
67
67
  * @bestPractice It renders a semantic `<kbd>`; reserve it for keyboard keys/shortcuts, not as a generic small-label chip (that's `Badge`).
68
+ * @keywords keyboard shortcut, hotkey
68
69
  * @category typography
69
70
  */
70
71
  declare const Kbd: ({ className, size, tone, emphasis, ...props }: KbdProps) => import("react").JSX.Element;
@@ -124,6 +124,7 @@ const kbdVariants = cva("pointer-events-none inline-flex w-fit items-center just
124
124
  *
125
125
  * @bestPractice Wrap multi-key chords in `KbdGroup` and set `size` on the group - children inherit it via context, so you size the combo once.
126
126
  * @bestPractice It renders a semantic `<kbd>`; reserve it for keyboard keys/shortcuts, not as a generic small-label chip (that's `Badge`).
127
+ * @keywords keyboard shortcut, hotkey
127
128
  * @category typography
128
129
  */
129
130
  const Kbd = ({ className, size, tone, emphasis, ...props }) => {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Material Bank mark's geometry, in one place: `Logo` draws it and
3
- * `scripts/generate-brand-assets.mjs` writes the shipped SVG files from it.
3
+ * `scripts/generate-brand-assets.ts` writes the shipped SVG files from it.
4
4
  * Plain constants with no imports, so a Node script can load this file
5
5
  * directly.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Material Bank mark's geometry, in one place: `Logo` draws it and
3
- * `scripts/generate-brand-assets.mjs` writes the shipped SVG files from it.
3
+ * `scripts/generate-brand-assets.ts` writes the shipped SVG files from it.
4
4
  * Plain constants with no imports, so a Node script can load this file
5
5
  * directly.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Material Bank logotype geometry, in one place: the `Logotype` component
3
- * draws it and `scripts/generate-brand-assets.mjs` writes the shipped SVG files
3
+ * draws it and `scripts/generate-brand-assets.ts` writes the shipped SVG files
4
4
  * from it. Plain constants with no imports, so a Node script can load this file
5
5
  * directly.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Material Bank logotype geometry, in one place: the `Logotype` component
3
- * draws it and `scripts/generate-brand-assets.mjs` writes the shipped SVG files
3
+ * draws it and `scripts/generate-brand-assets.ts` writes the shipped SVG files
4
4
  * from it. Plain constants with no imports, so a Node script can load this file
5
5
  * directly.
6
6
  *
@@ -41,6 +41,7 @@ export interface MonthYearPickerProps {
41
41
  * @bestPractice `value` is a union - a `Date`, `"beyond"`, or `"unsure"` - so branch on the string sentinels in `onChange` before treating it as a date.
42
42
  * @bestPractice Enable the "I'm not sure" escape hatch with `showUnsure` (off by default); `"unsure"`/`"beyond"` only ever arrive when their toggles are shown.
43
43
  * @bestPractice Bound the range with `yearsAhead` (from the current year); it auto-advances and commits once both month and year are chosen, so don't add your own "next" control.
44
+ * @keywords date picker, date, month, year
44
45
  * @category forms
45
46
  */
46
47
  export declare const MonthYearPicker: ({ value, onChange, yearsAhead, beyondLabel, showUnsure, unsureLabel, size, variant, monthLabel, yearLabel, className, }: MonthYearPickerProps) => import("react").JSX.Element;
@@ -60,6 +60,7 @@ const SpecialOptions = ({ isBeyond, isUnsure, onBeyondSelect, onUnsureSelect, re
60
60
  * @bestPractice `value` is a union - a `Date`, `"beyond"`, or `"unsure"` - so branch on the string sentinels in `onChange` before treating it as a date.
61
61
  * @bestPractice Enable the "I'm not sure" escape hatch with `showUnsure` (off by default); `"unsure"`/`"beyond"` only ever arrive when their toggles are shown.
62
62
  * @bestPractice Bound the range with `yearsAhead` (from the current year); it auto-advances and commits once both month and year are chosen, so don't add your own "next" control.
63
+ * @keywords date picker, date, month, year
63
64
  * @category forms
64
65
  */
65
66
  export const MonthYearPicker = ({ value, onChange, yearsAhead = 10, beyondLabel, showUnsure = false, unsureLabel = "I'm not sure", size = "lg", variant = "default", monthLabel = "Choose month", yearLabel = "Choose year", className, }) => {