@sableui/react 0.9.1 → 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 (212) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +95 -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.meta.js +3 -3
  35. package/dist/components/card/card.js +16 -7
  36. package/dist/components/card/card.meta.js +4 -4
  37. package/dist/components/checkbox-card/checkbox-card.meta.js +10 -10
  38. package/dist/components/checkbox-card/checkbox-card.variants.js +15 -15
  39. package/dist/components/code-block/code-block.meta.js +1 -1
  40. package/dist/components/command-menu/command-menu.meta.js +1 -1
  41. package/dist/components/context-card/context-card.meta.js +2 -2
  42. package/dist/components/destructive-action-modal/destructive-action-modal.meta.js +1 -1
  43. package/dist/components/dialog/dialog.meta.js +2 -2
  44. package/dist/components/disclosure-picker/disclosure-picker.js +48 -2
  45. package/dist/components/disclosure-picker/disclosure-picker.meta.js +3 -2
  46. package/dist/components/empty-state/empty-state.meta.js +4 -4
  47. package/dist/components/gradient-art/gradient-art.meta.js +3 -3
  48. package/dist/components/label/label.meta.js +1 -1
  49. package/dist/components/line-chart/line-chart.meta.js +3 -3
  50. package/dist/components/meter/meter.js +1 -1
  51. package/dist/components/meter/meter.meta.js +2 -2
  52. package/dist/components/meter/meter.variants.js +1 -1
  53. package/dist/components/middle-truncate/middle-truncate.meta.js +4 -4
  54. package/dist/components/note/note.meta.js +3 -3
  55. package/dist/components/page-header/page-header.js +1 -1
  56. package/dist/components/pagination/pagination.meta.js +2 -2
  57. package/dist/components/phone/phone.meta.js +1 -1
  58. package/dist/components/pie-chart/pie-chart.meta.js +3 -3
  59. package/dist/components/pill/pill.js +4 -2
  60. package/dist/components/pill/pill.meta.js +19 -2
  61. package/dist/components/pill/pill.variants.js +23 -2
  62. package/dist/components/popover/popover.meta.js +2 -2
  63. package/dist/components/radar-chart/radar-chart.meta.js +3 -3
  64. package/dist/components/radial-chart/radial-chart.meta.js +3 -3
  65. package/dist/components/radio/radio.meta.js +2 -2
  66. package/dist/components/radio-card/radio-card.meta.js +6 -6
  67. package/dist/components/radio-card/radio-card.variants.js +15 -15
  68. package/dist/components/scroller/scroller.meta.js +1 -1
  69. package/dist/components/search-input/search-input.meta.js +1 -1
  70. package/dist/components/section-header/section-header.js +1 -1
  71. package/dist/components/segmented-bar/segmented-bar.js +1 -1
  72. package/dist/components/segmented-bar/segmented-bar.meta.js +6 -6
  73. package/dist/components/segmented-bar/segmented-bar.variants.js +4 -4
  74. package/dist/components/select/select.meta.js +2 -2
  75. package/dist/components/sheet/sheet.meta.js +1 -1
  76. package/dist/components/side-nav/side-nav.meta.js +1 -1
  77. package/dist/components/sidebar/sidebar.meta.js +1 -1
  78. package/dist/components/sparkline/sparkline.meta.js +4 -4
  79. package/dist/components/spinner/spinner.meta.js +1 -1
  80. package/dist/components/status-dot/status-dot.js +4 -1
  81. package/dist/components/status-dot/status-dot.meta.js +8 -16
  82. package/dist/components/status-dot/status-dot.variants.js +13 -4
  83. package/dist/components/table/table.meta.js +4 -4
  84. package/dist/components/tabs/tabs.meta.js +1 -1
  85. package/dist/components/textarea/textarea.meta.js +2 -2
  86. package/dist/components/toast/toast.meta.js +1 -1
  87. package/dist/components/tooltip/tooltip.meta.js +2 -2
  88. package/dist/file-hashes.json +120 -118
  89. package/dist/foundations/spacing.js +8 -8
  90. package/dist/index.d.ts +137 -72
  91. package/dist/index.js +12 -1
  92. package/dist/lib/chart/types.js +3 -3
  93. package/dist/lib/palette.js +103 -0
  94. package/dist/lib/selection-card.js +4 -4
  95. package/dist/palette.css +669 -0
  96. package/dist/patterns/auth-page.js +6 -6
  97. package/dist/patterns/auth-page.meta.js +3 -3
  98. package/dist/patterns/brand-landing-page.js +2 -2
  99. package/dist/patterns/chat-panel.js +2 -2
  100. package/dist/patterns/dashboard-page.js +71 -71
  101. package/dist/patterns/dashboard-page.meta.js +5 -5
  102. package/dist/patterns/feed-page.js +25 -25
  103. package/dist/patterns/feed-page.meta.js +3 -3
  104. package/dist/patterns/landing-page.js +1 -1
  105. package/dist/patterns/list-detail-page.js +17 -17
  106. package/dist/patterns/settings-page.js +17 -17
  107. package/dist/presets/index.d.ts +1 -1
  108. package/dist/presets/index.js +17 -2
  109. package/dist/styles.css +115 -50
  110. package/dist/{theme-provider-S0NVJs2Y.d.ts → theme-provider-CdSicAad.d.ts} +1 -1
  111. package/dist/themes/_contract.js +22 -8
  112. package/dist/themes/atelier/atelier.css +13 -13
  113. package/dist/themes/atelier/index.d.ts +1 -1
  114. package/dist/themes/ember/ember.css +13 -13
  115. package/dist/themes/ember/index.d.ts +1 -1
  116. package/dist/themes/index.d.ts +2 -2
  117. package/dist/themes/meridian/index.d.ts +1 -1
  118. package/dist/themes/meridian/meridian.css +13 -13
  119. package/dist/themes/poppy/index.d.ts +1 -1
  120. package/dist/themes/poppy/poppy.css +19 -16
  121. package/dist/themes/prism/index.d.ts +1 -1
  122. package/dist/themes/prism/prism.css +18 -15
  123. package/dist/themes/sable/index.d.ts +1 -1
  124. package/dist/themes/sable/sable.css +18 -22
  125. package/dist/themes/verdant/index.d.ts +1 -1
  126. package/dist/themes/verdant/verdant.css +15 -15
  127. package/llms/blocks/danger-zone-block.md +4 -4
  128. package/llms/blocks/faq-block.md +3 -3
  129. package/llms/blocks/goal-progress-block.md +1 -1
  130. package/llms/blocks/notification-list-block.md +1 -1
  131. package/llms/blocks/pricing-table-block.md +12 -12
  132. package/llms/blocks/product-card-block.md +6 -6
  133. package/llms/blocks/profile-card-block.md +1 -1
  134. package/llms/blocks/profile-form-block.md +3 -3
  135. package/llms/blocks/revenue-breakdown-block.md +5 -5
  136. package/llms/blocks/stat-row-block.md +3 -3
  137. package/llms/blocks/task-list-block.md +2 -2
  138. package/llms/blocks/team-members-block.md +1 -1
  139. package/llms/blocks/wallet-block.md +7 -7
  140. package/llms/components/accordion.md +2 -2
  141. package/llms/components/app-header.md +1 -1
  142. package/llms/components/app-shell.md +2 -2
  143. package/llms/components/area-chart.md +1 -1
  144. package/llms/components/badge.md +15 -7
  145. package/llms/components/banner.md +6 -6
  146. package/llms/components/bar-chart.md +2 -2
  147. package/llms/components/breadcrumbs.md +1 -1
  148. package/llms/components/button.md +3 -3
  149. package/llms/components/card.md +4 -4
  150. package/llms/components/checkbox-card.md +5 -5
  151. package/llms/components/code-block.md +1 -1
  152. package/llms/components/command-menu.md +1 -1
  153. package/llms/components/context-card.md +2 -2
  154. package/llms/components/destructive-action-modal.md +1 -1
  155. package/llms/components/dialog.md +2 -2
  156. package/llms/components/disclosure-picker.md +2 -1
  157. package/llms/components/empty-state.md +4 -4
  158. package/llms/components/gradient-art.md +3 -3
  159. package/llms/components/label.md +1 -1
  160. package/llms/components/line-chart.md +1 -1
  161. package/llms/components/meter.md +2 -2
  162. package/llms/components/middle-truncate.md +5 -5
  163. package/llms/components/note.md +3 -3
  164. package/llms/components/pagination.md +2 -2
  165. package/llms/components/phone.md +1 -1
  166. package/llms/components/pie-chart.md +1 -1
  167. package/llms/components/pill.md +12 -2
  168. package/llms/components/popover.md +2 -2
  169. package/llms/components/radar-chart.md +1 -1
  170. package/llms/components/radial-chart.md +1 -1
  171. package/llms/components/radio-card.md +4 -4
  172. package/llms/components/radio.md +2 -2
  173. package/llms/components/scroller.md +1 -1
  174. package/llms/components/search-input.md +1 -1
  175. package/llms/components/segmented-bar.md +7 -7
  176. package/llms/components/select.md +2 -2
  177. package/llms/components/sheet.md +1 -1
  178. package/llms/components/side-nav.md +1 -1
  179. package/llms/components/sidebar.md +1 -1
  180. package/llms/components/sparkline.md +2 -2
  181. package/llms/components/spinner.md +1 -1
  182. package/llms/components/status-dot.md +4 -4
  183. package/llms/components/table.md +8 -8
  184. package/llms/components/tabs.md +1 -1
  185. package/llms/components/textarea.md +2 -2
  186. package/llms/components/toast.md +1 -1
  187. package/llms/components/tooltip.md +2 -2
  188. package/llms/foundations/spacing.md +7 -7
  189. package/llms/layout/grid.md +1 -1
  190. package/llms/layout/page.md +1 -1
  191. package/llms/layout/region.md +1 -1
  192. package/llms/layout/split-pane.md +1 -1
  193. package/llms/patterns/auth-page.md +11 -11
  194. package/llms/patterns/brand-landing-page.md +2 -2
  195. package/llms/patterns/chat-panel.md +2 -2
  196. package/llms/patterns/dashboard-page.md +78 -78
  197. package/llms/patterns/feed-page.md +31 -31
  198. package/llms/patterns/landing-page.md +1 -1
  199. package/llms/patterns/list-detail-page.md +18 -18
  200. package/llms/patterns/settings-page.md +18 -18
  201. package/llms/reference/token-intent.md +25 -11
  202. package/llms/reference/utilities.md +1 -1
  203. package/llms/tasks/adding-a-component.md +4 -1
  204. package/llms/tasks/building-a-page.md +40 -0
  205. package/llms/tasks/converting-an-app.md +3 -1
  206. package/llms/tasks/using-presets.md +4 -0
  207. package/llms-full.txt +429 -347
  208. package/llms.txt +7 -7
  209. package/package.json +4 -4
  210. package/registry.json +369 -233
  211. package/scripts/lint-rules.mjs +26 -5
  212. package/skills/sable/SKILL.md +14 -3
