@mitcsutt/kiln-ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/components/actions/Button/Button.module.js.map +1 -1
  2. package/dist/components/actions/ToggleChip/ToggleChip.d.ts +5 -0
  3. package/dist/components/actions/ToggleChip/ToggleChip.js +10 -6
  4. package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
  5. package/dist/components/actions/ToggleChip/chip.module.js +4 -3
  6. package/dist/components/actions/ToggleChip/chip.module.js.map +1 -1
  7. package/dist/components/display/AvatarGroup/AvatarGroup.d.ts +2 -2
  8. package/dist/components/display/AvatarGroup/AvatarGroup.js +1 -1
  9. package/dist/components/display/AvatarGroup/AvatarGroup.js.map +1 -1
  10. package/dist/components/display/Card/Card.d.ts +7 -4
  11. package/dist/components/display/Card/Card.js +8 -7
  12. package/dist/components/display/Card/Card.js.map +1 -1
  13. package/dist/components/display/Card/Card.module.js.map +1 -1
  14. package/dist/components/display/List/List.d.ts +18 -5
  15. package/dist/components/display/List/List.js +53 -43
  16. package/dist/components/display/List/List.js.map +1 -1
  17. package/dist/components/display/List/List.module.js.map +1 -1
  18. package/dist/components/display/List/index.d.ts +1 -1
  19. package/dist/components/display/Marquee/Marquee.js +1 -1
  20. package/dist/components/display/Marquee/Marquee.js.map +1 -1
  21. package/dist/components/display/Media/Media.d.ts +15 -0
  22. package/dist/components/display/Media/Media.js +43 -23
  23. package/dist/components/display/Media/Media.js.map +1 -1
  24. package/dist/components/display/Media/Media.module.js.map +1 -1
  25. package/dist/components/display/Media/index.d.ts +1 -1
  26. package/dist/components/display/Stat/Stat.module.js.map +1 -1
  27. package/dist/components/display/Table/Table.d.ts +23 -1
  28. package/dist/components/display/Table/Table.js +19 -14
  29. package/dist/components/display/Table/Table.js.map +1 -1
  30. package/dist/components/display/Table/Table.module.js.map +1 -1
  31. package/dist/components/display/Table/index.d.ts +1 -1
  32. package/dist/components/display/Tag/Tag.d.ts +3 -0
  33. package/dist/components/display/Tag/Tag.js +11 -10
  34. package/dist/components/display/Tag/Tag.js.map +1 -1
  35. package/dist/components/display/Tag/Tag.module.js.map +1 -1
  36. package/dist/components/display/Tag/index.d.ts +1 -1
  37. package/dist/components/feedback/Flash/Flash.d.ts +47 -0
  38. package/dist/components/feedback/Flash/Flash.js +36 -0
  39. package/dist/components/feedback/Flash/Flash.js.map +1 -0
  40. package/dist/components/feedback/Flash/Flash.module.js +10 -0
  41. package/dist/components/feedback/Flash/Flash.module.js.map +1 -0
  42. package/dist/components/feedback/Flash/index.d.ts +2 -0
  43. package/dist/components/feedback/RelativeTime/RelativeTime.d.ts +7 -0
  44. package/dist/components/feedback/RelativeTime/RelativeTime.js +11 -11
  45. package/dist/components/feedback/RelativeTime/RelativeTime.js.map +1 -1
  46. package/dist/components/feedback/StatusDot/StatusDot.d.ts +1 -1
  47. package/dist/components/feedback/StatusDot/StatusDot.js.map +1 -1
  48. package/dist/components/inputs/ChoiceCards/ChoiceCards.js +9 -9
  49. package/dist/components/inputs/Combobox/Combobox.js +5 -5
  50. package/dist/components/inputs/PasswordInput/PasswordInput.js +4 -4
  51. package/dist/components/layout/AppShell/AppShell.d.ts +4 -1
  52. package/dist/components/layout/AppShell/AppShell.js +58 -44
  53. package/dist/components/layout/AppShell/AppShell.js.map +1 -1
  54. package/dist/components/layout/AppShell/AppShell.module.js.map +1 -1
  55. package/dist/components/layout/Box/Box.d.ts +15 -3
  56. package/dist/components/layout/Box/Box.js +11 -10
  57. package/dist/components/layout/Box/Box.js.map +1 -1
  58. package/dist/components/layout/Box/Box.module.js.map +1 -1
  59. package/dist/components/layout/Divider/Divider.d.ts +7 -1
  60. package/dist/components/layout/Divider/Divider.js +18 -20
  61. package/dist/components/layout/Divider/Divider.js.map +1 -1
  62. package/dist/components/layout/ScrollArea/ScrollArea.d.ts +36 -0
  63. package/dist/components/layout/ScrollArea/ScrollArea.js +25 -0
  64. package/dist/components/layout/ScrollArea/ScrollArea.js.map +1 -0
  65. package/dist/components/layout/ScrollArea/ScrollArea.module.js +6 -0
  66. package/dist/components/layout/ScrollArea/ScrollArea.module.js.map +1 -0
  67. package/dist/components/layout/ScrollArea/index.d.ts +2 -0
  68. package/dist/components/layout/Section/Section.d.ts +18 -7
  69. package/dist/components/layout/Section/Section.js +10 -9
  70. package/dist/components/layout/Section/Section.js.map +1 -1
  71. package/dist/components/layout/Section/Section.module.js.map +1 -1
  72. package/dist/components/navigation/Accordion/Accordion.d.ts +6 -1
  73. package/dist/components/navigation/Accordion/Accordion.js +19 -11
  74. package/dist/components/navigation/Accordion/Accordion.js.map +1 -1
  75. package/dist/components/navigation/Accordion/Accordion.module.js +7 -6
  76. package/dist/components/navigation/Accordion/Accordion.module.js.map +1 -1
  77. package/dist/components/navigation/NavLinks/NavLinks.d.ts +4 -1
  78. package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
  79. package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
  80. package/dist/components/overlays/Tooltip/Tooltip.d.ts +23 -0
  81. package/dist/components/overlays/Tooltip/Tooltip.js +77 -31
  82. package/dist/components/overlays/Tooltip/Tooltip.js.map +1 -1
  83. package/dist/components/typography/Numeral/Numeral.d.ts +26 -2
  84. package/dist/components/typography/Numeral/Numeral.js +25 -21
  85. package/dist/components/typography/Numeral/Numeral.js.map +1 -1
  86. package/dist/components/typography/Numeral/Numeral.module.js +4 -3
  87. package/dist/components/typography/Numeral/Numeral.module.js.map +1 -1
  88. package/dist/components/typography/Text/Text.d.ts +5 -2
  89. package/dist/components/typography/Text/Text.js.map +1 -1
  90. package/dist/components/typography/Text/Text.module.js.map +1 -1
  91. package/dist/icons/Icon.js +1 -0
  92. package/dist/icons/Icon.js.map +1 -1
  93. package/dist/icons/icons.d.ts +12 -0
  94. package/dist/icons/icons.js +63 -13
  95. package/dist/icons/icons.js.map +1 -1
  96. package/dist/index.d.ts +19 -24
  97. package/dist/index.js +114 -112
  98. package/dist/styles.css +1 -1
  99. package/dist/themes/fiesta.css +1 -1
  100. package/dist/utils/tokens.d.ts +2 -0
  101. package/dist/utils/tokens.js.map +1 -1
  102. package/package.json +2 -2
  103. package/skills/custom-theme/SKILL.md +1 -1
  104. package/skills/design-rules/SKILL.md +8 -4
  105. package/skills/layout-composition/SKILL.md +2 -0
  106. package/skills/layout-composition/references/app-shell.md +2 -2
  107. package/skills/layout-composition/references/box.md +21 -1
  108. package/skills/layout-composition/references/divider.md +30 -1
  109. package/skills/layout-composition/references/scroll-area.md +68 -0
  110. package/skills/layout-composition/references/section.md +24 -2
  111. package/skills/setup-and-theming/SKILL.md +3 -3
  112. package/skills/setup-and-theming/references/fiesta.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Button.module.js","names":["button","spinner","icon","Button_module_default"],"sources":["../../../../src/components/actions/Button/Button.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --button-radius default var(--radius-action)\n * --button-shadow default var(--shadow-surface) for solid/outline\n * --button-weight default var(--label-weight)\n */\n.button {\n --_bg: transparent;\n --_bg-hover: var(--_bg);\n --_ink: var(--color-ink);\n --_border: transparent;\n --_shadow: none;\n --_h: var(--control-md);\n --_px: var(--space-4);\n --_fs: var(--text-sm);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5em;\n min-block-size: var(--_h);\n padding-inline: var(--_px);\n padding-block: 0;\n border: var(--border-width) solid var(--_border);\n border-radius: var(--button-radius, var(--radius-action));\n background: var(--_bg);\n color: var(--_ink);\n box-shadow: var(--_shadow);\n font-family: var(--font-text);\n font-size: var(--_fs);\n font-weight: var(--button-weight, var(--label-weight));\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n line-height: 1;\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-1) var(--ease-spring);\n}\n\n/* Sizes */\n.button[data-size='sm'] {\n --_h: var(--control-sm);\n --_px: var(--space-3);\n --_fs: var(--text-xs);\n}\n.button[data-size='lg'] {\n --_h: var(--control-lg);\n --_px: var(--space-5);\n --_fs: var(--text-md);\n}\n\n/* Tone → which colour family the variant draws with */\n.button[data-tone='accent'] {\n --_c: var(--color-accent);\n --_c-hover: var(--color-accent-hover);\n --_c-ink: var(--color-accent-ink);\n --_c-text: var(--color-accent-text);\n --_c-soft: var(--color-accent-soft);\n}\n.button[data-tone='neutral'] {\n --_c: var(--color-surface-inverse);\n --_c-hover: var(--color-ink-muted);\n --_c-ink: var(--color-ink-inverse);\n --_c-text: var(--color-ink);\n --_c-soft: var(--color-surface-sunken);\n}\n.button[data-tone='critical'] {\n --_c: var(--tone-critical);\n --_c-hover: var(--tone-critical-text);\n --_c-ink: var(--tone-critical-ink);\n --_c-text: var(--tone-critical-text);\n --_c-soft: var(--tone-critical-soft);\n}\n\n/* Variants */\n.button[data-variant='solid'] {\n --_bg: var(--_c);\n --_bg-hover: var(--_c-hover);\n --_ink: var(--_c-ink);\n --_border: var(--button-solid-border, var(--_c));\n --_shadow: var(--button-shadow, var(--shadow-surface));\n}\n.button[data-variant='outline'] {\n --_bg: transparent;\n --_bg-hover: var(--_c-soft);\n --_ink: var(--_c-text);\n --_border: var(--color-line-strong);\n --_shadow: var(--button-shadow, var(--shadow-surface));\n}\n.button[data-tone='neutral'][data-variant='outline'] {\n --_bg: var(--color-surface);\n}\n.button[data-variant='ghost'] {\n --_bg: transparent;\n --_bg-hover: var(--_c-soft);\n --_ink: var(--_c-text);\n}\n\n@media (hover: hover) {\n .button:hover:not(:disabled, [aria-disabled='true']) {\n background: var(--_bg-hover);\n }\n}\n\n.button:active:not(:disabled, [aria-disabled='true']) {\n translate: var(--active-shift) var(--active-shift);\n box-shadow: var(--shadow-active);\n}\n.button[data-variant='ghost']:active:not(:disabled) {\n translate: none;\n box-shadow: none;\n}\n\n.button:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.button:disabled,\n.button[aria-disabled='true'] {\n cursor: not-allowed;\n opacity: 0.45;\n box-shadow: none;\n}\n\n.button[data-loading] {\n cursor: progress;\n opacity: 1;\n /* Bare text children aren't elements, so hide the label via colour, not visibility */\n color: transparent;\n}\n.button[data-loading] > :not(.spinner) {\n visibility: hidden;\n}\n\n.button[data-full-width] {\n display: flex;\n inline-size: 100%;\n}\n\n.icon {\n display: inline-flex;\n font-size: 1.15em;\n margin-inline: -0.1em;\n}\n\n.spinner {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n color: var(--_ink);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Button.module.js","names":["button","spinner","icon","Button_module_default"],"sources":["../../../../src/components/actions/Button/Button.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --button-radius default var(--radius-action)\n * --button-shadow default var(--shadow-surface) for solid/outline\n * --button-weight default var(--label-weight)\n */\n.button {\n --_bg: transparent;\n --_bg-hover: var(--_bg);\n --_ink: var(--color-ink);\n --_border: transparent;\n --_shadow: none;\n --_h: var(--control-md);\n --_px: var(--space-4);\n --_fs: var(--text-sm);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5em;\n min-block-size: var(--_h);\n padding-inline: var(--_px);\n padding-block: 0;\n border: var(--border-width) solid var(--_border);\n border-radius: var(--button-radius, var(--radius-action));\n background: var(--_bg);\n color: var(--_ink);\n box-shadow: var(--_shadow);\n font-family: var(--font-text);\n font-size: var(--_fs);\n font-weight: var(--button-weight, var(--label-weight));\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n line-height: 1;\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-1) var(--ease-spring);\n}\n\n/* Sizes */\n.button[data-size='sm'] {\n --_h: var(--control-sm);\n --_px: var(--space-3);\n --_fs: var(--text-xs);\n}\n.button[data-size='lg'] {\n --_h: var(--control-lg);\n --_px: var(--space-5);\n --_fs: var(--text-md);\n}\n\n/* Tone → which colour family the variant draws with */\n.button[data-tone='accent'] {\n --_c: var(--color-accent);\n --_c-hover: var(--color-accent-hover);\n --_c-ink: var(--color-accent-ink);\n --_c-text: var(--color-accent-text);\n --_c-soft: var(--color-accent-soft);\n}\n.button[data-tone='neutral'] {\n --_c: var(--color-surface-inverse);\n --_c-hover: var(--color-ink-muted);\n --_c-ink: var(--color-ink-inverse);\n --_c-text: var(--color-ink);\n --_c-soft: var(--color-surface-sunken);\n}\n.button[data-tone='critical'] {\n --_c: var(--tone-critical);\n --_c-hover: var(--tone-critical-text);\n --_c-ink: var(--tone-critical-ink);\n --_c-text: var(--tone-critical-text);\n --_c-soft: var(--tone-critical-soft);\n}\n\n/* Variants */\n.button[data-variant='solid'] {\n --_bg: var(--_c);\n --_bg-hover: var(--_c-hover);\n --_ink: var(--_c-ink);\n --_border: var(--button-solid-border, var(--_c));\n --_shadow: var(--button-shadow, var(--shadow-surface));\n}\n.button[data-variant='outline'] {\n --_bg: transparent;\n --_bg-hover: var(--_c-soft);\n --_ink: var(--_c-text);\n --_border: var(--color-line-strong);\n --_shadow: var(--button-shadow, var(--shadow-surface));\n}\n.button[data-tone='neutral'][data-variant='outline'] {\n --_bg: var(--color-surface);\n}\n.button[data-variant='ghost'] {\n --_bg: transparent;\n --_bg-hover: var(--_c-soft);\n --_ink: var(--_c-text);\n}\n\n@media (hover: hover) {\n .button:hover:not(:disabled, [aria-disabled='true']) {\n background: var(--_bg-hover);\n }\n}\n\n.button:active:not(:disabled, [aria-disabled='true']) {\n translate: var(--active-shift) var(--active-shift);\n box-shadow: var(--shadow-active);\n}\n.button[data-variant='ghost']:active:not(:disabled, [aria-disabled='true']) {\n translate: none;\n box-shadow: none;\n}\n\n.button:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.button:disabled,\n.button[aria-disabled='true'] {\n cursor: not-allowed;\n opacity: 0.45;\n box-shadow: none;\n}\n\n.button[data-loading] {\n cursor: progress;\n opacity: 1;\n /* Bare text children aren't elements, so hide the label via colour, not visibility */\n color: transparent;\n}\n.button[data-loading] > :not(.spinner) {\n visibility: hidden;\n}\n\n.button[data-full-width] {\n display: flex;\n inline-size: 100%;\n}\n\n.icon {\n display: inline-flex;\n font-size: 1.15em;\n margin-inline: -0.1em;\n}\n\n.spinner {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n color: var(--_ink);\n}\n"],"mappings":""}
