@sableui/react 0.6.2 → 0.7.1

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 (642) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +315 -0
  3. package/CONTRIBUTING.md +16 -10
  4. package/DESIGN.md +3 -3
  5. package/README.md +3 -3
  6. package/bin/sable-lint.mjs +18 -0
  7. package/bin/sable.mjs +470 -62
  8. package/dist/blocks/api-keys-block.js +44 -0
  9. package/dist/blocks/api-keys-block.meta.js +21 -0
  10. package/dist/blocks/chat-thread-block.js +17 -0
  11. package/dist/blocks/chat-thread-block.meta.js +20 -0
  12. package/dist/blocks/command-palette-block.js +24 -0
  13. package/dist/blocks/command-palette-block.meta.js +21 -0
  14. package/dist/blocks/cta-band-block.js +27 -0
  15. package/dist/blocks/cta-band-block.meta.js +20 -0
  16. package/dist/blocks/danger-zone-block.js +39 -0
  17. package/dist/blocks/danger-zone-block.meta.js +21 -0
  18. package/dist/blocks/device-comparison-block.js +69 -0
  19. package/dist/blocks/device-comparison-block.meta.js +21 -0
  20. package/dist/blocks/event-card-block.js +40 -0
  21. package/dist/blocks/event-card-block.meta.js +21 -0
  22. package/dist/blocks/faq-block.js +38 -0
  23. package/dist/blocks/faq-block.meta.js +20 -0
  24. package/dist/blocks/feature-grid-block.js +38 -0
  25. package/dist/blocks/feature-grid-block.meta.js +21 -0
  26. package/dist/blocks/feedback-form-block.js +30 -0
  27. package/dist/blocks/feedback-form-block.meta.js +21 -0
  28. package/dist/blocks/goal-progress-block.js +24 -0
  29. package/dist/blocks/goal-progress-block.meta.js +21 -0
  30. package/dist/blocks/hero-block.js +33 -0
  31. package/dist/blocks/hero-block.meta.js +21 -0
  32. package/dist/blocks/index.js +162 -1964
  33. package/dist/blocks/invite-team-block.js +36 -0
  34. package/dist/blocks/invite-team-block.meta.js +20 -0
  35. package/dist/blocks/invoice-history-block.js +41 -0
  36. package/dist/blocks/invoice-history-block.meta.js +21 -0
  37. package/dist/blocks/kpi-sparkline-block.js +29 -0
  38. package/dist/blocks/kpi-sparkline-block.meta.js +20 -0
  39. package/dist/blocks/media-player-block.js +68 -0
  40. package/dist/blocks/media-player-block.meta.js +21 -0
  41. package/dist/blocks/newsletter-block.js +35 -0
  42. package/dist/blocks/newsletter-block.meta.js +21 -0
  43. package/dist/blocks/not-found-block.js +27 -0
  44. package/dist/blocks/not-found-block.meta.js +20 -0
  45. package/dist/blocks/notification-list-block.js +32 -0
  46. package/dist/blocks/notification-list-block.meta.js +21 -0
  47. package/dist/blocks/notification-settings-block.js +25 -0
  48. package/dist/blocks/notification-settings-block.meta.js +20 -0
  49. package/dist/blocks/order-tracking-block.js +26 -0
  50. package/dist/blocks/order-tracking-block.meta.js +20 -0
  51. package/dist/blocks/pricing-card-block.js +46 -0
  52. package/dist/blocks/pricing-card-block.meta.js +21 -0
  53. package/dist/blocks/pricing-table-block.js +88 -0
  54. package/dist/blocks/pricing-table-block.meta.js +20 -0
  55. package/dist/blocks/product-card-block.js +26 -0
  56. package/dist/blocks/product-card-block.meta.js +21 -0
  57. package/dist/blocks/profile-card-block.js +58 -0
  58. package/dist/blocks/profile-card-block.meta.js +21 -0
  59. package/dist/blocks/profile-form-block.js +70 -0
  60. package/dist/blocks/profile-form-block.meta.js +21 -0
  61. package/dist/blocks/revenue-breakdown-block.js +38 -0
  62. package/dist/blocks/revenue-breakdown-block.meta.js +21 -0
  63. package/dist/blocks/sign-in-block.js +38 -0
  64. package/dist/blocks/sign-in-block.meta.js +21 -0
  65. package/dist/blocks/sign-up-block.js +48 -0
  66. package/dist/blocks/sign-up-block.meta.js +21 -0
  67. package/dist/blocks/site-footer-block.js +54 -0
  68. package/dist/blocks/site-footer-block.meta.js +20 -0
  69. package/dist/blocks/stat-row-block.js +28 -0
  70. package/dist/blocks/stat-row-block.meta.js +21 -0
  71. package/dist/blocks/steps-block.js +37 -0
  72. package/dist/blocks/steps-block.meta.js +20 -0
  73. package/dist/blocks/task-list-block.js +52 -0
  74. package/dist/blocks/task-list-block.meta.js +21 -0
  75. package/dist/blocks/team-members-block.js +49 -0
  76. package/dist/blocks/team-members-block.meta.js +21 -0
  77. package/dist/blocks/testimonial-block.js +49 -0
  78. package/dist/blocks/testimonial-block.meta.js +20 -0
  79. package/dist/blocks/traffic-sources-block.js +39 -0
  80. package/dist/blocks/traffic-sources-block.meta.js +21 -0
  81. package/dist/blocks/traffic-trend-block.js +61 -0
  82. package/dist/blocks/traffic-trend-block.meta.js +21 -0
  83. package/dist/blocks/upload-list-block.js +39 -0
  84. package/dist/blocks/upload-list-block.meta.js +21 -0
  85. package/dist/blocks/verify-code-block.js +28 -0
  86. package/dist/blocks/verify-code-block.meta.js +21 -0
  87. package/dist/blocks/wallet-block.js +48 -0
  88. package/dist/blocks/wallet-block.meta.js +21 -0
  89. package/dist/components/accordion/accordion.js +63 -0
  90. package/dist/components/accordion/accordion.meta.js +155 -0
  91. package/dist/components/accordion/index.js +15 -0
  92. package/dist/components/app-header/app-header.js +30 -0
  93. package/dist/components/app-header/app-header.meta.js +88 -0
  94. package/dist/components/app-header/index.js +7 -0
  95. package/dist/components/app-shell/app-shell-dock.js +37 -0
  96. package/dist/components/app-shell/app-shell.js +67 -0
  97. package/dist/components/app-shell/app-shell.meta.js +176 -0
  98. package/dist/components/app-shell/index.js +7 -0
  99. package/dist/components/area-chart/area-chart.js +10 -0
  100. package/dist/components/area-chart/area-chart.meta.js +218 -0
  101. package/dist/components/area-chart/index.js +7 -0
  102. package/dist/components/attachment/attachment.js +176 -0
  103. package/dist/components/attachment/attachment.meta.js +179 -0
  104. package/dist/components/attachment/attachment.variants.js +47 -0
  105. package/dist/components/attachment/index.js +7 -0
  106. package/dist/components/avatar/avatar.js +192 -0
  107. package/dist/components/avatar/avatar.meta.js +233 -0
  108. package/dist/components/avatar/avatar.variants.js +44 -0
  109. package/dist/components/avatar/index.js +22 -0
  110. package/dist/components/badge/badge.js +26 -0
  111. package/dist/components/badge/badge.meta.js +171 -0
  112. package/dist/components/badge/badge.variants.js +103 -0
  113. package/dist/components/badge/index.js +11 -0
  114. package/dist/components/banner/banner.js +76 -0
  115. package/dist/components/banner/banner.meta.js +172 -0
  116. package/dist/components/banner/banner.variants.js +44 -0
  117. package/dist/components/banner/index.js +9 -0
  118. package/dist/components/bar-chart/bar-chart.js +10 -0
  119. package/dist/components/bar-chart/bar-chart.meta.js +245 -0
  120. package/dist/components/bar-chart/index.js +7 -0
  121. package/dist/components/bottom-nav/bottom-nav.js +63 -0
  122. package/dist/components/bottom-nav/bottom-nav.meta.js +95 -0
  123. package/dist/components/bottom-nav/index.js +11 -0
  124. package/dist/components/breadcrumbs/breadcrumbs.js +90 -0
  125. package/dist/components/breadcrumbs/breadcrumbs.meta.js +111 -0
  126. package/dist/components/breadcrumbs/index.js +17 -0
  127. package/dist/components/browser/browser.js +39 -0
  128. package/dist/components/browser/browser.meta.js +80 -0
  129. package/dist/components/browser/index.js +7 -0
  130. package/dist/components/bubble/bubble.js +110 -0
  131. package/dist/components/bubble/bubble.meta.js +158 -0
  132. package/dist/components/bubble/bubble.variants.js +90 -0
  133. package/dist/components/bubble/index.js +13 -0
  134. package/dist/components/button/button.js +87 -0
  135. package/dist/components/button/button.meta.js +302 -0
  136. package/dist/components/button/button.variants.js +137 -0
  137. package/dist/components/button/index.js +9 -0
  138. package/dist/components/calendar/calendar.js +89 -0
  139. package/dist/components/calendar/calendar.meta.js +136 -0
  140. package/dist/components/calendar/index.js +7 -0
  141. package/dist/components/card/card.js +203 -0
  142. package/dist/components/card/card.meta.js +212 -0
  143. package/dist/components/card/index.js +23 -0
  144. package/dist/components/carousel/carousel.js +428 -0
  145. package/dist/components/carousel/carousel.meta.js +100 -0
  146. package/dist/components/carousel/index.js +7 -0
  147. package/dist/components/chat-composer/chat-composer.js +174 -0
  148. package/dist/components/chat-composer/chat-composer.meta.js +241 -0
  149. package/dist/components/chat-composer/chat-composer.variants.js +17 -0
  150. package/dist/components/chat-composer/index.js +7 -0
  151. package/dist/components/checkbox/checkbox-mark.js +28 -0
  152. package/dist/components/checkbox/checkbox.js +30 -0
  153. package/dist/components/checkbox/checkbox.meta.js +127 -0
  154. package/dist/components/checkbox/index.js +7 -0
  155. package/dist/components/checkbox-card/checkbox-card.js +94 -0
  156. package/dist/components/checkbox-card/checkbox-card.meta.js +154 -0
  157. package/dist/components/checkbox-card/checkbox-card.variants.js +43 -0
  158. package/dist/components/checkbox-card/index.js +11 -0
  159. package/dist/components/code/code.js +19 -0
  160. package/dist/components/code/code.meta.js +71 -0
  161. package/dist/components/code/index.js +7 -0
  162. package/dist/components/code-block/code-block.js +84 -0
  163. package/dist/components/code-block/code-block.meta.js +103 -0
  164. package/dist/components/code-block/index.js +8 -0
  165. package/dist/components/collapsible/collapsible.js +38 -0
  166. package/dist/components/collapsible/collapsible.meta.js +117 -0
  167. package/dist/components/collapsible/index.js +15 -0
  168. package/dist/components/color-field/color-field.js +293 -0
  169. package/dist/components/color-field/color-field.meta.js +142 -0
  170. package/dist/components/color-field/color.js +69 -0
  171. package/dist/components/color-field/index.js +15 -0
  172. package/dist/components/combobox/combobox.js +486 -0
  173. package/dist/components/combobox/combobox.meta.js +217 -0
  174. package/dist/components/combobox/index.js +37 -0
  175. package/dist/components/command-menu/command-menu-trigger.js +122 -0
  176. package/dist/components/command-menu/command-menu.js +433 -0
  177. package/dist/components/command-menu/command-menu.meta.js +279 -0
  178. package/dist/components/command-menu/index.js +21 -0
  179. package/dist/components/context-card/context-card.js +62 -0
  180. package/dist/components/context-card/context-card.meta.js +106 -0
  181. package/dist/components/context-card/index.js +17 -0
  182. package/dist/components/context-menu/context-menu.js +92 -0
  183. package/dist/components/context-menu/context-menu.meta.js +138 -0
  184. package/dist/components/context-menu/index.js +23 -0
  185. package/dist/components/data-table/data-table.js +142 -0
  186. package/dist/components/data-table/data-table.meta.js +146 -0
  187. package/dist/components/data-table/index.js +9 -0
  188. package/dist/components/date-picker/date-picker.js +196 -0
  189. package/dist/components/date-picker/date-picker.meta.js +164 -0
  190. package/dist/components/date-picker/index.js +7 -0
  191. package/dist/components/date-tile/date-tile.js +29 -0
  192. package/dist/components/date-tile/date-tile.meta.js +72 -0
  193. package/dist/components/date-tile/index.js +7 -0
  194. package/dist/components/destructive-action-modal/destructive-action-modal.js +130 -0
  195. package/dist/components/destructive-action-modal/destructive-action-modal.meta.js +136 -0
  196. package/dist/components/destructive-action-modal/index.js +9 -0
  197. package/dist/components/dialog/dialog.js +207 -0
  198. package/dist/components/dialog/dialog.meta.js +239 -0
  199. package/dist/components/dialog/index.js +45 -0
  200. package/dist/components/disclosure-picker/disclosure-picker.js +417 -0
  201. package/dist/components/disclosure-picker/disclosure-picker.meta.js +213 -0
  202. package/dist/components/disclosure-picker/index.js +21 -0
  203. package/dist/components/empty-state/empty-state.js +52 -0
  204. package/dist/components/empty-state/empty-state.meta.js +158 -0
  205. package/dist/components/empty-state/index.js +7 -0
  206. package/dist/components/entity/entity.js +70 -0
  207. package/dist/components/entity/entity.meta.js +108 -0
  208. package/dist/components/entity/entity.variants.js +16 -0
  209. package/dist/components/entity/index.js +7 -0
  210. package/dist/components/feedback/feedback.js +93 -0
  211. package/dist/components/feedback/feedback.meta.js +109 -0
  212. package/dist/components/feedback/index.js +7 -0
  213. package/dist/components/fieldset/fieldset.js +80 -0
  214. package/dist/components/fieldset/fieldset.meta.js +160 -0
  215. package/dist/components/fieldset/index.js +17 -0
  216. package/dist/components/file-dropzone/file-dropzone.js +193 -0
  217. package/dist/components/file-dropzone/file-dropzone.meta.js +210 -0
  218. package/dist/components/file-dropzone/file-dropzone.variants.js +26 -0
  219. package/dist/components/file-dropzone/index.js +13 -0
  220. package/dist/components/font-picker/font-picker.js +77 -0
  221. package/dist/components/font-picker/font-picker.meta.js +119 -0
  222. package/dist/components/font-picker/index.js +7 -0
  223. package/dist/components/form/form.js +145 -0
  224. package/dist/components/form/form.meta.js +142 -0
  225. package/dist/components/form/index.js +11 -0
  226. package/dist/components/gliding-highlight/gliding-highlight.js +50 -0
  227. package/dist/components/gliding-highlight/gliding-highlight.meta.js +135 -0
  228. package/dist/components/gliding-highlight/index.js +9 -0
  229. package/dist/components/gradient-art/gradient-art.js +168 -0
  230. package/dist/components/gradient-art/gradient-art.meta.js +81 -0
  231. package/dist/components/gradient-art/index.js +7 -0
  232. package/dist/components/gradient-art/renderer.js +336 -0
  233. package/dist/components/inline-status/index.js +7 -0
  234. package/dist/components/inline-status/inline-status.js +33 -0
  235. package/dist/components/inline-status/inline-status.meta.js +83 -0
  236. package/dist/components/inline-status/inline-status.variants.js +18 -0
  237. package/dist/components/input/index.js +7 -0
  238. package/dist/components/input/input.js +33 -0
  239. package/dist/components/input/input.meta.js +155 -0
  240. package/dist/components/kbd/index.js +8 -0
  241. package/dist/components/kbd/kbd.js +54 -0
  242. package/dist/components/kbd/kbd.meta.js +95 -0
  243. package/dist/components/label/index.js +7 -0
  244. package/dist/components/label/label.js +51 -0
  245. package/dist/components/label/label.meta.js +98 -0
  246. package/dist/components/line-chart/index.js +7 -0
  247. package/dist/components/line-chart/line-chart.js +10 -0
  248. package/dist/components/line-chart/line-chart.meta.js +222 -0
  249. package/dist/components/marker/index.js +7 -0
  250. package/dist/components/marker/marker.js +39 -0
  251. package/dist/components/marker/marker.meta.js +132 -0
  252. package/dist/components/marker/marker.variants.js +25 -0
  253. package/dist/components/marquee/index.js +7 -0
  254. package/dist/components/marquee/marquee.js +146 -0
  255. package/dist/components/marquee/marquee.meta.js +106 -0
  256. package/dist/components/media-image/index.js +7 -0
  257. package/dist/components/media-image/media-image.js +56 -0
  258. package/dist/components/media-image/media-image.meta.js +92 -0
  259. package/dist/components/media-tile/index.js +7 -0
  260. package/dist/components/media-tile/media-tile.js +135 -0
  261. package/dist/components/media-tile/media-tile.meta.js +133 -0
  262. package/dist/components/media-tile/media-tile.variants.js +48 -0
  263. package/dist/components/menu/index.js +33 -0
  264. package/dist/components/menu/menu.js +168 -0
  265. package/dist/components/menu/menu.meta.js +176 -0
  266. package/dist/components/message/index.js +7 -0
  267. package/dist/components/message/message.js +83 -0
  268. package/dist/components/message/message.meta.js +150 -0
  269. package/dist/components/message/message.variants.js +41 -0
  270. package/dist/components/message-scroller/index.js +9 -0
  271. package/dist/components/message-scroller/message-scroller.js +300 -0
  272. package/dist/components/message-scroller/message-scroller.meta.js +172 -0
  273. package/dist/components/meter/index.js +20 -0
  274. package/dist/components/meter/meter.js +112 -0
  275. package/dist/components/meter/meter.meta.js +227 -0
  276. package/dist/components/meter/meter.variants.js +61 -0
  277. package/dist/components/middle-truncate/index.js +7 -0
  278. package/dist/components/middle-truncate/middle-truncate.js +28 -0
  279. package/dist/components/middle-truncate/middle-truncate.meta.js +77 -0
  280. package/dist/components/note/index.js +9 -0
  281. package/dist/components/note/note.js +73 -0
  282. package/dist/components/note/note.meta.js +112 -0
  283. package/dist/components/note/note.variants.js +22 -0
  284. package/dist/components/notification-badge/index.js +15 -0
  285. package/dist/components/notification-badge/notification-badge.js +48 -0
  286. package/dist/components/notification-badge/notification-badge.meta.js +107 -0
  287. package/dist/components/notification-badge/notification-badge.variants.js +57 -0
  288. package/dist/components/number-field/index.js +7 -0
  289. package/dist/components/number-field/number-field.js +70 -0
  290. package/dist/components/number-field/number-field.meta.js +109 -0
  291. package/dist/components/otp-field/index.js +7 -0
  292. package/dist/components/otp-field/otp-field.js +70 -0
  293. package/dist/components/otp-field/otp-field.meta.js +197 -0
  294. package/dist/components/overflow-menu/index.js +7 -0
  295. package/dist/components/overflow-menu/overflow-menu.js +26 -0
  296. package/dist/components/overflow-menu/overflow-menu.meta.js +100 -0
  297. package/dist/components/page-header/index.js +7 -0
  298. package/dist/components/page-header/page-header.js +34 -0
  299. package/dist/components/page-header/page-header.meta.js +104 -0
  300. package/dist/components/page-loader/index.js +7 -0
  301. package/dist/components/page-loader/page-loader.js +37 -0
  302. package/dist/components/page-loader/page-loader.meta.js +85 -0
  303. package/dist/components/pagination/index.js +7 -0
  304. package/dist/components/pagination/pagination.js +105 -0
  305. package/dist/components/pagination/pagination.meta.js +141 -0
  306. package/dist/components/panel-group/index.js +10 -0
  307. package/dist/components/panel-group/panel-group.js +168 -0
  308. package/dist/components/panel-group/panel-group.meta.js +153 -0
  309. package/dist/components/panel-section/index.js +9 -0
  310. package/dist/components/panel-section/panel-section.js +115 -0
  311. package/dist/components/panel-section/panel-section.meta.js +156 -0
  312. package/dist/components/phone/index.js +7 -0
  313. package/dist/components/phone/phone.js +50 -0
  314. package/dist/{chunk-KFZ43RKU.js → components/phone/phone.meta.js} +3 -50
  315. package/dist/{chunk-NEQNXI2G.js → components/phone/status-icons.js} +4 -4
  316. package/dist/components/pie-chart/index.js +7 -0
  317. package/dist/components/pie-chart/pie-chart.js +191 -0
  318. package/dist/components/pie-chart/pie-chart.meta.js +210 -0
  319. package/dist/components/pill/index.js +9 -0
  320. package/dist/components/pill/pill.js +24 -0
  321. package/dist/components/pill/pill.meta.js +108 -0
  322. package/dist/components/pill/pill.variants.js +65 -0
  323. package/dist/components/popover/index.js +23 -0
  324. package/dist/components/popover/popover.js +100 -0
  325. package/dist/components/popover/popover.meta.js +136 -0
  326. package/dist/components/progress/index.js +19 -0
  327. package/dist/components/progress/progress.js +70 -0
  328. package/dist/components/progress/progress.meta.js +171 -0
  329. package/dist/components/progress/progress.variants.js +17 -0
  330. package/dist/components/radar-chart/index.js +7 -0
  331. package/dist/components/radar-chart/radar-chart.js +161 -0
  332. package/dist/components/radar-chart/radar-chart.meta.js +204 -0
  333. package/dist/components/radial-chart/index.js +7 -0
  334. package/dist/components/radial-chart/radial-chart.js +175 -0
  335. package/dist/components/radial-chart/radial-chart.meta.js +216 -0
  336. package/dist/components/radio/index.js +8 -0
  337. package/dist/components/radio/radio.js +39 -0
  338. package/dist/components/radio/radio.meta.js +104 -0
  339. package/dist/components/radio-card/index.js +7 -0
  340. package/dist/components/radio-card/radio-card.js +81 -0
  341. package/dist/components/radio-card/radio-card.meta.js +144 -0
  342. package/dist/components/radio-card/radio-card.variants.js +43 -0
  343. package/dist/components/relative-time/index.js +7 -0
  344. package/dist/components/relative-time/relative-time.js +47 -0
  345. package/dist/components/relative-time/relative-time.meta.js +77 -0
  346. package/dist/components/scroller/index.js +7 -0
  347. package/dist/components/scroller/scroller.js +111 -0
  348. package/dist/components/scroller/scroller.meta.js +118 -0
  349. package/dist/components/scrub-field/index.js +7 -0
  350. package/dist/components/scrub-field/scrub-field.js +124 -0
  351. package/dist/components/scrub-field/scrub-field.meta.js +139 -0
  352. package/dist/components/search-input/index.js +7 -0
  353. package/dist/components/search-input/search-input.js +91 -0
  354. package/dist/components/search-input/search-input.meta.js +129 -0
  355. package/dist/components/section-header/index.js +7 -0
  356. package/dist/components/section-header/section-header.js +39 -0
  357. package/dist/components/section-header/section-header.meta.js +174 -0
  358. package/dist/components/segmented-bar/index.js +14 -0
  359. package/dist/components/segmented-bar/segmented-bar.js +26 -0
  360. package/dist/components/segmented-bar/segmented-bar.meta.js +108 -0
  361. package/dist/components/segmented-bar/segmented-bar.variants.js +39 -0
  362. package/dist/components/select/index.js +25 -0
  363. package/dist/components/select/select.js +191 -0
  364. package/dist/components/select/select.meta.js +189 -0
  365. package/dist/components/separator/index.js +7 -0
  366. package/dist/components/separator/separator.js +42 -0
  367. package/dist/components/separator/separator.meta.js +84 -0
  368. package/dist/components/settings-menu/index.js +11 -0
  369. package/dist/components/settings-menu/settings-menu.js +101 -0
  370. package/dist/components/settings-menu/settings-menu.meta.js +177 -0
  371. package/dist/components/settings-menu/settings-menu.variants.js +15 -0
  372. package/dist/components/sheet/index.js +29 -0
  373. package/dist/components/sheet/sheet.js +121 -0
  374. package/dist/components/sheet/sheet.meta.js +167 -0
  375. package/dist/components/sheet/sheet.variants.js +21 -0
  376. package/dist/components/show-more/index.js +7 -0
  377. package/dist/components/show-more/show-more.js +87 -0
  378. package/dist/components/show-more/show-more.meta.js +79 -0
  379. package/dist/components/side-nav/index.js +13 -0
  380. package/dist/components/side-nav/side-nav.js +75 -0
  381. package/dist/components/side-nav/side-nav.meta.js +139 -0
  382. package/dist/components/side-nav/side-nav.variants.js +34 -0
  383. package/dist/components/sidebar/index.js +21 -0
  384. package/dist/components/sidebar/sidebar.js +196 -0
  385. package/dist/components/sidebar/sidebar.meta.js +118 -0
  386. package/dist/components/skeleton/index.js +7 -0
  387. package/dist/components/skeleton/skeleton.js +16 -0
  388. package/dist/components/skeleton/skeleton.meta.js +90 -0
  389. package/dist/components/slider/index.js +21 -0
  390. package/dist/components/slider/slider.js +115 -0
  391. package/dist/components/slider/slider.meta.js +214 -0
  392. package/dist/components/sparkline/index.js +7 -0
  393. package/dist/components/sparkline/sparkline.js +84 -0
  394. package/dist/components/sparkline/sparkline.meta.js +147 -0
  395. package/dist/components/spinner/index.js +7 -0
  396. package/dist/components/spinner/spinner.js +59 -0
  397. package/dist/components/spinner/spinner.meta.js +118 -0
  398. package/dist/components/status-bar/index.js +9 -0
  399. package/dist/components/status-bar/status-bar.js +40 -0
  400. package/dist/components/status-bar/status-bar.meta.js +117 -0
  401. package/dist/components/status-dot/index.js +9 -0
  402. package/dist/components/status-dot/status-dot.js +40 -0
  403. package/dist/components/status-dot/status-dot.meta.js +113 -0
  404. package/dist/components/status-dot/status-dot.variants.js +28 -0
  405. package/dist/components/stepper/index.js +17 -0
  406. package/dist/components/stepper/stepper.js +161 -0
  407. package/dist/components/stepper/stepper.meta.js +190 -0
  408. package/dist/components/stepper/stepper.variants.js +72 -0
  409. package/dist/components/streaming-text/index.js +7 -0
  410. package/dist/components/streaming-text/streaming-text.js +55 -0
  411. package/dist/components/streaming-text/streaming-text.meta.js +147 -0
  412. package/dist/components/switch/index.js +7 -0
  413. package/dist/components/switch/switch.js +26 -0
  414. package/dist/components/switch/switch.meta.js +133 -0
  415. package/dist/components/table/index.js +23 -0
  416. package/dist/components/table/table.js +117 -0
  417. package/dist/components/table/table.meta.js +143 -0
  418. package/dist/components/tabs/index.js +17 -0
  419. package/dist/components/tabs/tabs.js +58 -0
  420. package/dist/components/tabs/tabs.meta.js +120 -0
  421. package/dist/components/textarea/index.js +7 -0
  422. package/dist/components/textarea/textarea.js +38 -0
  423. package/dist/components/textarea/textarea.meta.js +117 -0
  424. package/dist/components/theme-selector/index.js +11 -0
  425. package/dist/components/theme-selector/theme-selector.js +145 -0
  426. package/dist/components/theme-selector/theme-selector.meta.js +181 -0
  427. package/dist/components/theme-switcher/index.js +7 -0
  428. package/dist/components/theme-switcher/theme-switcher.js +106 -0
  429. package/dist/components/theme-switcher/theme-switcher.meta.js +99 -0
  430. package/dist/components/thinking-orb/index.js +9 -0
  431. package/dist/components/thinking-orb/thinking-orb.js +126 -0
  432. package/dist/components/thinking-orb/thinking-orb.meta.js +142 -0
  433. package/dist/components/thinking-orb/thinking-orb.render.js +252 -0
  434. package/dist/components/toast/index.js +29 -0
  435. package/dist/components/toast/toast.js +254 -0
  436. package/dist/components/toast/toast.meta.js +261 -0
  437. package/dist/components/toggle/index.js +13 -0
  438. package/dist/components/toggle/toggle.js +51 -0
  439. package/dist/components/toggle/toggle.meta.js +129 -0
  440. package/dist/components/toolbar/index.js +27 -0
  441. package/dist/components/toolbar/toolbar.js +80 -0
  442. package/dist/components/toolbar/toolbar.meta.js +272 -0
  443. package/dist/components/toolbar/toolbar.variants.js +16 -0
  444. package/dist/components/tooltip/index.js +21 -0
  445. package/dist/components/tooltip/tooltip.js +74 -0
  446. package/dist/components/tooltip/tooltip.meta.js +156 -0
  447. package/dist/components/tree/index.js +12 -0
  448. package/dist/components/tree/tree.js +364 -0
  449. package/dist/components/tree/tree.meta.js +334 -0
  450. package/dist/components/video/index.js +7 -0
  451. package/dist/components/video/video.js +59 -0
  452. package/dist/components/video/video.meta.js +81 -0
  453. package/dist/components/workspace/index.js +9 -0
  454. package/dist/components/workspace/workspace.js +79 -0
  455. package/dist/components/workspace/workspace.meta.js +183 -0
  456. package/dist/foundations/accessibility.js +107 -0
  457. package/dist/foundations/index.js +25 -792
  458. package/dist/foundations/motion.js +135 -0
  459. package/dist/foundations/scrolling.js +62 -0
  460. package/dist/foundations/shape.js +113 -0
  461. package/dist/foundations/spacing.js +121 -0
  462. package/dist/foundations/surfaces.js +107 -0
  463. package/dist/foundations/types.js +0 -0
  464. package/dist/foundations/typography.js +152 -0
  465. package/dist/icon/Icon.js +30 -0
  466. package/dist/icon/IconProvider.js +27 -0
  467. package/dist/icon/compose.js +13 -0
  468. package/dist/icon/index.d.ts +13 -5
  469. package/dist/icon/index.js +13 -2
  470. package/dist/icon/registry.js +0 -0
  471. package/dist/icon-sets/brands.generated.js +123 -0
  472. package/dist/icon-sets/brands.js +10 -123
  473. package/dist/icon-sets/reicon.d.ts +3 -1
  474. package/dist/icon-sets/reicon.js +209 -1
  475. package/dist/index.d.ts +618 -34
  476. package/dist/index.js +211 -11351
  477. package/dist/ios/chrome.js +36 -0
  478. package/dist/ios/index.js +19 -315
  479. package/dist/ios/liquid-glass.js +103 -0
  480. package/dist/ios/native-app.js +46 -0
  481. package/dist/ios/navigation.js +63 -0
  482. package/dist/ios/phone-frame.js +64 -0
  483. package/dist/ios/preview-theme.js +83 -0
  484. package/dist/ios/preview.js +10 -137
  485. package/dist/ios/sheet.js +85 -0
  486. package/dist/ios/theme.js +19 -0
  487. package/dist/layout/AspectBox.js +27 -0
  488. package/dist/layout/Bleed.js +15 -0
  489. package/dist/layout/Center.js +21 -0
  490. package/dist/layout/Columns.js +70 -0
  491. package/dist/layout/Grid.js +50 -0
  492. package/dist/layout/GridOverlay.js +41 -0
  493. package/dist/layout/Page.js +11 -0
  494. package/dist/layout/Region.js +39 -0
  495. package/dist/layout/Row.js +45 -0
  496. package/dist/layout/SafeArea.js +26 -0
  497. package/dist/layout/Spacer.js +9 -0
  498. package/dist/layout/SplitPane.js +55 -0
  499. package/dist/layout/Stack.js +42 -0
  500. package/dist/layout/_responsive.js +16 -0
  501. package/dist/layout/_safeArea.js +18 -0
  502. package/dist/layout/index.d.ts +30 -8
  503. package/dist/layout/index.js +14 -2
  504. package/dist/lib/anchored-scroll.js +7 -0
  505. package/dist/lib/bleed.js +7 -0
  506. package/dist/lib/chart/cartesian.js +365 -0
  507. package/dist/lib/chart/chart-frame.js +163 -0
  508. package/dist/lib/chart/chart-legend.js +13 -0
  509. package/dist/lib/chart/chart-tooltip.js +38 -0
  510. package/dist/lib/chart/format.js +24 -0
  511. package/dist/lib/chart/geometry.js +114 -0
  512. package/dist/lib/chart/motion.js +34 -0
  513. package/dist/lib/chart/scale.js +72 -0
  514. package/dist/lib/chart/types.js +45 -0
  515. package/dist/lib/chart/use-arrival.js +41 -0
  516. package/dist/{chunk-SRQWQUTW.js → lib/cn.js} +5 -5
  517. package/dist/lib/component-guidance.js +215 -0
  518. package/dist/lib/density.js +54 -0
  519. package/dist/lib/field-shell.js +11 -0
  520. package/dist/lib/glyphs.js +9 -0
  521. package/dist/lib/heading-row.js +36 -0
  522. package/dist/lib/highlight-glide.js +84 -0
  523. package/dist/lib/hit-target.js +5 -0
  524. package/dist/lib/meta.js +0 -0
  525. package/dist/lib/portal-theme-scope.js +74 -0
  526. package/dist/{chunk-FKZXAFIY.js → lib/presentation.js} +8 -3
  527. package/dist/lib/refs.js +14 -0
  528. package/dist/lib/scrub-gesture.js +50 -0
  529. package/dist/lib/segmented.js +13 -0
  530. package/dist/lib/selection-card.js +41 -0
  531. package/dist/lib/status-tone.js +13 -0
  532. package/dist/lib/taxonomy.js +214 -0
  533. package/dist/lib/trim-label.js +20 -0
  534. package/dist/lib/use-copy.js +27 -0
  535. package/dist/lib/use-edge-fade.js +32 -0
  536. package/dist/lib/use-isomorphic-layout-effect.js +8 -0
  537. package/dist/lib/use-resize-observer.js +18 -0
  538. package/dist/lib/use-scroll-activity.js +52 -0
  539. package/dist/lib/use-wheel-to-horizontal.js +65 -0
  540. package/dist/motion/MotionProvider.js +75 -0
  541. package/dist/motion/Presence.js +112 -0
  542. package/dist/motion/Reveal.js +42 -0
  543. package/dist/motion/TextReveal.js +61 -0
  544. package/dist/motion/index.js +24 -0
  545. package/dist/motion/useInView.js +36 -0
  546. package/dist/motion/useReducedMotion.js +25 -0
  547. package/dist/motion/viewTransition.js +47 -0
  548. package/dist/patterns/auth-page.js +90 -0
  549. package/dist/patterns/auth-page.meta.js +27 -0
  550. package/dist/patterns/brand-landing-page.js +341 -0
  551. package/dist/patterns/brand-landing-page.meta.js +28 -0
  552. package/dist/patterns/chat-panel.js +185 -0
  553. package/dist/patterns/chat-panel.meta.js +31 -0
  554. package/dist/patterns/dashboard-page.js +332 -0
  555. package/dist/patterns/dashboard-page.meta.js +29 -0
  556. package/dist/patterns/feed-page.js +205 -0
  557. package/dist/patterns/feed-page.meta.js +25 -0
  558. package/dist/patterns/index.js +34 -2140
  559. package/dist/patterns/landing-page.js +356 -0
  560. package/dist/patterns/landing-page.meta.js +26 -0
  561. package/dist/patterns/list-detail-page.js +373 -0
  562. package/dist/patterns/list-detail-page.meta.js +24 -0
  563. package/dist/patterns/settings-page.js +268 -0
  564. package/dist/patterns/settings-page.meta.js +27 -0
  565. package/dist/presets/index.d.ts +7 -1
  566. package/dist/presets/index.js +53 -185
  567. package/dist/styles.css +118 -3
  568. package/dist/{theme-provider-kQszHYji.d.ts → theme-provider-S0NVJs2Y.d.ts} +6 -1
  569. package/dist/{chunk-NETUFI34.js → themes/_contract.js} +14 -2
  570. package/dist/themes/atelier/index.js +17 -1
  571. package/dist/themes/contrast.js +288 -0
  572. package/dist/themes/ember/ember.css +6 -6
  573. package/dist/themes/ember/index.js +16 -1
  574. package/dist/themes/index.d.ts +1 -1
  575. package/dist/themes/index.js +3 -8
  576. package/dist/themes/meridian/index.js +16 -1
  577. package/dist/themes/poppy/index.js +17 -1
  578. package/dist/themes/prism/index.js +17 -1
  579. package/dist/themes/prism/prism.css +2 -2
  580. package/dist/themes/registry.js +59 -0
  581. package/dist/themes/sable/index.js +16 -1
  582. package/dist/{chunk-EFLC4NA3.js → themes/theme-provider.js} +38 -54
  583. package/dist/themes/verdant/index.js +17 -1
  584. package/llms/blocks/media-player-block.md +20 -7
  585. package/llms/blocks/product-card-block.md +6 -4
  586. package/llms/blocks/task-list-block.md +1 -1
  587. package/llms/blocks/traffic-sources-block.md +1 -1
  588. package/llms/blocks/traffic-trend-block.md +5 -3
  589. package/llms/blocks/verify-code-block.md +1 -1
  590. package/llms/components/app-shell.md +5 -2
  591. package/llms/components/avatar.md +25 -3
  592. package/llms/components/button.md +20 -1
  593. package/llms/components/card.md +1 -1
  594. package/llms/components/disclosure-picker.md +168 -0
  595. package/llms/components/font-picker.md +104 -0
  596. package/llms/components/media-image.md +98 -0
  597. package/llms/components/media-tile.md +143 -0
  598. package/llms/components/page-header.md +6 -5
  599. package/llms/components/pie-chart.md +2 -2
  600. package/llms/components/radial-chart.md +1 -1
  601. package/llms/components/section-header.md +144 -0
  602. package/llms/components/sheet.md +10 -0
  603. package/llms/components/sidebar.md +4 -3
  604. package/llms/components/slider.md +14 -2
  605. package/llms/components/theme-selector.md +44 -4
  606. package/llms/components/tree.md +3 -3
  607. package/llms/layout/grid.md +24 -3
  608. package/llms/layout/region.md +16 -3
  609. package/llms/patterns/dashboard-page.md +3 -6
  610. package/llms/patterns/feed-page.md +4 -4
  611. package/llms/patterns/list-detail-page.md +1 -0
  612. package/llms/patterns/settings-page.md +2 -5
  613. package/llms/reference/utilities.md +84 -4
  614. package/llms/tasks/building-a-page.md +34 -3
  615. package/llms/tasks/converting-an-app.md +14 -4
  616. package/llms/tasks/creating-a-preset.md +4 -1
  617. package/llms/tasks/reviewing-a-design.md +19 -0
  618. package/llms/tasks/using-presets.md +19 -0
  619. package/llms-full.txt +1066 -78
  620. package/llms.txt +26 -9
  621. package/package.json +1 -1
  622. package/registry.json +2342 -164
  623. package/scripts/agent-setup.mjs +90 -0
  624. package/scripts/design-presets.mjs +59 -6
  625. package/scripts/grade.mjs +195 -29
  626. package/scripts/lint-rules.mjs +486 -10
  627. package/scripts/review-evidence.mjs +28 -1
  628. package/skills/sable/SKILL.md +67 -24
  629. package/targets/ios.json +45 -0
  630. package/dist/chunk-3IWZYBGH.js +0 -398
  631. package/dist/chunk-7MG4SHYX.js +0 -15
  632. package/dist/chunk-7QSDYBXO.js +0 -7421
  633. package/dist/chunk-ADLLDWLW.js +0 -15
  634. package/dist/chunk-C4Z3CF54.js +0 -15
  635. package/dist/chunk-EDXLM7YL.js +0 -5078
  636. package/dist/chunk-EHH4MHO6.js +0 -14
  637. package/dist/chunk-K7RUHUGC.js +0 -14
  638. package/dist/chunk-KO3NAEBF.js +0 -15
  639. package/dist/chunk-L4IEIQQA.js +0 -14
  640. package/dist/chunk-QJ6FWTUG.js +0 -40
  641. package/dist/chunk-VVW4UCDI.js +0 -4908
  642. package/dist/chunk-XAZGMY73.js +0 -187
