@sableui/react 0.9.0 → 0.10.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 (221) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +124 -0
  3. package/CONTRIBUTING.md +2 -2
  4. package/DESIGN.md +55 -16
  5. package/README.md +12 -0
  6. package/dist/{_contract-C2M1SjBf.d.ts → _contract-CkqXDVww.d.ts} +25 -2
  7. package/dist/blocks/danger-zone-block.js +3 -3
  8. package/dist/blocks/danger-zone-block.meta.js +1 -1
  9. package/dist/blocks/faq-block.js +3 -3
  10. package/dist/blocks/goal-progress-block.js +1 -1
  11. package/dist/blocks/notification-list-block.js +1 -1
  12. package/dist/blocks/pricing-table-block.js +12 -12
  13. package/dist/blocks/product-card-block.js +3 -3
  14. package/dist/blocks/product-card-block.meta.js +3 -3
  15. package/dist/blocks/profile-card-block.js +1 -1
  16. package/dist/blocks/profile-form-block.js +3 -3
  17. package/dist/blocks/revenue-breakdown-block.js +5 -5
  18. package/dist/blocks/stat-row-block.js +3 -3
  19. package/dist/blocks/task-list-block.js +2 -2
  20. package/dist/blocks/team-members-block.js +1 -1
  21. package/dist/blocks/wallet-block.js +4 -4
  22. package/dist/blocks/wallet-block.meta.js +3 -3
  23. package/dist/components/accordion/accordion.meta.js +2 -2
  24. package/dist/components/app-header/app-header.meta.js +1 -1
  25. package/dist/components/app-shell/app-shell.meta.js +2 -2
  26. package/dist/components/area-chart/area-chart.meta.js +3 -3
  27. package/dist/components/badge/badge.js +13 -4
  28. package/dist/components/badge/badge.meta.js +24 -13
  29. package/dist/components/badge/badge.variants.js +37 -23
  30. package/dist/components/banner/banner.meta.js +8 -8
  31. package/dist/components/banner/banner.variants.js +3 -3
  32. package/dist/components/bar-chart/bar-chart.meta.js +4 -4
  33. package/dist/components/breadcrumbs/breadcrumbs.meta.js +1 -1
  34. package/dist/components/button/button.js +13 -2
  35. package/dist/components/button/button.meta.js +3 -3
  36. package/dist/components/card/card.js +16 -7
  37. package/dist/components/card/card.meta.js +4 -4
  38. package/dist/components/checkbox-card/checkbox-card.meta.js +10 -10
  39. package/dist/components/checkbox-card/checkbox-card.variants.js +15 -15
  40. package/dist/components/code-block/code-block.meta.js +1 -1
  41. package/dist/components/command-menu/command-menu.js +2 -0
  42. package/dist/components/command-menu/command-menu.meta.js +1 -1
  43. package/dist/components/context-card/context-card.meta.js +2 -2
  44. package/dist/components/destructive-action-modal/destructive-action-modal.meta.js +1 -1
  45. package/dist/components/dialog/dialog.meta.js +2 -2
  46. package/dist/components/disclosure-picker/disclosure-picker.js +48 -2
  47. package/dist/components/disclosure-picker/disclosure-picker.meta.js +3 -2
  48. package/dist/components/empty-state/empty-state.meta.js +4 -4
  49. package/dist/components/form/form.js +10 -5
  50. package/dist/components/gradient-art/gradient-art.meta.js +3 -3
  51. package/dist/components/label/label.meta.js +1 -1
  52. package/dist/components/line-chart/line-chart.meta.js +3 -3
  53. package/dist/components/meter/meter.js +1 -1
  54. package/dist/components/meter/meter.meta.js +2 -2
  55. package/dist/components/meter/meter.variants.js +1 -1
  56. package/dist/components/middle-truncate/middle-truncate.meta.js +4 -4
  57. package/dist/components/note/note.meta.js +3 -3
  58. package/dist/components/page-header/page-header.js +1 -1
  59. package/dist/components/pagination/pagination.meta.js +2 -2
  60. package/dist/components/phone/phone.meta.js +1 -1
  61. package/dist/components/pie-chart/pie-chart.meta.js +3 -3
  62. package/dist/components/pill/pill.js +4 -2
  63. package/dist/components/pill/pill.meta.js +19 -2
  64. package/dist/components/pill/pill.variants.js +23 -2
  65. package/dist/components/popover/popover.meta.js +2 -2
  66. package/dist/components/radar-chart/radar-chart.meta.js +3 -3
  67. package/dist/components/radial-chart/radial-chart.meta.js +3 -3
  68. package/dist/components/radio/radio.meta.js +2 -2
  69. package/dist/components/radio-card/radio-card.meta.js +6 -6
  70. package/dist/components/radio-card/radio-card.variants.js +15 -15
  71. package/dist/components/scroller/scroller.meta.js +1 -1
  72. package/dist/components/search-input/search-input.meta.js +1 -1
  73. package/dist/components/section-header/section-header.js +1 -1
  74. package/dist/components/segmented-bar/segmented-bar.js +1 -1
  75. package/dist/components/segmented-bar/segmented-bar.meta.js +6 -6
  76. package/dist/components/segmented-bar/segmented-bar.variants.js +4 -4
  77. package/dist/components/select/select.meta.js +2 -2
  78. package/dist/components/sheet/sheet.js +15 -1
  79. package/dist/components/sheet/sheet.meta.js +1 -1
  80. package/dist/components/side-nav/side-nav.meta.js +1 -1
  81. package/dist/components/sidebar/sidebar.meta.js +1 -1
  82. package/dist/components/sparkline/sparkline.meta.js +4 -4
  83. package/dist/components/spinner/spinner.meta.js +1 -1
  84. package/dist/components/status-dot/status-dot.js +4 -1
  85. package/dist/components/status-dot/status-dot.meta.js +8 -16
  86. package/dist/components/status-dot/status-dot.variants.js +13 -4
  87. package/dist/components/stepper/stepper.js +11 -2
  88. package/dist/components/table/table.meta.js +4 -4
  89. package/dist/components/tabs/tabs.meta.js +1 -1
  90. package/dist/components/textarea/textarea.meta.js +2 -2
  91. package/dist/components/toast/toast.js +1 -0
  92. package/dist/components/toast/toast.meta.js +1 -1
  93. package/dist/components/tooltip/tooltip.meta.js +2 -2
  94. package/dist/file-hashes.json +127 -124
  95. package/dist/foundations/spacing.js +8 -8
  96. package/dist/index.d.ts +138 -73
  97. package/dist/index.js +12 -1
  98. package/dist/lib/chart/types.js +3 -3
  99. package/dist/lib/is-promise.js +5 -0
  100. package/dist/lib/palette.js +103 -0
  101. package/dist/lib/selection-card.js +4 -4
  102. package/dist/palette.css +669 -0
  103. package/dist/patterns/auth-page.js +6 -6
  104. package/dist/patterns/auth-page.meta.js +3 -3
  105. package/dist/patterns/brand-landing-page.js +2 -2
  106. package/dist/patterns/chat-panel.js +2 -2
  107. package/dist/patterns/dashboard-page.js +71 -71
  108. package/dist/patterns/dashboard-page.meta.js +5 -5
  109. package/dist/patterns/feed-page.js +25 -25
  110. package/dist/patterns/feed-page.meta.js +3 -3
  111. package/dist/patterns/landing-page.js +1 -1
  112. package/dist/patterns/list-detail-page.js +17 -17
  113. package/dist/patterns/settings-page.js +17 -17
  114. package/dist/presets/index.d.ts +1 -1
  115. package/dist/presets/index.js +17 -2
  116. package/dist/styles.css +163 -55
  117. package/dist/{theme-provider-S0NVJs2Y.d.ts → theme-provider-CdSicAad.d.ts} +1 -1
  118. package/dist/themes/_contract.js +22 -8
  119. package/dist/themes/atelier/atelier.css +13 -13
  120. package/dist/themes/atelier/index.d.ts +1 -1
  121. package/dist/themes/ember/ember.css +13 -13
  122. package/dist/themes/ember/index.d.ts +1 -1
  123. package/dist/themes/index.d.ts +2 -2
  124. package/dist/themes/meridian/index.d.ts +1 -1
  125. package/dist/themes/meridian/meridian.css +13 -13
  126. package/dist/themes/poppy/index.d.ts +1 -1
  127. package/dist/themes/poppy/poppy.css +19 -16
  128. package/dist/themes/prism/index.d.ts +1 -1
  129. package/dist/themes/prism/prism.css +18 -15
  130. package/dist/themes/sable/index.d.ts +1 -1
  131. package/dist/themes/sable/sable.css +18 -22
  132. package/dist/themes/verdant/index.d.ts +1 -1
  133. package/dist/themes/verdant/verdant.css +15 -15
  134. package/llms/blocks/danger-zone-block.md +4 -4
  135. package/llms/blocks/faq-block.md +3 -3
  136. package/llms/blocks/goal-progress-block.md +1 -1
  137. package/llms/blocks/notification-list-block.md +1 -1
  138. package/llms/blocks/pricing-table-block.md +12 -12
  139. package/llms/blocks/product-card-block.md +6 -6
  140. package/llms/blocks/profile-card-block.md +1 -1
  141. package/llms/blocks/profile-form-block.md +3 -3
  142. package/llms/blocks/revenue-breakdown-block.md +5 -5
  143. package/llms/blocks/stat-row-block.md +3 -3
  144. package/llms/blocks/task-list-block.md +2 -2
  145. package/llms/blocks/team-members-block.md +1 -1
  146. package/llms/blocks/wallet-block.md +7 -7
  147. package/llms/components/accordion.md +2 -2
  148. package/llms/components/app-header.md +1 -1
  149. package/llms/components/app-shell.md +2 -2
  150. package/llms/components/area-chart.md +1 -1
  151. package/llms/components/badge.md +15 -7
  152. package/llms/components/banner.md +6 -6
  153. package/llms/components/bar-chart.md +2 -2
  154. package/llms/components/breadcrumbs.md +1 -1
  155. package/llms/components/button.md +3 -3
  156. package/llms/components/card.md +4 -4
  157. package/llms/components/checkbox-card.md +5 -5
  158. package/llms/components/code-block.md +1 -1
  159. package/llms/components/command-menu.md +1 -1
  160. package/llms/components/context-card.md +2 -2
  161. package/llms/components/destructive-action-modal.md +1 -1
  162. package/llms/components/dialog.md +2 -2
  163. package/llms/components/disclosure-picker.md +2 -1
  164. package/llms/components/empty-state.md +4 -4
  165. package/llms/components/gradient-art.md +3 -3
  166. package/llms/components/label.md +1 -1
  167. package/llms/components/line-chart.md +1 -1
  168. package/llms/components/meter.md +2 -2
  169. package/llms/components/middle-truncate.md +5 -5
  170. package/llms/components/note.md +3 -3
  171. package/llms/components/pagination.md +2 -2
  172. package/llms/components/phone.md +1 -1
  173. package/llms/components/pie-chart.md +1 -1
  174. package/llms/components/pill.md +12 -2
  175. package/llms/components/popover.md +2 -2
  176. package/llms/components/radar-chart.md +1 -1
  177. package/llms/components/radial-chart.md +1 -1
  178. package/llms/components/radio-card.md +4 -4
  179. package/llms/components/radio.md +2 -2
  180. package/llms/components/scroller.md +1 -1
  181. package/llms/components/search-input.md +1 -1
  182. package/llms/components/segmented-bar.md +7 -7
  183. package/llms/components/select.md +2 -2
  184. package/llms/components/sheet.md +1 -1
  185. package/llms/components/side-nav.md +1 -1
  186. package/llms/components/sidebar.md +1 -1
  187. package/llms/components/sparkline.md +2 -2
  188. package/llms/components/spinner.md +1 -1
  189. package/llms/components/status-dot.md +4 -4
  190. package/llms/components/table.md +8 -8
  191. package/llms/components/tabs.md +1 -1
  192. package/llms/components/textarea.md +2 -2
  193. package/llms/components/toast.md +1 -1
  194. package/llms/components/tooltip.md +2 -2
  195. package/llms/foundations/spacing.md +7 -7
  196. package/llms/layout/grid.md +1 -1
  197. package/llms/layout/page.md +1 -1
  198. package/llms/layout/region.md +1 -1
  199. package/llms/layout/split-pane.md +1 -1
  200. package/llms/patterns/auth-page.md +11 -11
  201. package/llms/patterns/brand-landing-page.md +2 -2
  202. package/llms/patterns/chat-panel.md +2 -2
  203. package/llms/patterns/dashboard-page.md +78 -78
  204. package/llms/patterns/feed-page.md +31 -31
  205. package/llms/patterns/landing-page.md +1 -1
  206. package/llms/patterns/list-detail-page.md +18 -18
  207. package/llms/patterns/settings-page.md +18 -18
  208. package/llms/reference/token-intent.md +25 -11
  209. package/llms/reference/utilities.md +1 -1
  210. package/llms/tasks/adding-a-component.md +4 -1
  211. package/llms/tasks/building-a-page.md +40 -0
  212. package/llms/tasks/building-with-sable.md +4 -0
  213. package/llms/tasks/converting-an-app.md +3 -1
  214. package/llms/tasks/using-presets.md +4 -0
  215. package/llms-full.txt +433 -347
  216. package/llms.txt +7 -7
  217. package/package.json +4 -4
  218. package/registry.json +369 -233
  219. package/scripts/lint-rules.mjs +26 -5
  220. package/scripts/sources.mjs +4 -1
  221. package/skills/sable/SKILL.md +14 -3