@@ -36,12 +36,12 @@ Use MiddleTruncate when both the beginning and end of a long identifier must rem
36
36
 
37
37
  ## Examples
38
38
 
39
- ### Solana address
39
+ ### API key
40
40
 
41
41
  ```tsx
42
42
  import { MiddleTruncate } from "@sableui/react"
43
43
 
44
- <MiddleTruncate text="5J7sX2QpHt9vK4mNbR8wYcZ3dF6gH1jL0pA8xQpVnTu" />
44
+ <MiddleTruncate text="demo_key_7f3a9c2e5b8d1f4a6c0e9b3d7a2f5c8e1b4" />
45
45
  ```
46
46
 
47
47
  ### Custom start/end counts
@@ -49,7 +49,7 @@ import { MiddleTruncate } from "@sableui/react"
49
49
  ```tsx
50
50
  import { MiddleTruncate } from "@sableui/react"
51
51
 
52
- <MiddleTruncate text="0xAbC1234567890dEf1234567890aBcDeF12345678" startChars={4} endChars={4} />
52
+ <MiddleTruncate text="9f2c4e7a1b3d5f60c8e2a4b6d8f0e1c3a5b7d9f2" startChars={4} endChars={4} />
53
53
  ```
54
54
 
55
55
  ### Copyable value