@@ -0,0 +1,59 @@
1
+ // src/themes/registry.ts
2
+ import { atelierTheme } from "./atelier/index.js";
3
+ import { meridianTheme } from "./meridian/index.js";
4
+ import { prismTheme } from "./prism/index.js";
5
+ import { verdantTheme } from "./verdant/index.js";
6
+ import { emberTheme } from "./ember/index.js";
7
+ import { sableTheme } from "./sable/index.js";
8
+ import { poppyTheme } from "./poppy/index.js";
9
+ var SABLE_THEME_ATTRIBUTE = "data-sable-theme";
10
+ var DEFAULT_THEME_ID = sableTheme.id;
11
+ var defaultThemeId = DEFAULT_THEME_ID;
12
+ var themeManifests = [
13
+ sableTheme,
14
+ meridianTheme,
15
+ prismTheme,
16
+ verdantTheme,
17
+ emberTheme,
18
+ poppyTheme,
19
+ atelierTheme
20
+ ];
21
+ var featuredThemeManifests = themeManifests.filter((theme) => !theme.deprecated);
22
+ var themeIds = themeManifests.map((theme) => theme.id);
23
+ var themeManifestById = Object.fromEntries(
24
+ themeManifests.map((theme) => [theme.id, theme])
25
+ );
26
+ function isThemeId(value) {
27
+ return Object.hasOwn(themeManifestById, value);
28
+ }
29
+ function getThemeManifest(themeId) {
30
+ return themeManifestById[themeId];
31
+ }
32
+ function buildThemeManifestById(customThemes = []) {
33
+ const merged = { ...themeManifestById };
34
+ for (const theme of customThemes) merged[theme.id] = theme;
35
+ return merged;
36
+ }
37
+ function isKnownThemeId(value, manifestById) {
38
+ return Object.hasOwn(manifestById, value);
39
+ }
40
+ export {
41
+ DEFAULT_THEME_ID,
42
+ SABLE_THEME_ATTRIBUTE,
43
+ atelierTheme,
44
+ buildThemeManifestById,
45
+ defaultThemeId,
46
+ emberTheme,
47
+ featuredThemeManifests,
48
+ getThemeManifest,
49
+ isKnownThemeId,
50
+ isThemeId,
51
+ meridianTheme,
52
+ poppyTheme,
53
+ prismTheme,
54
+ sableTheme,
55
+ themeIds,
56
+ themeManifestById,
57
+ themeManifests,
58
+ verdantTheme
59
+ };
@@ -1 +1,16 @@
1
- export { sable_default as default, sableTheme } from '../../chunk-EHH4MHO6.js';
1
+ // src/themes/sable/index.ts
2
+ var sableTheme = {
3
+ id: "sable",
4
+ label: "Sable",
5
+ modes: ["dark", "light"],
6
+ defaultMode: "dark",
7
+ fonts: {
8
+ sans: '"Figtree", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
9
+ mono: '"DM Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Courier New", monospace'
10
+ }
11
+ };
12
+ var sable_default = sableTheme;
13
+ export {
14
+ sable_default as default,
15
+ sableTheme
16
+ };
@@ -1,45 +1,23 @@
1
- import { prismTheme } from './chunk-7MG4SHYX.js';
2
- import { verdantTheme } from './chunk-KO3NAEBF.js';
3
- import { emberTheme } from './chunk-L4IEIQQA.js';
4
- import { sableTheme } from './chunk-EHH4MHO6.js';
5
- import { poppyTheme } from './chunk-ADLLDWLW.js';
6
- import { meridianTheme } from './chunk-K7RUHUGC.js';
7
- import { atelierTheme } from './chunk-C4Z3CF54.js';
8
- import { createContext, useMemo, useState, useEffect, useCallback, useContext } from 'react';
9
- import { jsx } from 'react/jsx-runtime';
1
+ "use client";
10
2
 