@@ -7,6 +7,11 @@ export interface ToggleChipProps extends ComponentPropsWithoutRef<typeof Toggle.
7
7
  icon?: ReactNode;
8
8
  /** How many items the filter matches. Rendered in tabular figures after the label. */
9
9
  count?: number;
10
+ /**
11
+ * Content after the label, spaced from it: an `AvatarGroup` of who reacted, a small figure.
12
+ * Keep it phrasing content, since the chip is a button.
13
+ */
14
+ trailing?: ReactNode;
10
15
  }
11
16
  /**
12
17
  * An independent on-off filter that sits in a row with others, with an optional count.
@@ -4,13 +4,13 @@ import { forwardRef as n } from "react";
4
4
  import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
5
  import { Toggle as a } from "radix-ui";
6
6
  //#region src/components/actions/ToggleChip/ToggleChip.tsx
7
- var o = n(function({ size: n = "md", icon: o, count: s, className: c, children: l, type: u, ...d }, f) {
7
+ var o = n(function({ size: n = "md", icon: o, count: s, trailing: c, className: l, children: u, type: d, ...f }, p) {
8
8
  return /* @__PURE__ */ i(a.Root, {
9
- ref: f,
10
- type: u ?? "button",
11
- className: e(t.chip, c),
9
+ ref: p,
10
+ type: d ?? "button",
11
+ className: e(t.chip, l),
12
12
  "data-size": n,
13
- ...d,
13
+ ...f,
14
14
  children: [
15
15
  o ? /* @__PURE__ */ r("span", {
16
16
  className: t.icon,
@@ -19,7 +19,11 @@ var o = n(function({ size: n = "md", icon: o, count: s, className: c, children:
19
19
  }) : null,
20
20
  /* @__PURE__ */ r("span", {
21
21
  className: t.label,
22
- children: l
22
+ children: u
23
+ }),
24
+ c === void 0 ? null : /* @__PURE__ */ r("span", {
25
+ className: t.trailing,
26
+ children: c
23
27
  }),
24
28
  s === void 0 ? null : /* @__PURE__ */ r("span", {
25
29
  className: t.count,
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleChip.js","names":["styles","chip_module_default","ToggleChip","forwardRef","rest","Toggle","type","cx","className","size","icon","count"],"sources":["../../../../src/components/actions/ToggleChip/ToggleChip.tsx"],"sourcesContent":["import { forwardRef, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport { Toggle } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport styles from './chip.module.css'\n\nexport type ToggleChipSize = 'sm' | 'md'\n\nexport interface ToggleChipProps extends ComponentPropsWithoutRef<typeof Toggle.Root> {\n size?: ToggleChipSize\n /** A leading glyph. Keep it meaningful — one icon per row at most. */\n icon?: ReactNode\n /** How many items the filter matches. Rendered in tabular figures after the label. */\n count?: number\n}\n\n/**\n * An independent on-off filter that sits in a row with others, with an optional count.\n *\n * @remarks\n * A `ToggleChip` is a pressed or unpressed button, announced as a toggle (`aria-pressed`). Each\n * chip in a row is independent, so a row of them is a set of filters, not a choice of one. For a\n * set of chips that act together (one of, or several of, one field), use {@link ChipGroup |\n * ChipGroup}.\n *\n * @privateRemarks\n * A pressable filter chip — an on/off switch that reads as a word (\"Mine\", \"Overdue\n * only\"). Built on Radix Toggle, so it is a real `<button aria-pressed>`; use\n * `pressed`/`onPressedChange` (controlled) or `defaultPressed`.\n *\n * Pressed chips take the accent's soft fill. Where the theme has a hard press shadow\n * (Fiesta), resting chips stand proud and pressed chips sit flat — literally pushed in.\n */\nexport const ToggleChip = forwardRef<HTMLButtonElement, ToggleChipProps>(function ToggleChip(\n { size = 'md', icon, count, className, children, type, ...rest },\n ref,\n) {\n return (\n <Toggle.Root\n ref={ref}\n type={type ?? 'button'}\n className={cx(styles.chip, className)}\n data-size={size}\n {...rest}\n >\n {icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className={styles.label}>{children}</span>\n {count !== undefined ? <span className={styles.count}>{count}</span> : null}\n </Toggle.Root>\n )\n})\n"],"mappings":";;;;;;AAgCA,IAAaE,IAAaC,EAA+C,SACvE,EAAE,UAAO,MAAM,SAAM,UAAO,cAAW,aAAU,SAAM,GAAGC,KAC1D,GACA;CACA,OACE,kBAACC,EAAO,MAAR;EACO;EACL,MAAMC,KAAQ;EACd,WAAWC,EAAGP,EAAO,MAAMQ,CAAS;EACpC,aAAWC;EACX,GAAIL;EALN,UAAA;GAOGM,IACC,kBAAC,QAAD;IAAM,WAAWV,EAAO;IAAM,eAAY;IACvC,UAAAU;GACG,CAAA,IACJ;GACJ,kBAAC,QAAD;IAAM,WAAWV,EAAO;IAAQ;GAAe,CAAA;GAC9CW,MAAU,KAAA,IAA4D,OAAhD,kBAAC,QAAD;IAAM,WAAWX,EAAO;IAAQ,UAAAW;GAAY,CAAA;EACxD;;AAEjB,CAAC"}
1
+ {"version":3,"file":"ToggleChip.js","names":["styles","chip_module_default","ToggleChip","forwardRef","rest","Toggle","type","cx","className","size","icon","trailing","count"],"sources":["../../../../src/components/actions/ToggleChip/ToggleChip.tsx"],"sourcesContent":["import { forwardRef, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport { Toggle } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport styles from './chip.module.css'\n\nexport type ToggleChipSize = 'sm' | 'md'\n\nexport interface ToggleChipProps extends ComponentPropsWithoutRef<typeof Toggle.Root> {\n size?: ToggleChipSize\n /** A leading glyph. Keep it meaningful — one icon per row at most. */\n icon?: ReactNode\n /** How many items the filter matches. Rendered in tabular figures after the label. */\n count?: number\n /**\n * Content after the label, spaced from it: an `AvatarGroup` of who reacted, a small figure.\n * Keep it phrasing content, since the chip is a button.\n */\n trailing?: ReactNode\n}\n\n/**\n * An independent on-off filter that sits in a row with others, with an optional count.\n *\n * @remarks\n * A `ToggleChip` is a pressed or unpressed button, announced as a toggle (`aria-pressed`). Each\n * chip in a row is independent, so a row of them is a set of filters, not a choice of one. For a\n * set of chips that act together (one of, or several of, one field), use {@link ChipGroup |\n * ChipGroup}.\n *\n * @privateRemarks\n * A pressable filter chip — an on/off switch that reads as a word (\"Mine\", \"Overdue\n * only\"). Built on Radix Toggle, so it is a real `<button aria-pressed>`; use\n * `pressed`/`onPressedChange` (controlled) or `defaultPressed`.\n *\n * Pressed chips take the accent's soft fill. Where the theme has a hard press shadow\n * (Fiesta), resting chips stand proud and pressed chips sit flat — literally pushed in.\n */\nexport const ToggleChip = forwardRef<HTMLButtonElement, ToggleChipProps>(function ToggleChip(\n { size = 'md', icon, count, trailing, className, children, type, ...rest },\n ref,\n) {\n return (\n <Toggle.Root\n ref={ref}\n type={type ?? 'button'}\n className={cx(styles.chip, className)}\n data-size={size}\n {...rest}\n >\n {icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className={styles.label}>{children}</span>\n {trailing !== undefined ? <span className={styles.trailing}>{trailing}</span> : null}\n {count !== undefined ? <span className={styles.count}>{count}</span> : null}\n </Toggle.Root>\n )\n})\n"],"mappings":";;;;;;AAqCA,IAAaE,IAAaC,EAA+C,SACvE,EAAE,UAAO,MAAM,SAAM,UAAO,aAAU,cAAW,aAAU,SAAM,GAAGC,KACpE,GACA;CACA,OACE,kBAACC,EAAO,MAAR;EACO;EACL,MAAMC,KAAQ;EACd,WAAWC,EAAGP,EAAO,MAAMQ,CAAS;EACpC,aAAWC;EACX,GAAIL;EALN,UAAA;GAOGM,IACC,kBAAC,QAAD;IAAM,WAAWV,EAAO;IAAM,eAAY;IACvC,UAAAU;GACG,CAAA,IACJ;GACJ,kBAAC,QAAD;IAAM,WAAWV,EAAO;IAAQ;GAAe,CAAA;GAC9CW,MAAa,KAAA,IAAkE,OAAtD,kBAAC,QAAD;IAAM,WAAWX,EAAO;IAAW,UAAAW;GAAe,CAAA;GAC3EC,MAAU,KAAA,IAA4D,OAAhD,kBAAC,QAAD;IAAM,WAAWZ,EAAO;IAAQ,UAAAY;GAAY,CAAA;EACxD;;AAEjB,CAAC"}
@@ -1,10 +1,11 @@
1
1
  //#region src/components/actions/ToggleChip/chip.module.css
2
- var e = "kiln-chip__chip", t = "kiln-chip__icon", n = "kiln-chip__count", r = {
2
+ var e = "kiln-chip__chip", t = "kiln-chip__icon", n = "kiln-chip__trailing", r = "kiln-chip__count", i = {
3
3
  chip: e,
4
4
  icon: t,
5
- count: n
5
+ trailing: n,
6
+ count: r
6
7
  };
7
8
  //#endregion
8
- export { e as chip, n as count, r as default, t as icon };
9
+ export { e as chip, r as count, i as default, t as icon, n as trailing };
9
10
 
10
11
  //# sourceMappingURL=chip.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chip.module.js","names":["chip","icon","count","chip_module_default"],"sources":["../../../../src/components/actions/ToggleChip/chip.module.css"],"sourcesContent":["/*\n * The chip look, shared by ToggleChip (Radix Toggle) and ChipGroup's items (Radix\n * ToggleGroup items) — both expose `data-state=\"on|off\"`, so one module styles both.\n * Internal: import it only from those two components.\n *\n * Component tokens:\n * --chip-radius default var(--radius-chip)\n * --chip-shadow resting shadow; default var(--shadow-active) (flat except Fiesta)\n * --chip-pressed-bg default var(--color-accent-soft)\n * --chip-pressed-ink default var(--color-accent-text)\n * --chip-pressed-line default var(--color-accent)\n */\n.chip {\n --_h: var(--control-sm);\n --_px: var(--space-3);\n --_fs: var(--text-sm);\n --_bg: transparent;\n --_ink: var(--color-ink-muted);\n --_line: var(--color-line-strong);\n --_shadow: var(--chip-shadow, var(--shadow-active));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 0.4em;\n min-block-size: var(--_h);\n padding-inline: var(--_px);\n padding-block: 0;\n border: var(--border-width) solid var(--_line);\n border-radius: var(--chip-radius, var(--radius-chip));\n background: var(--_bg);\n color: var(--_ink);\n box-shadow: var(--_shadow);\n font-family: var(--font-text);\n font-size: var(--_fs);\n font-weight: var(--label-weight);\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n line-height: 1;\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-2) var(--ease-spring);\n}\n\n/* Grow the hit area to a comfortable touch target without changing the visual size. */\n.chip::after {\n content: '';\n position: absolute;\n inset-inline: 0;\n inset-block: min(0px, calc((var(--_h) - var(--control-lg)) / 2));\n}\n\n.chip[data-size='sm'] {\n --_h: calc(var(--control-sm) * 0.8125);\n --_px: var(--space-2);\n --_fs: var(--text-xs);\n}\n\n@media (hover: hover) {\n .chip:hover:not(:disabled) {\n --_ink: var(--color-ink);\n --_line: var(--color-ink-subtle);\n }\n}\n\n.chip[data-state='on'] {\n --_bg: var(--chip-pressed-bg, var(--color-accent-soft));\n --_ink: var(--chip-pressed-ink, var(--color-accent-text));\n --_line: var(--chip-pressed-line, var(--color-accent));\n --_shadow: none;\n\n translate: var(--active-shift) var(--active-shift);\n}\n@media (hover: hover) {\n .chip[data-state='on']:hover:not(:disabled) {\n --_ink: var(--chip-pressed-ink, var(--color-accent-text));\n --_line: var(--chip-pressed-line, var(--color-accent));\n }\n}\n\n/* In an invalid ChipGroup the resting chips take the critical edge; pressed ones keep theirs. */\n.chip[data-invalid]:not([data-state='on']) {\n --_line: var(--tone-critical);\n}\n\n.chip:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.chip:disabled {\n cursor: not-allowed;\n opacity: 0.45;\n box-shadow: none;\n}\n\n.icon {\n display: inline-flex;\n font-size: 1.15em;\n margin-inline-start: -0.15em;\n}\n\n.count {\n display: inline-grid;\n place-items: center;\n min-inline-size: 1.6em;\n padding-inline: 0.35em;\n margin-inline-end: -0.35em;\n block-size: 1.6em;\n border-radius: var(--chip-radius, var(--radius-chip));\n background: var(--color-surface-sunken);\n color: var(--color-ink-muted);\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-size: 0.85em;\n font-weight: var(--label-weight);\n letter-spacing: 0;\n transition:\n background-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out);\n}\n.chip[data-state='on'] .count {\n background: var(--chip-pressed-line, var(--color-accent));\n color: var(--color-accent-ink);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"chip.module.js","names":["chip","icon","trailing","count","chip_module_default"],"sources":["../../../../src/components/actions/ToggleChip/chip.module.css"],"sourcesContent":["/*\n * The chip look, shared by ToggleChip (Radix Toggle) and ChipGroup's items (Radix\n * ToggleGroup items). Pressed is read from ARIA (aria-pressed, or aria-checked on a\n * single-choice group's radios), not data-state: an asChild trigger wrapped round a chip\n * (Tooltip, Popover) writes its own data-state over the Toggle's.\n * Internal: import it only from those two components.\n *\n * Component tokens:\n * --chip-radius default var(--radius-chip)\n * --chip-shadow resting shadow; default var(--shadow-active) (flat except Fiesta)\n * --chip-pressed-bg default var(--color-accent-soft)\n * --chip-pressed-ink default var(--color-accent-text)\n * --chip-pressed-line default var(--color-accent)\n */\n.chip {\n --_h: var(--control-sm);\n --_px: var(--space-3);\n --_fs: var(--text-sm);\n --_bg: transparent;\n --_ink: var(--color-ink-muted);\n --_line: var(--color-line-strong);\n --_shadow: var(--chip-shadow, var(--shadow-active));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 0.4em;\n min-block-size: var(--_h);\n padding-inline: var(--_px);\n padding-block: 0;\n border: var(--border-width) solid var(--_line);\n border-radius: var(--chip-radius, var(--radius-chip));\n background: var(--_bg);\n color: var(--_ink);\n box-shadow: var(--_shadow);\n font-family: var(--font-text);\n font-size: var(--_fs);\n font-weight: var(--label-weight);\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n line-height: 1;\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-2) var(--ease-spring);\n}\n\n/* Grow the hit area to a comfortable touch target without changing the visual size. */\n.chip::after {\n content: '';\n position: absolute;\n inset-inline: 0;\n inset-block: min(0px, calc((var(--_h) - var(--control-lg)) / 2));\n}\n\n.chip[data-size='sm'] {\n --_h: calc(var(--control-sm) * 0.8125);\n --_px: var(--space-2);\n --_fs: var(--text-xs);\n}\n\n@media (hover: hover) {\n .chip:hover:not(:disabled, [aria-disabled='true']) {\n --_ink: var(--color-ink);\n --_line: var(--color-ink-subtle);\n }\n}\n\n.chip:is([aria-pressed='true'], [aria-checked='true']) {\n --_bg: var(--chip-pressed-bg, var(--color-accent-soft));\n --_ink: var(--chip-pressed-ink, var(--color-accent-text));\n --_line: var(--chip-pressed-line, var(--color-accent));\n --_shadow: none;\n\n translate: var(--active-shift) var(--active-shift);\n}\n@media (hover: hover) {\n .chip:is([aria-pressed='true'], [aria-checked='true']):hover:not(\n :disabled,\n [aria-disabled='true']\n ) {\n --_ink: var(--chip-pressed-ink, var(--color-accent-text));\n --_line: var(--chip-pressed-line, var(--color-accent));\n }\n}\n\n/* In an invalid ChipGroup the resting chips take the critical edge; pressed ones keep theirs. */\n.chip[data-invalid]:not([aria-pressed='true'], [aria-checked='true']) {\n --_line: var(--tone-critical);\n}\n\n.chip:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.chip:is(:disabled, [aria-disabled='true']) {\n cursor: not-allowed;\n opacity: 0.45;\n box-shadow: none;\n}\n\n.icon {\n display: inline-flex;\n font-size: 1.15em;\n margin-inline-start: -0.15em;\n}\n\n.trailing {\n display: inline-flex;\n align-items: center;\n}\n\n.count {\n display: inline-grid;\n place-items: center;\n min-inline-size: 1.6em;\n padding-inline: 0.35em;\n margin-inline-end: -0.35em;\n block-size: 1.6em;\n border-radius: var(--chip-radius, var(--radius-chip));\n background: var(--color-surface-sunken);\n color: var(--color-ink-muted);\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-size: 0.85em;\n font-weight: var(--label-weight);\n letter-spacing: 0;\n transition:\n background-color var(--dur-1) var(--ease-out),\n color var(--dur-1) var(--ease-out);\n}\n.chip:is([aria-pressed='true'], [aria-checked='true']) .count {\n background: var(--chip-pressed-line, var(--color-accent));\n color: var(--color-accent-ink);\n}\n"],"mappings":""}
@@ -1,6 +1,6 @@
1
1
  import { type HTMLAttributes } from 'react';
2
2
  import { type AvatarSize } from '../Avatar/index.js';
3
- export interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {
3
+ export interface AvatarGroupProps extends HTMLAttributes<HTMLElement> {
4
4
  /** Show at most this many avatars; the rest collapse into a "+N" count. */
5
5
  max?: number;
6
6
  /** Size for every avatar in the stack. Default `sm`. */
@@ -20,4 +20,4 @@ export interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {
20
20
  *
21
21
  * <AvatarGroup max={4} aria-label="Members"><Avatar name="Noor" />…</AvatarGroup>
22
22
  */
23
- export declare const AvatarGroup: import("react").ForwardRefExoticComponent<AvatarGroupProps & import("react").RefAttributes<HTMLDivElement>>;
23
+ export declare const AvatarGroup: import("react").ForwardRefExoticComponent<AvatarGroupProps & import("react").RefAttributes<HTMLElement>>;
@@ -8,7 +8,7 @@ var c = i(function({ max: i, size: c = "sm", className: l, children: u, ...d },
8
8
  let p = r.toArray(u).filter(a), m = i !== void 0 && i >= 0 && p.length > i ? i : p.length, h = p.length - m;
9
9
  return /* @__PURE__ */ o(t.Provider, {
10
10
  value: c,
11
- children: /* @__PURE__ */ s("div", {
11
+ children: /* @__PURE__ */ s("span", {
12
12
  ref: f,
13
13
  role: "group",
14
14
  className: e(n.group, l),
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.js","names":["styles","AvatarGroup_module_default","AvatarGroup","forwardRef","rest","items","Children","children","isValidElement","limit","max","overflow","AvatarSizeContext","size","cx","className"],"sources":["../../../../src/components/display/AvatarGroup/AvatarGroup.tsx"],"sourcesContent":["import { Children, forwardRef, isValidElement, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { AvatarSizeContext, type AvatarSize } from '#components/display/Avatar'\nimport styles from './AvatarGroup.module.css'\n\nexport interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Show at most this many avatars; the rest collapse into a \"+N\" count. */\n max?: number\n /** Size for every avatar in the stack. Default `sm`. */\n size?: AvatarSize\n /** Accessible name for the group, e.g. \"Reacted: Noor, Kofi and 3 others\". */\n 'aria-label'?: string\n}\n\n/**\n * An overlapping row of avatars, like who's on a crew or who reacted, with a count for the rest.\n *\n * @remarks\n * `AvatarGroup` overlaps its `Avatar` children and, past `max`, replaces the rest with a count.\n * Give it an `aria-label` that names the group.\n *\n * @privateRemarks\n * An overlapping stack of `Avatar`s — who reacted, who owns a project, who's in a group.\n *\n * <AvatarGroup max={4} aria-label=\"Members\"><Avatar name=\"Noor\" />…</AvatarGroup>\n */\nexport const AvatarGroup = forwardRef<HTMLDivElement, AvatarGroupProps>(function AvatarGroup(\n { max, size = 'sm', className, children, ...rest },\n ref,\n) {\n const items = Children.toArray(children).filter(isValidElement)\n const limit = max !== undefined && max >= 0 && items.length > max ? max : items.length\n const overflow = items.length - limit\n return (\n <AvatarSizeContext.Provider value={size}>\n <div\n ref={ref}\n role=\"group\"\n className={cx(styles.group, className)}\n data-size={size}\n {...rest}\n >\n {items.slice(0, limit)}\n {overflow > 0 ? (\n <span\n className={styles.more}\n data-size={size}\n role=\"img\"\n aria-label={`${String(overflow)} more`}\n >\n <span aria-hidden=\"true\">+{overflow}</span>\n </span>\n ) : null}\n </div>\n </AvatarSizeContext.Provider>\n )\n})\n"],"mappings":";;;;;;AA0BA,IAAaE,IAAcC,EAA6C,SACtE,EAAE,QAAK,UAAO,MAAM,cAAW,aAAU,GAAGC,KAC5C,GACA;CACA,IAAMC,IAAQC,EAAS,QAAQC,CAAQ,CAAC,CAAC,OAAOC,CAAc,GACxDC,IAAQC,MAAQ,KAAA,KAAaA,KAAO,KAAKL,EAAM,SAASK,IAAMA,IAAML,EAAM,QAC1EM,IAAWN,EAAM,SAASI;CAChC,OACE,kBAACG,EAAkB,UAAnB;EAA4B,OAAOC;EACjC,UAAA,kBAAC,OAAD;GACO;GACL,MAAK;GACL,WAAWC,EAAGd,EAAO,OAAOe,CAAS;GACrC,aAAWF;GACX,GAAIT;GALN,UAAA,CAOGC,EAAM,MAAM,GAAGI,CAAK,GACpBE,IAAW,IACV,kBAAC,QAAD;IACE,WAAWX,EAAO;IAClB,aAAWa;IACX,MAAK;IACL,cAAY,GAAG,OAAOF,CAAQ,EAAE;IAEhC,UAAA,kBAAC,QAAD;KAAM,eAAY;KAAlB,UAAA,CAAyB,KAAEA,CAAe;;GACtC,CAAA,IACJ,IACD;;CACqB,CAAA;AAEhC,CAAC"}
1
+ {"version":3,"file":"AvatarGroup.js","names":["styles","AvatarGroup_module_default","AvatarGroup","forwardRef","rest","items","Children","children","isValidElement","limit","max","overflow","AvatarSizeContext","size","cx","className"],"sources":["../../../../src/components/display/AvatarGroup/AvatarGroup.tsx"],"sourcesContent":["import { Children, forwardRef, isValidElement, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { AvatarSizeContext, type AvatarSize } from '#components/display/Avatar'\nimport styles from './AvatarGroup.module.css'\n\nexport interface AvatarGroupProps extends HTMLAttributes<HTMLElement> {\n /** Show at most this many avatars; the rest collapse into a \"+N\" count. */\n max?: number\n /** Size for every avatar in the stack. Default `sm`. */\n size?: AvatarSize\n /** Accessible name for the group, e.g. \"Reacted: Noor, Kofi and 3 others\". */\n 'aria-label'?: string\n}\n\n/**\n * An overlapping row of avatars, like who's on a crew or who reacted, with a count for the rest.\n *\n * @remarks\n * `AvatarGroup` overlaps its `Avatar` children and, past `max`, replaces the rest with a count.\n * Give it an `aria-label` that names the group.\n *\n * @privateRemarks\n * An overlapping stack of `Avatar`s — who reacted, who owns a project, who's in a group.\n *\n * <AvatarGroup max={4} aria-label=\"Members\"><Avatar name=\"Noor\" />…</AvatarGroup>\n */\nexport const AvatarGroup = forwardRef<HTMLElement, AvatarGroupProps>(function AvatarGroup(\n { max, size = 'sm', className, children, ...rest },\n ref,\n) {\n const items = Children.toArray(children).filter(isValidElement)\n const limit = max !== undefined && max >= 0 && items.length > max ? max : items.length\n const overflow = items.length - limit\n return (\n <AvatarSizeContext.Provider value={size}>\n {/* A span, like Avatar, so a group can sit inside a button or a line of text. */}\n <span\n ref={ref}\n role=\"group\"\n className={cx(styles.group, className)}\n data-size={size}\n {...rest}\n >\n {items.slice(0, limit)}\n {overflow > 0 ? (\n <span\n className={styles.more}\n data-size={size}\n role=\"img\"\n aria-label={`${String(overflow)} more`}\n >\n <span aria-hidden=\"true\">+{overflow}</span>\n </span>\n ) : null}\n </span>\n </AvatarSizeContext.Provider>\n )\n})\n"],"mappings":";;;;;;AA0BA,IAAaE,IAAcC,EAA0C,SACnE,EAAE,QAAK,UAAO,MAAM,cAAW,aAAU,GAAGC,KAC5C,GACA;CACA,IAAMC,IAAQC,EAAS,QAAQC,CAAQ,CAAC,CAAC,OAAOC,CAAc,GACxDC,IAAQC,MAAQ,KAAA,KAAaA,KAAO,KAAKL,EAAM,SAASK,IAAMA,IAAML,EAAM,QAC1EM,IAAWN,EAAM,SAASI;CAChC,OACE,kBAACG,EAAkB,UAAnB;EAA4B,OAAOC;EAEjC,UAAA,kBAAC,QAAD;GACO;GACL,MAAK;GACL,WAAWC,EAAGd,EAAO,OAAOe,CAAS;GACrC,aAAWF;GACX,GAAIT;GALN,UAAA,CAOGC,EAAM,MAAM,GAAGI,CAAK,GACpBE,IAAW,IACV,kBAAC,QAAD;IACE,WAAWX,EAAO;IAClB,aAAWa;IACX,MAAK;IACL,cAAY,GAAG,OAAOF,CAAQ,EAAE;IAEhC,UAAA,kBAAC,QAAD;KAAM,eAAY;KAAlB,UAAA,CAAyB,KAAEA,CAAe;;GACtC,CAAA,IACJ,IACA;;CACoB,CAAA;AAEhC,CAAC"}
@@ -1,16 +1,19 @@
1
1
  import { type HTMLAttributes } from 'react';
2
2
  import { type Responsive } from '../../../utils/responsive.js';
3
- import { type Space } from '../../../utils/tokens.js';
4
- export type CardVariant = 'plain' | 'outline' | 'raised';
3
+ import { type CategoryColor, type Space } from '../../../utils/tokens.js';
4
+ export type CardVariant = 'plain' | 'outline' | 'raised' | 'live' | 'placeholder';
5
5
  export type CardTitleLevel = 2 | 3 | 4 | 5 | 6;
6
6
  export type CardMediaRatio = '1/1' | '4/3' | '3/2' | '16/9' | '21/9';
7
- export interface CardProps extends HTMLAttributes<HTMLDivElement> {
7
+ export interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
8
8
  /**
9
9
  * Edge treatment. `outline` (default) is a hairline; `plain` is a fill with no edge;
10
10
  * `raised` stands on `--shadow-surface` (nothing extra in Monograph/Ledger, the print
11
- * offset in Fiesta).
11
+ * offset in Fiesta). `live` is a heavier keyline in the accent, for something happening now;
12
+ * `placeholder` has no fill and crop marks at its corners, for a slot not yet decided.
12
13
  */
13
14
  variant?: CardVariant;
15
+ /** A categorical colour drawn as a keyline along the top: whose card it is, matching their `Tag`. */
16
+ color?: CategoryColor;
14
17
  /** Inner padding as a space step. Responsive. Default `5`. */
15
18
  padding?: Responsive<Space>;
16
19
  /** Hover/press affordance for cards that *are* the action. Implied by `asChild`. */
@@ -7,16 +7,17 @@ import { forwardRef as o } from "react";
7
7
  import { jsx as s } from "react/jsx-runtime";
8
8
  import { Slot as c } from "radix-ui";
9
9
  //#region src/components/display/Card/Card.tsx
10
- var l = o(function({ variant: i = "outline", padding: o, interactive: l = !1, asChild: u = !1, className: d, style: f, ...p }, m) {
11
- let h = u ? c.Root : "div";
12
- return /* @__PURE__ */ s(h, {
13
- ref: m,
14
- className: e(a.card, d),
10
+ var l = o(function({ variant: i = "outline", padding: o, interactive: l = !1, asChild: u = !1, color: d, className: f, style: p, ...m }, h) {
11
+ let g = u ? c.Root : "div";
12
+ return /* @__PURE__ */ s(g, {
13
+ ref: h,
14
+ className: e(a.card, f),
15
15
  "data-kiln-component": "",
16
16
  "data-variant": i,
17
+ "data-color": d,
17
18
  "data-interactive": l || u || void 0,
18
- style: t(n("card-padding", o, r), f),
19
- ...p
19
+ style: t(n("card-padding", o, r), p),
20
+ ...m
20
21
  });
21
22
  }), u = o(function({ ratio: t, inset: n = !1, className: r, ...i }, o) {
22
23
  return /* @__PURE__ */ s("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"Card.js","names":["styles","Card_module_default","CardRoot","forwardRef","rest","Comp","asChild","Slot","cx","className","variant","interactive","mergeStyles","responsiveVars","padding","space","style","CardMedia","ratio","inset","CardHeader","CardTitle","Tag","headingTag","level","CardDescription","CardBody","CardFooter","CardMeta","Card"],"sources":["../../../../src/components/display/Card/Card.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type Space } from '#utils/tokens'\nimport styles from './Card.module.css'\nimport { headingTag } from '#utils/heading'\n\nexport type CardVariant = 'plain' | 'outline' | 'raised'\nexport type CardTitleLevel = 2 | 3 | 4 | 5 | 6\nexport type CardMediaRatio = '1/1' | '4/3' | '3/2' | '16/9' | '21/9'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Edge treatment. `outline` (default) is a hairline; `plain` is a fill with no edge;\n * `raised` stands on `--shadow-surface` (nothing extra in Monograph/Ledger, the print\n * offset in Fiesta).\n */\n variant?: CardVariant\n /** Inner padding as a space step. Responsive. Default `5`. */\n padding?: Responsive<Space>\n /** Hover/press affordance for cards that *are* the action. Implied by `asChild`. */\n interactive?: boolean\n /**\n * Render the single child element as the card — usually a link, so the whole card is\n * one target: `<Card asChild><a href=\"/projects/atlas\">…</a></Card>`. Don't nest other\n * links or buttons inside a linked card.\n */\n asChild?: boolean\n}\n\n/**\n * A self-contained object, like a route, a ticket or a project. Use it sparingly; most content\n * reads better without a box.\n *\n * @remarks\n * A `Card` frames one object you could pick up, open or drag. Before reaching for one, try a\n * `List`, a `Table` or a plain section: three identical cards in a row is the most generic layout\n * there is, and most content is better as a document than as a set of boxes.\n *\n * ## Slots\n *\n * `Card.Media`, `Card.Header` (with `Card.Title` and `Card.Meta`), `Card.Description`, `Card.Body`\n * and `Card.Footer`. Use only the ones the object needs. `variant` is `outline` (the default, a\n * hairline), `raised` (the theme's surface shadow) or `plain` (a fill and no edge). `padding`\n * takes a space step.\n *\n * @privateRemarks\n * A self-contained object: a project, a release, a plan summary. Use sparingly —\n * most content reads better as a List, Table or plain section (DESIGN §2).\n *\n * <Card><Card.Header><Card.Title>Atlas</Card.Title><Card.Meta>2026</Card.Meta></Card.Header>…</Card>\n */\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n { variant = 'outline', padding, interactive = false, asChild = false, className, style, ...rest },\n ref,\n) {\n const Comp = asChild ? Slot.Root : 'div'\n return (\n <Comp\n ref={ref}\n className={cx(styles.card, className)}\n data-kiln-component=\"\"\n data-variant={variant}\n data-interactive={interactive || asChild || undefined}\n style={mergeStyles(responsiveVars('card-padding', padding, space), style)}\n {...rest}\n />\n )\n})\n\nexport interface CardMediaProps extends HTMLAttributes<HTMLDivElement> {\n /** Crop the media to a fixed ratio (the child img/video is fitted with `cover`). */\n ratio?: CardMediaRatio\n /**\n * Sit inside the padding instead of bleeding to the edges. The corner radius is then\n * the nested radius (outer − padding).\n */\n inset?: boolean\n}\n\n/** Image/video slot. Bleeds to the card's edges by default; put it first (or last). */\nconst CardMedia = forwardRef<HTMLDivElement, CardMediaProps>(function CardMedia(\n { ratio, inset = false, className, ...rest },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cx(styles.media, className)}\n data-ratio={ratio}\n data-inset={inset || undefined}\n {...rest}\n />\n )\n})\n\nconst CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardHeader(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.header, className)} {...rest} />\n})\n\nexport interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n /** Heading element, to fit the page outline. Visual size doesn't change. Default `3`. */\n level?: CardTitleLevel\n}\n\nconst CardTitle = forwardRef<HTMLHeadingElement, CardTitleProps>(function CardTitle(\n { level = 3, className, ...rest },\n ref,\n) {\n const Tag = headingTag(level)\n return <Tag ref={ref} className={cx(styles.title, className)} {...rest} />\n})\n\nconst CardDescription = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLParagraphElement>>(\n function CardDescription({ className, ...rest }, ref) {\n return <p ref={ref} className={cx(styles.description, className)} {...rest} />\n },\n)\n\nconst CardBody = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardBody(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.body, className)} {...rest} />\n})\n\n/** Actions or summary pinned to the bottom of the card (pushes down in equal-height grids). */\nconst CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardFooter(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.footer, className)} {...rest} />\n})\n\n/** Small secondary facts — year, stack, due date. Numbers are tabular. */\nconst CardMeta = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardMeta(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.meta, className)} {...rest} />\n})\n\nexport const Card = Object.assign(CardRoot, {\n Media: CardMedia,\n Header: CardHeader,\n Title: CardTitle,\n Description: CardDescription,\n Body: CardBody,\n Footer: CardFooter,\n Meta: CardMeta,\n})\n"],"mappings":";;;;;;;;;AAqDA,IAAME,IAAWC,EAAsC,SACrD,EAAE,aAAU,WAAW,YAAS,iBAAc,IAAO,aAAU,IAAO,cAAW,UAAO,GAAGC,KAC3F,GACA;CACA,IAAMC,IAAOC,IAAUC,EAAK,OAAO;CACnC,OACE,kBAACF,GAAD;EACO;EACL,WAAWG,EAAGR,EAAO,MAAMS,CAAS;EACpC,uBAAoB;EACpB,gBAAcC;EACd,oBAAkBC,KAAeL,KAAW,KAAA;EAC5C,OAAOM,EAAYC,EAAe,gBAAgBC,GAASC,CAAK,GAAGC,CAAK;EACxE,GAAIZ;CACL,CAAA;AAEL,CAAC,GAaKa,IAAYd,EAA2C,SAC3D,EAAE,UAAO,WAAQ,IAAO,cAAW,GAAGC,KACtC,GACA;CACA,OACE,kBAAC,OAAD;EACO;EACL,WAAWI,EAAGR,EAAO,OAAOS,CAAS;EACrC,cAAYS;EACZ,cAAYC,KAAS,KAAA;EACrB,GAAIf;CACL,CAAA;AAEL,CAAC,GAEKgB,IAAajB,EAA2D,SAC5E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,QAAQS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC5E,CAAC,GAOKiB,IAAYlB,EAA+C,SAC/D,EAAE,WAAQ,GAAG,cAAW,GAAGC,KAC3B,GACA;CACA,IAAMkB,IAAMC,EAAWC,CAAK;CAC5B,OAAO,kBAACF,GAAD;EAAU;EAAK,WAAWd,EAAGR,EAAO,OAAOS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC3E,CAAC,GAEKqB,IAAkBtB,EACtB,SAAyB,EAAE,cAAW,GAAGC,KAAQ,GAAK;CACpD,OAAO,kBAAC,KAAD;EAAQ;EAAK,WAAWI,EAAGR,EAAO,aAAaS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC/E,CACF,GAEMsB,IAAWvB,EAA2D,SAC1E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,MAAMS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC1E,CAAC,GAGKuB,IAAaxB,EAA2D,SAC5E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,QAAQS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC5E,CAAC,GAGKwB,IAAWzB,EAA2D,SAC1E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,MAAMS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC1E,CAAC,GAEYyB,IAAO,OAAO,OAAO3B,GAAU;CAC1C,OAAOe;CACP,QAAQG;CACR,OAAOC;CACP,aAAaI;CACb,MAAMC;CACN,QAAQC;CACR,MAAMC;AACR,CAAC"}
1
+ {"version":3,"file":"Card.js","names":["styles","Card_module_default","CardRoot","forwardRef","rest","Comp","asChild","Slot","cx","className","variant","color","interactive","mergeStyles","responsiveVars","padding","space","style","CardMedia","ratio","inset","CardHeader","CardTitle","Tag","headingTag","level","CardDescription","CardBody","CardFooter","CardMeta","Card"],"sources":["../../../../src/components/display/Card/Card.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type CategoryColor, type Space } from '#utils/tokens'\nimport styles from './Card.module.css'\nimport { headingTag } from '#utils/heading'\n\nexport type CardVariant = 'plain' | 'outline' | 'raised' | 'live' | 'placeholder'\nexport type CardTitleLevel = 2 | 3 | 4 | 5 | 6\nexport type CardMediaRatio = '1/1' | '4/3' | '3/2' | '16/9' | '21/9'\n\nexport interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {\n /**\n * Edge treatment. `outline` (default) is a hairline; `plain` is a fill with no edge;\n * `raised` stands on `--shadow-surface` (nothing extra in Monograph/Ledger, the print\n * offset in Fiesta). `live` is a heavier keyline in the accent, for something happening now;\n * `placeholder` has no fill and crop marks at its corners, for a slot not yet decided.\n */\n variant?: CardVariant\n /** A categorical colour drawn as a keyline along the top: whose card it is, matching their `Tag`. */\n color?: CategoryColor\n /** Inner padding as a space step. Responsive. Default `5`. */\n padding?: Responsive<Space>\n /** Hover/press affordance for cards that *are* the action. Implied by `asChild`. */\n interactive?: boolean\n /**\n * Render the single child element as the card — usually a link, so the whole card is\n * one target: `<Card asChild><a href=\"/projects/atlas\">…</a></Card>`. Don't nest other\n * links or buttons inside a linked card.\n */\n asChild?: boolean\n}\n\n/**\n * A self-contained object, like a route, a ticket or a project. Use it sparingly; most content\n * reads better without a box.\n *\n * @remarks\n * A `Card` frames one object you could pick up, open or drag. Before reaching for one, try a\n * `List`, a `Table` or a plain section: three identical cards in a row is the most generic layout\n * there is, and most content is better as a document than as a set of boxes.\n *\n * ## Slots\n *\n * `Card.Media`, `Card.Header` (with `Card.Title` and `Card.Meta`), `Card.Description`, `Card.Body`\n * and `Card.Footer`. Use only the ones the object needs. `variant` is `outline` (the default, a\n * hairline), `raised` (the theme's surface shadow) or `plain` (a fill and no edge). `padding`\n * takes a space step.\n *\n * @privateRemarks\n * A self-contained object: a project, a release, a plan summary. Use sparingly —\n * most content reads better as a List, Table or plain section (DESIGN §2).\n *\n * <Card><Card.Header><Card.Title>Atlas</Card.Title><Card.Meta>2026</Card.Meta></Card.Header>…</Card>\n */\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'outline',\n padding,\n interactive = false,\n asChild = false,\n color,\n className,\n style,\n ...rest\n },\n ref,\n) {\n const Comp = asChild ? Slot.Root : 'div'\n return (\n <Comp\n ref={ref}\n className={cx(styles.card, className)}\n data-kiln-component=\"\"\n data-variant={variant}\n data-color={color}\n data-interactive={interactive || asChild || undefined}\n style={mergeStyles(responsiveVars('card-padding', padding, space), style)}\n {...rest}\n />\n )\n})\n\nexport interface CardMediaProps extends HTMLAttributes<HTMLDivElement> {\n /** Crop the media to a fixed ratio (the child img/video is fitted with `cover`). */\n ratio?: CardMediaRatio\n /**\n * Sit inside the padding instead of bleeding to the edges. The corner radius is then\n * the nested radius (outer − padding).\n */\n inset?: boolean\n}\n\n/** Image/video slot. Bleeds to the card's edges by default; put it first (or last). */\nconst CardMedia = forwardRef<HTMLDivElement, CardMediaProps>(function CardMedia(\n { ratio, inset = false, className, ...rest },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cx(styles.media, className)}\n data-ratio={ratio}\n data-inset={inset || undefined}\n {...rest}\n />\n )\n})\n\nconst CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardHeader(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.header, className)} {...rest} />\n})\n\nexport interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n /** Heading element, to fit the page outline. Visual size doesn't change. Default `3`. */\n level?: CardTitleLevel\n}\n\nconst CardTitle = forwardRef<HTMLHeadingElement, CardTitleProps>(function CardTitle(\n { level = 3, className, ...rest },\n ref,\n) {\n const Tag = headingTag(level)\n return <Tag ref={ref} className={cx(styles.title, className)} {...rest} />\n})\n\nconst CardDescription = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLParagraphElement>>(\n function CardDescription({ className, ...rest }, ref) {\n return <p ref={ref} className={cx(styles.description, className)} {...rest} />\n },\n)\n\nconst CardBody = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardBody(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.body, className)} {...rest} />\n})\n\n/** Actions or summary pinned to the bottom of the card (pushes down in equal-height grids). */\nconst CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardFooter(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.footer, className)} {...rest} />\n})\n\n/** Small secondary facts — year, stack, due date. Numbers are tabular. */\nconst CardMeta = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function CardMeta(\n { className, ...rest },\n ref,\n) {\n return <div ref={ref} className={cx(styles.meta, className)} {...rest} />\n})\n\nexport const Card = Object.assign(CardRoot, {\n Media: CardMedia,\n Header: CardHeader,\n Title: CardTitle,\n Description: CardDescription,\n Body: CardBody,\n Footer: CardFooter,\n Meta: CardMeta,\n})\n"],"mappings":";;;;;;;;;AAwDA,IAAME,IAAWC,EAAsC,SACrD,EACE,aAAU,WACV,YACA,iBAAc,IACd,aAAU,IACV,UACA,cACA,UACA,GAAGC,KAEL,GACA;CACA,IAAMC,IAAOC,IAAUC,EAAK,OAAO;CACnC,OACE,kBAACF,GAAD;EACO;EACL,WAAWG,EAAGR,EAAO,MAAMS,CAAS;EACpC,uBAAoB;EACpB,gBAAcC;EACd,cAAYC;EACZ,oBAAkBC,KAAeN,KAAW,KAAA;EAC5C,OAAOO,EAAYC,EAAe,gBAAgBC,GAASC,CAAK,GAAGC,CAAK;EACxE,GAAIb;CACL,CAAA;AAEL,CAAC,GAaKc,IAAYf,EAA2C,SAC3D,EAAE,UAAO,WAAQ,IAAO,cAAW,GAAGC,KACtC,GACA;CACA,OACE,kBAAC,OAAD;EACO;EACL,WAAWI,EAAGR,EAAO,OAAOS,CAAS;EACrC,cAAYU;EACZ,cAAYC,KAAS,KAAA;EACrB,GAAIhB;CACL,CAAA;AAEL,CAAC,GAEKiB,IAAalB,EAA2D,SAC5E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,QAAQS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC5E,CAAC,GAOKkB,IAAYnB,EAA+C,SAC/D,EAAE,WAAQ,GAAG,cAAW,GAAGC,KAC3B,GACA;CACA,IAAMmB,IAAMC,EAAWC,CAAK;CAC5B,OAAO,kBAACF,GAAD;EAAU;EAAK,WAAWf,EAAGR,EAAO,OAAOS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC3E,CAAC,GAEKsB,IAAkBvB,EACtB,SAAyB,EAAE,cAAW,GAAGC,KAAQ,GAAK;CACpD,OAAO,kBAAC,KAAD;EAAQ;EAAK,WAAWI,EAAGR,EAAO,aAAaS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC/E,CACF,GAEMuB,IAAWxB,EAA2D,SAC1E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,MAAMS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC1E,CAAC,GAGKwB,IAAazB,EAA2D,SAC5E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,QAAQS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC5E,CAAC,GAGKyB,IAAW1B,EAA2D,SAC1E,EAAE,cAAW,GAAGC,KAChB,GACA;CACA,OAAO,kBAAC,OAAD;EAAU;EAAK,WAAWI,EAAGR,EAAO,MAAMS,CAAS;EAAG,GAAIL;CAAO,CAAA;AAC1E,CAAC,GAEY0B,IAAO,OAAO,OAAO5B,GAAU;CAC1C,OAAOgB;CACP,QAAQG;CACR,OAAOC;CACP,aAAaI;CACb,MAAMC;CACN,QAAQC;CACR,MAAMC;AACR,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Card.module.js","names":["card","media","header","title","description","body","footer","meta","Card_module_default"],"sources":["../../../../src/components/display/Card/Card.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --card-radius default var(--radius-surface)\n * --card-bg default var(--color-surface)\n * --card-shadow default var(--shadow-surface) for `raised`\n *\n * The root is `position: relative`, so absolutely placed children (a corner <Stamp>)\n * anchor to the card.\n *\n * Responsive padding: the component writes --card-padding-{bp}; the root resolves them\n * into --card-inset per breakpoint. Slots (Media) read the *resolved* --card-inset and\n * --card-inner-radius, which inherit as computed values — never set them yourself.\n */\n.card {\n --card-inset: var(--card-padding-base, var(--space-5));\n --card-inner-radius: calc(var(--card-radius, var(--radius-surface)) - var(--border-width));\n --_bg: var(--card-bg, var(--color-surface));\n --_bg-hover: var(--color-surface-raised);\n --_border: var(--color-line);\n --_border-hover: var(--color-line-strong);\n --_shadow: none;\n\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n min-inline-size: 0;\n padding: var(--card-inset);\n border: var(--border-width) solid var(--_border);\n border-radius: var(--card-radius, var(--radius-surface));\n background: var(--_bg);\n box-shadow: var(--_shadow);\n color: var(--color-ink);\n font-family: var(--font-text);\n text-decoration: none;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-1) var(--ease-spring);\n}\n\n@media (min-width: 40em) {\n .card {\n --card-inset: var(--card-padding-sm, var(--space-5));\n }\n}\n@media (min-width: 48em) {\n .card {\n --card-inset: var(--card-padding-md, var(--space-5));\n }\n}\n@media (min-width: 64em) {\n .card {\n --card-inset: var(--card-padding-lg, var(--space-5));\n }\n}\n@media (min-width: 80em) {\n .card {\n --card-inset: var(--card-padding-xl, var(--space-5));\n }\n}\n\n/* Variants — one edge treatment each (DESIGN §2). */\n.card[data-variant='plain'] {\n --_bg: var(--card-bg, var(--color-surface));\n --_bg-hover: var(--color-surface-raised);\n --_border: transparent;\n --_border-hover: transparent;\n}\n.card[data-variant='raised'] {\n --_bg: var(--card-bg, var(--color-surface-raised));\n --_bg-hover: var(--color-surface-raised);\n --_border: var(--color-line-strong);\n --_shadow: var(--card-shadow, var(--shadow-surface));\n}\n\n/* Interactive: an edge/fill change, never a scale. Raised cards press toward their shadow. */\n.card[data-interactive] {\n cursor: pointer;\n}\n@media (hover: hover) {\n .card[data-interactive]:hover {\n background: var(--_bg-hover);\n border-color: var(--_border-hover);\n }\n}\n.card[data-interactive][data-variant='raised']:active {\n translate: var(--active-shift) var(--active-shift);\n box-shadow: var(--shadow-active);\n}\n.card:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n/* ── Slots ───────────────────────────────────────────────────────────────── */\n\n.media {\n position: relative;\n overflow: hidden;\n margin-inline: calc(var(--card-inset) * -1);\n background: var(--color-surface-sunken);\n}\n.media:first-child {\n margin-block-start: calc(var(--card-inset) * -1);\n border-start-start-radius: var(--card-inner-radius);\n border-start-end-radius: var(--card-inner-radius);\n}\n.media:last-child {\n margin-block-end: calc(var(--card-inset) * -1);\n border-end-start-radius: var(--card-inner-radius);\n border-end-end-radius: var(--card-inner-radius);\n}\n/* Bled media gets a rule where it meets the content, so the edge reads as structure. */\n.media:first-child:not(:last-child) {\n border-block-end: var(--border-width) solid var(--color-line);\n}\n.media[data-inset] {\n margin: 0;\n border: 0;\n border-radius: max(\n calc(var(--card-radius, var(--radius-surface)) - var(--card-inset)),\n calc(var(--radius-media) / 2)\n );\n}\n.media[data-ratio] > :is(img, video, picture) {\n position: absolute;\n inset: 0;\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n}\n.media > :is(img, video) {\n inline-size: 100%;\n}\n.media[data-ratio='1/1'] {\n aspect-ratio: 1;\n}\n.media[data-ratio='4/3'] {\n aspect-ratio: 4 / 3;\n}\n.media[data-ratio='3/2'] {\n aspect-ratio: 3 / 2;\n}\n.media[data-ratio='16/9'] {\n aspect-ratio: 16 / 9;\n}\n.media[data-ratio='21/9'] {\n aspect-ratio: 21 / 9;\n}\n\n/* The media → header step is larger than the rhythm between text slots. */\n.media:first-child + * {\n margin-block-start: var(--space-2);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-1) var(--space-3);\n min-inline-size: 0;\n}\n.header > :first-child {\n min-inline-size: 0;\n}\n\n.title {\n margin: 0;\n font-family: var(--heading-font);\n font-weight: var(--heading-weight);\n letter-spacing: var(--heading-tracking);\n text-transform: var(--heading-transform);\n font-size: var(--card-title-size, var(--text-xl));\n line-height: var(--leading-snug);\n color: var(--color-ink);\n}\n\n.description {\n margin: 0;\n max-inline-size: 60ch;\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n line-height: var(--leading-body);\n}\n\n.body {\n min-inline-size: 0;\n font-size: var(--text-md);\n line-height: var(--leading-body);\n}\n\n.footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2) var(--space-3);\n margin-block-start: auto;\n padding-block-start: var(--space-2);\n}\n\n.meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n color: var(--color-ink-subtle);\n font-size: var(--text-xs);\n font-variant-numeric: lining-nums;\n line-height: var(--leading-snug);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Card.module.js","names":["card","media","header","title","description","body","footer","meta","Card_module_default"],"sources":["../../../../src/components/display/Card/Card.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --card-radius default var(--radius-surface)\n * --card-bg default var(--color-surface)\n * --card-shadow default var(--shadow-surface) for `raised`\n * --card-keyline-width default var(--space-1) — the categorical keyline of a `color` card\n *\n * The root is `position: relative`, so absolutely placed children (a corner <Stamp>)\n * anchor to the card.\n *\n * Responsive padding: the component writes --card-padding-{bp}; the root resolves them\n * into --card-inset per breakpoint. Slots (Media) read the *resolved* --card-inset and\n * --card-inner-radius, which inherit as computed values — never set them yourself.\n */\n.card {\n --card-inset: var(--card-padding-base, var(--space-5));\n --card-inner-radius: calc(var(--card-radius, var(--radius-surface)) - var(--border-width));\n --_bg: var(--card-bg, var(--color-surface));\n --_bg-hover: var(--color-surface-raised);\n --_border: var(--color-line);\n --_border-hover: var(--color-line-strong);\n --_shadow: none;\n\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n min-inline-size: 0;\n padding: var(--card-inset);\n border: var(--border-width) solid var(--_border);\n border-radius: var(--card-radius, var(--radius-surface));\n background: var(--_bg);\n box-shadow: var(--_shadow);\n color: var(--color-ink);\n font-family: var(--font-text);\n text-decoration: none;\n transition:\n background-color var(--dur-1) var(--ease-out),\n border-color var(--dur-1) var(--ease-out),\n box-shadow var(--dur-1) var(--ease-out),\n translate var(--dur-1) var(--ease-spring);\n}\n\n@media (min-width: 40em) {\n .card {\n --card-inset: var(--card-padding-sm, var(--space-5));\n }\n}\n@media (min-width: 48em) {\n .card {\n --card-inset: var(--card-padding-md, var(--space-5));\n }\n}\n@media (min-width: 64em) {\n .card {\n --card-inset: var(--card-padding-lg, var(--space-5));\n }\n}\n@media (min-width: 80em) {\n .card {\n --card-inset: var(--card-padding-xl, var(--space-5));\n }\n}\n\n/* Variants — one edge treatment each (DESIGN §2). */\n.card[data-variant='plain'] {\n --_bg: var(--card-bg, var(--color-surface));\n --_bg-hover: var(--color-surface-raised);\n --_border: transparent;\n --_border-hover: transparent;\n}\n.card[data-variant='raised'] {\n --_bg: var(--card-bg, var(--color-surface-raised));\n --_bg-hover: var(--color-surface-raised);\n --_border: var(--color-line-strong);\n --_shadow: var(--card-shadow, var(--shadow-surface));\n}\n\n/* Live: something happening now. The accent owns live state, so the edge is a heavier accent keyline. */\n.card[data-variant='live'] {\n --_border: var(--color-accent);\n --_border-hover: var(--color-accent);\n --_shadow: inset 0 0 0 calc(var(--border-width-strong) - var(--border-width)) var(--color-accent);\n}\n\n/*\n * Placeholder: a slot not yet decided. No fill, and printer's crop marks at the corners\n * instead of a dashed box (DESIGN.md: space marked out for what will go there). The marks\n * are solid-colour background images, eight short bars, not a gradient.\n */\n.card[data-variant='placeholder'] {\n --_bg: transparent;\n --_bg-hover: var(--color-surface-sunken);\n --_border: transparent;\n --_border-hover: transparent;\n --_m: var(--space-4);\n --_w: var(--border-width-strong);\n --_c: var(--color-line-strong);\n\n background:\n linear-gradient(var(--_c) 0 0) top left / var(--_m) var(--_w) no-repeat,\n linear-gradient(var(--_c) 0 0) top left / var(--_w) var(--_m) no-repeat,\n linear-gradient(var(--_c) 0 0) top right / var(--_m) var(--_w) no-repeat,\n linear-gradient(var(--_c) 0 0) top right / var(--_w) var(--_m) no-repeat,\n linear-gradient(var(--_c) 0 0) bottom left / var(--_m) var(--_w) no-repeat,\n linear-gradient(var(--_c) 0 0) bottom left / var(--_w) var(--_m) no-repeat,\n linear-gradient(var(--_c) 0 0) bottom right / var(--_m) var(--_w) no-repeat,\n linear-gradient(var(--_c) 0 0) bottom right / var(--_w) var(--_m) no-repeat,\n var(--_bg);\n color: var(--color-ink-muted);\n}\n\n/* A categorical keyline along the top: whose card it is, in their Tag's colour. The top border\n of a box the card's own shape, so it follows rounded corners down into the sides. */\n.card[data-color]::before {\n content: '';\n position: absolute;\n inset: calc(var(--border-width) * -1);\n border-block-start: var(--card-keyline-width, var(--space-1)) solid var(--_cat);\n border-radius: var(--card-radius, var(--radius-surface));\n pointer-events: none;\n}\n.card[data-color='1'] {\n --_cat: var(--color-cat-1);\n}\n.card[data-color='2'] {\n --_cat: var(--color-cat-2);\n}\n.card[data-color='3'] {\n --_cat: var(--color-cat-3);\n}\n.card[data-color='4'] {\n --_cat: var(--color-cat-4);\n}\n.card[data-color='5'] {\n --_cat: var(--color-cat-5);\n}\n.card[data-color='6'] {\n --_cat: var(--color-cat-6);\n}\n.card[data-color='7'] {\n --_cat: var(--color-cat-7);\n}\n.card[data-color='8'] {\n --_cat: var(--color-cat-8);\n}\n\n/* Interactive: an edge/fill change, never a scale. Raised cards press toward their shadow. */\n.card[data-interactive] {\n cursor: pointer;\n}\n@media (hover: hover) {\n .card[data-interactive]:hover {\n background-color: var(--_bg-hover);\n border-color: var(--_border-hover);\n }\n}\n.card[data-interactive][data-variant='raised']:active {\n translate: var(--active-shift) var(--active-shift);\n box-shadow: var(--shadow-active);\n}\n.card:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n/* ── Slots ───────────────────────────────────────────────────────────────── */\n\n.media {\n position: relative;\n overflow: hidden;\n margin-inline: calc(var(--card-inset) * -1);\n background: var(--color-surface-sunken);\n}\n.media:first-child {\n margin-block-start: calc(var(--card-inset) * -1);\n border-start-start-radius: var(--card-inner-radius);\n border-start-end-radius: var(--card-inner-radius);\n}\n.media:last-child {\n margin-block-end: calc(var(--card-inset) * -1);\n border-end-start-radius: var(--card-inner-radius);\n border-end-end-radius: var(--card-inner-radius);\n}\n/* Bled media gets a rule where it meets the content, so the edge reads as structure. */\n.media:first-child:not(:last-child) {\n border-block-end: var(--border-width) solid var(--color-line);\n}\n.media[data-inset] {\n margin: 0;\n border: 0;\n border-radius: max(\n calc(var(--card-radius, var(--radius-surface)) - var(--card-inset)),\n calc(var(--radius-media) / 2)\n );\n}\n.media[data-ratio] > :is(img, video, picture) {\n position: absolute;\n inset: 0;\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n}\n.media > :is(img, video) {\n inline-size: 100%;\n}\n.media[data-ratio='1/1'] {\n aspect-ratio: 1;\n}\n.media[data-ratio='4/3'] {\n aspect-ratio: 4 / 3;\n}\n.media[data-ratio='3/2'] {\n aspect-ratio: 3 / 2;\n}\n.media[data-ratio='16/9'] {\n aspect-ratio: 16 / 9;\n}\n.media[data-ratio='21/9'] {\n aspect-ratio: 21 / 9;\n}\n\n/* The media → header step is larger than the rhythm between text slots. */\n.media:first-child + * {\n margin-block-start: var(--space-2);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-1) var(--space-3);\n min-inline-size: 0;\n}\n.header > :first-child {\n min-inline-size: 0;\n}\n\n.title {\n margin: 0;\n font-family: var(--heading-font);\n font-weight: var(--heading-weight);\n letter-spacing: var(--heading-tracking);\n text-transform: var(--heading-transform);\n font-size: var(--card-title-size, var(--text-xl));\n line-height: var(--leading-snug);\n color: var(--color-ink);\n}\n\n.description {\n margin: 0;\n max-inline-size: 60ch;\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n line-height: var(--leading-body);\n}\n\n.body {\n min-inline-size: 0;\n font-size: var(--text-md);\n line-height: var(--leading-body);\n}\n\n.footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2) var(--space-3);\n margin-block-start: auto;\n padding-block-start: var(--space-2);\n}\n\n.meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n color: var(--color-ink-subtle);\n font-size: var(--text-xs);\n font-variant-numeric: lining-nums;\n line-height: var(--leading-snug);\n}\n"],"mappings":""}
@@ -1,6 +1,9 @@
1
1
  import { type HTMLAttributes, type LiHTMLAttributes, type ReactNode } from 'react';
2
+ import type { CategoryColor } from '../../../utils/tokens.js';
2
3
  export type ListDensity = 'compact' | 'regular';
3
4
  export type ListElement = 'ul' | 'ol';
5
+ /** `surface` and `raised` set the list on one sheet, like `Card`'s `outline` and `raised`. */
6
+ export type ListSurface = 'none' | 'surface' | 'raised';
4
7
  export interface ListProps extends HTMLAttributes<HTMLUListElement> {
5
8
  /** Hairline rules between rows. Default `true`. */
6
9
  divided?: boolean;
@@ -8,8 +11,14 @@ export interface ListProps extends HTMLAttributes<HTMLUListElement> {
8
11
  density?: ListDensity;
9
12
  /** `ol` when order is the content (a leaderboard). Default `ul`. */
10
13
  as?: ListElement;
14
+ /**
15
+ * Set the rows on a sheet so they read as rows, not text on the page: `surface` is the
16
+ * surface fill inside a hairline edge, `raised` stands on the theme's surface shadow. Rows run
17
+ * edge to edge, clipped to the sheet's corners. Default `none`.
18
+ */
19
+ surface?: ListSurface;
11
20
  }
12
- export interface ListItemProps extends LiHTMLAttributes<HTMLLIElement> {
21
+ export interface ListItemProps extends Omit<LiHTMLAttributes<HTMLLIElement>, 'color'> {
13
22
  /** Hover affordance. Implied by `asChild`. */
14
23
  interactive?: boolean;
15
24
  /**
@@ -22,12 +31,16 @@ export interface ListItemProps extends LiHTMLAttributes<HTMLLIElement> {
22
31
  selected?: boolean;
23
32
  /** Draw attention to a row with `--color-highlight` — typically "you". */
24
33
  highlighted?: boolean;
34
+ /** Out of play (eliminated, archived, past): every ink drops to the muted step, which still reads. */
35
+ muted?: boolean;
36
+ /** A categorical colour drawn as a rail at the row's start: whose row it is, matching their `Tag`. */
37
+ color?: CategoryColor;
25
38
  children?: ReactNode;
26
39
  }
27
40
  export declare const List: import("react").ForwardRefExoticComponent<ListProps & import("react").RefAttributes<HTMLUListElement>> & {
28
41
  Item: import("react").ForwardRefExoticComponent<ListItemProps & import("react").RefAttributes<HTMLLIElement>>;
29
- Leading: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
30
- Content: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
31
- Description: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
32
- Trailing: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
42
+ Leading: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
43
+ Content: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
44
+ Description: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
45
+ Trailing: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
33
46
  };
@@ -1,64 +1,74 @@
1
1
  import { cx as e } from "../../../utils/cx.js";
2
2
  import t from "./List.module.js";
3
- import { forwardRef as n } from "react";
4
- import { jsx as r } from "react/jsx-runtime";
5
- import { Slot as i } from "radix-ui";
3
+ import { createContext as n, forwardRef as r, useContext as i } from "react";
4
+ import { jsx as a } from "react/jsx-runtime";
5
+ import { Slot as o } from "radix-ui";
6
6
  //#region src/components/display/List/List.tsx
7
- var a = n(function({ divided: n = !0, density: i = "regular", as: a = "ul", className: o, ...s }, c) {
8
- return /* @__PURE__ */ r(a, {
9
- ref: c,
7
+ var s = r(function({ divided: n = !0, density: r = "regular", as: i = "ul", surface: o = "none", className: s, ...c }, l) {
8
+ return /* @__PURE__ */ a(i, {
9
+ ref: l,
10
10
  role: "list",
11
- className: e(t.list, o),
11
+ className: e(t.list, s),
12
12
  "data-divided": n || void 0,
13
- "data-density": i,
14
- ...s
13
+ "data-density": r,
14
+ "data-surface": o === "none" ? void 0 : o,
15
+ ...c
15
16
  });
16
- }), o = n(function({ interactive: n = !1, asChild: a = !1, selected: o = !1, highlighted: s = !1, className: c, children: l, ...u }, d) {
17
- let f = a ? i.Root : "div";
18
- return /* @__PURE__ */ r("li", {
19
- ref: d,
20
- className: e(t.item, c),
21
- "data-interactive": n || a || void 0,
22
- "data-selected": o || void 0,
17
+ }), c = n(!1), l = r(function({ interactive: n = !1, asChild: r = !1, selected: i = !1, highlighted: s = !1, muted: l = !1, color: u, className: d, children: f, ...p }, m) {
18
+ let h = r ? o.Root : "div";
19
+ return /* @__PURE__ */ a("li", {
20
+ ref: m,
21
+ className: e(t.item, d),
22
+ "data-interactive": n || r || void 0,
23
+ "data-selected": i || void 0,
23
24
  "data-highlighted": s || void 0,
24
- ...u,
25
- children: /* @__PURE__ */ r(f, {
26
- className: t.row,
27
- children: l
25
+ "data-muted": l || void 0,
26
+ "data-color": u,
27
+ ...p,
28
+ children: /* @__PURE__ */ a(c.Provider, {
29
+ value: r,
30
+ children: /* @__PURE__ */ a(h, {
31
+ className: t.row,
32
+ children: f
33
+ })
28
34
  })
29
35
  });
30
- }), s = n(function({ className: n, ...i }, a) {
31
- return /* @__PURE__ */ r("span", {
32
- ref: a,
36
+ }), u = r(function({ className: n, ...r }, o) {
37
+ let s = i(c) ? "span" : "div";
38
+ return /* @__PURE__ */ a(s, {
39
+ ref: o,
33
40
  className: e(t.leading, n),
34
- ...i
41
+ ...r
35
42
  });
36
- }), c = n(function({ className: n, ...i }, a) {
37
- return /* @__PURE__ */ r("span", {
38
- ref: a,
43
+ }), d = r(function({ className: n, ...r }, o) {
44
+ let s = i(c) ? "span" : "div";
45
+ return /* @__PURE__ */ a(s, {
46
+ ref: o,
39
47
  className: e(t.content, n),
40
- ...i
48
+ ...r
41
49
  });
42
- }), l = n(function({ className: n, ...i }, a) {
43
- return /* @__PURE__ */ r("span", {
44
- ref: a,
50
+ }), f = r(function({ className: n, ...r }, o) {
51
+ let s = i(c) ? "span" : "div";
52
+ return /* @__PURE__ */ a(s, {
53
+ ref: o,
45
54
  className: e(t.description, n),
46
- ...i
55
+ ...r
47
56
  });
48
- }), u = n(function({ className: n, ...i }, a) {
49
- return /* @__PURE__ */ r("span", {
50
- ref: a,
57
+ }), p = r(function({ className: n, ...r }, o) {
58
+ let s = i(c) ? "span" : "div";
59
+ return /* @__PURE__ */ a(s, {
60
+ ref: o,
51
61
  className: e(t.trailing, n),
52
- ...i
62
+ ...r
53
63
  });
54
- }), d = Object.assign(a, {
55
- Item: o,
56
- Leading: s,
57
- Content: c,
58
- Description: l,
59
- Trailing: u
64
+ }), m = Object.assign(s, {
65
+ Item: l,
66
+ Leading: u,
67
+ Content: d,
68
+ Description: f,
69
+ Trailing: p
60
70
  });
61
71
  //#endregion
62
- export { d as List };
72
+ export { m as List };
63
73
 
64
74
  //# sourceMappingURL=List.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"List.js","names":["styles","List_module_default","ListRoot","forwardRef","Comp","rest","cx","className","divided","density","ListItem","Row","asChild","Slot","interactive","selected","highlighted","ListLeading","ListContent","ListDescription","ListTrailing","List"],"sources":["../../../../src/components/display/List/List.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type LiHTMLAttributes, type ReactNode } from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport styles from './List.module.css'\n\nexport type ListDensity = 'compact' | 'regular'\nexport type ListElement = 'ul' | 'ol'\n\nexport interface ListProps extends HTMLAttributes<HTMLUListElement> {\n /** Hairline rules between rows. Default `true`. */\n divided?: boolean\n /** Row height. Default `regular`. */\n density?: ListDensity\n /** `ol` when order is the content (a leaderboard). Default `ul`. */\n as?: ListElement\n}\n\n/**\n * The workhorse row list. Leading, content and trailing slots, divided by hairlines, never boxed\n * in cards.\n *\n * @remarks\n * `List` is for rows of similar things: trips, people, invoices, recent activity. Each row has up\n * to three slots: `List.Leading` (an avatar, an icon, a rank), `List.Content` (a title and\n * `List.Description`), and `List.Trailing` (an amount, a time, an action). Rows are divided by\n * hairlines.\n *\n * @privateRemarks\n * The workhorse row list: leaderboards, team members, invoices, recent work. Rows are\n * `Leading · Content · Trailing`, divided by hairlines, never boxed in cards.\n *\n * <List><List.Item><List.Leading>1</List.Leading><List.Content>…</List.Content></List.Item></List>\n */\nconst ListRoot = forwardRef<HTMLUListElement, ListProps>(function List(\n { divided = true, density = 'regular', as: Comp = 'ul', className, ...rest },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — ul/ol share HTMLOListElement-compatible attributes; ref type differs only nominally\n ref={ref}\n role=\"list\"\n className={cx(styles.list, className)}\n data-divided={divided || undefined}\n data-density={density}\n {...rest}\n />\n )\n})\n\nexport interface ListItemProps extends LiHTMLAttributes<HTMLLIElement> {\n /** Hover affordance. Implied by `asChild`. */\n interactive?: boolean\n /**\n * Make the whole row one link or button: the single child becomes the row, so there\n * is exactly one interactive element and no nested anchors.\n * `<List.Item asChild><a href=\"/projects/atlas\">…slots…</a></List.Item>`\n */\n asChild?: boolean\n /** The current item (accent-soft fill) — e.g. the open page in a list of links. */\n selected?: boolean\n /** Draw attention to a row with `--color-highlight` — typically \"you\". */\n highlighted?: boolean\n children?: ReactNode\n}\n\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>(function ListItem(\n {\n interactive = false,\n asChild = false,\n selected = false,\n highlighted = false,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const Row = asChild ? Slot.Root : 'div'\n return (\n <li\n ref={ref}\n className={cx(styles.item, className)}\n data-interactive={interactive || asChild || undefined}\n data-selected={selected || undefined}\n data-highlighted={highlighted || undefined}\n {...rest}\n >\n <Row className={styles.row}>{children}</Row>\n </li>\n )\n})\n\n/** Rank, avatar or icon at the start of the row. Numbers are tabular and right-aligned. */\nconst ListLeading = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(\n function ListLeading({ className, ...rest }, ref) {\n return <span ref={ref} className={cx(styles.leading, className)} {...rest} />\n },\n)\n\n/** Title (the direct text) and an optional `List.Description` below it. */\nconst ListContent = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(\n function ListContent({ className, ...rest }, ref) {\n return <span ref={ref} className={cx(styles.content, className)} {...rest} />\n },\n)\n\nconst ListDescription = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(\n function ListDescription({ className, ...rest }, ref) {\n return <span ref={ref} className={cx(styles.description, className)} {...rest} />\n },\n)\n\n/** Value, meta or actions at the end of the row. Numbers are tabular. */\nconst ListTrailing = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(\n function ListTrailing({ className, ...rest }, ref) {\n return <span ref={ref} className={cx(styles.trailing, className)} {...rest} />\n },\n)\n\nexport const List = Object.assign(ListRoot, {\n Item: ListItem,\n Leading: ListLeading,\n Content: ListContent,\n Description: ListDescription,\n Trailing: ListTrailing,\n})\n"],"mappings":";;;;;;AAiCA,IAAME,IAAWC,EAAwC,SACvD,EAAE,aAAU,IAAM,aAAU,WAAW,IAAIC,IAAO,MAAM,cAAW,GAAGC,KACtE,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,MAAK;EACL,WAAWE,EAAGN,EAAO,MAAMO,CAAS;EACpC,gBAAcC,KAAW,KAAA;EACzB,gBAAcC;EACd,GAAIJ;CACL,CAAA;AAEL,CAAC,GAkBKK,IAAWP,EAAyC,SACxD,EACE,iBAAc,IACd,aAAU,IACV,cAAW,IACX,iBAAc,IACd,cACA,aACA,GAAGE,KAEL,GACA;CACA,IAAMM,IAAMC,IAAUC,EAAK,OAAO;CAClC,OACE,kBAAC,MAAD;EACO;EACL,WAAWP,EAAGN,EAAO,MAAMO,CAAS;EACpC,oBAAkBO,KAAeF,KAAW,KAAA;EAC5C,iBAAeG,KAAY,KAAA;EAC3B,oBAAkBC,KAAe,KAAA;EACjC,GAAIX;EAEJ,UAAA,kBAACM,GAAD;GAAK,WAAWX,EAAO;GAAM;EAAc,CAAA;CACzC,CAAA;AAER,CAAC,GAGKiB,IAAcd,EAClB,SAAqB,EAAE,cAAW,GAAGE,KAAQ,GAAK;CAChD,OAAO,kBAAC,QAAD;EAAW;EAAK,WAAWC,EAAGN,EAAO,SAASO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC9E,CACF,GAGMa,IAAcf,EAClB,SAAqB,EAAE,cAAW,GAAGE,KAAQ,GAAK;CAChD,OAAO,kBAAC,QAAD;EAAW;EAAK,WAAWC,EAAGN,EAAO,SAASO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC9E,CACF,GAEMc,IAAkBhB,EACtB,SAAyB,EAAE,cAAW,GAAGE,KAAQ,GAAK;CACpD,OAAO,kBAAC,QAAD;EAAW;EAAK,WAAWC,EAAGN,EAAO,aAAaO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAClF,CACF,GAGMe,IAAejB,EACnB,SAAsB,EAAE,cAAW,GAAGE,KAAQ,GAAK;CACjD,OAAO,kBAAC,QAAD;EAAW;EAAK,WAAWC,EAAGN,EAAO,UAAUO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC/E,CACF,GAEagB,IAAO,OAAO,OAAOnB,GAAU;CAC1C,MAAMQ;CACN,SAASO;CACT,SAASC;CACT,aAAaC;CACb,UAAUC;AACZ,CAAC"}
1
+ {"version":3,"file":"List.js","names":["styles","List_module_default","ListRoot","forwardRef","Comp","rest","cx","className","divided","density","surface","RowIsControl","createContext","ListItem","Row","asChild","Slot","interactive","selected","highlighted","muted","color","ListLeading","useContext","ListContent","ListDescription","ListTrailing","List"],"sources":["../../../../src/components/display/List/List.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n type HTMLAttributes,\n type LiHTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport type { CategoryColor } from '#utils/tokens'\nimport styles from './List.module.css'\n\nexport type ListDensity = 'compact' | 'regular'\nexport type ListElement = 'ul' | 'ol'\n/** `surface` and `raised` set the list on one sheet, like `Card`'s `outline` and `raised`. */\nexport type ListSurface = 'none' | 'surface' | 'raised'\n\nexport interface ListProps extends HTMLAttributes<HTMLUListElement> {\n /** Hairline rules between rows. Default `true`. */\n divided?: boolean\n /** Row height. Default `regular`. */\n density?: ListDensity\n /** `ol` when order is the content (a leaderboard). Default `ul`. */\n as?: ListElement\n /**\n * Set the rows on a sheet so they read as rows, not text on the page: `surface` is the\n * surface fill inside a hairline edge, `raised` stands on the theme's surface shadow. Rows run\n * edge to edge, clipped to the sheet's corners. Default `none`.\n */\n surface?: ListSurface\n}\n\n/**\n * The workhorse row list. Leading, content and trailing slots, divided by hairlines, never boxed\n * in cards.\n *\n * @remarks\n * `List` is for rows of similar things: trips, people, invoices, recent activity. Each row has up\n * to three slots: `List.Leading` (an avatar, an icon, a rank), `List.Content` (a title and\n * `List.Description`), and `List.Trailing` (an amount, a time, an action). Rows are divided by\n * hairlines.\n *\n * ## On a surface\n *\n * On a busy page, or a theme whose canvas has a texture, `surface=\"surface\"` sets the whole list\n * on one sheet, and `surface=\"raised\"` stands it on the theme's surface shadow. The rows stay rows\n * on it and run edge to edge: a highlighted, selected or hovered row is a band across the sheet,\n * and a categorical rail is the row's edge, following the sheet's corners at either end.\n *\n * @privateRemarks\n * The workhorse row list: leaderboards, team members, invoices, recent work. Rows are\n * `Leading · Content · Trailing`, divided by hairlines, never boxed in cards.\n *\n * <List><List.Item><List.Leading>1</List.Leading><List.Content>…</List.Content></List.Item></List>\n */\nconst ListRoot = forwardRef<HTMLUListElement, ListProps>(function List(\n { divided = true, density = 'regular', as: Comp = 'ul', surface = 'none', className, ...rest },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — ul/ol share HTMLOListElement-compatible attributes; ref type differs only nominally\n ref={ref}\n role=\"list\"\n className={cx(styles.list, className)}\n data-divided={divided || undefined}\n data-density={density}\n data-surface={surface === 'none' ? undefined : surface}\n {...rest}\n />\n )\n})\n\n/**\n * Whether the row is the asChild link or button. Its slots are then spans, the only content a\n * button may hold; elsewhere they're divs, so block components (Stat, Stack) fit in them.\n */\nconst RowIsControl = createContext(false)\n\nexport interface ListItemProps extends Omit<LiHTMLAttributes<HTMLLIElement>, 'color'> {\n /** Hover affordance. Implied by `asChild`. */\n interactive?: boolean\n /**\n * Make the whole row one link or button: the single child becomes the row, so there\n * is exactly one interactive element and no nested anchors.\n * `<List.Item asChild><a href=\"/projects/atlas\">…slots…</a></List.Item>`\n */\n asChild?: boolean\n /** The current item (accent-soft fill) — e.g. the open page in a list of links. */\n selected?: boolean\n /** Draw attention to a row with `--color-highlight` — typically \"you\". */\n highlighted?: boolean\n /** Out of play (eliminated, archived, past): every ink drops to the muted step, which still reads. */\n muted?: boolean\n /** A categorical colour drawn as a rail at the row's start: whose row it is, matching their `Tag`. */\n color?: CategoryColor\n children?: ReactNode\n}\n\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>(function ListItem(\n {\n interactive = false,\n asChild = false,\n selected = false,\n highlighted = false,\n muted = false,\n color,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const Row = asChild ? Slot.Root : 'div'\n return (\n <li\n ref={ref}\n className={cx(styles.item, className)}\n data-interactive={interactive || asChild || undefined}\n data-selected={selected || undefined}\n data-highlighted={highlighted || undefined}\n data-muted={muted || undefined}\n data-color={color}\n {...rest}\n >\n <RowIsControl.Provider value={asChild}>\n <Row className={styles.row}>{children}</Row>\n </RowIsControl.Provider>\n </li>\n )\n})\n\n/** Rank, avatar or icon at the start of the row. Numbers are tabular and right-aligned. */\nconst ListLeading = forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(function ListLeading(\n { className, ...rest },\n ref,\n) {\n const Comp = useContext(RowIsControl) ? 'span' : 'div'\n // @ts-expect-error — polymorphic ref across span/div is safe here\n return <Comp ref={ref} className={cx(styles.leading, className)} {...rest} />\n})\n\n/** Title (the direct text) and an optional `List.Description` below it. */\nconst ListContent = forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(function ListContent(\n { className, ...rest },\n ref,\n) {\n const Comp = useContext(RowIsControl) ? 'span' : 'div'\n // @ts-expect-error — polymorphic ref across span/div is safe here\n return <Comp ref={ref} className={cx(styles.content, className)} {...rest} />\n})\n\nconst ListDescription = forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(\n function ListDescription({ className, ...rest }, ref) {\n const Comp = useContext(RowIsControl) ? 'span' : 'div'\n // @ts-expect-error — polymorphic ref across span/div is safe here\n return <Comp ref={ref} className={cx(styles.description, className)} {...rest} />\n },\n)\n\n/** Value, meta or actions at the end of the row. Numbers are tabular. */\nconst ListTrailing = forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(function ListTrailing(\n { className, ...rest },\n ref,\n) {\n const Comp = useContext(RowIsControl) ? 'span' : 'div'\n // @ts-expect-error — polymorphic ref across span/div is safe here\n return <Comp ref={ref} className={cx(styles.trailing, className)} {...rest} />\n})\n\nexport const List = Object.assign(ListRoot, {\n Item: ListItem,\n Leading: ListLeading,\n Content: ListContent,\n Description: ListDescription,\n Trailing: ListTrailing,\n})\n"],"mappings":";;;;;;AAwDA,IAAME,IAAWC,EAAwC,SACvD,EAAE,aAAU,IAAM,aAAU,WAAW,IAAIC,IAAO,MAAM,aAAU,QAAQ,cAAW,GAAGC,KACxF,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,MAAK;EACL,WAAWE,EAAGN,EAAO,MAAMO,CAAS;EACpC,gBAAcC,KAAW,KAAA;EACzB,gBAAcC;EACd,gBAAcC,MAAY,SAAS,KAAA,IAAYA;EAC/C,GAAIL;CACL,CAAA;AAEL,CAAC,GAMKM,IAAeC,EAAc,EAAK,GAsBlCC,IAAWV,EAAyC,SACxD,EACE,iBAAc,IACd,aAAU,IACV,cAAW,IACX,iBAAc,IACd,WAAQ,IACR,UACA,cACA,aACA,GAAGE,KAEL,GACA;CACA,IAAMS,IAAMC,IAAUC,EAAK,OAAO;CAClC,OACE,kBAAC,MAAD;EACO;EACL,WAAWV,EAAGN,EAAO,MAAMO,CAAS;EACpC,oBAAkBU,KAAeF,KAAW,KAAA;EAC5C,iBAAeG,KAAY,KAAA;EAC3B,oBAAkBC,KAAe,KAAA;EACjC,cAAYC,KAAS,KAAA;EACrB,cAAYC;EACZ,GAAIhB;EAEJ,UAAA,kBAACM,EAAa,UAAd;GAAuB,OAAOI;GAC5B,UAAA,kBAACD,GAAD;IAAK,WAAWd,EAAO;IAAM;GAAc,CAAA;EACtB,CAAA;CACrB,CAAA;AAER,CAAC,GAGKsB,IAAcnB,EAAqD,SACvE,EAAE,cAAW,GAAGE,KAChB,GACA;CACA,IAAMD,IAAOmB,EAAWZ,CAAY,IAAI,SAAS;CAEjD,OAAO,kBAACP,GAAD;EAAW;EAAK,WAAWE,EAAGN,EAAO,SAASO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC9E,CAAC,GAGKmB,IAAcrB,EAAqD,SACvE,EAAE,cAAW,GAAGE,KAChB,GACA;CACA,IAAMD,IAAOmB,EAAWZ,CAAY,IAAI,SAAS;CAEjD,OAAO,kBAACP,GAAD;EAAW;EAAK,WAAWE,EAAGN,EAAO,SAASO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC9E,CAAC,GAEKoB,IAAkBtB,EACtB,SAAyB,EAAE,cAAW,GAAGE,KAAQ,GAAK;CACpD,IAAMD,IAAOmB,EAAWZ,CAAY,IAAI,SAAS;CAEjD,OAAO,kBAACP,GAAD;EAAW;EAAK,WAAWE,EAAGN,EAAO,aAAaO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAClF,CACF,GAGMqB,IAAevB,EAAqD,SACxE,EAAE,cAAW,GAAGE,KAChB,GACA;CACA,IAAMD,IAAOmB,EAAWZ,CAAY,IAAI,SAAS;CAEjD,OAAO,kBAACP,GAAD;EAAW;EAAK,WAAWE,EAAGN,EAAO,UAAUO,CAAS;EAAG,GAAIF;CAAO,CAAA;AAC/E,CAAC,GAEYsB,IAAO,OAAO,OAAOzB,GAAU;CAC1C,MAAMW;CACN,SAASS;CACT,SAASE;CACT,aAAaC;CACb,UAAUC;AACZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"List.module.js","names":["list","item","row","leading","content","description","trailing","List_module_default"],"sources":["../../../../src/components/display/List/List.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --list-inset default var(--space-2) — row padding-inline (room for fills)\n * --list-row-radius default var(--radius-field) — hover/selected/highlighted fill\n * --list-trailing-size default: the row's text size (same as the title)\n * --highlight-tone-{positive,caution,critical,info}-text, --highlight-accent-text\n * tone text inside a highlighted row (shared with Table)\n *\n * Structure: li.item > .row (a div, or the asChild link/button) > slots. The row carries\n * padding, hover and focus so a linked row is one target edge to edge. Slots are spans,\n * valid inside <a> and <button>.\n */\n.list {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--font-text);\n color: var(--color-ink);\n}\n\n.item {\n --_py: var(--space-3);\n --_fill: transparent;\n --_fill-ink: inherit;\n\n position: relative;\n min-inline-size: 0;\n}\n.list[data-density='compact'] > .item {\n --_py: var(--space-2);\n}\n\n.list[data-divided] > .item + .item {\n border-block-start: var(--border-width) solid var(--color-line);\n}\n/* A filled row doesn't need rules either side — the fill is its edge. */\n.list[data-divided] > .item:is([data-highlighted], [data-selected]),\n.list[data-divided] > .item:is([data-highlighted], [data-selected]) + .item {\n border-block-start-color: transparent;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n inline-size: 100%;\n min-inline-size: 0;\n margin: 0;\n padding-block: var(--_py);\n padding-inline: var(--list-inset, var(--space-2));\n border: 0;\n border-radius: var(--list-row-radius, var(--radius-field));\n background: var(--_fill);\n color: var(--_fill-ink);\n font: inherit;\n text-align: start;\n text-decoration: none;\n transition: background-color var(--dur-1) var(--ease-out);\n}\n\n.item[data-selected] {\n --_fill: var(--color-accent-soft);\n --_fill-ink: var(--color-ink);\n}\n.item[data-highlighted] {\n --_fill: var(--color-highlight);\n --_fill-ink: var(--color-highlight-ink);\n --_band-positive: var(\n --highlight-tone-positive-text,\n color-mix(in oklab, var(--tone-positive-text) 75%, var(--color-highlight-ink))\n );\n --_band-caution: var(\n --highlight-tone-caution-text,\n color-mix(in oklab, var(--tone-caution-text) 75%, var(--color-highlight-ink))\n );\n --_band-critical: var(\n --highlight-tone-critical-text,\n color-mix(in oklab, var(--tone-critical-text) 75%, var(--color-highlight-ink))\n );\n --_band-info: var(\n --highlight-tone-info-text,\n color-mix(in oklab, var(--tone-info-text) 75%, var(--color-highlight-ink))\n );\n --_band-accent: var(\n --highlight-accent-text,\n color-mix(in oklab, var(--color-accent-text) 75%, var(--color-highlight-ink))\n );\n}\n\n/*\n * A filled row re-points the colour roles for its content, so a muted description, a\n * tone-coloured Numeral or a LiveIndicator stays legible on the fill (gold in Fiesta\n * night). The item publishes fill/ink under private names and the row swaps the roles —\n * redefining a role from itself on one element would be a var() cycle (see Section).\n */\n.item:is([data-highlighted], [data-selected]) > .row {\n --color-ink: var(--_fill-ink);\n --color-ink-muted: color-mix(in oklab, var(--_fill-ink), var(--_fill) 25%);\n --color-ink-subtle: color-mix(in oklab, var(--_fill-ink), var(--_fill) 35%);\n}\n.item[data-highlighted] > .row {\n --tone-positive-text: var(--_band-positive);\n --tone-caution-text: var(--_band-caution);\n --tone-critical-text: var(--_band-critical);\n --tone-info-text: var(--_band-info);\n --color-accent-text: var(--_band-accent);\n /* Soft fills (a soft Badge or Tag) tint the band, like Section's accent band, so the\n re-pointed tone texts above stay legible on them in every mode. */\n --tone-positive-soft: color-mix(in oklab, var(--_band-positive) 8%, var(--_fill));\n --tone-caution-soft: color-mix(in oklab, var(--_band-caution) 8%, var(--_fill));\n --tone-critical-soft: color-mix(in oklab, var(--_band-critical) 8%, var(--_fill));\n --tone-info-soft: color-mix(in oklab, var(--_band-info) 8%, var(--_fill));\n --color-accent-soft: color-mix(in oklab, var(--_band-accent) 8%, var(--_fill));\n}\n\n.item[data-interactive] > .row {\n cursor: pointer;\n}\n@media (hover: hover) {\n .item[data-interactive]:not([data-highlighted], [data-selected]) > .row:hover {\n background: var(--color-surface-sunken);\n }\n .item[data-interactive]:is([data-highlighted], [data-selected]) > .row:hover {\n background: color-mix(in oklch, var(--_fill) 88%, var(--color-ink));\n }\n}\n.row:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: -2px;\n}\n\n/* ── Slots ───────────────────────────────────────────────────────────────── */\n\n.leading {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: flex-end;\n min-inline-size: 2ch;\n color: var(--color-ink-muted);\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-weight: var(--label-weight);\n font-variant-numeric: tabular-nums lining-nums;\n font-size: var(--text-md);\n}\n.item[data-highlighted] .leading {\n color: inherit;\n}\n\n.content {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n gap: calc(var(--space-1) / 2);\n min-inline-size: 0;\n font-size: var(--text-md);\n font-weight: var(--label-weight);\n line-height: var(--leading-snug);\n overflow-wrap: anywhere;\n}\n\n.description {\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n font-weight: 400;\n}\n\n.trailing {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-inline-start: auto;\n text-align: end;\n /*\n * The row's text face and size, with tabular figures: a bare \"7 tasks\" sits level with the\n * title instead of looming in the numeric face. Put a <Numeral>/<Amount> here for figures\n * that should carry the numeric face (receipt mono in Ledger).\n */\n font-variant-numeric: tabular-nums lining-nums;\n font-size: var(--list-trailing-size, var(--text-md));\n font-weight: var(--label-weight);\n line-height: var(--leading-snug);\n white-space: nowrap;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"List.module.js","names":["list","item","row","leading","content","description","trailing","List_module_default"],"sources":["../../../../src/components/display/List/List.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --list-inset default var(--space-2), var(--space-4) on a surface — row padding-inline\n * --list-row-radius default var(--radius-field), square on a surface — row fills\n * --list-trailing-size default: the row's text size (same as the title)\n * --list-rail-width default var(--space-1) — the categorical rail of a `color` row\n * --list-surface-bg default var(--color-surface), var(--color-surface-raised) when `raised`\n * --list-surface-radius default var(--radius-surface) — the sheet of a `surface` list\n * --highlight-tone-{positive,caution,critical,info}-text, --highlight-accent-text\n * tone text inside a highlighted row (shared with Table)\n *\n * Structure: li.item > .row (a div, or the asChild link/button) > slots. The row carries\n * padding, hover and focus so a linked row is one target edge to edge. Slots are divs, so\n * block components (Stat, Stack, a sized Media) fit in them, and spans inside an asChild row,\n * the only content a button may hold.\n */\n.list {\n --_inset: var(--space-2);\n --_row-radius: var(--radius-field);\n\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--font-text);\n color: var(--color-ink);\n}\n\n/*\n * On a surface: the whole list on one sheet, with Card's edges (`outline` for surface,\n * `raised` for raised), so rows read as rows on a textured or busy canvas. Rows run edge to\n * edge and the sheet clips them to its radius, so a fill is a band across the sheet, and a\n * categorical rail sits flush with the sheet's inner edge and follows its corners on the\n * first and last rows. Rows take a wider inset so text clears the edge.\n */\n.list[data-surface] {\n --_inset: var(--space-4);\n --_row-radius: 0px;\n\n overflow: hidden;\n border: var(--border-width) solid var(--color-line);\n border-radius: var(--list-surface-radius, var(--radius-surface));\n background: var(--list-surface-bg, var(--color-surface));\n}\n.list[data-surface='raised'] {\n border-color: var(--color-line-strong);\n background: var(--list-surface-bg, var(--color-surface-raised));\n box-shadow: var(--shadow-surface);\n}\n\n.item {\n --_py: var(--space-3);\n --_fill: transparent;\n --_fill-ink: inherit;\n\n position: relative;\n min-inline-size: 0;\n}\n.list[data-density='compact'] > .item {\n --_py: var(--space-2);\n}\n\n.list[data-divided] > .item + .item {\n border-block-start: var(--border-width) solid var(--color-line);\n}\n/* A filled row doesn't need rules either side — the fill is its edge. */\n.list[data-divided] > .item:is([data-highlighted], [data-selected]),\n.list[data-divided] > .item:is([data-highlighted], [data-selected]) + .item {\n border-block-start-color: transparent;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n inline-size: 100%;\n min-inline-size: 0;\n margin: 0;\n padding-block: var(--_py);\n padding-inline: var(--list-inset, var(--_inset));\n border: 0;\n border-radius: var(--list-row-radius, var(--_row-radius));\n background: var(--_fill);\n color: var(--_fill-ink);\n font: inherit;\n text-align: start;\n text-decoration: none;\n transition: background-color var(--dur-1) var(--ease-out);\n}\n\n.item[data-selected] {\n --_fill: var(--color-accent-soft);\n --_fill-ink: var(--color-ink);\n}\n.item[data-highlighted] {\n --_fill: var(--color-highlight);\n --_fill-ink: var(--color-highlight-ink);\n --_band-positive: var(\n --highlight-tone-positive-text,\n color-mix(in oklab, var(--tone-positive-text) 75%, var(--color-highlight-ink))\n );\n --_band-caution: var(\n --highlight-tone-caution-text,\n color-mix(in oklab, var(--tone-caution-text) 75%, var(--color-highlight-ink))\n );\n --_band-critical: var(\n --highlight-tone-critical-text,\n color-mix(in oklab, var(--tone-critical-text) 75%, var(--color-highlight-ink))\n );\n --_band-info: var(\n --highlight-tone-info-text,\n color-mix(in oklab, var(--tone-info-text) 75%, var(--color-highlight-ink))\n );\n --_band-accent: var(\n --highlight-accent-text,\n color-mix(in oklab, var(--color-accent-text) 75%, var(--color-highlight-ink))\n );\n}\n\n/*\n * A filled row re-points the colour roles for its content, so a muted description, a\n * tone-coloured Numeral or a LiveIndicator stays legible on the fill (gold in Fiesta\n * night). The item publishes fill/ink under private names and the row swaps the roles —\n * redefining a role from itself on one element would be a var() cycle (see Section).\n */\n.item:is([data-highlighted], [data-selected]) > .row {\n --color-ink: var(--_fill-ink);\n --color-ink-muted: color-mix(in oklab, var(--_fill-ink), var(--_fill) 25%);\n --color-ink-subtle: color-mix(in oklab, var(--_fill-ink), var(--_fill) 35%);\n}\n.item[data-highlighted] > .row {\n --tone-positive-text: var(--_band-positive);\n --tone-caution-text: var(--_band-caution);\n --tone-critical-text: var(--_band-critical);\n --tone-info-text: var(--_band-info);\n --color-accent-text: var(--_band-accent);\n /* Soft fills (a soft Badge or Tag) tint the band, like Section's accent band, so the\n re-pointed tone texts above stay legible on them in every mode. */\n --tone-positive-soft: color-mix(in oklab, var(--_band-positive) 8%, var(--_fill));\n --tone-caution-soft: color-mix(in oklab, var(--_band-caution) 8%, var(--_fill));\n --tone-critical-soft: color-mix(in oklab, var(--_band-critical) 8%, var(--_fill));\n --tone-info-soft: color-mix(in oklab, var(--_band-info) 8%, var(--_fill));\n --color-accent-soft: color-mix(in oklab, var(--_band-accent) 8%, var(--_fill));\n}\n\n.item[data-interactive] > .row {\n cursor: pointer;\n}\n\n/* Muted: out of play. The title drops to the muted step, which still clears AA. */\n.item[data-muted] > .row {\n --color-ink: var(--color-ink-muted);\n\n color: var(--color-ink-muted);\n}\n\n/* A categorical rail in the row's start inset: whose row it is, in their Tag's colour. */\n.item[data-color]::before {\n content: '';\n position: absolute;\n inset-block: var(--space-1);\n inset-inline-start: 0;\n inline-size: var(--list-rail-width, var(--space-1));\n border-radius: var(--radius-chip);\n background: var(--_cat);\n}\n/* On a sheet the rail is an edge of the row: full height, square, and over the rule above it. */\n.list[data-surface] > .item[data-color]::before {\n inset-block: 0;\n border-radius: 0;\n}\n.list[data-surface][data-divided] > .item + .item[data-color]::before {\n inset-block-start: calc(var(--border-width) * -1);\n}\n.item[data-color='1'] {\n --_cat: var(--color-cat-1);\n}\n.item[data-color='2'] {\n --_cat: var(--color-cat-2);\n}\n.item[data-color='3'] {\n --_cat: var(--color-cat-3);\n}\n.item[data-color='4'] {\n --_cat: var(--color-cat-4);\n}\n.item[data-color='5'] {\n --_cat: var(--color-cat-5);\n}\n.item[data-color='6'] {\n --_cat: var(--color-cat-6);\n}\n.item[data-color='7'] {\n --_cat: var(--color-cat-7);\n}\n.item[data-color='8'] {\n --_cat: var(--color-cat-8);\n}\n.item[data-color] > .row {\n padding-inline-start: calc(var(--list-inset, var(--_inset)) + var(--space-2));\n}\n@media (hover: hover) {\n .item[data-interactive]:not([data-highlighted], [data-selected]) > .row:hover {\n background: var(--color-surface-sunken);\n }\n .item[data-interactive]:is([data-highlighted], [data-selected]) > .row:hover {\n background: color-mix(in oklch, var(--_fill) 88%, var(--color-ink));\n }\n}\n.row:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: -2px;\n}\n\n/* ── Slots ───────────────────────────────────────────────────────────────── */\n\n.leading {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: flex-end;\n min-inline-size: 2ch;\n color: var(--color-ink-muted);\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-weight: var(--label-weight);\n font-variant-numeric: tabular-nums lining-nums;\n font-size: var(--text-md);\n}\n.item[data-highlighted] .leading {\n color: inherit;\n}\n\n.content {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n gap: calc(var(--space-1) / 2);\n min-inline-size: 0;\n font-size: var(--text-md);\n font-weight: var(--label-weight);\n line-height: var(--leading-snug);\n /* Wrap between words; break inside one only when a single word can't fit the column. */\n overflow-wrap: break-word;\n}\n\n.description {\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n font-weight: 400;\n}\n\n.trailing {\n --stat-align: end;\n --stat-container-type: normal;\n\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-inline-start: auto;\n text-align: end;\n /*\n * The row's text face and size, with tabular figures: a bare \"7 tasks\" sits level with the\n * title instead of looming in the numeric face. Put a <Numeral>/<Amount> here for figures\n * that should carry the numeric face (receipt mono in Ledger).\n */\n font-variant-numeric: tabular-nums lining-nums;\n font-size: var(--list-trailing-size, var(--text-md));\n font-weight: var(--label-weight);\n line-height: var(--leading-snug);\n white-space: nowrap;\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
1
  export { List } from './List.js';
2
- export type { ListProps, ListItemProps, ListDensity, ListElement } from './List.js';
2
+ export type { ListProps, ListItemProps, ListDensity, ListElement, ListSurface } from './List.js';
@@ -14,7 +14,7 @@ var m = {
14
14
  slow: 7,
15
15
  normal: 4.5,
16
16
  fast: 2.5
17
- }, g = t("PauseIcon", /* @__PURE__ */ f("path", { d: "M7.5 5.5v9M12.5 5.5v9" })), _ = t("PlayIcon", /* @__PURE__ */ f("path", { d: "M7 5.25v9.5L14.75 10z" })), v = o(function({ items: t, children: o, label: v, speed: y = "normal", direction: b = "left", pauseOnHover: x = !0, pauseControl: S = !0, gap: C = 5, separator: w, surface: T = "plain", className: E, style: D, ...O }, k) {
17
+ }, g = /* @__PURE__ */ t("PauseIcon", /* @__PURE__ */ f("path", { d: "M7.5 5.5v9M12.5 5.5v9" })), _ = /* @__PURE__ */ t("PlayIcon", /* @__PURE__ */ f("path", { d: "M7 5.25v9.5L14.75 10z" })), v = o(function({ items: t, children: o, label: v, speed: y = "normal", direction: b = "left", pauseOnHover: x = !0, pauseControl: S = !0, gap: C = 5, separator: w, surface: T = "plain", className: E, style: D, ...O }, k) {
18
18
  let A = (t ?? a.toArray(o)).filter((e) => e != null && e !== !1), [j, M] = d(!1), [N, P] = d(null), F = u(null);
19
19
  l(() => {
20
20
  let e = F.current;