@instruments/materia-ui 0.4.5 → 0.4.7

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 (127) hide show
  1. package/agent-docs.md +4 -0
  2. package/dist/components/accordion/accordion-variants.js +1 -0
  3. package/dist/components/alert/alert-root.js +1 -0
  4. package/dist/components/anchor/anchor-root.js +1 -0
  5. package/dist/components/aspect-ratio/aspect-ratio-root.d.ts +7 -3
  6. package/dist/components/aspect-ratio/aspect-ratio-root.js +5 -3
  7. package/dist/components/avatar/avatar-badge.d.ts +1 -1
  8. package/dist/components/avatar/avatar-fallback.d.ts +1 -1
  9. package/dist/components/avatar/avatar-root.d.ts +1 -1
  10. package/dist/components/avatar/avatar-status.d.ts +2 -1
  11. package/dist/components/badge/badge-button.d.ts +1 -0
  12. package/dist/components/badge/badge-button.js +1 -0
  13. package/dist/components/badge/badge-root.d.ts +4 -1
  14. package/dist/components/breadcrumb/breadcrumb-root.d.ts +1 -0
  15. package/dist/components/button/button-variants.js +7 -0
  16. package/dist/components/button-group/button-group-root.js +4 -0
  17. package/dist/components/card/card-root.d.ts +1 -0
  18. package/dist/components/card/card-root.js +1 -0
  19. package/dist/components/checkbox-card/checkbox-card-root.d.ts +1 -1
  20. package/dist/components/checkbox-field/checkbox-field-root.d.ts +4 -1
  21. package/dist/components/context-menu/context-menu-checkbox-item.d.ts +1 -1
  22. package/dist/components/context-menu/context-menu-content.d.ts +1 -1
  23. package/dist/components/context-menu/context-menu-item.d.ts +1 -1
  24. package/dist/components/context-menu/context-menu-radio-item.d.ts +1 -1
  25. package/dist/components/context-menu/context-menu-separator.d.ts +2 -2
  26. package/dist/components/context-menu/context-menu-separator.js +1 -1
  27. package/dist/components/context-menu/context-menu-sub-trigger.d.ts +1 -1
  28. package/dist/components/dot/dot-root.js +1 -0
  29. package/dist/components/drawer/drawer-root.d.ts +1 -0
  30. package/dist/components/dropdown-menu/dropdown-menu-checkbox-item.d.ts +1 -1
  31. package/dist/components/dropdown-menu/dropdown-menu-content.d.ts +1 -1
  32. package/dist/components/dropdown-menu/dropdown-menu-item.d.ts +1 -1
  33. package/dist/components/dropdown-menu/dropdown-menu-radio-item.d.ts +1 -1
  34. package/dist/components/dropdown-menu/dropdown-menu-separator.d.ts +2 -2
  35. package/dist/components/dropdown-menu/dropdown-menu-separator.js +1 -1
  36. package/dist/components/dropdown-menu/dropdown-menu-sub-trigger.d.ts +1 -1
  37. package/dist/components/empty/empty-root.js +1 -0
  38. package/dist/components/expand-button/expand-button-root.js +1 -0
  39. package/dist/components/field/field-error.d.ts +1 -0
  40. package/dist/components/field/field-variants.js +1 -0
  41. package/dist/components/icon-box/icon-box-root.js +4 -0
  42. package/dist/components/identified-surface.d.ts +5 -0
  43. package/dist/components/input/input-variants.js +1 -0
  44. package/dist/components/input-card/input-card-root.d.ts +3 -0
  45. package/dist/components/input-group/input-group-button.d.ts +7 -3
  46. package/dist/components/item/item-group.js +1 -0
  47. package/dist/components/item/item-media.d.ts +8 -0
  48. package/dist/components/item/item-media.js +1 -0
  49. package/dist/components/item/item-root.d.ts +1 -0
  50. package/dist/components/item/item-root.js +1 -0
  51. package/dist/components/kbd/kbd-root.js +2 -0
  52. package/dist/components/media-frame/media-frame-root.d.ts +2 -0
  53. package/dist/components/media-frame/media-frame-root.js +2 -0
  54. package/dist/components/menu-item/menu-item-variants.js +5 -0
  55. package/dist/components/menu-parts-types.d.ts +82 -0
  56. package/dist/components/menu-parts-types.js +1 -0
  57. package/dist/components/menu-parts.d.ts +3 -66
  58. package/dist/components/menubar/menubar-checkbox-item.d.ts +1 -1
  59. package/dist/components/menubar/menubar-content.d.ts +1 -1
  60. package/dist/components/menubar/menubar-item.d.ts +1 -1
  61. package/dist/components/menubar/menubar-radio-item.d.ts +1 -1
  62. package/dist/components/menubar/menubar-separator.d.ts +2 -2
  63. package/dist/components/menubar/menubar-separator.js +1 -1
  64. package/dist/components/menubar/menubar-sub-trigger.d.ts +1 -1
  65. package/dist/components/phone-input/phone-input-root.js +2 -0
  66. package/dist/components/pill/pill-root.d.ts +1 -0
  67. package/dist/components/pill/pill-variants.js +3 -0
  68. package/dist/components/popover/popover-root.d.ts +2 -0
  69. package/dist/components/progress/progress-root.d.ts +2 -0
  70. package/dist/components/scroll-frame/scroll-frame-root.d.ts +8 -2
  71. package/dist/components/segmented-control/segmented-control-root.d.ts +8 -2
  72. package/dist/components/select/select-content.d.ts +1 -0
  73. package/dist/components/select/select-trigger.d.ts +9 -1
  74. package/dist/components/select/select-trigger.js +1 -1
  75. package/dist/components/sidepanel/sidepanel-header.d.ts +4 -0
  76. package/dist/components/sub-navigation/sub-navigation-link.d.ts +1 -0
  77. package/dist/components/swatch/swatch-root.d.ts +2 -0
  78. package/dist/components/swatch/swatch-root.js +2 -0
  79. package/dist/components/swatch/swatch-tile.d.ts +2 -1
  80. package/dist/components/swatch/swatch-tile.js +1 -1
  81. package/dist/components/tab-navigation/tab-navigation-link.d.ts +1 -0
  82. package/dist/components/tabs/tabs-panel.d.ts +4 -0
  83. package/dist/components/tabs/tabs-variants.js +4 -0
  84. package/dist/components/thinking-loader/thinking-loader-counter.d.ts +2 -0
  85. package/dist/components/thinking-loader/thinking-loader-icon.d.ts +2 -0
  86. package/dist/components/thinking-loader/thinking-loader-step.d.ts +2 -0
  87. package/dist/components/toggle/toggle-root.js +2 -0
  88. package/dist/components/voice/voice-error-popover.d.ts +2 -0
  89. package/dist/components/voice/voice-pill.d.ts +2 -0
  90. package/dist/compositions/attribute-card.d.ts +1 -0
  91. package/dist/compositions/card-grid/card-grid-rows.d.ts +13 -0
  92. package/dist/compositions/data-grid/data-grid-checkbox.d.ts +8 -0
  93. package/dist/compositions/data-grid/data-grid-expand.d.ts +1 -0
  94. package/dist/compositions/data-grid/data-grid-filterable-header.d.ts +1 -0
  95. package/dist/compositions/data-grid/data-grid-types.d.ts +6 -0
  96. package/dist/compositions/data-grid-column-header/data-grid-column-header-root.d.ts +5 -0
  97. package/dist/compositions/data-grid-table/data-grid-table-body.d.ts +13 -1
  98. package/dist/compositions/data-grid-table/data-grid-table-body.js +1 -1
  99. package/dist/compositions/data-grid-table/data-grid-table-header.d.ts +5 -0
  100. package/dist/compositions/document-list/document-list-icon.d.ts +1 -0
  101. package/dist/compositions/document-list/document-list-root.js +4 -0
  102. package/dist/compositions/editorial-card/editorial-card-content.d.ts +2 -0
  103. package/dist/compositions/file-upload/file-upload-dropzone.d.ts +3 -0
  104. package/dist/compositions/folder-tile/folder-tile-types.d.ts +2 -0
  105. package/dist/compositions/mobile-navigation/mobile-navigation-header.d.ts +5 -2
  106. package/dist/compositions/mobile-navigation/mobile-navigation-header.js +0 -1
  107. package/dist/compositions/mobile-navigation/mobile-navigation-item.d.ts +2 -0
  108. package/dist/compositions/mobile-navigation/mobile-navigation-profile.d.ts +1 -0
  109. package/dist/compositions/mobile-navigation/mobile-navigation-root.d.ts +1 -0
  110. package/dist/compositions/page-toolbar/page-toolbar-applied.d.ts +4 -1
  111. package/dist/compositions/page-toolbar/page-toolbar-sort.d.ts +3 -0
  112. package/dist/compositions/product-card/product-card-content.d.ts +1 -0
  113. package/dist/compositions/product-card/product-card-image-types.d.ts +8 -2
  114. package/dist/compositions/product-card/product-card-provider-types.d.ts +47 -2
  115. package/dist/compositions/product-card/product-card-root.d.ts +3 -0
  116. package/dist/compositions/product-card/product-card-root.js +2 -0
  117. package/dist/compositions/product-card/product-card-swatch.d.ts +2 -0
  118. package/dist/compositions/product-card/product-card-tools-types.d.ts +6 -0
  119. package/dist/compositions/product-specifications-selector/product-specifications-selector.d.ts +14 -0
  120. package/dist/compositions/sidebar/sidebar-group.d.ts +4 -0
  121. package/dist/compositions/sidebar/sidebar-menu-button.d.ts +11 -0
  122. package/dist/compositions/sidebar/sidebar-menu-sub.d.ts +4 -0
  123. package/dist/compositions/sidebar/sidebar-trigger.d.ts +2 -0
  124. package/dist/compositions/variant-selector/variant-selector-item.d.ts +1 -0
  125. package/dist/data/docs-manifest.js +580 -32
  126. package/dist/utils/with-test-id.d.ts +1 -0
  127. package/package.json +2 -1