11
- // src/themes/registry.ts
12
- var SABLE_THEME_ATTRIBUTE = "data-sable-theme";
13
- var DEFAULT_THEME_ID = sableTheme.id;
14
- var defaultThemeId = DEFAULT_THEME_ID;
15
- var themeManifests = [
16
- sableTheme,
17
- meridianTheme,
18
- prismTheme,
19
- verdantTheme,
20
- emberTheme,
21
- poppyTheme,
22
- atelierTheme
23
- ];
24
- var featuredThemeManifests = themeManifests.filter((theme) => !theme.deprecated);
25
- var themeIds = themeManifests.map((theme) => theme.id);
26
- var themeManifestById = Object.fromEntries(
27
- themeManifests.map((theme) => [theme.id, theme])
28
- );
29
- function isThemeId(value) {
30
- return Object.hasOwn(themeManifestById, value);
31
- }
32
- function getThemeManifest(themeId) {
33
- return themeManifestById[themeId];
34
- }
35
- function buildThemeManifestById(customThemes = []) {
36
- const merged = { ...themeManifestById };
37
- for (const theme of customThemes) merged[theme.id] = theme;
38
- return merged;
39
- }
40
- function isKnownThemeId(value, manifestById) {
41
- return Object.hasOwn(manifestById, value);
42
- }
3
+ // src/themes/theme-provider.tsx
4
+ import {
5
+ createContext,
6
+ useCallback,
7
+ useContext,
8
+ useEffect,
9
+ useMemo,
10
+ useState
11
+ } from "react";
12
+ import {
13
+ SABLE_THEME_ATTRIBUTE,
14
+ buildThemeManifestById,
15
+ defaultThemeId as sableDefaultThemeId,
16
+ isKnownThemeId,
17
+ isThemeId,
18
+ featuredThemeManifests
19
+ } from "./registry.js";
20
+ import { jsx } from "react/jsx-runtime";
43
21
  var SABLE_COLOR_STORAGE_KEY = "sable-color-preference";