@@ -57,6 +57,6 @@ import { MiddleTruncate } from "@sableui/react"
57
57
  ```tsx
58
58
  import { Button, Icon, MiddleTruncate, Row, useCopy } from "@sableui/react"
59
59
 
60
- const { copy, copied } = useCopy(address)
61
- <Row gap={1}><MiddleTruncate text={address} /><Button variant="ghost" size="icon-xs" aria-label="Copy address" onClick={copy}><Icon name={copied ? "check" : "copy"} /></Button></Row>
60
+ const { copy, copied } = useCopy(commitHash)
61
+ <Row gap={1}><MiddleTruncate text={commitHash} /><Button variant="ghost" size="icon-xs" aria-label="Copy commit hash" onClick={copy}><Icon name={copied ? "check" : "copy"} /></Button></Row>
62
62
  ```
@@ -53,7 +53,7 @@ Use Note for helpful supporting information that should sit near the relevant co
53
53
  ```tsx
54
54
  import { Note } from "@sableui/react"
55
55
 
56
- <Note tone="info">Editions mint on Solana mainnet.</Note>
56
+ <Note tone="info">Reports refresh every hour.</Note>
57
57
  ```
58
58
 
59
59
  ### With title
@@ -61,7 +61,7 @@ import { Note } from "@sableui/react"
61
61
  ```tsx
62
62
  import { Note } from "@sableui/react"
63
63
 
64
- <Note tone="warning" title="Low balance">Top up SOL before minting.</Note>
64
+ <Note tone="warning" title="Low balance">Add credits before your next export.</Note>
65
65
  ```
66
66
 
67
67
  ### Warning with a remedy, inside a dialog
@@ -77,5 +77,5 @@ import { Note } from "@sableui/react"
77
77
  ```tsx
78
78
  import { Note } from "@sableui/react"
79
79
 
80
- <Note tone="neutral" icon="lock">Pricing and supply cannot be changed after an edition is purchased.</Note>
80
+ <Note tone="neutral" icon="lock">Pricing cannot be changed after an order is placed.</Note>
81
81
  ```
@@ -13,7 +13,7 @@ Use Pagination when a result set is split into discrete pages and the user needs
13
13
  ### Best practices
14
14
 
15
15
  - Do: Keep page state controlled by the parent route or data layer so URL, filters, and result fetches stay in sync.
16
- - Do: Use a specific label when multiple pagers appear on a page, such as "Collector pages".
16
+ - Do: Use a specific label when multiple pagers appear on a page, such as "Customer pages".
17
17
  - Do: Reset to page 1 when filters or search terms materially change the result set.
18
18
  - Don't: Use Pagination for tiny lists where all items fit comfortably on one page.
19
19
  - Don't: Hide disabled previous/next buttons at the bounds; disabled controls make the current position clearer.
@@ -79,7 +79,7 @@ const [page, setPage] = useState(8)
79
79
  ```tsx
80
80
  import { DataTable, Pagination, Stack } from "@sableui/react"
81
81
 
82
- <Stack gap={2}><DataTable data={rows} columns={columns} rowKey={(row) => row.id} /><Pagination label="Collector pages" page={page} total={12} onPageChange={setPage} /></Stack>
82
+ <Stack gap={2}><DataTable data={rows} columns={columns} rowKey={(row) => row.id} /><Pagination label="Customer pages" page={page} total={12} onPageChange={setPage} /></Stack>
83
83
  ```
84
84
 
85
85
  ### Server query state
@@ -46,7 +46,7 @@ Use Phone to frame a mobile product preview when the device context is useful.
46
46
  ```tsx
47
47
  import { Phone } from "@sableui/react"
48
48
 
49
- <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>
49
+ <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>
50
50
  ```
51
51
 
52
52
  ### Mockup, not a responsive preview
@@ -43,7 +43,7 @@ Use PieChart for a share of one total across two to six categories — traffic s
43
43
 
44
44
  ## Tokens used
45
45
 
46
- `tone-edition`, `tone-collectible`, `tone-standard`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
46
+ `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
47
47
 
48
48
  ## Motion
49
49
 
@@ -25,6 +25,7 @@ Use Pill for a row of filters or choices a person clicks to narrow or toggle wha
25
25
  | selected | boolean | false | Marks the pill as chosen. Solid lifts onto the primary surface; outline takes a primary tint and soft primary edge. Sets aria-pressed. |
26
26
  | appearance | "solid" \| "outline" | "solid" | solid for a filter row; outline for quiet chips that annotate other content (a reaction under a message, a tag on a card), where a filled chip would compete with what it annotates. |
27
27
  | size | "md" \| "sm" | "md" | md sits on the density ladder's xs control height (28px); sm is 24px, for chips under or inside other content. |
28
+ | tone | "neutral" \| "red" \| "orange" \| "yellow" \| "green" \| "teal" \| "blue" \| "purple" \| "pink" | "neutral" | 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. |
28
29
  | icon | ReactNode | — | Optional leading glyph (e.g. <Icon name="lock" />), rendered before the children with the base gap. |
29
30
 
30
31
  ## Variants
@@ -32,10 +33,11 @@ Use Pill for a row of filters or choices a person clicks to narrow or toggle wha
32
33
  - **appearance**: solid, outline
33
34
  - **size**: md, sm
34
35
  - **selected**: true, false
36
+ - **tone**: neutral, red, orange, yellow, green, teal, blue, purple, pink
35
37
 
36
38
  ## Tokens used
37
39
 
38
- `secondary`, `secondary-foreground`, `accent`, `accent-foreground`, `primary`, `primary-foreground`, `card`, `border`, `muted-foreground`, `foreground`
40
+ `palette-wash`, `palette-wash-strong`, `palette-edge`, `palette-solid`, `palette-text`, `palette-solid-ink`, `secondary`, `secondary-foreground`, `accent`, `accent-foreground`, `primary`, `primary-foreground`, `card`, `border`, `muted-foreground`, `foreground`
39
41
 
40
42
  ## Accessibility
41
43
 
@@ -48,12 +50,20 @@ Use Pill for a row of filters or choices a person clicks to narrow or toggle wha
48
50
 
49
51
  ## Examples
50
52
 
53
+ ### Tag picker
54
+
55
+ ```tsx
56
+ import { Pill, Row } from "@sableui/react"
57
+
58
+ <Row gap={1}><Pill tone="blue" selected onClick={() => {}}>Design</Pill><Pill tone="teal" onClick={() => {}}>Research</Pill><Pill tone="orange" onClick={() => {}}>Marketing</Pill></Row>
59
+ ```
60
+
51
61
  ### Filter row
52
62
 
53
63
  ```tsx