package/agent-docs.md CHANGED
@@ -80,6 +80,7 @@ Constrains its content to a fixed width-to-height ratio, sizing itself to the av
80
80
 
81
81
  - Give it exactly one child and let it fill - set the media to `size-full object-cover`; `AspectRatio` sizes to the available width and derives height from `ratio`.
82
82
  - Use `as` to change the element (a tag); use `render` only to swap in a component (e.g. a router Link). Never `render={<Box as=…/>}` - pass `as` directly.
83
+ - Show a material, swatch or sample at the default 1:1 - never landscape. A sample is cut square, and a wide crop reads as room photography; set a wide `ratio` only for a scene, an interior or video.
83
84
 
84
85
  ## AttributeCard
85
86
 
@@ -1033,6 +1034,7 @@ Extracted from the product-card and editorial-card media frames; available to an
1033
1034
  - Use `as` to change the element (a tag); use `render` only to swap in a component (e.g. a router Link). Never `render={<Box as=…/>}` - pass `as` directly.
1034
1035
  - Set `edge` to frame photography with an inset hairline that stays above the media; do not fake it with a border or an inset shadow on the frame, which the media hides.
1035
1036
  - Reach for `raised` only when the frame sits on the same fill as its surface; in a dense row the edge already separates it.
1037
+ - Frame a material, swatch or sample square: give the frame `aspect-square` (or wrap it in `AspectRatio`, which defaults to 1:1). Never crop a material landscape.
1036
1038
 
1037
1039
  ## MediaFrameEmbed
1038
1040
 