44
22
  var SABLE_THEME_STORAGE_KEY = "sable-theme-id";
45
23
  var SableThemeContext = createContext(null);
@@ -117,7 +95,7 @@ function applySableColorMode(mode, target = rootElement()) {
117
95
  function applySableTheme(themeId, target = rootElement()) {
118
96
  if (!target) return;
119
97
  withSuppressedTransitions(() => {
120
- if (themeId === defaultThemeId) {
98
+ if (themeId === sableDefaultThemeId) {
121
99
  target.removeAttribute(SABLE_THEME_ATTRIBUTE);
122
100
  return;
123
101
  }
@@ -126,10 +104,10 @@ function applySableTheme(themeId, target = rootElement()) {
126
104
  }
127
105
  function SableThemeProvider({
128
106
  children,
129
- defaultPreference = "dark",
107
+ defaultPreference = "system",
130
108
  preference: controlledPreference,
131
109
  onPreferenceChange,
132
- defaultThemeId: defaultThemeId2 = defaultThemeId,
110
+ defaultThemeId = sableDefaultThemeId,
133
111
  themeId: controlledThemeId,
134
112
  onThemeIdChange,
135
113
  colorStorageKey = SABLE_COLOR_STORAGE_KEY,
@@ -137,7 +115,7 @@ function SableThemeProvider({
137
115
  target = "root",
138
116
  customThemes
139
117
  }) {
140
- const themeManifestById2 = useMemo(
118
+ const themeManifestById = useMemo(
141
119
  () => buildThemeManifestById(customThemes),
142
120
  [customThemes]
143
121
  );
@@ -145,7 +123,7 @@ function SableThemeProvider({
145
123
  () => coercePreference(readStorage(colorStorageKey), defaultPreference)
146
124
  );
147
125
  const [uncontrolledThemeId, setUncontrolledThemeId] = useState(
148
- () => coerceThemeId(readStorage(themeStorageKey), defaultThemeId2, themeManifestById2)
126
+ () => coerceThemeId(readStorage(themeStorageKey), defaultThemeId, themeManifestById)
149
127
  );
150
128
  const [resolvedSystem, setResolvedSystem] = useState(systemColorMode);
151
129
  const preference = controlledPreference ?? uncontrolledPreference;
@@ -176,15 +154,15 @@ function SableThemeProvider({
176
154
  if (controlledThemeId === void 0) {
177
155
  if (event.key === themeStorageKey) {
178
156
  setUncontrolledThemeId(
179
- coerceThemeId(event.newValue, defaultThemeId2, themeManifestById2)
157
+ coerceThemeId(event.newValue, defaultThemeId, themeManifestById)
180
158
  );
181
159
  }
182
160
  if (event.key === null) {
183
161
  setUncontrolledThemeId(
184
162
  coerceThemeId(
185
163
  readStorage(themeStorageKey),
186
- defaultThemeId2,
187
- themeManifestById2
164
+ defaultThemeId,
165
+ themeManifestById
188
166
  )
189
167
  );
190
168
  }
@@ -197,8 +175,8 @@ function SableThemeProvider({
197
175
  controlledPreference,
198
176
  controlledThemeId,
199
177
  defaultPreference,
200
- defaultThemeId2,
201
- themeManifestById2,
178
+ defaultThemeId,
179
+ themeManifestById,
202
180
  themeStorageKey
203
181
  ]);
204
182
  useEffect(() => {
@@ -252,7 +230,7 @@ function useSableTheme() {
252
230
  colorMode: "dark",
253
231
  preference: "dark",
254
232
  colorPreference: "dark",
255
- themeId: defaultThemeId,
233
+ themeId: sableDefaultThemeId,
256
234
  themes: featuredThemeManifests,
257
235
  setPreference: () => {
258
236
  },
@@ -266,5 +244,11 @@ function useSableTheme() {
266
244
  }
267
245
  };
268
246
  }
269
-
270
- export { DEFAULT_THEME_ID, SABLE_COLOR_STORAGE_KEY, SABLE_THEME_ATTRIBUTE, SABLE_THEME_STORAGE_KEY, SableThemeProvider, applySableColorMode, applySableTheme, buildThemeManifestById, defaultThemeId, featuredThemeManifests, getThemeManifest, isKnownThemeId, isThemeId, themeIds, themeManifestById, themeManifests, useSableTheme };
247
+ export {
248
+ SABLE_COLOR_STORAGE_KEY,
249
+ SABLE_THEME_STORAGE_KEY,
250
+ SableThemeProvider,
251
+ applySableColorMode,
252
+ applySableTheme,
253
+ useSableTheme
254
+ };
@@ -1 +1,17 @@
1
- export { verdant_default as default, verdantTheme } from '../../chunk-KO3NAEBF.js';
1
+ // src/themes/verdant/index.ts
2
+ var verdantTheme = {
3
+ id: "verdant",
4
+ label: "Verdant",
5
+ modes: ["light", "dark"],
6
+ defaultMode: "light",
7
+ fonts: {
8
+ sans: '"Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
9
+ mono: '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Courier New", monospace',
10
+ display: '"Instrument Serif", Georgia, "Times New Roman", serif'
11
+ }
12
+ };
13
+ var verdant_default = verdantTheme;
14
+ export {
15
+ verdant_default as default,
16
+ verdantTheme
17
+ };
@@ -21,9 +21,15 @@ A now-playing card: cover, title and artist as an Entity with a Like action, a p
21
21
 
22
22
  ```tsx
23
23
  import { useState } from "react"
24
- import { Button, Card, CardContent, cn, Entity, GradientArt, Icon, Slider } from "@sableui/react"
24
+ import { Button, Card, CardContent, cn, Entity, Icon, MediaImage, Slider } from "@sableui/react"
25
25
 
26
- const track = { title: "Low tide, high noon", artist: "Juno Avery", position: 38, elapsed: "1:24", remaining: "-2:16" }
26
+ // `cover` is the artwork URL; left empty, the cover paints art seeded by the title.
27
+ const track = { title: "Low tide, high noon", artist: "Juno Avery", cover: "", duration: 220, position: 84 }
28
+
29
+ /** Seconds → m:ss, the way the readout and the screen reader both say it. */
30
+ function formatTime(seconds: number) {
31
+ return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, "0")}`
32
+ }
27
33
 
28
34
 
29
35
  export interface MediaPlayerBlockProps {
@@ -38,6 +44,7 @@ export interface MediaPlayerBlockProps {
38
44
 
39
45
  export function MediaPlayerBlock({ className, framed = true, onPlayingChange, onPrevious, onNext }: MediaPlayerBlockProps) {
40
46
  const [playing, setPlaying] = useState(true)
47
+ const [position, setPosition] = useState(track.position)
41
48
  return (
42
49
  <Card variant={framed ? "default" : "flat"} className={cn("w-full max-w-xs", className)}>
43
50
  <CardContent className="flex flex-col gap-4">
@@ -45,8 +52,7 @@ export function MediaPlayerBlock({ className, framed = true, onPlayingChange, on
45
52
  card already pads it. */}
46
53
  <Entity
47
54
  className="p-0"
48
- // Placeholder cover painted from the theme. Replace with the cover image.
49
- leading={<GradientArt aria-hidden seed={track.title} className="size-14 rounded-md" />}
55
+ leading={<MediaImage src={track.cover} seed={track.title} className="size-14 shrink-0 rounded-md" />}
50
56
  title={track.title}
51
57
  subtitle={track.artist}
52
58
  action={
@@ -56,10 +62,17 @@ export function MediaPlayerBlock({ className, framed = true, onPlayingChange, on
56
62
  }
57
63
  />
58
64
  <div className="flex flex-col gap-1.5">
59
- <Slider defaultValue={track.position} aria-label="Position" />
65
+ <Slider
66
+ value={position}
67
+ max={track.duration}
68
+ onValueChange={setPosition}
69
+ aria-label="Position"
70
+ // Spoken as a time, not "38": the number alone means nothing.
71
+ getAriaValueText={(_, value) => `${formatTime(value)} of ${formatTime(track.duration)}`}
72
+ />
60
73
  <div className="flex justify-between text-mono-caption text-muted-foreground">
61
- <span>{track.elapsed}</span>
62
- <span>{track.remaining}</span>
74
+ <span>{formatTime(position)}</span>
75
+ <span>-{formatTime(track.duration - position)}</span>
63
76
  </div>
64
77
  </div>
65
78
  <div className="flex items-center justify-center gap-3">
@@ -20,9 +20,10 @@ A product card: edge-to-edge artwork, title and maker, an edition Badge, and the
20
20
  ## Source
21
21
 
22
22
  ```tsx
23
- import { Badge, Button, Card, CardAction, CardDescription, CardFooter, CardHeader, CardTitle, cn, GradientArt } from "@sableui/react"
23
+ import { AspectBox, Badge, Button, Card, CardAction, CardDescription, CardFooter, CardHeader, CardTitle, cn, MediaImage } from "@sableui/react"
24
24
 
25
- const product = { title: "Untitled (gold rush)", maker: "Mara Okafor", edition: "12 of 50", price: "0.42 SOL" }
25
+ // `image` is the product shot URL; left empty, it paints art seeded by the title.
26
+ const product = { title: "Untitled (gold rush)", maker: "Mara Okafor", image: "", edition: "12 of 50", price: "0.42 SOL" }
26
27
 
27
28
 
28
29
  export interface ProductCardBlockProps {
@@ -36,8 +37,9 @@ export interface ProductCardBlockProps {
36
37
  export function ProductCardBlock({ className, framed = true, onCollect }: ProductCardBlockProps) {
37
38
  return (
38
39
  <Card variant={framed ? "default" : "flat"} className={cn("w-full max-w-xs overflow-hidden", className)}>
39
- {/* Placeholder art painted from the theme, so it follows every look. Replace with the product image. */}
40
- <GradientArt aria-hidden seed={product.title} className="aspect-[4/3]" />
40
+ <AspectBox ratio={4 / 3}>
41
+ <MediaImage src={product.image} seed={product.title} />
42
+ </AspectBox>
41
43
  <CardHeader>
42
44
  <CardTitle>{product.title}</CardTitle>
43
45
  <CardDescription>{product.maker}</CardDescription>
@@ -71,7 +71,7 @@ export function TaskListBlock({ className, framed = true, onAddTask }: TaskListB
71
71
  </ul>
72
72
  </CardContent>
73
73
  <CardFooter>
74
- <Button variant="ghost" size="sm" iconStart={<Icon name="plus" />} onClick={onAddTask}>
74
+ <Button variant="ghost" size="sm" bleed="start" iconStart={<Icon name="plus" />} onClick={onAddTask}>
75
75
  Add task
76
76
  </Button>
77
77
  </CardFooter>
@@ -51,7 +51,7 @@ export function TrafficSourcesBlock({ className, framed = true }: TrafficSources
51
51
  index="source"
52
52
  valueKey="visitors"
53
53
  donut
54
- centerLabel={{ value: total.toLocaleString("en-US"), label: "Visitors" }}
54
+ centerLabel={{ value: total, label: "Visitors" }}
55
55
  />
56
56
  </CardContent>
57
57
  <CardFooter className="text-body-sm text-muted-foreground">
@@ -56,11 +56,13 @@ export function TrafficTrendBlock({ className, framed = true }: TrafficTrendBloc
56
56
  const [range, setRange] = useState("90d")
57
57
  const shown = days.slice(-(ranges.find((r) => r.id === range)?.days ?? 90))
58
58
  return (
59
- <Card variant={framed ? "default" : "flat"} className={cn("w-full max-w-3xl", className)}>
60
- <CardHeader>
59
+ <Card variant={framed ? "default" : "flat"} className={cn("@container/trend w-full max-w-3xl", className)}>
60
+ <CardHeader className="@max-sm/trend:has-data-[slot=card-action]:grid-cols-1">
61
61
  <CardTitle render={<h2 />}>Visitors</CardTitle>
62
62
  <CardDescription>Desktop and mobile, by day.</CardDescription>
63
- <CardAction>
63
+ {/* Beside the title on a wide card; under it on a narrow one, where three
64
+ ranges would squeeze the title and description into a sliver. */}
65
+ <CardAction className="@max-sm/trend:col-start-1 @max-sm/trend:row-span-1 @max-sm/trend:row-start-auto @max-sm/trend:mt-2 @max-sm/trend:justify-self-start">
64
66
  <ToggleGroup value={[range]} onValueChange={(v: unknown[]) => v[0] && setRange(String(v[0]))} aria-label="Time range">
65
67
  {ranges.map((r) => (
66
68
  <Toggle key={r.id} value={r.id}>
@@ -49,7 +49,7 @@ export function VerifyCodeBlock({ className, framed = true, onVerify, onResend }
49
49
  </CardContent>
50
50
  <CardFooter className="justify-between gap-3">
51
51
  <span className="text-caption text-muted-foreground">Didn’t get it?</span>
52
- <Button variant="ghost" size="sm" onClick={onResend}>
52
+ <Button variant="ghost" size="sm" bleed="end" onClick={onResend}>
53
53
  Resend code
54
54
  </Button>
55
55
  </CardFooter>
@@ -2,9 +2,9 @@
2
2
 
3
3
  **Status:** stable
4
4
 
5
- The application frame: slots for status banners, a mobile header, a desktop sidebar, main content, a mobile bottom nav, and floating overlays — plus a built-in skip link and #main-content target.
5
+ The application frame: slots for status banners, a mobile header, a desktop sidebar, main content, a mobile bottom nav, a persistent dock (a now-playing or call bar), and floating overlays — plus a built-in skip link and #main-content target.
6
6
 
7
- **Keywords:** app shell, layout, frame, sidebar, header, bottom nav, mobile, banners, main
7
+ **Keywords:** app shell, layout, frame, sidebar, header, bottom nav, mobile, banners, main, dock, player bar, now playing, persistent
8
8
 
9
9
  ## Usage
10
10
 
@@ -28,6 +28,7 @@ Use AppShell as the outer product frame for authenticated or app-like experience
28
28
  | Sidebar | no | Desktop navigation chrome, usually Sidebar. |
29
29
  | Main | yes | The route content landmark with id main-content. |
30
30
  | Bottom nav | no | Mobile fixed navigation with reserved bottom space. |
31
+ | Dock | no | Persistent bottom chrome that outlives routes — a now-playing bar, a call bar. Sticky above the bottom nav; the desktop Sidebar shortens to clear it. |
31
32
 
32
33
  ## Props
33
34
 
@@ -37,6 +38,7 @@ Use AppShell as the outer product frame for authenticated or app-like experience
37
38
  | header | ReactNode | — | Mobile top header (e.g. AppHeader); expected to hide itself at lg. |
38
39
  | sidebar | ReactNode | — | Desktop side navigation (e.g. Sidebar); expected to hide itself below lg. Leading column of the body row. |
39
40
  | bottomNav | ReactNode | — | Mobile bottom navigation (e.g. BottomNav); fixed to the bottom edge. main reserves space for it. |
41
+ | dock | ReactNode | — | Persistent chrome kept on screen across routes (a now-playing bar, an active-call bar, an upload tray). Full width, sticky to the bottom edge and above bottomNav on mobile; its height is published as --dock-height and the app Sidebar subtracts it. In flow, so main needs no reserved space. The contents paint their own surface and top border, and name themselves (e.g. <section aria-label="Player">). Mount AppShell in a layout that survives navigation, or the playback restarts. |
40
42
  | overlays | ReactNode | — | Floating overlays — a message launcher, FAB, or modal mount points. |
41
43
 
42
44
  ## Tokens used
@@ -48,6 +50,7 @@ Use AppShell as the outer product frame for authenticated or app-like experience
48
50
  - Renders a skip link to #main-content as the first focusable element.
49
51
  - Wraps content in a <main id="main-content"> landmark.
50
52
  - Slot components own their own ARIA (nav landmarks, labels).
53
+ - The dock follows <main> in DOM order, so keyboard and screen-reader users reach the player after the page content, not before it.
51
54
 
52
55
  ## Related
53
56
 
@@ -15,11 +15,12 @@ Use Avatar to represent a person, team, or account with a compact visual identit
15
15
  - Do: Use `variant="art"` where people without photos sit side by side — a member list, an activity feed, a chat. Seeded by the person, each gets their own colour, so faces stay tellable apart at a glance; the neutral fallback makes everyone the same grey circle.
16
16
  - Do: Provide meaningful alt text for profile images, or an empty alt when the adjacent text already names the person.
17
17
  - Do: Use initials or a simple glyph fallback so missing images still communicate identity.
18
- - Do: Use consistent sizes within a group; reserve lg for profile headers or major identity moments.
18
+ - Do: Pick the size by the job: sm in dense rows and tables, md (the default) beside one line of text, lg in a row with a title and subtitle, xl (96px) for a profile header beside the person's name, 2xl (160px) for an artist or profile hero and roster portraits. Keep one size within a list or group.
19
19
  - Do: Use AvatarGroup for a stack of people, and give it an aria-label with the real count ("12 collaborators"). Set `surface` (or `--avatar-group-ring`) to whatever the group sits on, so the separating ring matches a card or popover, not the page. When it shares a row with actions, set `fit` so it gives up avatars to the "+N" count before the row has to wrap.
20
20
  - Don't: Hand-build a stack with negative margins and per-avatar ring classes, or fake the overflow as an Avatar with "+4" initials — screen readers hear "plus 4" with no context. Use AvatarGroup's `max`/`total`, or AvatarGroupCount.
21
21
  - Don't: Use avatars as decoration without nearby identity context. They should help users recognize a person or account.
22
22
  - Don't: Overload a dense table with large avatars; use sm or omit images when scanning data is more important.
23
+ - Don't: Build a portrait by stretching an Avatar with size classes (`className="size-40"`) — the initials, the status indicator and the image fade stay at row scale. Use size="xl" or "2xl", which scale all three. Past 160px, or for a non-circular cover, it is media: an AspectBox, not an avatar.
23
24
 
24
25
  ### Anatomy
25
26
 
@@ -50,19 +51,26 @@ Use Avatar to represent a person, team, or account with a compact visual identit
50
51
  | fallback | ReactNode | — | Initials or a glyph rendered when no image is displayed. |
51
52
  | fallbackDelay | number | — | Delay before showing the fallback, in ms — avoids a flash on fast loads. |
52
53
  | status | ReactNode | — | A presence indicator pinned to the bottom-end edge, usually <StatusDot tone="success" />. It sits outside the clipped circle and wears a ring in the surface colour (--avatar-group-ring, else the page background). Use this instead of absolutely positioning a dot over an Avatar. |
53
- | size | "sm" \| "md" \| "lg" | "md" | Square footprint: 32px / 40px / 48px. |
54
+ | size | "sm" \| "md" \| "lg" \| "xl" \| "2xl" | "md" | Square footprint: 32px / 40px / 48px for rows; 96px / 160px for portraits (a profile header, an artist hero, a roster tile). The initials, a status indicator and its cut-out ring scale with it, and at the portrait sizes the photo fades in over the resting surface. |
54
55
  | variant | "neutral" \| "art" | "neutral" | What the fallback looks like. neutral: initials on the muted surface. art: initials over GradientArt seeded by the person, so each person without a photo gets their own stable colour from the theme. |
55
56
  | seed | string \| number | — | The art variant's seed. Defaults to the fallback text, then `alt`, so a person keeps one colour wherever they appear; pass a user id to tell apart two people who share initials. |
56
57
 
57
58
  ## Variants
58
59
 
59
- - **size**: sm, md, lg
60
+ - **size**: sm, md, lg, xl, 2xl
60
61
  - **variant**: neutral, art
61
62
 
62
63
  ## Tokens used
63
64
 
64
65
  `muted`, `muted-foreground`, `background`, `card`, `popover`, `overlay`, `overlay-foreground`
65
66
 
67
+ ## Motion
68
+
69
+ - **arrival** · Image · `motion-fade` — At the portrait sizes (xl, 2xl) the photo replacing the initials is a visible pop across one of the page's largest elements; fading it in reads as the picture arriving, not the layout glitching. Row sizes swap instantly — too small to register, and a list of fading faces would shimmer.
70
+ - **response** · Root · _no motion_ — An avatar is not interactive itself; a link or button wrapping it owns the response.
71
+ - **transition** · Root · _no motion_ — It has no states of its own to move between beyond the image arriving.
72
+ - **activity** · Root · _no motion_ — Loading shows the fallback, which is already a finished resting state rather than a spinner.
73
+
66
74
  ## Accessibility
67
75
 
68
76
  - Base UI tracks the image loading status and swaps to the fallback on missing/loading/error — no manual onError wiring.
@@ -112,6 +120,20 @@ import { Avatar } from "@sableui/react"
112
120
  <Avatar src="/pfp.png" alt="Alex Morgan" fallback="AM" size="lg" />
113
121
  ```
114
122
 
123
+ ### Profile portrait
124
+
125
+ ```tsx
126
+ import { Avatar, StatusDot } from "@sableui/react"
127
+
128
+ <div className="flex flex-col items-center gap-3 text-center">
129
+ <Avatar variant="art" size="2xl" fallback="LV" alt="Lena Vale" status={<StatusDot tone="success" />} />
130
+ <div className="flex flex-col gap-1">
131
+ <h1 className="text-heading-1">Lena Vale</h1>
132
+ <p className="text-body-sm text-muted-foreground">1.2M monthly listeners</p>
133
+ </div>
134
+ </div>
135
+ ```
136
+
115
137
  ### Low-level parts
116
138
 
117
139
  ```tsx
@@ -4,7 +4,7 @@
4
4
 
5
5
  Pill-shaped action primitive (theme-driven radius via --button-radius, defaults to full). Neutral tiers (primary/secondary/ghost/outline), plus destructive and link, and three on-color tiers (on-color/on-color-outline/on-color-ghost) that paint with the surrounding ink so a button reads on any tone or brand fill. Optional loading state shows a spinner and disables the button.
6
6
 
7
- **Keywords:** button, action, cta, submit, save, cancel, destructive, loading, link, icon button, on color, inverse, band, brand fill, tone fill
7
+ **Keywords:** button, action, cta, submit, save, cancel, destructive, loading, link, icon button, on color, inverse, band, brand fill, tone fill, bleed, optical alignment, align label to edge, negative margin, view all
8
8
 
9
9
  ## Usage
10
10
 
@@ -16,7 +16,9 @@ Use Button when the user commits an action, submits a form, opens UI, or confirm
16
16
  - Do: Write labels as actions, such as "Save changes" or "Delete draft", instead of vague labels like "OK".
17
17
  - Do: Use loading with loadingLabel for async work so the action cannot double-fire and the state is announced.
18
18
  - Do: Put icons in iconStart / iconEnd rather than as children, so the button applies its optical padding. Start icons say what the action is (plus, share); end icons say where it goes (chevron-right, external).
19
+ - Do: Set bleed on a ghost or link button that sits at the start or end of a row, so its LABEL lines up with the content edge the row shares ("View all" over a grid, "Add task" under a list, "Resend code" at a card footer's end). The box moves out by exactly its own padding; the hit area and hover fill stay full size and run past the edge. SectionHeader, PageHeader (back and actions) and CardAction already do this for their outermost ghost/link child — don't add it there, and use bleed="none" to opt one out.
19
20
  - Do: On a coloured fill — a solid Banner, a bg-tone-* or bg-primary band, an inverse (bg-foreground) section, a brand panel — use variant="on-color" for the main action and on-color-outline / on-color-ghost for the rest. They paint with the band's inherited ink (currentColor), so the surface must set its paired ink (text-tone-info-foreground, text-primary-foreground, text-background…), which it already should. Name the fill once on the surface, e.g. [--on-color-fill:var(--tone-info)], and the solid button's label takes the fill colour; unnamed, it falls back to black or white against the ink. Both clear 4.5:1 in every shipped theme and mode.
21
+ - Don't: Pull a ghost button onto an edge with -ms-3 / -me-3 classNames. That number is one size's padding: it is wrong at xs, md and cta, wrong on a side carrying an icon, and wrong once a preset retunes the spacing. bleed reads the button's own padding var. And don't bleed a filled or outlined button — its visible edge is what aligns, so bleed is a no-op there.
20
22
  - Don't: Use destructive for reversible or low-risk actions; reserve it for operations with real loss or danger.
21
23
  - Don't: Use a button for plain navigation. Compose with render={<a />} when the element should behave like a link.
22
24
  - Don't: Use secondary on a tinted surface — inside a Note, a soft Banner, or any tone fill. `secondary` is a near-background surface token (in some themes within 2% of the page), so on a tint it reads as a hole punched in the fill rather than as a control sitting on it. On a soft tint use outline or ghost; on a full-strength fill use the on-color tiers.
@@ -43,6 +45,7 @@ Use Button when the user commits an action, submits a form, opens UI, or confirm
43
45
  | loadingLabel | ReactNode | — | Optional text shown in place of children while loading. |
44
46
  | iconStart | ReactNode | — | Icon before the label. The button takes one 2px step off its start padding so icon + label read as centred. Replaced by the spinner while loading. |
45
47
  | iconEnd | ReactNode | — | Icon after the label (disclosure, external link, next). Same optical correction on the end side. |
48
+ | bleed | "start" \| "end" \| "both" \| "none" | — | Optical alignment for a borderless button (ghost, link, on-color-ghost): a negative inline margin of exactly its own padding on that side — --button-px, or the icon side's optical padding when an icon sits there; an icon-only size bleeds by its inset to the glyph — so the label (or glyph) lands on the content edge. Hit area and hover/focus fill keep their full size. Logical sides, so it mirrors in RTL. A no-op on variants with a visible edge (primary, secondary, outline, destructive, floating, field, on-color, on-color-outline): a filled button aligns its edge, not its label. Unset, a borderless button renders data-bleed="auto" and SectionHeader, PageHeader and CardAction bleed it when it is their outermost child; none opts out. |
46
49
 
47
50
  ## Variants
48
51
 
@@ -68,6 +71,7 @@ Use Button when the user commits an action, submits a form, opens UI, or confirm
68
71
  - Use render={<a/>} for link semantics rather than onClick navigation.
69
72
  - On-color tiers replace the --ring focus ring with one drawn in the band's ink past a transparent 2px gap, so focus stays visible on any fill (ink-on-fill is the theme's own tested pair).
70
73
  - On-color contrast is measured in button.test.tsx for every shipped theme and mode on each tone, primary, destructive, success, highlight and inverse fill: solid label at rest and hover, and outline/ghost label on the hover wash, all at least 4.5:1.
74
+ - bleed moves only the box, never the hit target: the full padded area stays clickable and the focus ring still draws around the whole button, past the content edge.
71
75
  - loading sets aria-busy and disables activation (disabled on a native button, aria-disabled on a render element) so the action can't double-fire.
72
76
 
73
77
  ## Related
@@ -174,6 +178,21 @@ import { Button, Icon } from "@sableui/react"
174
178
  <Button size="icon" variant="ghost" aria-label="Share"><Icon name="share" /></Button>
175
179
  ```
176
180
 
181
+ ### Optically aligned to the row's edges
182
+
183
+ ```tsx
184
+ import { Button, Icon, Row, Stack } from "@sableui/react"
185
+
186
+ <Stack gap={1.5}>
187
+ <Row justify="between">
188
+ <span className="text-title-md">Tasks</span>
189
+ <Button variant="ghost" size="sm" bleed="end">View all</Button>
190
+ </Row>
191
+ <span className="text-body-sm text-muted-foreground">Ship the release notes</span>
192
+ <Button variant="ghost" size="sm" bleed="start" iconStart={<Icon name="plus" />} className="self-start">Add task</Button>
193
+ </Stack>
194
+ ```
195
+
177
196
  ### Icon button with an unread badge
178
197
 
179
198
  ```tsx
@@ -36,7 +36,7 @@ Use Card for a discrete thing with its own boundary, such as one product, one no
36
36
  | CardHeader | ComponentPropsWithRef<"div"> | Top section holding CardTitle/CardDescription (and optionally CardAction). Padding follows the density knob. |
37
37
  | CardTitle | ComponentPropsWithRef<"div"> & { render?: useRender.RenderProp } | The card's name (text-title-lg). A div by default; pass `render={<h2 />}` (or h3…) to make it a heading in the page outline, at the level the card's position calls for. |
38
38
  | CardDescription | ComponentPropsWithRef<"div"> | Muted supporting line under the title. |
39
- | CardAction | ComponentPropsWithRef<"div"> | Header-aligned top-right action slot (e.g. an overflow menu, switch, or close button). Place inside CardHeader, which becomes a 2-column grid when present and collapses to a single column otherwise. |
39
+ | CardAction | ComponentPropsWithRef<"div"> | Header-aligned top-right action slot (e.g. an overflow menu, switch, or close button). Place inside CardHeader, which becomes a 2-column grid when present and collapses to a single column otherwise. A ghost or link Button that ends the slot bleeds by its own padding at the end, so a "View all" label or a "⋯" glyph sits on the card's content edge; filled buttons keep their edge there. |
40
40
  | CardContent | ComponentPropsWithRef<"div"> & { flush?: boolean } | The body region. Padding follows the density knob on all sides — does not assume a preceding CardHeader, so it is safe to use standalone (e.g. no CardHeader in the card). When paired with CardHeader, the seam stays tight because CardHeader zeroes its own bottom padding. `flush` runs it edge to edge for a table: the Table insets its first and last columns by exactly the card padding, so it lines up with the header — never hand-set pl-6/pr-6 on columns. |
41
41
  | CardList | ComponentPropsWithRef<"div"> | Rows that run edge to edge in the card (Entity rows, most often), divided by hairlines. Insets each row to the card's own padding, so a list card lines up with every other card at any density — no hand-tuned px-* on the rows. Under a CardHeader it opens with a hairline and a gap; alone it fills the card. |
42
42
  | CardFooter | ComponentPropsWithRef<"div"> & { actions?: boolean } | Bottom row for actions/meta. Padding follows the density knob. `actions` marks it as the card's action row (buttons only): in a sheet (IosSheet, a bottom SheetContent) it becomes a full-width stack pinned to the bottom, primary on top; on a page nothing changes. |