54
64
  import { Pill, Row } from "@sableui/react"
55
65
 
56
- <Row gap={1}><Pill selected onClick={() => {}}>All</Pill><Pill onClick={() => {}}>Editions</Pill><Pill onClick={() => {}}>Collectibles</Pill></Row>
66
+ <Row gap={1}><Pill selected onClick={() => {}}>All</Pill><Pill onClick={() => {}}>Projects</Pill><Pill onClick={() => {}}>Reports</Pill></Row>
57
67
  ```
58
68
 
59
69
  ### Outline, small (reactions)
@@ -67,7 +67,7 @@ Use Popover for anchored secondary content that needs more room than a tooltip b
67
67
  ```tsx
68
68
  import { Button, Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@sableui/react"
69
69
 
70
- <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>
70
+ <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>
71
71
  ```
72
72
 
73
73
  ### With close
@@ -75,5 +75,5 @@ import { Button, Popover, PopoverContent, PopoverDescription, PopoverTitle, Popo
75
75
  ```tsx
76
76
  import { Button, Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@sableui/react"
77
77
 
78
- <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>
78
+ <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>
79
79
  ```
@@ -42,7 +42,7 @@ Use RadarChart to compare the shape of a profile across five to eight dimensions
42
42
 
43
43
  ## Tokens used
44
44
 
45
- `tone-edition`, `tone-collectible`, `tone-standard`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
45
+ `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
46
46
 
47
47
  ## Motion
48
48
 
@@ -44,7 +44,7 @@ Use RadialChart for progress toward goals (several rings), a single score or usa
44
44
 
45
45
  ## Tokens used
46
46
 
47
- `tone-edition`, `tone-collectible`, `tone-standard`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
47
+ `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `primary`, `muted-foreground`, `border`, `popover`, `popover-foreground`, `foreground`, `background`
48
48
 
49
49
  ## Motion
50
50
 
@@ -39,18 +39,18 @@ Use RadioCard for visual choice cards when users compare a small set of named op
39
39
  | description | ReactNode | — | Optional supporting copy beneath the title (text-body-sm, muted). |
40
40
  | trailing | ReactNode | — | End-aligned on the title's line: a price, a delivery date, a count. The title takes the rest of the row. |
41
41
  | icon | ReactNode | — | Leading icon (e.g. a solid <Icon>). Its presence switches to the two-dimensional card — icon top-left, indicator top-right, copy below — and the glyph is rendered as a solid-fill icon in the tone colour. |
42
- | tone | "neutral" \| "standard" \| "collectible" \| "edition" \| "info" \| "warning" | "neutral" | Semantic colour the selected state carries across the border, radio, and icon glyph. Neutral uses the primary ring with a muted wash. |
42
+ | tone | "neutral" \| "3" \| "2" \| "1" \| "info" \| "warning" | "neutral" | Semantic colour the selected state carries across the border, radio, and icon glyph. Neutral uses the primary ring with a muted wash. |
43
43
  | disabled | boolean | false | Dims the card and blocks selection. The group skips it during keyboard navigation. |
44
44
  | titleClassName | string | — | Merged onto the title span (default text-title-sm) — e.g. to tighten copy in a two-column layout. |
45
45
  | descriptionClassName | string | — | Merged onto the description span (default text-body-sm text-muted-foreground). |
46
46
 
47
47
  ## Variants
48
48
 
49
- - **tone**: neutral, standard, collectible, edition, info, warning
49
+ - **tone**: neutral, 3, 2, 1, info, warning
50
50
 
51
51
  ## Tokens used
52
52
 
53
- `input`, `card`, `foreground`, `primary`, `muted`, `ring`, `muted-foreground`, `tone-standard`, `tone-collectible`, `tone-edition`, `tone-info`, `tone-warning`
53
+ `input`, `card`, `foreground`, `primary`, `muted`, `ring`, `muted-foreground`, `tone-3`, `tone-2`, `tone-1`, `tone-info`, `tone-warning`
54
54
 
55
55
  ## Accessibility
56
56
 
@@ -71,7 +71,7 @@ Use RadioCard for visual choice cards when users compare a small set of named op
71
71
  ```tsx
72
72
  import { Icon, RadioCard, RadioGroup } from "@sableui/react"
73
73
 
74
- <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>
74
+ <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>
75
75
  ```
76
76
 
77
77
  ### Plan picker (plain)
@@ -63,7 +63,7 @@ import { Field, Fieldset, FieldsetContent, FieldsetLegend, Radio, RadioGroup } f
63
63
  <FieldsetContent>
64
64
  <RadioGroup defaultValue="standard">
65
65
  <Field label="Standard" orientation="horizontal"><Radio value="standard" /></Field>
66
- <Field label="Edition" orientation="horizontal"><Radio value="edition" /></Field>
66
+ <Field label="Poll" orientation="horizontal"><Radio value="poll" /></Field>
67
67
  </RadioGroup>
68
68
  </FieldsetContent>
69
69
  </Fieldset>
@@ -79,7 +79,7 @@ import { Field, Fieldset, FieldsetContent, FieldsetLegend, Radio, RadioGroup } f
79
79
  <FieldsetContent>
80
80
  <RadioGroup defaultValue="standard">
81
81
  <Field label="Standard" orientation="horizontal"><Radio value="standard" /></Field>
82
- <Field label="Edition" orientation="horizontal" disabled><Radio value="edition" /></Field>
82
+ <Field label="Poll" orientation="horizontal" disabled><Radio value="poll" /></Field>
83
83
  </RadioGroup>
84
84
  </FieldsetContent>
85
85
  </Fieldset>
@@ -60,7 +60,7 @@ Use Scroller to create a contained overflow region for content that naturally ex
60
60
  ```tsx
61
61
  import { Scroller } from "@sableui/react"
62
62
 
63
- <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>
63
+ <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>
64
64
  ```
65
65
 
66
66
  ### Capped, scrolls past the cap
@@ -72,7 +72,7 @@ import { SearchInput } from "@sableui/react"
72
72
  ```tsx
73
73
  import { Field, SearchInput } from "@sableui/react"
74
74
 
75
- <Field label="Search posts"><SearchInput defaultValue="editions" className="max-w-80" /></Field>
75
+ <Field label="Search posts"><SearchInput defaultValue="roadmap" className="max-w-80" /></Field>
76
76
  ```
77
77
 
78
78
  ### Disabled
@@ -36,11 +36,11 @@ Use SegmentedBar when a stat card or row needs to show how a total divides into
36
36
  ## Variants
37
37
 
38
38
  - **size**: sm, md, lg
39
- - **tone**: edition, collectible, standard, info, primary, neutral, success, warning, destructive
39
+ - **tone**: 1, 2, 3, info, primary, neutral, success, warning, destructive
40
40
 
41
41
  ## Tokens used
42
42
 
43
- `tone-edition`, `tone-collectible`, `tone-standard`, `tone-info`, `primary`, `muted-foreground`, `success`, `tone-warning`, `destructive`
43
+ `tone-1`, `tone-2`, `tone-3`, `tone-info`, `primary`, `muted-foreground`, `success`, `tone-warning`, `destructive`
44
44
 
45
45
  ## Motion
46
46
 
@@ -51,7 +51,7 @@ Use SegmentedBar when a stat card or row needs to show how a total divides into
51
51
 
52
52
  ## Accessibility
53
53
 
54
- - 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.
54
+ - 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.
55
55
  - Colour alone does not identify a segment: always show a legend with each segment's label beside the bar.
56
56
 
57
57
  ## Related
@@ -67,13 +67,13 @@ Use SegmentedBar when a stat card or row needs to show how a total divides into
67
67
  import { SegmentedBar, Stack, StatusDot } from "@sableui/react"
68
68
 
69
69
  const sales = [
70
- { label: "Editions", value: 42, tone: "edition" },
71
- { label: "Collectibles", value: 27, tone: "collectible" },
72
- { label: "Standard", value: 19, tone: "standard" },
70
+ { label: "Direct", value: 42, tone: "1" },
71
+ { label: "Partners", value: 27, tone: "2" },
72
+ { label: "Referrals", value: 19, tone: "3" },
73
73
  ] as const
74
74
 
75
75
  <Stack gap={3}>
76
- <SegmentedBar label="Revenue by type" segments={[...sales]} size="lg" />
76
+ <SegmentedBar label="Revenue by channel" segments={[...sales]} size="lg" />
77
77
  <ul className="flex flex-col gap-1.5">
78
78
  {sales.map((s) => (
79
79
  <li key={s.label} className="flex items-center gap-2 text-body-sm">
@@ -94,7 +94,7 @@ import { SelectContent, SelectGroup, SelectGroupLabel, SelectItem } from "@sable
94
94
  ```tsx
95
95
  import { Field, Select, SelectContent, SelectItem, SelectTrigger } from "@sableui/react"
96
96
 
97
- <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>
97
+ <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>
98
98
  ```
99
99
 
100
100
  ### Rich item labels
@@ -102,5 +102,5 @@ import { Field, Select, SelectContent, SelectItem, SelectTrigger } from "@sableu
102
102
  ```tsx
103
103
  import { Badge, Select, SelectContent, SelectItem, SelectTrigger } from "@sableui/react"
104
104
 
105
- <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>
105
+ <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>
106
106
  ```
@@ -103,5 +103,5 @@ import { Button, Sheet, SheetClose, SheetContent, SheetFooter, SheetHeader, Shee
103
103
  ```tsx
104
104
  import { Button, Sheet, SheetClose, SheetContent, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@sableui/react"
105
105
 
106
- <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>
106
+ <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>
107
107
  ```
@@ -84,7 +84,7 @@ import { SideNav, SideNavGroup, SideNavItem } from "@sableui/react"
84
84
  import { SideNav, SideNavItem } from "@sableui/react"
85
85
  // <Link> = your router's link (react-router, next/link, @tanstack/router, …)
86
86
 
87
- <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>
87
+ <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>
88
88
  ```
89
89
 
90
90
  ### Inside Sidebar chrome
@@ -67,7 +67,7 @@ Use Sidebar for persistent desktop navigation or application chrome outside the
67
67
  import { Icon, NotificationBadge, Sidebar, SidebarBrand, SidebarFooter, SidebarHeader, SidebarItem, SidebarNav } from "@sableui/react"
68
68
  // <Link> = your router's link (react-router, next/link, @tanstack/router, …)
69
69
 
70
- <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>
70
+ <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>
71
71
  ```
72
72
 
73
73
  ### Collapsible (icon rail)
@@ -24,7 +24,7 @@ Use Sparkline next to a number to show where it has been — a KPI's last 30 day
24
24
  | data | number[] | — | The values, oldest first. |
25
25
  | label | string | — | What the line tracks ("Revenue, last 30 days"). The spoken summary adds the first and last values, low and high. |
26
26
  | variant | "line" \| "area" \| "bar" | "line" | A line, a line over a soft fill, or columns. |
27
- | tone | "edition" \| "collectible" \| "standard" \| "info" \| "warning" \| "primary" \| "neutral" \| "success" \| "destructive" | "primary" | Colour by role. |
27
+ | tone | "1" \| "2" \| "3" \| "info" \| "warning" \| "primary" \| "neutral" \| "success" \| "destructive" | "primary" | Colour by role. |
28
28
  | className | string | "h-8 w-24" | Sizes it; the drawing stretches to fit. |
29
29
  | animate | boolean | true | Draw on (or rise) when it scrolls into view. |
30
30
  | locale | string | runtime locale | BCP 47 locale for default number and date formatting. |
@@ -35,7 +35,7 @@ Use Sparkline next to a number to show where it has been — a KPI's last 30 day
35
35
 
36
36
  ## Tokens used
37
37
 
38
- `primary`, `tone-edition`, `tone-collectible`, `tone-standard`, `tone-info`, `tone-warning`, `muted-foreground`, `success`, `destructive`
38
+ `primary`, `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `muted-foreground`, `success`, `destructive`
39
39
 
40
40
  ## Motion
41
41
 
@@ -83,5 +83,5 @@ import { Spinner } from "@sableui/react"
83
83
  ```tsx
84
84
  import { Button } from "@sableui/react"
85
85
 
86
- <Button loading>Collecting</Button>
86
+ <Button loading>Saving</Button>
87
87
  ```
@@ -28,18 +28,18 @@ Use StatusDot as a compact visual state cue next to text, avatars, rows, or labe
28
28
 
29
29
  | Name | Type | Default | Description |
30
30
  | --- | --- | --- | --- |
31
- | tone | "neutral" \| "standard" \| "success" \| "warning" \| "info" \| "edition" \| "collectible" \| "destructive" | "neutral" | Semantic color of the dot. |
31
+ | tone | "neutral" \| "1" \| "2" \| "3" \| "success" \| "warning" \| "info" \| "destructive" \| "red" \| "orange" \| "yellow" \| "green" \| "teal" \| "blue" \| "purple" \| "pink" | "neutral" | Semantic color of the dot, or a palette family (red … pink) for a category legend. |
32
32
  | size | "sm" \| "md" \| "lg" | "md" | Dot diameter. |
33
33
  | pulse | boolean | false | Wrap the dot in an animated ping ring to signal a live state. |
34
34
 
35
35
  ## Variants
36
36
 
37
- - **tone**: neutral, standard, success, warning, info, edition, collectible, destructive
37
+ - **tone**: neutral, 1, 2, 3, success, warning, info, destructive, red, orange, yellow, green, teal, blue, purple, pink
38
38
  - **size**: sm, md, lg
39
39
 
40
40
  ## Tokens used
41
41
 
42
- `muted-foreground`, `tone-standard`, `success`, `tone-warning`, `tone-info`, `tone-edition`, `tone-collectible`, `destructive`
42
+ `palette-dot`, `muted-foreground`, `tone-3`, `success`, `tone-warning`, `tone-info`, `tone-1`, `tone-2`, `destructive`
43
43
 
44
44
  ## Accessibility
45
45
 
@@ -58,7 +58,7 @@ Use StatusDot as a compact visual state cue next to text, avatars, rows, or labe
58
58
  ```tsx
59
59
  import { Row, StatusDot } from "@sableui/react"
60
60
 
61
- <Row gap={2}><StatusDot tone="standard" /><StatusDot tone="info" /><StatusDot tone="warning" /><StatusDot tone="destructive" /></Row>
61
+ <Row gap={2}><StatusDot tone="3" /><StatusDot tone="info" /><StatusDot tone="warning" /><StatusDot tone="destructive" /></Row>
62
62
  ```
63
63
 
64
64
  ### With label — use Badge
@@ -63,25 +63,25 @@ Use Table for structured data with consistent columns and rows. Use DataTable wh
63
63
 
64
64
  ## Examples
65
65
 
66
- ### Collectors
66
+ ### Orders
67
67
 
68
68
  ```tsx
69
69
  import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@sableui/react"
70
70
 
71
71
  <Table>
72
- <TableCaption>Recent collectors</TableCaption>
72
+ <TableCaption>Recent orders</TableCaption>
73
73
  <TableHeader>
74
74
  <TableRow>
75
- <TableHead>Collector</TableHead>
76
- <TableHead>Edition</TableHead>
75
+ <TableHead>Customer</TableHead>
76
+ <TableHead>Order</TableHead>
77
77
  <TableHead>Paid</TableHead>
78
78
  </TableRow>
79
79
  </TableHeader>
80
80
  <TableBody>
81
81
  <TableRow>
82
82
  <TableCell>@nova</TableCell>
83
- <TableCell>#012</TableCell>
84
- <TableCell>0.5 SOL</TableCell>
83
+ <TableCell>1042</TableCell>
84
+ <TableCell>$48.00</TableCell>
85
85
  </TableRow>
86
86
  </TableBody>
87
87
  </Table>
@@ -100,7 +100,7 @@ import { Avatar, Badge, Button, Row, Table, TableBody, TableCaption, TableCell,
100
100
  ```tsx
101
101
  import { Card, CardContent, CardHeader, CardTitle, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@sableui/react"
102
102
 
103
- <Card><CardHeader><CardTitle>Collectors</CardTitle></CardHeader><CardContent flush><Table><TableHeader><TableRow><TableHead>Collector</TableHead><TableHead>Paid</TableHead></TableRow></TableHeader><TableBody><TableRow><TableCell>@nova</TableCell><TableCell>0.5 SOL</TableCell></TableRow></TableBody></Table></CardContent></Card>
103
+ <Card><CardHeader><CardTitle>Customers</CardTitle></CardHeader><CardContent flush><Table><TableHeader><TableRow><TableHead>Customer</TableHead><TableHead>Paid</TableHead></TableRow></TableHeader><TableBody><TableRow><TableCell>@nova</TableCell><TableCell>$48.00</TableCell></TableRow></TableBody></Table></CardContent></Card>
104
104
  ```
105
105
 
106
106
  ### Summary footer
@@ -108,5 +108,5 @@ import { Card, CardContent, CardHeader, CardTitle, Table, TableBody, TableCell,
108
108
  ```tsx
109
109
  import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@sableui/react"
110
110
 
111
- <Table><TableHeader><TableRow><TableHead>Item</TableHead><TableHead className="text-end">Amount</TableHead></TableRow></TableHeader><TableBody><TableRow><TableCell>Primary sale</TableCell><TableCell className="text-end">42 SOL</TableCell></TableRow></TableBody><TableFooter><TableRow><TableCell>Total</TableCell><TableCell className="text-end">42 SOL</TableCell></TableRow></TableFooter></Table>
111
+ <Table><TableHeader><TableRow><TableHead>Item</TableHead><TableHead className="text-end">Amount</TableHead></TableRow></TableHeader><TableBody><TableRow><TableCell>Studio plan</TableCell><TableCell className="text-end">$192.00</TableCell></TableRow></TableBody><TableFooter><TableRow><TableCell>Total</TableCell><TableCell className="text-end">$192.00</TableCell></TableRow></TableFooter></Table>
112
112
  ```
@@ -80,5 +80,5 @@ import { Tabs, TabsList, TabsPanel, TabsTrigger } from "@sableui/react"
80
80
  ```tsx
81
81
  import { Tabs, TabsList, TabsPanel, TabsTrigger } from "@sableui/react"
82
82
 
83
- <Tabs defaultValue="overview"><TabsList><TabsTrigger value="overview">Overview</TabsTrigger><TabsTrigger value="holders" disabled>Holders</TabsTrigger></TabsList><TabsPanel value="overview">Overview content</TabsPanel></Tabs>
83
+ <Tabs defaultValue="overview"><TabsList><TabsTrigger value="overview">Overview</TabsTrigger><TabsTrigger value="billing" disabled>Billing</TabsTrigger></TabsList><TabsPanel value="overview">Overview content</TabsPanel></Tabs>
84
84
  ```
@@ -60,7 +60,7 @@ import { Textarea } from "@sableui/react"
60
60
  ```tsx
61
61
  import { Textarea } from "@sableui/react"
62
62
 
63
- <Textarea rows={6} placeholder="Tell the story behind this edition…" />
63
+ <Textarea rows={6} placeholder="Tell your team what this project is for…" />
64
64
  ```
65
65
 
66
66
  ### Auto-resize
@@ -84,5 +84,5 @@ import { Textarea } from "@sableui/react"
84
84
  ```tsx
85
85
  import { Textarea } from "@sableui/react"
86
86
 
87
- <Textarea disabled defaultValue="Captions lock once the edition is minted." />
87
+ <Textarea disabled defaultValue="Notes lock once the invoice is sent." />
88
88
  ```
@@ -104,7 +104,7 @@ toast.promise(publish(), { loading: "Publishing…", success: "Published", error
104
104
  ```tsx
105
105
  import { toast } from "@sableui/react"
106
106
 
107
- const id = toast.loading("Pinning to Arweave…"); /* later */ toast.update(id, { title: "Pinned", type: "success", timeout: 4000 })
107
+ const id = toast.loading("Uploading report…"); /* later */ toast.update(id, { title: "Uploaded", type: "success", timeout: 4000 })
108
108
  ```
109
109
 
110
110
  ### Custom toast markup (composed parts)
@@ -73,7 +73,7 @@ Use Tooltip for brief nonessential hints tied to a specific control or piece of
73
73
  ```tsx
74
74
  import { Button, Icon, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@sableui/react"
75
75
 
76
- <TooltipProvider><Tooltip><TooltipTrigger render={<Button variant="ghost" size="icon-sm" aria-label="Info"><Icon name="info" /></Button>} /><TooltipContent>Stored permanently on Arweave.</TooltipContent></Tooltip></TooltipProvider>
76
+ <TooltipProvider><Tooltip><TooltipTrigger render={<Button variant="ghost" size="icon-sm" aria-label="Info"><Icon name="info" /></Button>} /><TooltipContent>Saved to your workspace.</TooltipContent></Tooltip></TooltipProvider>
77
77
  ```
78
78
 
79
79
  ### Sides
@@ -89,5 +89,5 @@ import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@sableui/react"
89
89
  ```tsx
90
90
  import { Button, Icon, SimpleTooltip } from "@sableui/react"
91
91
 
92
- <SimpleTooltip content="Stored permanently on Arweave."><Button variant="ghost" size="icon-sm" aria-label="Info"><Icon name="info" /></Button></SimpleTooltip>
92
+ <SimpleTooltip content="Saved to your workspace."><Button variant="ghost" size="icon-sm" aria-label="Info"><Icon name="info" /></Button></SimpleTooltip>
93
93
  ```
@@ -1,8 +1,8 @@
1
1
  # Spacing & sizing
2
2
 
3
- One 4px scale governs every gap, inset and size, and space is assigned by role. Controls read a height ladder that a density scope can retune all at once.
3
+ One scale, derived from the type: the baseline is one line of body text, split into steps every gap, inset and line height lands on. Space is assigned by role. Controls read a height ladder that a density scope can retune all at once.
4
4
 
5
- **4px base · 8px rhythm · 3 roles · 1 control ladder**
5
+ **Baseline from the type · 8px steps · 3 roles · 1 control ladder**
6
6
 
7
7
  ## Spacing by role
8
8
 
@@ -11,8 +11,8 @@ Steps below 2 (8px) are optical correction only.
11
11
  | Name | Value | Use |
12
12
  |---|---|---|
13
13
  | `Inset p-4` | 16px | Padding inside a surface. p-3 for a dense card, px-3 py-2 for a row. |
14
- | `Stack, within a group gap-1.5 – gap-2` | 6–8px | Label to field, title to description. |
15
- | `Stack, between groups gap-4 – gap-6` | 16–24px | Field to field, card to card. |
14
+ | `Stack, within a group gap-2` | 1 step · 8px | Label to field, title to description. |
15
+ | `Stack, between groups gap-4 – gap-6` | 2–3 steps · 16–24px | Field to field, card to card. |
16
16
  | `Stack, between sections gap-12+` | 48px+ | Major regions of a page. |
17
17
  | `Inline gap-2 – gap-3` | 8–12px | Icon to label, control to control. |
18
18
 
@@ -38,8 +38,8 @@ Comfortable values; data-density="compact" (or <Density>) redefines every step f
38
38
 
39
39
  ## Rules
40
40
 
41
- 1. **Every margin, padding and gap is a step on the 4px scale.** Off-scale values break the rhythm that lets adjacent components line up without coordination.
42
- 2. **Padding, gaps and insets in a component sit on the spacing scale: a step (p-4, gap-2) or --spacing(n) inside an arbitrary value (p-[var(--card-p,--spacing(6))]).** The density (Character) control works by retuning --spacing, so anything on the scale moves with it. A literal p-[1.5rem] or padding: "12px" stays put while everything around it tightens. Keep fixed rem/px for what must not scale: a 1px hairline, a ring width. *Enforced by design-lint: fixed-spacing (library source).*
41
+ 1. **Every margin, padding and gap is a step on the scale, and vertical space between blocks is whole baseline steps: an even Tailwind step (2, 4, 6, 8, 12) or a Stack/Row/Grid gap number.** The baseline is one line of body text split into steps; line heights round to it. An odd step (3, 5) is half a baseline step. It is a rhythm to keep, not a grid to force: components stay as tall as their content.
42
+ 2. **Padding, gaps and insets in a component sit on the spacing scale: a step (p-4, gap-2) or --spacing(n) inside an arbitrary value (p-[var(--card-p,--spacing(6))]).** --spacing derives from the baseline step and the density (Character) control moves the leading it comes from, so anything on the scale moves with it. A literal p-[1.5rem] or padding: "12px" stays put while everything around it tightens. Keep fixed rem/px for what must not scale: a 1px hairline, a ring width. *Enforced by design-lint: fixed-spacing (library source).*
43
43
  3. **Related things sit closer than unrelated things.** Proximity groups content without a divider line. Use space first; reach for a border only when space is not enough.
44
44
  4. **Space lives on the container (gap), not on children (margins).** gap survives reordering, conditional children and RTL; per-child margins do not.
45
45
  5. **Control heights read the --control-* ladder.** A density scope retunes every control at once. A hardcoded height has to be found and overridden by hand. *Enforced by sable-lint: raw-control-height.*
@@ -77,6 +77,6 @@ Every control, menu and popup inside retunes, including portaled overlays.
77
77
  <Stack gap={3}> between groups (24px), <Stack gap={1}> inside a group (8px)
78
78
  ```
79
79
 
80
- Two spacing steps do the work of every divider, with less ink. Stack's numeric gap counts --rhythm-unit — two spacing steps — so it follows the density control like every other spacing value.
80
+ Spacing steps do the work of every divider, with less ink. Stack's numeric gap counts --rhythm-unit — one baseline step — so it follows the type and the density control like every other spacing value.
81
81
 
82
82
  **Related:** `sable docs shape` · `sable docs typography` · `sable docs building-a-tool` · `sable token layout`
@@ -64,5 +64,5 @@ import { Card, CardDescription, CardHeader, Grid } from "@sableui/react"
64
64
  ```tsx
65
65
  import { Badge, Grid } from "@sableui/react"
66
66
 
67
- <Grid cols={{ base: 1, md: 2, lg: 4 }}><Badge appearance="plain" tone="standard" dot /><Badge appearance="plain" tone="warning" dot /><Badge appearance="plain" tone="neutral" dot /><Badge appearance="plain" tone="destructive" dot /></Grid>
67
+ <Grid cols={{ base: 1, md: 2, lg: 4 }}><Badge appearance="plain" tone="3" dot /><Badge appearance="plain" tone="warning" dot /><Badge appearance="plain" tone="neutral" dot /><Badge appearance="plain" tone="destructive" dot /></Grid>
68
68
  ```
@@ -35,5 +35,5 @@ Use Page as a route content shell that combines Region sizing with vertical rhyt
35
35
  ```tsx
36
36
  import { Card, CardContent, Page, PageHeader } from "@sableui/react"
37
37
 
38
- <Page as="main" max="feed"><PageHeader title="Home" description="Latest posts from artists you follow." /><Card><CardContent><p className="text-body-md">First post.</p></CardContent></Card></Page>
38
+ <Page as="main" max="feed"><PageHeader title="Home" description="Latest posts from people you follow." /><Card><CardContent><p className="text-body-md">First post.</p></CardContent></Card></Page>
39
39
  ```
@@ -50,7 +50,7 @@ import { PageHeader, Region } from "@sableui/react"
50
50
  ```tsx
51
51
  import { Card, CardHeader, CardTitle, Grid, Region } from "@sableui/react"
52
52
 
53
- <Region max="wide"><Grid minItemWidth="16rem"><Card><CardHeader><CardTitle>Revenue</CardTitle></CardHeader></Card><Card><CardHeader><CardTitle>Collects</CardTitle></CardHeader></Card></Grid></Region>
53
+ <Region max="wide"><Grid minItemWidth="16rem"><Card><CardHeader><CardTitle>Revenue</CardTitle></CardHeader></Card><Card><CardHeader><CardTitle>Orders</CardTitle></CardHeader></Card></Grid></Region>
54
54
  ```
55
55
 
56
56
  ### Fluid workspace: the queue's table takes the extra width
@@ -37,5 +37,5 @@ Use SplitPane for responsive two-pane layouts where a primary pane and supportin
37
37
  ```tsx
38
38
  import { AspectBox, Button, SplitPane, Stack } from "@sableui/react"
39
39
 
40
- <SplitPane ratio="2/1" primary={<AspectBox ratio={1}><img src={post.imageUrl} alt={post.title} className="size-full object-cover" /></AspectBox>} secondary={<Stack gap={2}><h1 className="text-heading-1">{post.title}</h1><p className="text-body-md text-muted-foreground">{post.description}</p><Button>Collect</Button></Stack>} />
40
+ <SplitPane ratio="2/1" primary={<AspectBox ratio={1}><img src={post.imageUrl} alt={post.title} className="size-full object-cover" /></AspectBox>} secondary={<Stack gap={2}><h1 className="text-heading-1">{post.title}</h1><p className="text-body-md text-muted-foreground">{post.description}</p><Button>Add to cart</Button></Stack>} />
41
41
  ```