@@ -1244,6 +1246,7 @@ This is a presentational component that accepts handlers via props for app-speci
1244
1246
 
1245
1247
  - In Next.js apps pass `renderImage` wrapping `next/image` and `linkAs={Link}` - the defaults are a plain `<img>` and `<a>`.
1246
1248
  - Cart UI renders only when a `renderAddToCart` slot is provided; keep `dragAdapter` referentially stable (module-level constant).
1249
+ - Use ProductCard for a material in a grid or list; its image is square, which is how a material is always shown. Don't rebuild the card with a landscape image.
1247
1250
 
1248
1251
  ## ProductCardProvider
1249
1252
 
@@ -1833,6 +1836,7 @@ Chips paint the darkening overlay on every fill and draw the double-ring selecti
1833
1836
  - Feed fills through `color`/`background`/`colors`, never a hex in `className`/`style` - the props drive the contrast-aware text colour, selection ring, and darkening overlay.
1834
1837
  - Reach for `Swatch` for a selectable colour/gradient/material chip or tile; a tiny non-interactive status marker is `Dot`, and a display-only status/category label is `Badge`.
1835
1838
  - For a gradient or image chip fill pass `light` - auto contrast detection (`isLightColor`) only reads solid colours, so overlaid icons/labels lose legibility without it.
1839
+ - A material swatch is always square, as Swatch draws it; never stretch a tile into a landscape crop, and in a grid let the column set the size.
1836
1840
 
1837
1841
  ## SwatchFan
1838
1842
 