@@ -91,11 +91,11 @@ var noteMeta = {
91
91
  examples: [
92
92
  {
93
93
  label: "Info",
94
- code: '<Note tone="info">Editions mint on Solana mainnet.</Note>'
94
+ code: '<Note tone="info">Reports refresh every hour.</Note>'
95
95
  },
96
96
  {
97
97
  label: "With title",
98
- code: '<Note tone="warning" title="Low balance">Top up SOL before minting.</Note>'
98
+ code: '<Note tone="warning" title="Low balance">Add credits before your next export.</Note>'
99
99
  },
100
100
  {
101
101
  label: "Warning with a remedy, inside a dialog",
@@ -103,7 +103,7 @@ var noteMeta = {
103
103
  },
104
104
  {
105
105
  label: "Custom icon",
106
- code: '<Note tone="neutral" icon="lock">Pricing and supply cannot be changed after an edition is purchased.</Note>'
106
+ code: '<Note tone="neutral" icon="lock">Pricing cannot be changed after an order is placed.</Note>'
107
107
  }
108
108
  ]
109
109
  };
@@ -12,7 +12,7 @@ function PageHeader({
12
12
  children,
13
13
  ...props
14
14
  }) {
15
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-4", className), ...props, children: [
15
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2 pb-4", className), ...props, children: [
16
16
  /* @__PURE__ */ jsx(
17
17
  HeadingRow,
18
18
  {
@@ -21,7 +21,7 @@ var paginationMeta = {
21
21
  },
22
22
  {
23
23
  guidance: "do",
24
- description: 'Use a specific label when multiple pagers appear on a page, such as "Collector pages".'
24
+ description: 'Use a specific label when multiple pagers appear on a page, such as "Customer pages".'
25
25
  },
26
26
  {
27
27
  guidance: "do",
@@ -128,7 +128,7 @@ var paginationMeta = {
128
128
  },
129
129
  {
130
130
  label: "Table results footer",
131
- code: '<Stack gap={2}><DataTable data={rows} columns={columns} rowKey={(row) => row.id} /><Pagination label="Collector pages" page={page} total={12} onPageChange={setPage} /></Stack>'
131
+ code: '<Stack gap={2}><DataTable data={rows} columns={columns} rowKey={(row) => row.id} /><Pagination label="Customer pages" page={page} total={12} onPageChange={setPage} /></Stack>'
132
132
  },
133
133
  {
134
134
  label: "Server query state",
@@ -67,7 +67,7 @@ var phoneMeta = {
67
67
  examples: [
68
68
  {
69
69
  label: "Framing a mobile layout",
70
- code: '<Phone><div className="p-4"><h2 className="text-title-lg">Activity</h2><p className="text-body-sm text-muted-foreground">3 new collects today.</p></div></Phone>'
70
+ code: '<Phone><div className="p-4"><h2 className="text-title-lg">Activity</h2><p className="text-body-sm text-muted-foreground">3 new orders today.</p></div></Phone>'
71
71
  },
72
72
  {
73
73
  label: "Mockup, not a responsive preview",
@@ -150,9 +150,9 @@ var pieChartMeta = {
150
150
  }
151
151
  ],
152
152
  tokensUsed: [
153
- "tone-edition",
154
- "tone-collectible",
155
- "tone-standard",
153
+ "tone-1",
154
+ "tone-2",
155
+ "tone-3",
156
156
  "tone-info",
157
157
  "tone-warning",
158
158
  "primary",
@@ -1,15 +1,17 @@
1
1
  // src/components/pill/pill.tsx
2
2
  import { cn } from "../../lib/cn.js";
3
+ import { isPaletteColor } from "../../lib/palette.js";
3
4
  import { trimLabel } from "../../lib/trim-label.js";
4
5
  import { pillVariants } from "./pill.variants.js";
5
6
  import { jsxs } from "react/jsx-runtime";
6
- function Pill({ selected = false, appearance, size, icon, className, children, type, ...props }) {
7
+ function Pill({ selected = false, appearance, size, tone, icon, className, children, type, ...props }) {
7
8
  return /* @__PURE__ */ jsxs(
8
9
  "button",
9
10
  {
10
11
  type: type ?? "button",
11
12
  "aria-pressed": selected,
12
- className: cn(pillVariants({ appearance, size, selected }), className),
13
+ "data-palette": isPaletteColor(tone) ? tone : void 0,
14
+ className: cn(pillVariants({ appearance, size, selected, tone }), className),
13
15
  ...props,
14
16
  children: [
15
17
  icon,
@@ -61,6 +61,12 @@ var pillMeta = {
61
61
  default: '"md"',
62
62
  description: "md sits on the density ladder's xs control height (28px); sm is 24px, for chips under or inside other content."
63
63
  },
64
+ {
65
+ name: "tone",
66
+ type: '"neutral" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "purple" | "pink"',
67
+ default: '"neutral"',
68
+ description: "neutral is the chip as described. A palette family colours it as a category, like the choices in a tag picker: a wash at rest, the solid family colour when selected. Painted from the theme's generated palette."
69
+ },
64
70
  {
65
71
  name: "icon",
66
72
  type: "ReactNode",
@@ -70,9 +76,16 @@ var pillMeta = {
70
76
  variants: {
71
77
  appearance: ["solid", "outline"],
72
78
  size: ["md", "sm"],
73
- selected: ["true", "false"]
79
+ selected: ["true", "false"],
80
+ tone: ["neutral", "red", "orange", "yellow", "green", "teal", "blue", "purple", "pink"]
74
81
  },
75
82
  tokensUsed: [
83
+ "palette-wash",
84
+ "palette-wash-strong",
85
+ "palette-edge",
86
+ "palette-solid",
87
+ "palette-text",
88
+ "palette-solid-ink",
76
89
  "secondary",
77
90
  "secondary-foreground",
78
91
  "accent",
@@ -89,9 +102,13 @@ var pillMeta = {
89
102
  "Selected state is exposed via aria-pressed."
90
103
  ],
91
104
  examples: [
105
+ {
106
+ label: "Tag picker",
107
+ code: '<Row gap={1}><Pill tone="blue" selected onClick={() => {}}>Design</Pill><Pill tone="teal" onClick={() => {}}>Research</Pill><Pill tone="orange" onClick={() => {}}>Marketing</Pill></Row>'
108
+ },
92
109
  {
93
110
  label: "Filter row",
94
- code: "<Row gap={1}><Pill selected onClick={() => {}}>All</Pill><Pill onClick={() => {}}>Editions</Pill><Pill onClick={() => {}}>Collectibles</Pill></Row>"
111
+ code: "<Row gap={1}><Pill selected onClick={() => {}}>All</Pill><Pill onClick={() => {}}>Projects</Pill><Pill onClick={() => {}}>Reports</Pill></Row>"
95
112
  },
96
113
  {
97
114
  label: "Outline, small (reactions)",
@@ -1,5 +1,6 @@
1
1
  // src/components/pill/pill.variants.ts
2
2
  import { cva } from "class-variance-authority";
3
+ import { PALETTE_COLORS } from "../../lib/palette.js";
3
4
  var pillVariants = cva(
4
5
  /*
5
6
  * The asymmetric `pt-[0.23em] pb-[0.1em]` is the LEGACY optical correction: a
@@ -31,6 +32,20 @@ var pillVariants = cva(
31
32
  selected: {
32
33
  true: "",
33
34
  false: ""
35
+ },
36
+ // `neutral` is the chip as described above. A palette family is a
37
+ // category colour (a tag someone picks): the chip paints from the slots
38
+ // its data-palette scope fills, so no step is named here.
39
+ tone: {
40
+ neutral: "",
41
+ red: "",
42
+ orange: "",
43
+ yellow: "",
44
+ green: "",
45
+ teal: "",
46
+ blue: "",
47
+ purple: "",
48
+ pink: ""
34
49
  }
35
50
  },
36
51
  compoundVariants: [
@@ -51,12 +66,18 @@ var pillVariants = cva(
51
66
  // Transparent on whatever it sits on; the hover is derived from that
52
67
  // surface (sable-surface-interactive), not a fixed accent fill.
53
68
  class: "border-border text-muted-foreground sable-surface-interactive"
54
- }
69
+ },
70
+ // After the neutral looks, so cn's merge lets these win.
71
+ { appearance: "solid", selected: false, tone: [...PALETTE_COLORS], class: "bg-palette-wash text-palette-text hover:bg-palette-wash-strong hover:text-palette-text" },
72
+ { appearance: "solid", selected: true, tone: [...PALETTE_COLORS], class: "bg-palette-solid text-palette-solid-ink hover:bg-palette-solid" },
73
+ { appearance: "outline", selected: false, tone: [...PALETTE_COLORS], class: "border-palette-edge text-palette-text" },
74
+ { appearance: "outline", selected: true, tone: [...PALETTE_COLORS], class: "border-palette-edge bg-palette-wash text-palette-text hover:bg-palette-wash-strong" }
55
75
  ],
56
76
  defaultVariants: {
57
77
  appearance: "solid",
58
78
  size: "md",
59
- selected: false
79
+ selected: false,
80
+ tone: "neutral"
60
81
  }
61
82
  }
62
83
  );
@@ -123,11 +123,11 @@ var popoverMeta = {
123
123
  examples: [
124
124
  {
125
125
  label: "Basic",
126
- code: '<Popover><PopoverTrigger render={<Button variant="secondary">Details</Button>} /><PopoverContent><PopoverTitle>Edition details</PopoverTitle><PopoverDescription>A limited run of 100, stored permanently on Arweave.</PopoverDescription></PopoverContent></Popover>'
126
+ code: '<Popover><PopoverTrigger render={<Button variant="secondary">Details</Button>} /><PopoverContent><PopoverTitle>Plan details</PopoverTitle><PopoverDescription>Up to 10 seats, billed monthly per seat.</PopoverDescription></PopoverContent></Popover>'
127
127
  },
128
128
  {
129
129
  label: "With close",
130
- code: '<Popover><PopoverTrigger render={<Button variant="secondary">Open</Button>} /><PopoverContent><PopoverTitle>Heads up</PopoverTitle><PopoverDescription>Collecting mints a compressed NFT to your wallet.</PopoverDescription><PopoverClose render={<Button size="sm">Got it</Button>} /></PopoverContent></Popover>'
130
+ code: '<Popover><PopoverTrigger render={<Button variant="secondary">Open</Button>} /><PopoverContent><PopoverTitle>Heads up</PopoverTitle><PopoverDescription>Upgrading starts a new billing period today.</PopoverDescription><PopoverClose render={<Button size="sm">Got it</Button>} /></PopoverContent></Popover>'
131
131
  }
132
132
  ]
133
133
  };
@@ -144,9 +144,9 @@ var radarChartMeta = {
144
144
  }
145
145
  ],
146
146
  tokensUsed: [
147
- "tone-edition",
148
- "tone-collectible",
149
- "tone-standard",
147
+ "tone-1",
148
+ "tone-2",
149
+ "tone-3",
150
150
  "tone-info",
151
151
  "tone-warning",
152
152
  "primary",
@@ -156,9 +156,9 @@ var radialChartMeta = {
156
156
  }
157
157
  ],
158
158
  tokensUsed: [
159
- "tone-edition",
160
- "tone-collectible",
161
- "tone-standard",
159
+ "tone-1",
160
+ "tone-2",
161
+ "tone-3",
162
162
  "tone-info",
163
163
  "tone-warning",
164
164
  "primary",
@@ -80,7 +80,7 @@ var radioMeta = {
80
80
  <FieldsetContent>
81
81
  <RadioGroup defaultValue="standard">
82
82
  <Field label="Standard" orientation="horizontal"><Radio value="standard" /></Field>
83
- <Field label="Edition" orientation="horizontal"><Radio value="edition" /></Field>
83
+ <Field label="Poll" orientation="horizontal"><Radio value="poll" /></Field>
84
84
  </RadioGroup>
85
85
  </FieldsetContent>
86
86
  </Fieldset>`
@@ -92,7 +92,7 @@ var radioMeta = {
92
92
  <FieldsetContent>
93
93
  <RadioGroup defaultValue="standard">
94
94
  <Field label="Standard" orientation="horizontal"><Radio value="standard" /></Field>
95
- <Field label="Edition" orientation="horizontal" disabled><Radio value="edition" /></Field>
95
+ <Field label="Poll" orientation="horizontal" disabled><Radio value="poll" /></Field>
96
96
  </RadioGroup>
97
97
  </FieldsetContent>
98
98
  </Fieldset>`
@@ -77,7 +77,7 @@ var radioCardMeta = {
77
77
  },
78
78
  {
79
79
  name: "tone",
80
- type: '"neutral" | "standard" | "collectible" | "edition" | "info" | "warning"',
80
+ type: '"neutral" | "3" | "2" | "1" | "info" | "warning"',
81
81
  default: '"neutral"',
82
82
  description: "Semantic colour the selected state carries across the border, radio, and icon glyph. Neutral uses the primary ring with a muted wash."
83
83
  },
@@ -106,7 +106,7 @@ var radioCardMeta = {
106
106
  }
107
107
  ],
108
108
  variants: {
109
- tone: ["neutral", "standard", "collectible", "edition", "info", "warning"]
109
+ tone: ["neutral", "3", "2", "1", "info", "warning"]
110
110
  },
111
111
  tokensUsed: [
112
112
  "input",
@@ -116,9 +116,9 @@ var radioCardMeta = {
116
116
  "muted",
117
117
  "ring",
118
118
  "muted-foreground",
119
- "tone-standard",
120
- "tone-collectible",
121
- "tone-edition",
119
+ "tone-3",
120
+ "tone-2",
121
+ "tone-1",
122
122
  "tone-info",
123
123
  "tone-warning"
124
124
  ],
@@ -132,7 +132,7 @@ var radioCardMeta = {
132
132
  examples: [
133
133
  {
134
134
  label: "Post type (tone + icon)",
135
- code: '<RadioGroup defaultValue="post" className="grid sm:grid-cols-3"><RadioCard value="post" tone="standard" icon={<Icon name="plus" />} title="Standard" description="Share without minting" /><RadioCard value="collectible" tone="collectible" icon={<Icon name="gem" />} title="Collectible" description="Free to collect as NFT" /><RadioCard value="edition" tone="edition" icon={<Icon name="image-stack" />} title="Edition" description="Sell as NFT editions" /></RadioGroup>'
135
+ code: '<RadioGroup defaultValue="starter" className="grid sm:grid-cols-3"><RadioCard value="starter" tone="3" icon={<Icon name="plus" />} title="Starter" description="Free for one person" /><RadioCard value="studio" tone="2" icon={<Icon name="gem" />} title="Studio" description="For small teams" /><RadioCard value="business" tone="1" icon={<Icon name="image-stack" />} title="Business" description="SSO and audit log" /></RadioGroup>'
136
136
  },
137
137
  {
138
138
  label: "Plan picker (plain)",
@@ -7,23 +7,23 @@ var radioCardToneClasses = {
7
7
  dot: "bg-primary",
8
8
  glyph: "text-foreground"
9
9
  },
10
- standard: {
11
- card: SELECTION_CARD_CHECKED.standard,
12
- marker: "group-data-[checked]:border-tone-standard",
13
- dot: "bg-tone-standard",
14
- glyph: "text-tone-standard"
10
+ "3": {
11
+ card: SELECTION_CARD_CHECKED["3"],
12
+ marker: "group-data-[checked]:border-tone-3",
13
+ dot: "bg-tone-3",
14
+ glyph: "text-tone-3"
15
15
  },
16
- collectible: {
17
- card: SELECTION_CARD_CHECKED.collectible,
18
- marker: "group-data-[checked]:border-tone-collectible",
19
- dot: "bg-tone-collectible",
20
- glyph: "text-tone-collectible"
16
+ "2": {
17
+ card: SELECTION_CARD_CHECKED["2"],
18
+ marker: "group-data-[checked]:border-tone-2",
19
+ dot: "bg-tone-2",
20
+ glyph: "text-tone-2"
21
21
  },
22
- edition: {
23
- card: SELECTION_CARD_CHECKED.edition,
24
- marker: "group-data-[checked]:border-tone-edition",
25
- dot: "bg-tone-edition",
26
- glyph: "text-tone-edition"
22
+ "1": {
23
+ card: SELECTION_CARD_CHECKED["1"],
24
+ marker: "group-data-[checked]:border-tone-1",
25
+ dot: "bg-tone-1",
26
+ glyph: "text-tone-1"
27
27
  },
28
28
  info: {
29
29
  card: SELECTION_CARD_CHECKED.info,
@@ -97,7 +97,7 @@ var scrollerMeta = {
97
97
  examples: [
98
98
  {
99
99
  label: "Vertical with overflow",
100
- code: '<Scroller label="Editions" className="h-64"><ul className="space-y-2 p-4">{items.map((item) => (<li key={item.id} className="text-body-sm">{item.title}</li>))}</ul></Scroller>'
100
+ code: '<Scroller label="Projects" className="h-64"><ul className="space-y-2 p-4">{items.map((item) => (<li key={item.id} className="text-body-sm">{item.title}</li>))}</ul></Scroller>'
101
101
  },
102
102
  {
103
103
  label: "Capped, scrolls past the cap",
@@ -116,7 +116,7 @@ var searchInputMeta = {
116
116
  },
117
117
  {
118
118
  label: "Uncontrolled, sized as a whole",
119
- code: '<Field label="Search posts"><SearchInput defaultValue="editions" className="max-w-80" /></Field>'
119
+ code: '<Field label="Search posts"><SearchInput defaultValue="roadmap" className="max-w-80" /></Field>'
120
120
  },
121
121
  {
122
122
  label: "Disabled",
@@ -18,7 +18,7 @@ function SectionHeader({
18
18
  ...props
19
19
  }) {
20
20
  const generatedId = useId();
21
- return /* @__PURE__ */ jsxs("div", { "data-slot": "section-header", className: cn("flex flex-col gap-1", className), ...props, children: [
21
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "section-header", className: cn("flex flex-col gap-2", className), ...props, children: [
22
22
  /* @__PURE__ */ jsx(
23
23
  HeadingRow,
24
24
  {
@@ -2,7 +2,7 @@
2
2
  import { cn } from "../../lib/cn.js";
3
3
  import { segmentedBarSegmentVariants, segmentedBarVariants } from "./segmented-bar.variants.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
- var SEGMENTED_BAR_TONES = ["edition", "collectible", "standard", "info", "primary", "neutral"];
5
+ var SEGMENTED_BAR_TONES = ["1", "2", "3", "info", "primary", "neutral"];
6
6
  function SegmentedBar({ segments, label, locale, size, className, ...props }) {
7
7
  const total = segments.reduce((sum, s) => sum + Math.max(0, s.value), 0);
8
8
  const percent = new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 0 });
@@ -59,12 +59,12 @@ var segmentedBarMeta = {
59
59
  ],
60
60
  variants: {
61
61
  size: ["sm", "md", "lg"],
62
- tone: ["edition", "collectible", "standard", "info", "primary", "neutral", "success", "warning", "destructive"]
62
+ tone: ["1", "2", "3", "info", "primary", "neutral", "success", "warning", "destructive"]
63
63
  },
64
64
  tokensUsed: [
65
- "tone-edition",
66
- "tone-collectible",
67
- "tone-standard",
65
+ "tone-1",
66
+ "tone-2",
67
+ "tone-3",
68
68
  "tone-info",
69
69
  "primary",
70
70
  "muted-foreground",
@@ -89,13 +89,13 @@ var segmentedBarMeta = {
89
89
  { slot: "activity", recipe: "none", part: "SegmentedBar", why: "No indeterminate state \u2014 an unknown breakdown is not drawn." }
90
90
  ],
91
91
  a11y: [
92
- 'Rendered role=img with an aria-label built from `label` and each segment\'s share ("Revenue by type: Editions 42%, Collectibles 27%"), so the whole breakdown is read in one stop.',
92
+ 'Rendered role=img with an aria-label built from `label` and each segment\'s share ("Revenue by channel: Direct 42%, Partners 27%"), so the whole breakdown is read in one stop.',
93
93
  "Colour alone does not identify a segment: always show a legend with each segment's label beside the bar."
94
94
  ],
95
95
  examples: [
96
96
  {
97
97
  label: "With a legend",
98
- code: 'const sales = [\n { label: "Editions", value: 42, tone: "edition" },\n { label: "Collectibles", value: 27, tone: "collectible" },\n { label: "Standard", value: 19, tone: "standard" },\n] as const\n\n<Stack gap={3}>\n <SegmentedBar label="Revenue by type" segments={[...sales]} size="lg" />\n <ul className="flex flex-col gap-1.5">\n {sales.map((s) => (\n <li key={s.label} className="flex items-center gap-2 text-body-sm">\n <StatusDot tone={s.tone} />\n <span className="flex-1 text-muted-foreground">{s.label}</span>\n <span className="text-mono-caption">{s.value}%</span>\n </li>\n ))}\n </ul>\n</Stack>'
98
+ code: 'const sales = [\n { label: "Direct", value: 42, tone: "1" },\n { label: "Partners", value: 27, tone: "2" },\n { label: "Referrals", value: 19, tone: "3" },\n] as const\n\n<Stack gap={3}>\n <SegmentedBar label="Revenue by channel" segments={[...sales]} size="lg" />\n <ul className="flex flex-col gap-1.5">\n {sales.map((s) => (\n <li key={s.label} className="flex items-center gap-2 text-body-sm">\n <StatusDot tone={s.tone} />\n <span className="flex-1 text-muted-foreground">{s.label}</span>\n <span className="text-mono-caption">{s.value}%</span>\n </li>\n ))}\n </ul>\n</Stack>'
99
99
  },
100
100
  {
101
101
  label: "Test results \u2014 status tones",
@@ -5,9 +5,9 @@ var segmentedBarSegmentVariants = cva(
5
5
  {
6
6
  variants: {
7
7
  tone: {
8
- edition: "bg-tone-edition",
9
- collectible: "bg-tone-collectible",
10
- standard: "bg-tone-standard",
8
+ "1": "bg-tone-1",
9
+ "2": "bg-tone-2",
10
+ "3": "bg-tone-3",
11
11
  info: "bg-tone-info",
12
12
  primary: "bg-primary",
13
13
  neutral: "bg-muted-foreground",
@@ -17,7 +17,7 @@ var segmentedBarSegmentVariants = cva(
17
17
  }
18
18
  },
19
19
  defaultVariants: {
20
- tone: "standard"
20
+ tone: "3"
21
21
  }
22
22
  }
23
23
  );
@@ -176,11 +176,11 @@ var selectMeta = {
176
176
  },
177
177
  {
178
178
  label: "Inside Field",
179
- code: '<Field label="Default visibility" description="Controls how new editions appear."><Select defaultValue="public"><SelectTrigger placeholder="Choose visibility" /><SelectContent><SelectItem value="public">Public</SelectItem><SelectItem value="private">Private</SelectItem><SelectItem value="unlisted">Unlisted</SelectItem></SelectContent></Select></Field>'
179
+ code: '<Field label="Default visibility" description="Controls how new projects appear."><Select defaultValue="public"><SelectTrigger placeholder="Choose visibility" /><SelectContent><SelectItem value="public">Public</SelectItem><SelectItem value="private">Private</SelectItem><SelectItem value="unlisted">Unlisted</SelectItem></SelectContent></Select></Field>'
180
180
  },
181
181
  {
182
182
  label: "Rich item labels",
183
- code: '<Select defaultValue="edition" items={[{ value: "edition", label: "Edition" }, { value: "collectible", label: "Collectible" }]}><SelectTrigger /><SelectContent><SelectItem value="edition" label="Edition"><span className="flex items-center gap-2"><Badge tone="edition">Edition</Badge><span>Edition drop</span></span></SelectItem><SelectItem value="collectible" label="Collectible"><span className="flex items-center gap-2"><Badge tone="collectible">Collectible</Badge><span>Collectible</span></span></SelectItem></SelectContent></Select>'
183
+ code: '<Select defaultValue="business" items={[{ value: "business", label: "Business" }, { value: "studio", label: "Studio" }]}><SelectTrigger /><SelectContent><SelectItem value="business" label="Business"><span className="flex items-center gap-2"><Badge tone="1">Business</Badge><span>Business plan</span></span></SelectItem><SelectItem value="studio" label="Studio"><span className="flex items-center gap-2"><Badge tone="2">Studio</Badge><span>Studio</span></span></SelectItem></SelectContent></Select>'
184
184
  }
185
185
  ]
186
186
  };
@@ -42,7 +42,21 @@ function SheetContent({
42
42
  reportSide?.(resolvedSide);
43
43
  }, [reportSide, resolvedSide]);
44
44
  const popupRef = useRef(null);
45
- const mergedRef = useMemo(() => mergeRefs(popupRef, ref), [ref]);
45
+ const [popup, setPopup] = useState(null);
46
+ const mergedRef = useMemo(() => mergeRefs(popupRef, ref, setPopup), [ref]);
47
+ useIsomorphicLayoutEffect(() => {
48
+ if (!popup || resolvedSide !== "left" && resolvedSide !== "right") return;
49
+ const root = document.documentElement;
50
+ const name = `--sable-sheet-${resolvedSide}-w`;
51
+ const publish = () => root.style.setProperty(name, `${popup.offsetWidth}px`);
52
+ publish();
53
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(publish);
54
+ observer?.observe(popup);
55
+ return () => {
56
+ observer?.disconnect();
57
+ root.style.removeProperty(name);
58
+ };
59
+ }, [popup, resolvedSide]);
46
60
  return /* @__PURE__ */ jsxs(SheetPortal, { children: [
47
61
  /* @__PURE__ */ jsx(Base.Backdrop, { className: "fixed inset-0 z-(--z-overlay) bg-overlay/(--scrim-alpha) opacity-[calc(1_-_var(--drawer-swipe-progress))] motion-fade data-[swiping]:transition-none" }),
48
62
  /* @__PURE__ */ jsx(Base.Viewport, { className: "fixed inset-0 z-(--z-overlay)", children: /* @__PURE__ */ jsx(
@@ -158,7 +158,7 @@ var sheetMeta = {
158
158
  },
159
159
  {
160
160
  label: "Bottom side",
161
- code: '<Sheet><SheetTrigger render={<Button variant="secondary">Details</Button>} /><SheetContent side="bottom"><SheetHeader><SheetTitle>Edition details</SheetTitle></SheetHeader><SheetFooter><SheetClose render={<Button variant="secondary">Close</Button>} /></SheetFooter></SheetContent></Sheet>'
161
+ code: '<Sheet><SheetTrigger render={<Button variant="secondary">Details</Button>} /><SheetContent side="bottom"><SheetHeader><SheetTitle>Order details</SheetTitle></SheetHeader><SheetFooter><SheetClose render={<Button variant="secondary">Close</Button>} /></SheetFooter></SheetContent></Sheet>'
162
162
  }
163
163
  ]
164
164
  };
@@ -122,7 +122,7 @@ var sideNavMeta = {
122
122
  },
123
123
  {
124
124
  label: "Chrome-weight rail (size=lg)",
125
- code: '<SideNav size="lg"><SideNavItem label="Profile" active render={<Link to="/settings/profile" />} /><SideNavItem label="Wallets" render={<Link to="/settings/wallets" />} /><SideNavItem label="Security" render={<Link to="/settings/security" />} /></SideNav>'
125
+ code: '<SideNav size="lg"><SideNavItem label="Profile" active render={<Link to="/settings/profile" />} /><SideNavItem label="Billing" render={<Link to="/settings/billing" />} /><SideNavItem label="Security" render={<Link to="/settings/security" />} /></SideNav>'
126
126
  },
127
127
  {
128
128
  label: "Inside Sidebar chrome",
@@ -106,7 +106,7 @@ var sidebarMeta = {
106
106
  examples: [
107
107
  {
108
108
  label: "Rail with nav",
109
- code: '<Sidebar><SidebarHeader><SidebarBrand mark={<Icon name="music" variant="solid" />} label="Undertow" render={<Link to="/" />} /></SidebarHeader><SidebarNav><SidebarItem icon={<Icon name="bell" />} label="Notifications" badge={<NotificationBadge count={3} />} render={<Link to="/notifications" />} /></SidebarNav><SidebarFooter>{wallet}</SidebarFooter></Sidebar>'
109
+ code: '<Sidebar><SidebarHeader><SidebarBrand mark={<Icon name="music" variant="solid" />} label="Undertow" render={<Link to="/" />} /></SidebarHeader><SidebarNav><SidebarItem icon={<Icon name="bell" />} label="Notifications" badge={<NotificationBadge count={3} />} render={<Link to="/notifications" />} /></SidebarNav><SidebarFooter>{account}</SidebarFooter></Sidebar>'
110
110
  },
111
111
  {
112
112
  label: "Collapsible (icon rail)",
@@ -60,7 +60,7 @@ var sparklineMeta = {
60
60
  },
61
61
  {
62
62
  name: "tone",
63
- type: '"edition" | "collectible" | "standard" | "info" | "warning" | "primary" | "neutral" | "success" | "destructive"',
63
+ type: '"1" | "2" | "3" | "info" | "warning" | "primary" | "neutral" | "success" | "destructive"',
64
64
  default: '"primary"',
65
65
  description: "Colour by role."
66
66
  },
@@ -92,9 +92,9 @@ var sparklineMeta = {
92
92
  },
93
93
  tokensUsed: [
94
94
  "primary",
95
- "tone-edition",
96
- "tone-collectible",
97
- "tone-standard",
95
+ "tone-1",
96
+ "tone-2",
97
+ "tone-3",
98
98
  "tone-info",
99
99
  "tone-warning",
100
100
  "muted-foreground",
@@ -109,7 +109,7 @@ var spinnerMeta = {
109
109
  },
110
110
  {
111
111
  label: "Inside a button (Button owns it \u2014 use loading)",
112
- code: "<Button loading>Collecting</Button>"
112
+ code: "<Button loading>Saving</Button>"
113
113
  }
114
114
  ]
115
115
  };
@@ -1,5 +1,6 @@
1
1
  // src/components/status-dot/status-dot.tsx
2
2
  import { cn } from "../../lib/cn.js";
3
+ import { isPaletteColor } from "../../lib/palette.js";
3
4
  import { statusDotVariants } from "./status-dot.variants.js";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  function StatusDot({
@@ -10,11 +11,13 @@ function StatusDot({
10
11
  ...props
11
12
  }) {
12
13
  const dot = statusDotVariants({ tone, size });
14
+ const palette = isPaletteColor(tone) ? tone : void 0;
13
15
  if (pulse) {
14
16
  return /* @__PURE__ */ jsxs(
15
17
  "span",
16
18
  {
17
19
  "aria-hidden": "true",
20
+ "data-palette": palette,
18
21
  className: cn("relative inline-flex shrink-0", className),
19
22
  ...props,
20
23
  children: [
@@ -32,7 +35,7 @@ function StatusDot({
32
35
  }
33
36
  );
34
37
  }
35
- return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(dot, className), ...props });
38
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-palette": palette, className: cn(dot, className), ...props });
36
39
  }
37
40
  StatusDot.displayName = "StatusDot";
38
41
  export {