@@ -9,6 +9,7 @@ export const accordionRootVariants = cva("", {
9
9
  variant: "default",
10
10
  },
11
11
  variants: {
12
+ /** Item styling, inherited by every item: `default` is ruled rows divided by bottom borders, `outline` bordered cards, `solid` filled cards. `outline` and `solid` space the items apart. @default "default" */
12
13
  variant: {
13
14
  default: "",
14
15
  outline: "space-y-2",
@@ -7,6 +7,7 @@ const alertVariants = cva("text-paragraph-sm relative grid w-full grid-cols-[0_1
7
7
  },
8
8
  variants: {
9
9
  // Lockstep: Alert's tone is the canon subset Extract<Tone, neutral|danger>.
10
+ /** Semantic colour: `neutral` for information, `danger` for an error or a destructive warning. @default "neutral" */
10
11
  tone: {
11
12
  neutral: "bg-card text-card-foreground",
12
13
  danger: "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current",
@@ -16,6 +16,7 @@ const anchorVariants = cva("rounded-xs underline underline-offset-4 transition-c
16
16
  variant: "default",
17
17
  },
18
18
  variants: {
19
+ /** Link treatment: `default` is a medium-weight underlined link, `muted` reads as body text until hovered, `plain` has no underline until hovered. @default "default" */
19
20
  variant: {
20
21
  default: "text-foreground decoration-foreground/40 hover:decoration-foreground font-medium",
21
22
  muted: "text-muted-foreground decoration-muted-foreground/40 hover:text-foreground hover:decoration-current",
@@ -14,7 +14,9 @@ interface AspectRatioProps extends useRender.ComponentProps<"div"> {
14
14
  as?: LayoutElement;
15
15
  /**
16
16
  * Desired width-to-height ratio, expressed as a single number (width / height).
17
- * @default 16 / 9
17
+ * Square unless asked: a material is shown at 1:1, and only scenes and
18
+ * video take a wide ratio.
19
+ * @default 1
18
20
  */
19
21
  ratio?: number;
20
22
  }
@@ -25,13 +27,15 @@ interface AspectRatioProps extends useRender.ComponentProps<"div"> {
25
27
  *
26
28
  * @example
27
29
  * ```tsx
28
- * <AspectRatio ratio={16 / 9}>
29
- * <img alt="" className="size-full object-cover" src="/hero.jpg" />
30
+ * <AspectRatio>
31
+ * <img alt="" className="size-full object-cover" src="/oak-plank.jpg" />
30
32
  * </AspectRatio>
31
33
  * ```
32
34
  *
33
35
  * @bestPractice Give it exactly one child and let it fill - set the media to `size-full object-cover`; `AspectRatio` sizes to the available width and derives height from `ratio`.
34
36
  * @bestPractice Use `as` to change the element (a tag); use `render` only to swap in a component (e.g. a router Link). Never `render={<Box as=…/>}` - pass `as` directly.
37
+ * @bestPractice Show a material, swatch or sample at the default 1:1 - never landscape. A sample is cut square, and a wide crop reads as room photography; set a wide `ratio` only for a scene, an interior or video.
38
+ * @keywords material image, swatch image, sample image, thumbnail, square, image ratio
35
39
  * @category layout
36
40
  */
37
41
  declare const AspectRatio: ({ as, className, ratio, ref, render, style, ...props }: AspectRatioProps) => import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -2,7 +2,7 @@
2
2
  import { useRender } from "@base-ui/react/use-render";
3
3
  import { cn } from "../../utils/cn.js";
4
4
  import { reportDevIssue } from "../../utils/dev-issue.js";
5
- const DEFAULT_RATIO = 16 / 9;
5
+ const DEFAULT_RATIO = 1;
6
6
  /**
7
7
  * Constrains its content to a fixed width-to-height ratio, sizing itself to the
8
8
  * available width with CSS `aspect-ratio`; drop a single child (image, video,
@@ -10,13 +10,15 @@ const DEFAULT_RATIO = 16 / 9;
10
10
  *
11
11
  * @example
12
12
  * ```tsx
13
- * <AspectRatio ratio={16 / 9}>
14
- * <img alt="" className="size-full object-cover" src="/hero.jpg" />
13
+ * <AspectRatio>
14
+ * <img alt="" className="size-full object-cover" src="/oak-plank.jpg" />
15
15
  * </AspectRatio>
16
16
  * ```
17
17
  *
18
18
  * @bestPractice Give it exactly one child and let it fill - set the media to `size-full object-cover`; `AspectRatio` sizes to the available width and derives height from `ratio`.
19
19
  * @bestPractice Use `as` to change the element (a tag); use `render` only to swap in a component (e.g. a router Link). Never `render={<Box as=…/>}` - pass `as` directly.
20
+ * @bestPractice Show a material, swatch or sample at the default 1:1 - never landscape. A sample is cut square, and a wide crop reads as room photography; set a wide `ratio` only for a scene, an interior or video.
21
+ * @keywords material image, swatch image, sample image, thumbnail, square, image ratio
20
22
  * @category layout
21
23
  */
22
24
  const AspectRatio = ({ as, className, ratio = DEFAULT_RATIO, ref, render, style, ...props }) => {
@@ -15,7 +15,7 @@ export interface AvatarBadgeProps {
15
15
  dot?: boolean | Tone;
16
16
  /** Cap above which the count renders as `{max}+`. @default 99 */
17
17
  max?: number;
18
- /** @default "top-right" */
18
+ /** Which corner of the avatar the badge overlaps. @default "top-right" */
19
19
  position?: "bottom-right" | "top-right" | "bottom-left" | "top-left";
20
20
  /** Component size */
21
21
  size?: ComponentSize;
@@ -4,7 +4,7 @@ import type { AvatarSize } from "../avatar/avatar-root.js";
4
4
  export type AvatarFallbackProps = Omit<AvatarPrimitive.Fallback.Props, "style"> & {
5
5
  /** Inline styles merged over the derived colours; a plain object only. */
6
6
  style?: React.CSSProperties | undefined;
7
- /** @default "base" */
7
+ /** Initials text size; set it to the same `size` as the parent `AvatarRoot`, as it does not inherit it. At `2xs` and `xs` only one initial shows. @default "base" */
8
8
  size?: AvatarSize | undefined;
9
9
  /**
10
10
  * Full name or label used to:
@@ -19,7 +19,7 @@ export declare const AVATAR_SIZE_CLASS: Record<AvatarSize, string>;
19
19
  */
20
20
  export declare const AVATAR_SIZE_PX: Record<AvatarSize, number>;
21
21
  export type AvatarRootProps = AvatarPrimitive.Root.Props & {
22
- /** @default "base" */
22
+ /** Avatar width and height, `2xs` (20px) to `6xl` (128px). Inside an `AvatarGroup`, the group's `size` wins. @default "base" */
23
23
  size?: AvatarSize | undefined;
24
24
  /** Border radius. Defaults to "full" (circular). */
25
25
  radius?: Radius | undefined;
@@ -4,10 +4,11 @@ export type AvatarStatusType = "online" | "offline" | "busy" | "away" | "dnd";
4
4
  export interface AvatarStatusProps {
5
5
  /** CSS class name */
6
6
  className?: string;
7
- /** @default "bottom-right" */
7
+ /** Which corner of the avatar the dot sits in. @default "bottom-right" */
8
8
  position?: "bottom-right" | "top-right" | "bottom-left" | "top-left";
9
9
  /** Component size */
10
10
  size?: ComponentSize;
11
+ /** Presence shown by the dot colour: `online` green, `away` and `busy` amber (the same colour), `dnd` red, `offline` muted grey. */
11
12
  status: AvatarStatusType;
12
13
  /** Ring separating the dot from the avatar. @default true */
13
14
  withBorder?: boolean;
@@ -5,6 +5,7 @@ declare const badgeButtonVariants: (props?: ({
5
5
  variant?: "default" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  export interface BadgeButtonProps extends useRender.ComponentProps<"button">, VariantProps<typeof badgeButtonVariants> {
8
+ /** Element shown when no `children` are given, an X icon unless replaced; an icon-only button needs an `aria-label`. */
8
9
  icon?: React.ReactNode;
9
10
  }
10
11
  /**
@@ -10,6 +10,7 @@ const badgeButtonVariants = cva("-me-0.5 inline-flex cursor-pointer items-center
10
10
  variant: "default",
11
11
  },
12
12
  variants: {
13
+ /** Button style; `default` is the only one, so leave it unset. @default "default" */
13
14
  variant: {
14
15
  default: "",
15
16
  },
@@ -18,13 +18,15 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, Omit<V
18
18
  * `{ base: "sm", md: "lg" }`. Forwarded to the underlying Pill. @default "base"
19
19
  */
20
20
  size?: ResponsiveValue<PillSize>;
21
+ /** Dims the badge to half opacity and stops it receiving pointer events. */
21
22
  disabled?: boolean;
22
23
  /** Force focus ring display (for documentation/testing) */
23
24
  focused?: boolean;
24
25
  /** Force hover state display (for documentation/testing) */
25
26
  hovered?: boolean;
27
+ /** Icon component (not an element) drawn beside the text, sized to match the badge. Replaced by a spinner while `loading`. */
26
28
  icon?: LucideIcon | React.ComponentType<React.SVGProps<SVGSVGElement>>;
27
- /** @default "start" */
29
+ /** Which side of the text `icon` sits on. @default "start" */
28
30
  iconPlacement?: "start" | "end";
29
31
  /** Left segment of a split badge; renders a divider before `value`. */
30
32
  label?: string;
@@ -32,6 +34,7 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, Omit<V
32
34
  loading?: boolean;
33
35
  /** Label shown during loading */
34
36
  loadingLabel?: string;
37
+ /** Sets `data-testid` on the badge. Lower-case `testid`, unlike the `testId` prop on other components. */
35
38
  testid?: string;
36
39
  /** Right (emphasised) segment; shown alone when no `label` is set. */
37
40
  value?: string;
@@ -9,6 +9,7 @@ import type * as React from "react";
9
9
  * @category navigation
10
10
  */
11
11
  declare const Breadcrumb: ({ ...props }: React.ComponentProps<"nav"> & {
12
+ /** Not used by `Breadcrumb`: set the divider by passing children to each `BreadcrumbSeparator` instead. */
12
13
  separator?: React.ReactNode;
13
14
  }) => React.JSX.Element;
14
15
  /**
@@ -327,11 +327,13 @@ const buttonVariants = cva([
327
327
  // drift from ButtonTone/ButtonEmphasis (declared below).
328
328
  // Danger fades only to /95 on hover: a lighter red under the light
329
329
  // foreground and the sheen drops below 4.5:1 at /90.
330
+ /** Semantic colour: `brand` for the primary action, `danger` for a destructive one. @default "neutral" */
330
331
  tone: {
331
332
  neutral: "",
332
333
  brand: "border-brand-accent/40 bg-brand text-brand-foreground focus-visible:ring-brand/25 data-[focused=true]:ring-brand/25",
333
334
  danger: "border-destructive bg-destructive text-destructive-foreground hover:bg-destructive/95 data-[hovered=true]:bg-destructive/95 focus-visible:ring-red-400/50 data-[focused=true]:ring-red-400/50",
334
335
  },
336
+ /** Visual weight, paired with `tone`: `solid` and `soft` are filled, `outline` and `ghost` lighter, `transparent` a blurred translucent fill, `link` plain text. @default "solid" */
335
337
  emphasis: {
336
338
  solid: "",
337
339
  soft: "",
@@ -340,21 +342,26 @@ const buttonVariants = cva([
340
342
  transparent: "transform-gpu backdrop-blur-md will-change-[filter,background-color] before:hidden",
341
343
  link: "",
342
344
  },
345
+ /** Style the button as a form field (input background and border), for a trigger that opens a picker. @default false */
343
346
  asInput: {
344
347
  true: "border-border bg-input text-foreground hover:bg-input/90 data-[hovered=true]:bg-input/90 before:hidden",
345
348
  false: "",
346
349
  },
350
+ /** Corner shape: `full` is a pill (or circle when square), `rounded` a soft corner, `square` sharp. @default "full" */
347
351
  radius: RADIUS_CLASSES,
348
352
  size: BUTTON_SIZE_CLASSES,
353
+ /** Where the content sits along the button; `start` or `end` only shows on a button wider than its content. @default "center" */
349
354
  align: {
350
355
  center: "justify-center",
351
356
  start: "justify-start",
352
357
  end: "justify-end",
353
358
  },
359
+ /** Shrink slightly while held down (`:active`); `false` keeps the button still. @default true */
354
360
  pressed: {
355
361
  true: "active:scale-[0.97]",
356
362
  false: "",
357
363
  },
364
+ /** Lock width to height so an `icon-*` size draws a square or circle; ignored with `expandable`. @default false */
358
365
  square: {
359
366
  true: "",
360
367
  false: "",
@@ -89,6 +89,7 @@ const buttonGroupVariants = cva("flex w-fit items-stretch *:focus-visible:relati
89
89
  variant: "joined",
90
90
  },
91
91
  variants: {
92
+ /** Group style: `joined` lets each child draw its own border and merges the shared edges; `segmented` draws one bordered, shadowed container around the children. @default "joined" */
92
93
  variant: {
93
94
  /**
94
95
  * Default "joined" behaviour - relies on each child for borders/background,
@@ -101,15 +102,18 @@ const buttonGroupVariants = cva("flex w-fit items-stretch *:focus-visible:relati
101
102
  */
102
103
  segmented: "border-border bg-card isolate overflow-hidden border shadow-xs [&>[data-slot=button-group-text]]:border-0 [&>[data-slot=button-group-text]]:shadow-none [&>[data-slot=select-trigger]]:border-0 [&>[data-slot=select-trigger]]:shadow-none",
103
104
  },
105
+ /** Direction the children are laid out: `horizontal` in a row, `vertical` in a column. @default "horizontal" */
104
106
  orientation: {
105
107
  horizontal: "flex-row [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none",
106
108
  vertical: "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
107
109
  },
110
+ /** Outer corners of the group: only the first and last child are rounded, the inner edges stay square. `segmented` rounds the container too. @default "full" */
108
111
  radius: {
109
112
  rounded: "",
110
113
  square: "",
111
114
  full: "",
112
115
  },
116
+ /** Draw a line between children. Defaults on for the `segmented` variant and off for `joined`. */
113
117
  dividers: {
114
118
  true: "",
115
119
  false: "",
@@ -8,6 +8,7 @@ declare const cardVariants: (props?: ({
8
8
  variant?: "accent" | "card" | "ghost" | "muted" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
10
  interface CardProps extends WithTestId<React.ComponentProps<"div">>, VariantProps<typeof cardVariants> {
11
+ /** Outline: `none` draws no border, `solid` a 1px border, `dashed` a faint dashed one for placeholder or drop areas. @default "none" */
11
12
  border?: BorderStyle;
12
13
  /**
13
14
  * Padding around the card's `CardHeader` and `CardContent`, and the gap
@@ -9,6 +9,7 @@ const cardVariants = cva("text-card-foreground flex flex-col gap-(--card-inset)
9
9
  variant: "card",
10
10
  },
11
11
  variants: {
12
+ /** Surface: `card` is the standard card fill, `muted` and `accent` are tinted fills, `ghost` has no fill or shadow. @default "card" */
12
13
  variant: {
13
14
  card: "bg-card shadow-sm",
14
15
  muted: "bg-muted shadow-sm",
@@ -18,7 +18,7 @@ export interface CheckboxCardGroupProps extends Omit<React.ComponentProps<"div">
18
18
  required?: boolean;
19
19
  /** Show the checkbox indicator on each item. @default true */
20
20
  showIndicator?: boolean;
21
- /** @default "base" */
21
+ /** Padding, corner radius and icon size of every card in the group; items read it from context. @default "base" */
22
22
  size?: ComponentSize;
23
23
  }
24
24
  /**
@@ -6,10 +6,13 @@ export type CheckboxFieldProps = Omit<CheckboxProps, "size"> & {
6
6
  label: React.ReactNode;
7
7
  /** Optional helper text below the label; wired to the checkbox via `aria-describedby`. */
8
8
  description?: React.ReactNode;
9
- /** @default "xs" */
9
+ /** Checkbox size; only `xs` and `sm` are allowed. @default "xs" */
10
10
  size?: Extract<ComponentSize, "xs" | "sm">;
11
+ /** Extra classes for the checkbox itself; `className` styles the outer field row. */
11
12
  checkboxClassName?: string;
13
+ /** Extra classes for the label text. */
12
14
  labelClassName?: string;
15
+ /** Extra classes for the description text; only applied when `description` is set. */
13
16
  descriptionClassName?: string;
14
17
  };
15
18
  /**
@@ -2,5 +2,5 @@
2
2
  * Menu item with a toggleable checkmark. Controlled via `checked`/`onCheckedChange`;
3
3
  * the menu stays open on select unless you set `closeOnClick`.
4
4
  */
5
- declare const ContextMenuCheckboxItem: (props: import("../menu-parts.js").MenuCheckboxItemProps) => React.JSX.Element;
5
+ declare const ContextMenuCheckboxItem: (props: import("../menu-parts-types.js").MenuCheckboxItemProps) => React.JSX.Element;
6
6
  export { ContextMenuCheckboxItem };
@@ -4,5 +4,5 @@
4
4
  * descendants via context, so `size`/`itemRadius` set here flow to every item,
5
5
  * label, and shortcut inside.
6
6
  */
7
- declare const ContextMenuContent: (props: import("../menu-parts.js").MenuContentProps) => React.JSX.Element;
7
+ declare const ContextMenuContent: (props: import("../menu-parts-types.js").MenuContentProps) => React.JSX.Element;
8
8
  export { ContextMenuContent };
@@ -4,5 +4,5 @@
4
4
  * for a leading icon rather than nesting icon elements in `children`. Handle
5
5
  * selection with `onClick`; set `closeOnClick={false}` to keep the menu open.
6
6
  */
7
- declare const ContextMenuItem: (props: import("../menu-parts.js").MenuItemPartProps) => React.JSX.Element;
7
+ declare const ContextMenuItem: (props: import("../menu-parts-types.js").MenuItemPartProps) => React.JSX.Element;
8
8
  export { ContextMenuItem };
@@ -2,5 +2,5 @@
2
2
  * Single-select menu item showing a trailing checkmark when active. Must be
3
3
  * rendered inside a ContextMenuRadioGroup, which supplies its `value`.
4
4
  */
5
- declare const ContextMenuRadioItem: (props: import("../menu-parts.js").MenuRadioItemProps) => React.JSX.Element;
5
+ declare const ContextMenuRadioItem: (props: import("../menu-parts-types.js").MenuRadioItemProps) => React.JSX.Element;
6
6
  export { ContextMenuRadioItem };
@@ -1,3 +1,3 @@
1
- /** Horizontal divider between groups of menu items. `spacing="compact"` tightens the vertical gap. */
2
- declare const ContextMenuSeparator: (props: import("../menu-parts.js").MenuSeparatorProps) => React.JSX.Element;
1
+ /** Horizontal divider between groups of menu items. `spacing="compact"` leaves more room around the rule. */
2
+ declare const ContextMenuSeparator: (props: import("../menu-parts-types.js").MenuSeparatorProps) => React.JSX.Element;
3
3
  export { ContextMenuSeparator };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
2
  import { contextMenuParts } from "./context-menu-parts.js";
3
- /** Horizontal divider between groups of menu items. `spacing="compact"` tightens the vertical gap. */
3
+ /** Horizontal divider between groups of menu items. `spacing="compact"` leaves more room around the rule. */
4
4
  const ContextMenuSeparator = contextMenuParts.Separator;
5
5
  export { ContextMenuSeparator };
@@ -3,5 +3,5 @@
3
3
  * arrow key, with a trailing chevron. Pass label text via `children` and a
4
4
  * leading icon via `icon`.
5
5
  */
6
- declare const ContextMenuSubTrigger: (props: import("../menu-parts.js").MenuSubTriggerProps) => React.JSX.Element;
6
+ declare const ContextMenuSubTrigger: (props: import("../menu-parts-types.js").MenuSubTriggerProps) => React.JSX.Element;
7
7
  export { ContextMenuSubTrigger };
@@ -46,6 +46,7 @@ const dotVariants = cva("inline-block shrink-0 rounded-full", {
46
46
  },
47
47
  variants: {
48
48
  // Lockstep: Dot's tone is the full canonical Tone vocabulary.
49
+ /** Semantic colour: `success`, `warning`, `danger` and `info` for status, `brand` for the accent, `neutral` for a muted grey. Ignored when `color` is set. @default "neutral" */
49
50
  tone: DOT_TONE_BG_CLASSES,
50
51
  },
51
52
  });
@@ -20,6 +20,7 @@ export declare const DrawerContext: import("react").Context<DrawerContextValue>;
20
20
  * @category overlays
21
21
  */
22
22
  export declare const Drawer: ({ container, ...props }: ComponentProps<typeof DrawerPrimitive.Root> & {
23
+ /** Element the drawer and its scrim portal into, bounding them to that element instead of the page. Omit to portal to the document body. */
23
24
  container?: HTMLElement | null;
24
25
  }) => import("react").JSX.Element;
25
26
  export {};
@@ -2,5 +2,5 @@
2
2
  * Menu item with a toggleable checkmark. Controlled via `checked`/`onCheckedChange`;
3
3
  * the menu stays open on select unless you set `closeOnClick`.
4
4
  */
5
- declare const DropdownMenuCheckboxItem: (props: import("../menu-parts.js").MenuCheckboxItemProps) => React.JSX.Element;
5
+ declare const DropdownMenuCheckboxItem: (props: import("../menu-parts-types.js").MenuCheckboxItemProps) => React.JSX.Element;
6
6
  export { DropdownMenuCheckboxItem };
@@ -3,5 +3,5 @@
3
3
  * open/close. Provides item size and radius to descendants via context, so
4
4
  * `size`/`itemRadius` set here flow to every item, label, and shortcut inside.
5
5
  */
6
- declare const DropdownMenuContent: (props: import("../menu-parts.js").MenuContentProps) => React.JSX.Element;
6
+ declare const DropdownMenuContent: (props: import("../menu-parts-types.js").MenuContentProps) => React.JSX.Element;
7
7
  export { DropdownMenuContent };
@@ -4,5 +4,5 @@
4
4
  * for a leading icon rather than nesting icon elements in `children`. Handle
5
5
  * selection with `onClick`; set `closeOnClick={false}` to keep the menu open.
6
6
  */
7
- declare const DropdownMenuItem: (props: import("../menu-parts.js").MenuItemPartProps) => React.JSX.Element;
7
+ declare const DropdownMenuItem: (props: import("../menu-parts-types.js").MenuItemPartProps) => React.JSX.Element;
8
8
  export { DropdownMenuItem };
@@ -2,5 +2,5 @@
2
2
  * Single-select menu item showing a trailing checkmark when active. Must be
3
3
  * rendered inside a DropdownMenuRadioGroup, which supplies its `value`.
4
4
  */
5
- declare const DropdownMenuRadioItem: (props: import("../menu-parts.js").MenuRadioItemProps) => React.JSX.Element;
5
+ declare const DropdownMenuRadioItem: (props: import("../menu-parts-types.js").MenuRadioItemProps) => React.JSX.Element;
6
6
  export { DropdownMenuRadioItem };
@@ -1,3 +1,3 @@
1
- /** Horizontal divider between groups of menu items. `spacing="compact"` tightens the vertical gap. */
2
- declare const DropdownMenuSeparator: (props: import("../menu-parts.js").MenuSeparatorProps) => React.JSX.Element;
1
+ /** Horizontal divider between groups of menu items. `spacing="compact"` leaves more room around the rule. */
2
+ declare const DropdownMenuSeparator: (props: import("../menu-parts-types.js").MenuSeparatorProps) => React.JSX.Element;
3
3
  export { DropdownMenuSeparator };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
2
  import { dropdownMenuParts } from "./dropdown-menu-parts.js";
3
- /** Horizontal divider between groups of menu items. `spacing="compact"` tightens the vertical gap. */
3
+ /** Horizontal divider between groups of menu items. `spacing="compact"` leaves more room around the rule. */
4
4
  const DropdownMenuSeparator = dropdownMenuParts.Separator;
5
5
  export { DropdownMenuSeparator };
@@ -3,5 +3,5 @@
3
3
  * arrow key, with a trailing chevron. Pass label text via `children` and a
4
4
  * leading icon via `icon`.
5
5
  */
6
- declare const DropdownMenuSubTrigger: (props: import("../menu-parts.js").MenuSubTriggerProps) => React.JSX.Element;
6
+ declare const DropdownMenuSubTrigger: (props: import("../menu-parts-types.js").MenuSubTriggerProps) => React.JSX.Element;
7
7
  export { DropdownMenuSubTrigger };
@@ -26,6 +26,7 @@ const emptyVariants = cva("", {
26
26
  size: "base",
27
27
  },
28
28
  variants: {
29
+ /** Scale of the whole empty state: the title, description and icon sizes, the gaps, and the vertical padding in the `card` layouts. @default "base" */
29
30
  size: {
30
31
  sm: "",
31
32
  base: "",
@@ -11,6 +11,7 @@ const expandButtonVariants = cva(cn(focusRing(), `group inline-flex shrink-0 ite
11
11
  size: "sm",
12
12
  },
13
13
  variants: {
14
+ /** Square button edge and icon size, `2xs` (14px) to `3xl` (32px). Smaller than a `Button` of the same size, so it suits dense rows. @default "sm" */
14
15
  size: SQUARE_CONTROL_SIZE_CLASSES,
15
16
  },
16
17
  });
@@ -18,6 +18,7 @@
18
18
  * ```
19
19
  */
20
20
  export declare const FieldError: ({ className, children, errors, id, ...props }: React.ComponentProps<"div"> & {
21
+ /** Validation errors to show: one renders as plain text, several as a bulleted list. Duplicate messages collapse; ignored when `children` is set. */
21
22
  errors?: ({
22
23
  message?: string;
23
24
  } | undefined)[];
@@ -9,6 +9,7 @@ export const fieldVariants = cva("group/field data-[invalid=true]:text-destructi
9
9
  orientation: "vertical",
10
10
  },
11
11
  variants: {
12
+ /** How label and control are arranged: `vertical` stacks them, `horizontal` puts them in a row, `responsive` stacks until the enclosing `FieldGroup` reaches its `md` container width, then switches to a row (needs a `FieldGroup` ancestor). @default "vertical" */
12
13
  orientation: {
13
14
  vertical: ["flex-col *:w-full [&>.sr-only]:w-auto"],
14
15
  horizontal: [
@@ -35,6 +35,7 @@ const iconBoxVariants = cva("flex shrink-0 items-center justify-center border bo
35
35
  tone: "neutral",
36
36
  },
37
37
  variants: {
38
+ /** Box width and height, `2xs` (16px) to `3xl` (96px); the icon and corner radius scale with it. @default "base" */
38
39
  size: {
39
40
  "2xs": "size-4",
40
41
  xs: "size-6",
@@ -52,6 +53,7 @@ const iconBoxVariants = cva("flex shrink-0 items-center justify-center border bo
52
53
  // former `primary` dark look is retired. `muted`/`secondary` collapsed
53
54
  // onto `neutral` (muted → neutral+soft compound above; secondary →
54
55
  // neutral).
56
+ /** Semantic colour of the icon and its tinted surface: `brand` for the accent, `danger`, `warning`, `success` and `info` for status, `neutral` for everything else. @default "neutral" */
55
57
  tone: {
56
58
  neutral: "bg-accent text-foreground",
57
59
  brand: "bg-brand text-brand-foreground",
@@ -60,12 +62,14 @@ const iconBoxVariants = cva("flex shrink-0 items-center justify-center border bo
60
62
  success: "bg-affirmative-soft text-affirmative-foreground dark:bg-affirmative-soft/20 dark:text-affirmative-accent",
61
63
  info: "bg-info-soft text-info-foreground dark:bg-info-soft/20 dark:text-info-accent",
62
64
  },
65
+ /** Surface fill: `solid` is the tinted fill, `soft` the same except `neutral` takes the muted fill, `outline` a border with no fill, `ghost` neither. The icon keeps the tone's colour in every case. @default "solid" */
63
66
  emphasis: {
64
67
  solid: "",
65
68
  soft: "",
66
69
  outline: "border-border bg-transparent",
67
70
  ghost: "border-transparent bg-transparent",
68
71
  },
72
+ /** Corner shape: `rounded` scales with `size`, `square` has sharp corners, `full` is a circle. @default "rounded" */
69
73
  radius: RADIUS_CLASSES,
70
74
  },
71
75
  });
@@ -4,12 +4,17 @@ export interface IdentifiedSurfaceFrameProps {
4
4
  className?: string;
5
5
  /** Reveals the complete frame while a related control is hovered or focused. */
6
6
  highlighted?: boolean;
7
+ /** Name of the identified object, shown in the label pill. The label appears only while `highlighted` or `active`. */
7
8
  label: string;
9
+ /** Which edge of the frame the label lines up with: `start` the left, `end` the right, `center` centred. @default "center" */
8
10
  labelAlign?: "center" | "end" | "start";
11
+ /** Whether the label sits above or below the frame. @default "above" */
9
12
  labelPlacement?: "above" | "below";
10
13
  /** Keeps the complete evidence boundary visible before interaction. */
11
14
  persistentFrame?: boolean;
15
+ /** Smaller grey text after `label`, such as a code or category; truncated to a short width. */
12
16
  secondaryLabel?: string | undefined;
17
+ /** Image URL for a small round thumbnail at the start of the label. Decorative, so it carries empty alt text. */
13
18
  thumbnailUrl?: string | null | undefined;
14
19
  }
15
20
  /**
@@ -35,6 +35,7 @@ export const standaloneInputVariants = cva("border-border bg-input selection:bg-
35
35
  },
36
36
  variants: {
37
37
  // Input radius is 8px (Figma rounded-md), not the shared 10px `rounded-lg`.
38
+ /** Corner shape: `rounded` is the standard 8px radius, `square` has sharp corners, `full` is a pill. @default "rounded" */
38
39
  radius: {
39
40
  full: "rounded-full",
40
41
  rounded: "rounded-md",
@@ -15,8 +15,11 @@ declare const INPUT_CARD_ICON_SIZE: Record<ComponentSize, ComponentSize>;
15
15
  declare const getInputCardIconSize: (cardSize: ComponentSize) => ComponentSize;
16
16
  interface InputCardIconProps {
17
17
  className?: string;
18
+ /** Icon component (not an element) to draw. */
18
19
  icon: LucideIcon | React.ComponentType<React.SVGProps<SVGSVGElement>>;
20
+ /** Tints the icon with the primary colour instead of muted. */
19
21
  selected?: boolean;
22
+ /** Size of the parent card, not of the icon: the icon renders smaller than the card (`xs` at `base`). */
20
23
  size: ComponentSize;
21
24
  }
22
25
  /** Renders an icon for InputCard with proper sizing and selection state styling */
@@ -1,14 +1,18 @@
1
1
  import type { LucideIcon } from "lucide-react";
2
2
  import type * as React from "react";
3
- import type { ButtonEmphasis, ButtonTone } from "../button.js";
3
+ import type { ButtonEmphasis, ButtonProps, ButtonTone } from "../button.js";
4
4
  import { Button } from "../button.js";
5
5
  export type InputGroupButtonProps = Omit<React.ComponentProps<typeof Button>, "size"> & {
6
6
  /** Icon to display. */
7
7
  icon?: LucideIcon | React.ComponentType<React.SVGProps<SVGSVGElement>>;
8
- /** Button tone. */
8
+ /** Semantic colour, as on Button. @default "neutral" */
9
9
  tone?: ButtonTone;
10
- /** Button emphasis. */
10
+ /** Visual weight, as on Button; ghost keeps the button quiet inside the field. @default "ghost" */
11
11
  emphasis?: ButtonEmphasis;
12
+ /** Corner shape; leave unset - the corners follow the InputGroup's `radius`, tighter inside the field. */
13
+ radius?: ButtonProps["radius"];
14
+ /** Square by default, as an icon button sized from the InputGroup. @default true */
15
+ square?: ButtonProps["square"];
12
16
  };
13
17
  /**
14
18
  * Button element for use inside InputGroup.
@@ -12,6 +12,7 @@ const itemGroupVariants = cva("group/item-group flex flex-col", {
12
12
  variant: "divided",
13
13
  },
14
14
  variants: {
15
+ /** List style: `divided` is plain rows with lines between, `separated` makes each item its own card with a gap, `grouped` joins the items inside one bordered card. @default "divided" */
15
16
  variant: {
16
17
  divided: "divide-border divide-y",
17
18
  separated: "gap-3",