@usefragments/ui 1.6.0 → 1.7.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 (457) hide show
  1. package/README.md +4 -4
  2. package/dist/assets/fragments-wordmark.cjs +2 -2
  3. package/dist/assets/fragments-wordmark.d.ts.map +1 -1
  4. package/dist/assets/fragments-wordmark.js +2 -2
  5. package/dist/assets/ui.css +4720 -4159
  6. package/dist/chart.cjs +24 -6
  7. package/dist/chart.js +24 -6
  8. package/dist/codeblock.cjs +55 -29
  9. package/dist/codeblock.js +55 -29
  10. package/dist/colorpicker.cjs +3 -1
  11. package/dist/colorpicker.js +3 -1
  12. package/dist/components/Accordion/Accordion.module.scss.cjs +8 -8
  13. package/dist/components/Accordion/Accordion.module.scss.js +8 -8
  14. package/dist/components/Alert/Alert.module.scss.cjs +15 -12
  15. package/dist/components/Alert/Alert.module.scss.js +15 -12
  16. package/dist/components/Alert/index.cjs +7 -1
  17. package/dist/components/Alert/index.d.ts +12 -6
  18. package/dist/components/Alert/index.d.ts.map +1 -1
  19. package/dist/components/Alert/index.js +7 -1
  20. package/dist/components/AppShell/AppShell.module.scss.cjs +14 -14
  21. package/dist/components/AppShell/AppShell.module.scss.js +14 -14
  22. package/dist/components/Avatar/Avatar.module.scss.cjs +14 -14
  23. package/dist/components/Avatar/Avatar.module.scss.js +14 -14
  24. package/dist/components/Badge/Badge.module.scss.cjs +19 -19
  25. package/dist/components/Badge/Badge.module.scss.js +19 -19
  26. package/dist/components/BentoGrid/BentoGrid.module.scss.cjs +14 -14
  27. package/dist/components/BentoGrid/BentoGrid.module.scss.js +14 -14
  28. package/dist/components/Box/Box.module.scss.cjs +152 -152
  29. package/dist/components/Box/Box.module.scss.js +152 -152
  30. package/dist/components/Box/index.cjs +64 -75
  31. package/dist/components/Box/index.d.ts +16 -16
  32. package/dist/components/Box/index.d.ts.map +1 -1
  33. package/dist/components/Box/index.js +64 -75
  34. package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.cjs +8 -8
  35. package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.js +8 -8
  36. package/dist/components/Button/Button.module.scss.cjs +14 -14
  37. package/dist/components/Button/Button.module.scss.js +14 -14
  38. package/dist/components/Card/Card.module.scss.cjs +29 -17
  39. package/dist/components/Card/Card.module.scss.js +30 -18
  40. package/dist/components/Card/index.cjs +8 -0
  41. package/dist/components/Card/index.d.ts +12 -2
  42. package/dist/components/Card/index.d.ts.map +1 -1
  43. package/dist/components/Card/index.js +8 -0
  44. package/dist/components/Chart/Chart.module.scss.cjs +15 -15
  45. package/dist/components/Chart/Chart.module.scss.js +15 -15
  46. package/dist/components/Chart/index.d.ts.map +1 -1
  47. package/dist/components/Checkbox/Checkbox.module.scss.cjs +9 -9
  48. package/dist/components/Checkbox/Checkbox.module.scss.js +9 -9
  49. package/dist/components/Checkbox/index.cjs +2 -2
  50. package/dist/components/Checkbox/index.d.ts.map +1 -1
  51. package/dist/components/Checkbox/index.js +2 -2
  52. package/dist/components/Chip/Chip.module.scss.cjs +15 -15
  53. package/dist/components/Chip/Chip.module.scss.js +15 -15
  54. package/dist/components/Chip/index.cjs +2 -1
  55. package/dist/components/Chip/index.d.ts.map +1 -1
  56. package/dist/components/Chip/index.js +2 -1
  57. package/dist/components/CodeBlock/CodeBlock.module.scss.cjs +26 -23
  58. package/dist/components/CodeBlock/CodeBlock.module.scss.js +26 -23
  59. package/dist/components/CodeBlock/css-variables-theme.cjs +98 -0
  60. package/dist/components/CodeBlock/css-variables-theme.d.ts +27 -0
  61. package/dist/components/CodeBlock/css-variables-theme.d.ts.map +1 -0
  62. package/dist/components/CodeBlock/css-variables-theme.js +98 -0
  63. package/dist/components/CodeBlock/index.d.ts +17 -3
  64. package/dist/components/CodeBlock/index.d.ts.map +1 -1
  65. package/dist/components/Collapsible/Collapsible.module.scss.cjs +9 -9
  66. package/dist/components/Collapsible/Collapsible.module.scss.js +9 -9
  67. package/dist/components/ColorPicker/ColorPicker.module.scss.cjs +14 -14
  68. package/dist/components/ColorPicker/ColorPicker.module.scss.js +14 -14
  69. package/dist/components/ColorPicker/index.d.ts.map +1 -1
  70. package/dist/components/Combobox/Combobox.module.scss.cjs +21 -21
  71. package/dist/components/Combobox/Combobox.module.scss.js +21 -21
  72. package/dist/components/Combobox/index.cjs +17 -1
  73. package/dist/components/Combobox/index.d.ts.map +1 -1
  74. package/dist/components/Combobox/index.js +17 -1
  75. package/dist/components/Command/Command.module.scss.cjs +11 -11
  76. package/dist/components/Command/Command.module.scss.js +11 -11
  77. package/dist/components/Command/index.cjs +26 -15
  78. package/dist/components/Command/index.d.ts +2 -2
  79. package/dist/components/Command/index.d.ts.map +1 -1
  80. package/dist/components/Command/index.js +26 -15
  81. package/dist/components/ConversationList/ConversationList.module.scss.cjs +10 -10
  82. package/dist/components/ConversationList/ConversationList.module.scss.js +10 -10
  83. package/dist/components/DataTable/DataTable.icons.cjs +6 -33
  84. package/dist/components/DataTable/DataTable.icons.d.ts.map +1 -1
  85. package/dist/components/DataTable/DataTable.icons.js +6 -33
  86. package/dist/components/DataTable/DataTable.module.scss.cjs +27 -27
  87. package/dist/components/DataTable/DataTable.module.scss.js +27 -27
  88. package/dist/components/DataTable/index.d.ts.map +1 -1
  89. package/dist/components/DatePicker/DatePicker.module.scss.cjs +33 -33
  90. package/dist/components/DatePicker/DatePicker.module.scss.js +33 -33
  91. package/dist/components/DatePicker/index.d.ts.map +1 -1
  92. package/dist/components/Dialog/Dialog.module.scss.cjs +14 -14
  93. package/dist/components/Dialog/Dialog.module.scss.js +14 -14
  94. package/dist/components/Dialog/index.cjs +11 -14
  95. package/dist/components/Dialog/index.d.ts +7 -7
  96. package/dist/components/Dialog/index.d.ts.map +1 -1
  97. package/dist/components/Dialog/index.js +11 -14
  98. package/dist/components/Drawer/Drawer.module.scss.cjs +29 -29
  99. package/dist/components/Drawer/Drawer.module.scss.js +29 -29
  100. package/dist/components/Editor/Editor.module.scss.cjs +17 -17
  101. package/dist/components/Editor/Editor.module.scss.js +17 -17
  102. package/dist/components/Editor/index.d.ts +10 -10
  103. package/dist/components/Editor/index.d.ts.map +1 -1
  104. package/dist/components/EmptyState/EmptyState.module.scss.cjs +11 -8
  105. package/dist/components/EmptyState/EmptyState.module.scss.js +11 -8
  106. package/dist/components/EmptyState/index.cjs +8 -6
  107. package/dist/components/EmptyState/index.d.ts +9 -4
  108. package/dist/components/EmptyState/index.d.ts.map +1 -1
  109. package/dist/components/EmptyState/index.js +8 -6
  110. package/dist/components/Field/Field.module.scss.cjs +5 -5
  111. package/dist/components/Field/Field.module.scss.js +5 -5
  112. package/dist/components/Field/index.cjs +9 -1
  113. package/dist/components/Field/index.d.ts.map +1 -1
  114. package/dist/components/Field/index.js +9 -1
  115. package/dist/components/Fieldset/Fieldset.module.scss.cjs +3 -3
  116. package/dist/components/Fieldset/Fieldset.module.scss.js +3 -3
  117. package/dist/components/Grid/index.cjs +1 -1
  118. package/dist/components/Grid/index.js +1 -1
  119. package/dist/components/Header/Header.module.scss.cjs +33 -33
  120. package/dist/components/Header/Header.module.scss.js +33 -33
  121. package/dist/components/Header/index.cjs +17 -38
  122. package/dist/components/Header/index.d.ts +15 -11
  123. package/dist/components/Header/index.d.ts.map +1 -1
  124. package/dist/components/Header/index.js +17 -38
  125. package/dist/components/Icon/Icon.module.scss.cjs +15 -15
  126. package/dist/components/Icon/Icon.module.scss.js +15 -15
  127. package/dist/components/IconButton/IconButton.module.scss.cjs +8 -8
  128. package/dist/components/IconButton/IconButton.module.scss.js +8 -8
  129. package/dist/components/IconButton/index.cjs +2 -1
  130. package/dist/components/IconButton/index.d.ts.map +1 -1
  131. package/dist/components/IconButton/index.js +2 -1
  132. package/dist/components/Image/Image.module.scss.cjs +27 -27
  133. package/dist/components/Image/Image.module.scss.js +27 -27
  134. package/dist/components/Input/Input.module.scss.cjs +17 -17
  135. package/dist/components/Input/Input.module.scss.js +17 -17
  136. package/dist/components/Link/Link.module.scss.cjs +14 -10
  137. package/dist/components/Link/Link.module.scss.js +14 -10
  138. package/dist/components/Link/index.d.ts +1 -1
  139. package/dist/components/Link/index.d.ts.map +1 -1
  140. package/dist/components/List/List.module.scss.cjs +19 -19
  141. package/dist/components/List/List.module.scss.js +19 -19
  142. package/dist/components/Listbox/Listbox.module.scss.cjs +8 -8
  143. package/dist/components/Listbox/Listbox.module.scss.js +8 -8
  144. package/dist/components/Loading/Loading.module.scss.cjs +34 -34
  145. package/dist/components/Loading/Loading.module.scss.js +34 -34
  146. package/dist/components/Loading/index.cjs +1 -1
  147. package/dist/components/Loading/index.js +1 -1
  148. package/dist/components/Markdown/Markdown.module.scss.cjs +1 -1
  149. package/dist/components/Markdown/Markdown.module.scss.js +1 -1
  150. package/dist/components/Markdown/index.d.ts +2 -2
  151. package/dist/components/Markdown/index.d.ts.map +1 -1
  152. package/dist/components/Menu/Menu.module.scss.cjs +14 -14
  153. package/dist/components/Menu/Menu.module.scss.js +14 -14
  154. package/dist/components/Message/Message.module.scss.cjs +18 -18
  155. package/dist/components/Message/Message.module.scss.js +18 -18
  156. package/dist/components/NavigationMenu/NavigationMenu.module.scss.cjs +34 -31
  157. package/dist/components/NavigationMenu/NavigationMenu.module.scss.js +34 -31
  158. package/dist/components/NavigationMenu/index.cjs +32 -15
  159. package/dist/components/NavigationMenu/index.d.ts +12 -6
  160. package/dist/components/NavigationMenu/index.d.ts.map +1 -1
  161. package/dist/components/NavigationMenu/index.js +32 -15
  162. package/dist/components/Pagination/Pagination.module.scss.cjs +10 -10
  163. package/dist/components/Pagination/Pagination.module.scss.js +10 -10
  164. package/dist/components/Popover/Popover.module.scss.cjs +10 -10
  165. package/dist/components/Popover/Popover.module.scss.js +10 -10
  166. package/dist/components/Progress/Progress.module.scss.cjs +25 -25
  167. package/dist/components/Progress/Progress.module.scss.js +25 -25
  168. package/dist/components/Prompt/Prompt.module.scss.cjs +28 -28
  169. package/dist/components/Prompt/Prompt.module.scss.js +28 -28
  170. package/dist/components/RadioGroup/RadioGroup.module.scss.cjs +15 -15
  171. package/dist/components/RadioGroup/RadioGroup.module.scss.js +15 -15
  172. package/dist/components/ScrollArea/ScrollArea.module.scss.cjs +5 -5
  173. package/dist/components/ScrollArea/ScrollArea.module.scss.js +5 -5
  174. package/dist/components/ScrollArea/index.d.ts +4 -4
  175. package/dist/components/ScrollArea/index.d.ts.map +1 -1
  176. package/dist/components/ScrollArea/scroll-state.d.ts +5 -5
  177. package/dist/components/Select/Select.module.scss.cjs +21 -21
  178. package/dist/components/Select/Select.module.scss.js +21 -21
  179. package/dist/components/Separator/Separator.module.scss.cjs +11 -11
  180. package/dist/components/Separator/Separator.module.scss.js +11 -11
  181. package/dist/components/Sidebar/Sidebar.module.scss.cjs +43 -43
  182. package/dist/components/Sidebar/Sidebar.module.scss.js +43 -43
  183. package/dist/components/Sidebar/index.cjs +12 -35
  184. package/dist/components/Sidebar/index.d.ts +19 -19
  185. package/dist/components/Sidebar/index.d.ts.map +1 -1
  186. package/dist/components/Sidebar/index.js +12 -35
  187. package/dist/components/Skeleton/Skeleton.module.scss.cjs +50 -46
  188. package/dist/components/Skeleton/Skeleton.module.scss.js +50 -46
  189. package/dist/components/Slider/Slider.module.scss.cjs +12 -12
  190. package/dist/components/Slider/Slider.module.scss.js +12 -12
  191. package/dist/components/Stack/Stack.module.scss.cjs +25 -25
  192. package/dist/components/Stack/Stack.module.scss.js +25 -25
  193. package/dist/components/Stack/index.cjs +1 -1
  194. package/dist/components/Stack/index.js +1 -1
  195. package/dist/components/Switch/Switch.module.scss.cjs +9 -9
  196. package/dist/components/Switch/Switch.module.scss.js +9 -9
  197. package/dist/components/Table/Table.module.scss.cjs +19 -19
  198. package/dist/components/Table/Table.module.scss.js +19 -19
  199. package/dist/components/TableOfContents/TableOfContents.module.scss.cjs +15 -15
  200. package/dist/components/TableOfContents/TableOfContents.module.scss.js +15 -15
  201. package/dist/components/TableOfContents/index.cjs +13 -9
  202. package/dist/components/TableOfContents/index.d.ts +5 -3
  203. package/dist/components/TableOfContents/index.d.ts.map +1 -1
  204. package/dist/components/TableOfContents/index.js +13 -9
  205. package/dist/components/Tabs/Tabs.module.scss.cjs +12 -12
  206. package/dist/components/Tabs/Tabs.module.scss.js +12 -12
  207. package/dist/components/Tabs/index.cjs +26 -6
  208. package/dist/components/Tabs/index.d.ts.map +1 -1
  209. package/dist/components/Tabs/index.js +26 -6
  210. package/dist/components/Text/Text.module.scss.cjs +87 -75
  211. package/dist/components/Text/Text.module.scss.js +87 -75
  212. package/dist/components/Text/index.cjs +49 -41
  213. package/dist/components/Text/index.d.ts +12 -11
  214. package/dist/components/Text/index.d.ts.map +1 -1
  215. package/dist/components/Text/index.js +49 -41
  216. package/dist/components/Textarea/Textarea.module.scss.cjs +24 -24
  217. package/dist/components/Textarea/Textarea.module.scss.js +24 -24
  218. package/dist/components/Theme/index.cjs +2 -1
  219. package/dist/components/Theme/index.d.ts.map +1 -1
  220. package/dist/components/Theme/index.js +2 -1
  221. package/dist/components/ThemeToggle/ThemeToggle.module.scss.cjs +9 -6
  222. package/dist/components/ThemeToggle/ThemeToggle.module.scss.js +9 -6
  223. package/dist/components/ThemeToggle/index.cjs +31 -6
  224. package/dist/components/ThemeToggle/index.d.ts +7 -2
  225. package/dist/components/ThemeToggle/index.d.ts.map +1 -1
  226. package/dist/components/ThemeToggle/index.js +32 -7
  227. package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.cjs +13 -13
  228. package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.js +13 -13
  229. package/dist/components/Toast/Toast.module.scss.cjs +20 -20
  230. package/dist/components/Toast/Toast.module.scss.js +20 -20
  231. package/dist/components/ToggleGroup/ToggleGroup.module.scss.cjs +17 -17
  232. package/dist/components/ToggleGroup/ToggleGroup.module.scss.js +17 -17
  233. package/dist/components/Tooltip/Tooltip.module.scss.cjs +3 -3
  234. package/dist/components/Tooltip/Tooltip.module.scss.js +3 -3
  235. package/dist/components/Tooltip/index.cjs +24 -40
  236. package/dist/components/Tooltip/index.d.ts +4 -4
  237. package/dist/components/Tooltip/index.d.ts.map +1 -1
  238. package/dist/components/Tooltip/index.js +24 -40
  239. package/dist/components/VisuallyHidden/index.d.ts +2 -2
  240. package/dist/data-table.cjs +2 -1
  241. package/dist/data-table.js +2 -1
  242. package/dist/datepicker.cjs +3 -2
  243. package/dist/datepicker.js +3 -2
  244. package/dist/editor.cjs +68 -28
  245. package/dist/editor.js +68 -28
  246. package/dist/index.cjs +1 -1
  247. package/dist/index.d.ts +1 -1
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +2 -2
  250. package/dist/markdown.cjs +21 -29
  251. package/dist/markdown.js +21 -29
  252. package/dist/measurements/generated.cjs +9 -1
  253. package/dist/measurements/generated.d.ts +7 -0
  254. package/dist/measurements/generated.d.ts.map +1 -1
  255. package/dist/measurements/generated.js +9 -1
  256. package/dist/utils/a11y.cjs +5 -2
  257. package/dist/utils/a11y.d.ts +5 -5
  258. package/dist/utils/a11y.d.ts.map +1 -1
  259. package/dist/utils/a11y.js +5 -2
  260. package/dist/utils/canonical-stamp.cjs +2 -8
  261. package/dist/utils/canonical-stamp.d.ts.map +1 -1
  262. package/dist/utils/canonical-stamp.js +1 -7
  263. package/dist/utils/css-warning.cjs +1 -1
  264. package/dist/utils/css-warning.js +1 -1
  265. package/dist/utils/env.cjs +17 -0
  266. package/dist/utils/env.d.ts +3 -0
  267. package/dist/utils/env.d.ts.map +1 -0
  268. package/dist/utils/env.js +17 -0
  269. package/dist/utils/keyboard-shortcuts.cjs +3 -10
  270. package/dist/utils/keyboard-shortcuts.d.ts +4 -4
  271. package/dist/utils/keyboard-shortcuts.d.ts.map +1 -1
  272. package/dist/utils/keyboard-shortcuts.js +3 -10
  273. package/dist/utils/seed-derivation.cjs +10 -6
  274. package/dist/utils/seed-derivation.d.ts.map +1 -1
  275. package/dist/utils/seed-derivation.js +10 -6
  276. package/fragments.json +1 -1
  277. package/package.json +6 -4
  278. package/src/assets/fragments-logo.tsx +2 -2
  279. package/src/assets/fragments-wordmark.tsx +4 -2
  280. package/src/components/Accordion/Accordion.contract.json +24 -48
  281. package/src/components/Alert/Alert.contract.json +37 -53
  282. package/src/components/Alert/Alert.module.scss +24 -0
  283. package/src/components/Alert/index.tsx +55 -29
  284. package/src/components/AppShell/AppShell.contract.json +34 -51
  285. package/src/components/AppShell/AppShell.module.scss +53 -40
  286. package/src/components/Avatar/Avatar.contract.json +31 -48
  287. package/src/components/Avatar/Avatar.module.scss +4 -1
  288. package/src/components/Badge/Badge.contract.json +37 -42
  289. package/src/components/Badge/Badge.module.scss +9 -2
  290. package/src/components/BentoGrid/BentoGrid.contract.json +21 -45
  291. package/src/components/Box/Box.contract.json +40 -148
  292. package/src/components/Box/index.tsx +92 -99
  293. package/src/components/Breadcrumbs/Breadcrumbs.contract.json +21 -34
  294. package/src/components/Breadcrumbs/Breadcrumbs.module.scss +12 -7
  295. package/src/components/Button/Button.module.scss +8 -7
  296. package/src/components/ButtonGroup/ButtonGroup.contract.json +32 -47
  297. package/src/components/Card/Card.module.scss +82 -1
  298. package/src/components/Card/index.tsx +21 -2
  299. package/src/components/Chart/Chart.contract.json +21 -29
  300. package/src/components/Chart/index.tsx +36 -6
  301. package/src/components/Checkbox/Checkbox.contract.json +24 -24
  302. package/src/components/Checkbox/Checkbox.module.scss +32 -23
  303. package/src/components/Checkbox/index.tsx +4 -2
  304. package/src/components/Chip/Chip.contract.json +33 -40
  305. package/src/components/Chip/Chip.module.scss +2 -2
  306. package/src/components/Chip/index.tsx +2 -1
  307. package/src/components/CodeBlock/CodeBlock.contract.json +46 -76
  308. package/src/components/CodeBlock/CodeBlock.module.scss +40 -15
  309. package/src/components/CodeBlock/css-variables-theme.ts +102 -0
  310. package/src/components/CodeBlock/index.tsx +91 -35
  311. package/src/components/Collapsible/Collapsible.contract.json +21 -36
  312. package/src/components/ColorPicker/ColorPicker.contract.json +29 -48
  313. package/src/components/ColorPicker/ColorPicker.module.scss +15 -12
  314. package/src/components/ColorPicker/index.tsx +5 -1
  315. package/src/components/Combobox/Combobox.contract.json +36 -37
  316. package/src/components/Combobox/Combobox.module.scss +1 -1
  317. package/src/components/Combobox/index.tsx +31 -5
  318. package/src/components/Command/Command.contract.json +21 -43
  319. package/src/components/Command/index.tsx +58 -47
  320. package/src/components/ConversationList/ConversationList.contract.json +27 -32
  321. package/src/components/DataTable/DataTable.icons.tsx +4 -21
  322. package/src/components/DataTable/DataTable.module.scss +12 -8
  323. package/src/components/DataTable/index.tsx +8 -7
  324. package/src/components/DatePicker/DatePicker.contract.json +27 -28
  325. package/src/components/DatePicker/DatePicker.module.scss +12 -5
  326. package/src/components/DatePicker/index.tsx +5 -2
  327. package/src/components/Dialog/Dialog.module.scss +3 -3
  328. package/src/components/Dialog/index.tsx +47 -37
  329. package/src/components/Drawer/Drawer.contract.json +22 -36
  330. package/src/components/Editor/Editor.contract.json +31 -48
  331. package/src/components/Editor/Editor.module.scss +36 -14
  332. package/src/components/Editor/index.tsx +240 -179
  333. package/src/components/EmptyState/EmptyState.contract.json +31 -43
  334. package/src/components/EmptyState/EmptyState.module.scss +8 -0
  335. package/src/components/EmptyState/index.tsx +48 -23
  336. package/src/components/Field/Field.contract.json +28 -46
  337. package/src/components/Field/index.tsx +5 -1
  338. package/src/components/Fieldset/Fieldset.contract.json +21 -38
  339. package/src/components/Fieldset/Fieldset.module.scss +10 -3
  340. package/src/components/Form/Form.contract.json +20 -20
  341. package/src/components/Grid/Grid.contract.json +28 -64
  342. package/src/components/Grid/index.tsx +10 -10
  343. package/src/components/Header/Header.contract.json +31 -67
  344. package/src/components/Header/Header.module.scss +36 -21
  345. package/src/components/Header/index.tsx +134 -122
  346. package/src/components/Icon/Icon.contract.json +22 -62
  347. package/src/components/IconButton/IconButton.contract.json +34 -18
  348. package/src/components/IconButton/IconButton.module.scss +6 -7
  349. package/src/components/IconButton/index.tsx +2 -1
  350. package/src/components/Image/Image.contract.json +23 -56
  351. package/src/components/Input/Input.contract.json +26 -32
  352. package/src/components/Input/Input.module.scss +3 -2
  353. package/src/components/Link/Link.contract.json +32 -52
  354. package/src/components/Link/Link.module.scss +23 -6
  355. package/src/components/Link/index.tsx +1 -1
  356. package/src/components/List/List.contract.json +23 -52
  357. package/src/components/List/List.module.scss +1 -1
  358. package/src/components/Listbox/Listbox.contract.json +21 -37
  359. package/src/components/Loading/Loading.contract.json +37 -61
  360. package/src/components/Loading/Loading.module.scss +10 -7
  361. package/src/components/Loading/index.tsx +2 -2
  362. package/src/components/Main/Main.contract.json +17 -9
  363. package/src/components/Markdown/Markdown.contract.json +22 -43
  364. package/src/components/Markdown/Markdown.module.scss +43 -5
  365. package/src/components/Markdown/index.tsx +48 -49
  366. package/src/components/Menu/Menu.contract.json +25 -41
  367. package/src/components/Menu/Menu.module.scss +23 -8
  368. package/src/components/Message/Message.contract.json +29 -52
  369. package/src/components/Message/Message.module.scss +12 -5
  370. package/src/components/NavigationMenu/NavigationMenu.contract.json +36 -45
  371. package/src/components/NavigationMenu/NavigationMenu.module.scss +64 -19
  372. package/src/components/NavigationMenu/index.tsx +105 -81
  373. package/src/components/Pagination/Pagination.contract.json +22 -40
  374. package/src/components/Pagination/Pagination.module.scss +2 -2
  375. package/src/components/Popover/Popover.contract.json +24 -46
  376. package/src/components/Popover/Popover.module.scss +6 -5
  377. package/src/components/Progress/Progress.contract.json +32 -28
  378. package/src/components/Progress/Progress.module.scss +3 -2
  379. package/src/components/Prompt/Prompt.contract.json +31 -47
  380. package/src/components/Prompt/Prompt.module.scss +13 -5
  381. package/src/components/RadioGroup/RadioGroup.contract.json +23 -24
  382. package/src/components/RadioGroup/RadioGroup.module.scss +13 -14
  383. package/src/components/ScrollArea/ScrollArea.contract.json +18 -19
  384. package/src/components/ScrollArea/ScrollArea.module.scss +15 -15
  385. package/src/components/ScrollArea/index.tsx +16 -16
  386. package/src/components/ScrollArea/scroll-state.ts +24 -24
  387. package/src/components/Select/Select.module.scss +2 -2
  388. package/src/components/Separator/Separator.contract.json +24 -48
  389. package/src/components/Sidebar/Sidebar.contract.json +35 -67
  390. package/src/components/Sidebar/Sidebar.module.scss +22 -13
  391. package/src/components/Sidebar/index.tsx +164 -164
  392. package/src/components/Skeleton/Skeleton.contract.json +28 -54
  393. package/src/components/Skeleton/Skeleton.module.scss +27 -10
  394. package/src/components/Slider/Slider.contract.json +27 -39
  395. package/src/components/Slider/Slider.module.scss +3 -3
  396. package/src/components/Stack/Stack.contract.json +29 -56
  397. package/src/components/Stack/Stack.module.scss +13 -12
  398. package/src/components/Stack/index.tsx +3 -3
  399. package/src/components/Switch/Switch.contract.json +33 -46
  400. package/src/components/Switch/Switch.module.scss +64 -26
  401. package/src/components/Table/Table.contract.json +28 -46
  402. package/src/components/Table/Table.module.scss +15 -3
  403. package/src/components/TableOfContents/TableOfContents.contract.json +34 -21
  404. package/src/components/TableOfContents/TableOfContents.module.scss +15 -5
  405. package/src/components/TableOfContents/index.tsx +26 -9
  406. package/src/components/Tabs/Tabs.contract.json +24 -45
  407. package/src/components/Tabs/Tabs.module.scss +1 -1
  408. package/src/components/Tabs/index.tsx +15 -3
  409. package/src/components/Text/Text.contract.json +30 -72
  410. package/src/components/Text/Text.module.scss +21 -4
  411. package/src/components/Text/index.tsx +113 -75
  412. package/src/components/Textarea/Textarea.contract.json +25 -43
  413. package/src/components/Textarea/Textarea.module.scss +2 -4
  414. package/src/components/Theme/Theme.contract.json +32 -51
  415. package/src/components/Theme/index.tsx +2 -1
  416. package/src/components/ThemeToggle/ThemeToggle.module.scss +23 -7
  417. package/src/components/ThemeToggle/index.tsx +43 -7
  418. package/src/components/ThinkingIndicator/ThinkingIndicator.contract.json +23 -40
  419. package/src/components/Toast/Toast.contract.json +30 -40
  420. package/src/components/Toast/Toast.module.scss +1 -1
  421. package/src/components/ToggleGroup/ToggleGroup.contract.json +29 -30
  422. package/src/components/ToggleGroup/ToggleGroup.module.scss +38 -5
  423. package/src/components/Tooltip/Tooltip.contract.json +31 -52
  424. package/src/components/Tooltip/index.tsx +19 -24
  425. package/src/components/VisuallyHidden/VisuallyHidden.contract.json +22 -44
  426. package/src/components/VisuallyHidden/index.tsx +5 -5
  427. package/src/index.ts +2 -2
  428. package/src/measurements/generated.ts +9 -2
  429. package/src/measurements/measurements.json +7 -0
  430. package/src/recipes/_boolean-range.scss +3 -11
  431. package/src/recipes/_field.scss +5 -1
  432. package/src/recipes/_layout.scss +14 -7
  433. package/src/recipes/_popup.scss +12 -2
  434. package/src/recipes/_prose.scss +13 -5
  435. package/src/recipes/_table-chrome.scss +16 -2
  436. package/src/scss.d.ts +1 -1
  437. package/src/styles/globals.scss +20 -19
  438. package/src/tokens/_computed.scss +5 -16
  439. package/src/tokens/_derive.scss +112 -210
  440. package/src/tokens/_measurements.catalog.generated.css +6 -1
  441. package/src/tokens/_measurements.generated.scss +14 -1
  442. package/src/tokens/_mixins.scss +7 -8
  443. package/src/tokens/_palettes.scss +39 -167
  444. package/src/tokens/_seeds.scss +20 -20
  445. package/src/tokens/_variables.scss +183 -38
  446. package/src/utils/a11y.tsx +69 -69
  447. package/src/utils/aria.ts +3 -3
  448. package/src/utils/canonical-stamp.ts +2 -12
  449. package/src/utils/css-warning.ts +7 -7
  450. package/src/utils/env.ts +25 -0
  451. package/src/utils/keyboard-shortcuts.ts +131 -126
  452. package/src/utils/seed-derivation.ts +10 -6
  453. package/src/components/Button/Button.contract.json +0 -218
  454. package/src/components/Card/Card.contract.json +0 -175
  455. package/src/components/DataTable/DataTable.contract.json +0 -302
  456. package/src/components/Dialog/Dialog.contract.json +0 -159
  457. package/src/components/Select/Select.contract.json +0 -259
@@ -1,8 +1,8 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import * as React from 'react';
4
- import { Dialog as BaseDialog } from '@base-ui/react/dialog';
5
- import styles from './Dialog.module.scss';
3
+ import * as React from "react";
4
+ import { Dialog as BaseDialog } from "@base-ui/react/dialog";
5
+ import styles from "./Dialog.module.scss";
6
6
 
7
7
  // ============================================
8
8
  // Types
@@ -30,17 +30,20 @@ export interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement>
30
30
  /** Dialog width.
31
31
  * @default "md"
32
32
  * @see https://usefragments.com/components/dialog#sizes */
33
- size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
33
+ size?: "sm" | "md" | "lg" | "xl" | "full";
34
34
  /** Whether the dialog should autofocus content on open.
35
35
  * @default true */
36
36
  initialFocus?: boolean;
37
37
  }
38
38
 
39
- export interface DialogTitleProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {
39
+ export interface DialogTitleProps extends Omit<React.HTMLAttributes<HTMLElement>, "children"> {
40
40
  children: React.ReactNode;
41
41
  }
42
42
 
43
- export interface DialogDescriptionProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {
43
+ export interface DialogDescriptionProps extends Omit<
44
+ React.HTMLAttributes<HTMLElement>,
45
+ "children"
46
+ > {
44
47
  children: React.ReactNode;
45
48
  }
46
49
 
@@ -61,7 +64,7 @@ type DialogTriggerAsButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>
61
64
  asChild?: false;
62
65
  };
63
66
 
64
- type DialogTriggerAsChildProps = Omit<React.HTMLAttributes<HTMLElement>, 'children'> & {
67
+ type DialogTriggerAsChildProps = Omit<React.HTMLAttributes<HTMLElement>, "children"> & {
65
68
  children: React.ReactElement;
66
69
  asChild: true;
67
70
  };
@@ -73,7 +76,7 @@ type DialogCloseAsButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
73
76
  asChild?: false;
74
77
  };
75
78
 
76
- type DialogCloseAsChildProps = Omit<React.HTMLAttributes<HTMLElement>, 'children'> & {
79
+ type DialogCloseAsChildProps = Omit<React.HTMLAttributes<HTMLElement>, "children"> & {
77
80
  children: React.ReactElement;
78
81
  asChild: true;
79
82
  };
@@ -108,13 +111,7 @@ function CloseIcon() {
108
111
  // Components
109
112
  // ============================================
110
113
 
111
- function DialogRoot({
112
- children,
113
- open,
114
- defaultOpen,
115
- onOpenChange,
116
- modal = true,
117
- }: DialogProps) {
114
+ function DialogRoot({ children, open, defaultOpen, onOpenChange, modal = true }: DialogProps) {
118
115
  return (
119
116
  <BaseDialog.Root
120
117
  open={open}
@@ -127,15 +124,14 @@ function DialogRoot({
127
124
  );
128
125
  }
129
126
 
130
- function DialogTrigger({
131
- children,
132
- asChild,
133
- className,
134
- ...htmlProps
135
- }: DialogTriggerProps) {
127
+ function DialogTrigger({ children, asChild, className, ...htmlProps }: DialogTriggerProps) {
136
128
  if (asChild) {
137
129
  return (
138
- <BaseDialog.Trigger {...htmlProps} className={className} render={children as React.ReactElement}>
130
+ <BaseDialog.Trigger
131
+ {...htmlProps}
132
+ className={className}
133
+ render={children as React.ReactElement}
134
+ >
139
135
  {null}
140
136
  </BaseDialog.Trigger>
141
137
  );
@@ -150,14 +146,12 @@ function DialogTrigger({
150
146
 
151
147
  function DialogContent({
152
148
  children,
153
- size = 'md',
149
+ size = "md",
154
150
  initialFocus = true,
155
151
  className,
156
152
  ...htmlProps
157
153
  }: DialogContentProps) {
158
- const popupClasses = [styles.popup, styles[size], className]
159
- .filter(Boolean)
160
- .join(' ');
154
+ const popupClasses = [styles.popup, styles[size], className].filter(Boolean).join(" ");
161
155
 
162
156
  return (
163
157
  <BaseDialog.Portal>
@@ -172,17 +166,25 @@ function DialogContent({
172
166
  }
173
167
 
174
168
  function DialogHeader({ children, className, ...htmlProps }: DialogHeaderProps) {
175
- const classes = [styles.header, className].filter(Boolean).join(' ');
176
- return <div {...htmlProps} className={classes}>{children}</div>;
169
+ const classes = [styles.header, className].filter(Boolean).join(" ");
170
+ return (
171
+ <div {...htmlProps} className={classes}>
172
+ {children}
173
+ </div>
174
+ );
177
175
  }
178
176
 
179
177
  function DialogTitle({ children, className, ...htmlProps }: DialogTitleProps) {
180
- const classes = [styles.title, className].filter(Boolean).join(' ');
181
- return <BaseDialog.Title {...htmlProps} className={classes}>{children}</BaseDialog.Title>;
178
+ const classes = [styles.title, className].filter(Boolean).join(" ");
179
+ return (
180
+ <BaseDialog.Title {...htmlProps} className={classes}>
181
+ {children}
182
+ </BaseDialog.Title>
183
+ );
182
184
  }
183
185
 
184
186
  function DialogDescription({ children, className, ...htmlProps }: DialogDescriptionProps) {
185
- const classes = [styles.description, className].filter(Boolean).join(' ');
187
+ const classes = [styles.description, className].filter(Boolean).join(" ");
186
188
  return (
187
189
  <BaseDialog.Description {...htmlProps} className={classes}>
188
190
  {children}
@@ -191,13 +193,21 @@ function DialogDescription({ children, className, ...htmlProps }: DialogDescript
191
193
  }
192
194
 
193
195
  function DialogBody({ children, className, ...htmlProps }: DialogBodyProps) {
194
- const classes = [styles.body, className].filter(Boolean).join(' ');
195
- return <div {...htmlProps} className={classes}>{children}</div>;
196
+ const classes = [styles.body, className].filter(Boolean).join(" ");
197
+ return (
198
+ <div {...htmlProps} className={classes}>
199
+ {children}
200
+ </div>
201
+ );
196
202
  }
197
203
 
198
204
  function DialogFooter({ children, className, ...htmlProps }: DialogFooterProps) {
199
- const classes = [styles.footer, className].filter(Boolean).join(' ');
200
- return <div {...htmlProps} className={classes}>{children}</div>;
205
+ const classes = [styles.footer, className].filter(Boolean).join(" ");
206
+ return (
207
+ <div {...htmlProps} className={classes}>
208
+ {children}
209
+ </div>
210
+ );
201
211
  }
202
212
 
203
213
  function DialogClose({ children, asChild, className, ...htmlProps }: DialogCloseProps) {
@@ -208,7 +218,7 @@ function DialogClose({ children, asChild, className, ...htmlProps }: DialogClose
208
218
  {...htmlProps}
209
219
  data-dialog-close
210
220
  aria-label="Close dialog"
211
- className={[styles.close, className].filter(Boolean).join(' ')}
221
+ className={[styles.close, className].filter(Boolean).join(" ")}
212
222
  >
213
223
  <CloseIcon />
214
224
  </BaseDialog.Close>
@@ -1,15 +1,9 @@
1
1
  {
2
2
  "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
3
  "name": "Drawer",
4
- "description": "A panel that slides in from screen edges. Extends the Dialog pattern with slide animations and edge positioning.",
5
- "category": "feedback",
6
- "tags": [
7
- "drawer",
8
- "sheet",
9
- "panel",
10
- "sidebar",
11
- "slide-over"
12
- ],
4
+ "description": "Slides a panel in from a screen edge and dims the page behind it.",
5
+ "category": "overlays",
6
+ "tags": ["drawer", "sheet", "panel", "sidebar", "slide-over"],
13
7
  "status": "stable",
14
8
  "sourcePath": "src/components/Drawer/index.tsx",
15
9
  "exportName": "Drawer",
@@ -51,25 +45,23 @@
51
45
  },
52
46
  "usage": {
53
47
  "when": [
54
- "Side panels for editing or creating content",
55
- "Mobile-style bottom sheets for actions",
56
- "Navigation panels that slide in from the left",
57
- "Detail views that overlay the main content"
48
+ "Editing or creating alongside the page behind it",
49
+ "Touch-reachable action sheets",
50
+ "Navigation that slides in and back out",
51
+ "Detail views that overlay rather than replace"
58
52
  ],
59
53
  "whenNot": [
60
- "Centered modal dialogs (use Dialog)",
61
- "Non-blocking notifications (use Toast)",
62
- "Permanent side navigation (use Sidebar)",
63
- "Small contextual menus (use Menu or Popover)"
54
+ "A centred task (use Dialog)",
55
+ "Navigation that stays on screen (use Sidebar)",
56
+ "A short list of actions (use Menu or Popover)",
57
+ "Feedback the user does not act on (use Toast)"
64
58
  ],
65
59
  "guidelines": [
66
- "Default to right side for content editing and forms",
67
- "Use left side for navigation drawers",
68
- "Use bottom for mobile-style action sheets",
69
- "Provide clear close affordance (X button or cancel)",
70
- "Keep drawer content focused on a single task",
71
- "Drawer.Trigger and Drawer.Close with asChild require a single valid React element child",
72
- "Set Drawer.Content initialFocus={false} when custom focus management is needed"
60
+ "Right for editing, left for navigation, bottom for touch",
61
+ "Always give the user a visible way out",
62
+ "One task per drawer",
63
+ "asChild on Trigger and Close needs a single element child",
64
+ "Set initialFocus={false} when you place focus yourself"
73
65
  ],
74
66
  "accessibility": [
75
67
  "Automatically traps focus within the drawer",
@@ -81,22 +73,22 @@
81
73
  "examples": [
82
74
  {
83
75
  "name": "Default",
84
- "description": "Right-side drawer with header, body, and footer",
76
+ "description": "Enters from the right, the default for editing and forms.",
85
77
  "code": "<Drawer>\n <Drawer.Trigger asChild>\n <Button>Open Drawer</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Close />\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n <Drawer.Description>\n A panel sliding in from the right.\n </Drawer.Description>\n </Drawer.Header>\n <Drawer.Body>\n <p>Drawer content goes here.</p>\n </Drawer.Body>\n <Drawer.Footer>\n <Drawer.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Drawer.Close>\n <Button variant=\"primary\">Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n</Drawer>"
86
78
  },
87
79
  {
88
80
  "name": "Left Side",
89
- "description": "Left-side drawer for navigation",
81
+ "description": "Enters from the left, where navigation belongs.",
90
82
  "code": "<Drawer>\n <Drawer.Trigger asChild>\n <Button variant=\"secondary\">Open Left</Button>\n </Drawer.Trigger>\n <Drawer.Content side=\"left\">\n <Drawer.Close />\n <Drawer.Header>\n <Drawer.Title>Navigation</Drawer.Title>\n </Drawer.Header>\n <Drawer.Body>\n <p>Left-side drawer for navigation or filters.</p>\n </Drawer.Body>\n </Drawer.Content>\n</Drawer>"
91
83
  },
92
84
  {
93
85
  "name": "Bottom Sheet",
94
- "description": "Bottom drawer for mobile-style actions",
86
+ "description": "Rises from the bottom for touch-reachable actions.",
95
87
  "code": "<Drawer>\n <Drawer.Trigger asChild>\n <Button variant=\"secondary\">Open Bottom Sheet</Button>\n </Drawer.Trigger>\n <Drawer.Content side=\"bottom\" size=\"sm\">\n <Drawer.Header>\n <Drawer.Title>Actions</Drawer.Title>\n </Drawer.Header>\n <Drawer.Body>\n <p>Bottom sheet for mobile-style actions.</p>\n </Drawer.Body>\n </Drawer.Content>\n</Drawer>"
96
88
  },
97
89
  {
98
90
  "name": "With Form",
99
- "description": "Drawer with a form layout",
91
+ "description": "Fields in the body, submit and cancel pinned to the footer.",
100
92
  "code": "<Drawer>\n <Drawer.Trigger asChild>\n <Button>Edit Settings</Button>\n </Drawer.Trigger>\n <Drawer.Content size=\"md\">\n <Drawer.Close />\n <Drawer.Header>\n <Drawer.Title>Settings</Drawer.Title>\n <Drawer.Description>Update your preferences.</Drawer.Description>\n </Drawer.Header>\n <Drawer.Body>\n <Stack gap=\"md\">\n <Input label=\"Display Name\" placeholder=\"Enter name\" />\n <Input label=\"Email\" type=\"email\" placeholder=\"you@example.com\" />\n </Stack>\n </Drawer.Body>\n <Drawer.Footer>\n <Drawer.Close asChild>\n <Button variant=\"secondary\">Cancel</Button>\n </Drawer.Close>\n <Button variant=\"primary\">Save Changes</Button>\n </Drawer.Footer>\n </Drawer.Content>\n</Drawer>"
101
93
  }
102
94
  ],
@@ -126,11 +118,7 @@
126
118
  "Drawer.Content size: sm|md|lg|xl|full - panel size",
127
119
  "Drawer.Content initialFocus: boolean - auto-focus popup on open (default: true)"
128
120
  ],
129
- "a11yRules": [
130
- "A11Y_DIALOG_FOCUS",
131
- "A11Y_DIALOG_ESCAPE",
132
- "A11Y_DIALOG_LABEL"
133
- ]
121
+ "a11yRules": ["A11Y_DIALOG_FOCUS", "A11Y_DIALOG_ESCAPE", "A11Y_DIALOG_LABEL"]
134
122
  },
135
123
  "ai": {
136
124
  "compositionPattern": "compound",
@@ -145,9 +133,7 @@
145
133
  "Body",
146
134
  "Footer"
147
135
  ],
148
- "requiredChildren": [
149
- "Content"
150
- ],
136
+ "requiredChildren": ["Content"],
151
137
  "commonPatterns": [
152
138
  "<Drawer><Drawer.Trigger><Button>Open</Button></Drawer.Trigger><Drawer.Content><Drawer.Close /><Drawer.Header><Drawer.Title>{title}</Drawer.Title></Drawer.Header><Drawer.Body>{content}</Drawer.Body><Drawer.Footer><Drawer.Close asChild><Button variant=\"secondary\">Cancel</Button></Drawer.Close><Button>Save</Button></Drawer.Footer></Drawer.Content></Drawer>"
153
139
  ]
@@ -1,17 +1,9 @@
1
1
  {
2
2
  "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
3
  "name": "Editor",
4
- "description": "Rich text editor with formatting toolbar, auto-save, and word count",
5
- "category": "forms",
6
- "tags": [
7
- "editor",
8
- "rich-text",
9
- "markdown",
10
- "toolbar",
11
- "writing",
12
- "blog",
13
- "content"
14
- ],
4
+ "description": "Edits rich text with formatting, autosave, and a word count.",
5
+ "category": "inputs",
6
+ "tags": ["editor", "rich-text", "markdown", "toolbar", "writing", "blog", "content"],
15
7
  "status": "stable",
16
8
  "dependencies": [
17
9
  {
@@ -123,11 +115,7 @@
123
115
  "description": "Editor size preset: \"sm\" (120px), \"md\" (200px), or \"lg\" (400px)",
124
116
  "default": "md",
125
117
  "required": false,
126
- "values": [
127
- "sm",
128
- "md",
129
- "lg"
130
- ]
118
+ "values": ["sm", "md", "lg"]
131
119
  },
132
120
  "maxLength": {
133
121
  "type": "number",
@@ -142,27 +130,26 @@
142
130
  },
143
131
  "usage": {
144
132
  "when": [
145
- "Building blog post or article editors",
146
- "Need rich text editing with formatting controls",
147
- "Content management with auto-save and word count",
148
- "Markdown or WYSIWYG editing interfaces"
133
+ "Blog posts and long-form articles",
134
+ "Text that needs formatting controls beside it",
135
+ "Drafts that autosave and report a word count",
136
+ "Markdown or WYSIWYG authoring"
149
137
  ],
150
138
  "whenNot": [
151
- "Simple single-line text input (use Input)",
152
- "Plain multi-line without formatting (use Textarea)",
153
- "Chat/AI prompt input (use Prompt)",
139
+ "Single-line text (use Input)",
140
+ "Multi-line with no formatting (use Textarea)",
141
+ "Chat or AI prompt input (use Prompt)",
154
142
  "Code editing (use CodeBlock)"
155
143
  ],
156
144
  "guidelines": [
157
- "Use compound pattern for custom toolbar layouts",
158
- "Install @tiptap/react, @tiptap/starter-kit, and @tiptap/extension-link for rich text mode",
159
- "Falls back to a markdown-aware textarea when TipTap is not installed",
160
- "Use onAutoSave for periodic content persistence",
161
- "onAutoSave may return a Promise; save status updates after the async save resolves/rejects",
162
- "Use size prop (sm/md/lg) to control editor height",
163
- "Use maxLength to show character limit with visual warning states",
164
- "New formats (headings, blockquote, orderedList, undo, redo) are opt-in via the formats prop",
165
- "Use toolbarIcons to swap in icons from any icon package without changing toolbar button labels or accessibility behavior"
145
+ "Compose Editor.Toolbar and Editor.Content to control toolbar layout",
146
+ "Rich text needs @tiptap/react, @tiptap/starter-kit, and @tiptap/extension-link",
147
+ "Without TipTap it falls back to a markdown-aware textarea",
148
+ "onAutoSave may return a Promise; save status updates once it settles",
149
+ "size sets the minimum body height: sm 120px, md 200px, lg 400px",
150
+ "maxLength drives the counter's warning and over-limit states",
151
+ "Headings, blockquote, orderedList, undo, and redo are opt-in via formats",
152
+ "toolbarIcons swaps glyphs without changing labels or keyboard behavior"
166
153
  ],
167
154
  "accessibility": [
168
155
  "Toolbar has role=\"toolbar\" with aria-label",
@@ -177,47 +164,47 @@
177
164
  "examples": [
178
165
  {
179
166
  "name": "Default",
180
- "description": "Editor with default toolbar and status bar",
167
+ "description": "Toolbar and status bar you get with no configuration.",
181
168
  "code": "<Editor placeholder=\"Start typing your masterpiece here...\" />"
182
169
  },
183
170
  {
184
171
  "name": "With Auto-Save and Publish",
185
- "description": "Full compound usage with custom toolbar, auto-save indicator, and publish button",
172
+ "description": "Save state sits next to the primary action in the toolbar.",
186
173
  "code": "<Editor\n placeholder=\"Start typing your masterpiece here...\"\n onValueChange={(v) => console.log(v)}\n>\n <Editor.Toolbar>\n <Editor.ToolbarGroup aria-label=\"Text formatting\">\n <Editor.ToolbarButton format=\"bold\" />\n <Editor.ToolbarButton format=\"italic\" />\n <Editor.ToolbarButton format=\"strikethrough\" />\n <Editor.ToolbarButton format=\"link\" />\n <Editor.ToolbarButton format=\"code\" />\n <Editor.ToolbarButton format=\"bulletList\" />\n </Editor.ToolbarGroup>\n <Editor.ToolbarGroup aria-label=\"Actions\">\n <Editor.StatusIndicator status=\"saved\" />\n <Button variant=\"accent\" size=\"sm\">\n Publish\n </Button>\n </Editor.ToolbarGroup>\n </Editor.Toolbar>\n <Editor.Content />\n <Editor.StatusBar showWordCount showCharCount />\n</Editor>"
187
174
  },
188
175
  {
189
- "name": "Minimal",
190
- "description": "Editor with subset of formats",
191
- "code": "<Editor\n placeholder=\"Quick note...\"\n formats={['bold', 'italic', 'code']}\n/>"
176
+ "name": "Save Failed",
177
+ "description": "A failed autosave turns the status text red.",
178
+ "code": "<Editor defaultValue=\"This draft could not be saved.\">\n <Editor.Toolbar>\n <Editor.ToolbarGroup aria-label=\"Text formatting\">\n <Editor.ToolbarButton format=\"bold\" />\n <Editor.ToolbarButton format=\"italic\" />\n </Editor.ToolbarGroup>\n <Editor.ToolbarGroup aria-label=\"Status\">\n <Editor.StatusIndicator status=\"error\" />\n </Editor.ToolbarGroup>\n </Editor.Toolbar>\n <Editor.Content />\n <Editor.StatusBar showWordCount showCharCount />\n</Editor>"
192
179
  },
193
180
  {
194
181
  "name": "Disabled",
195
- "description": "Non-interactive editor with content",
182
+ "description": "Dimmed and inert, but the text stays readable.",
196
183
  "code": "<Editor\n defaultValue=\"This content cannot be edited.\"\n disabled\n/>"
197
184
  },
198
185
  {
199
186
  "name": "Read Only",
200
- "description": "Visible content, non-editable",
187
+ "description": "Text can be selected and copied, but never changed.",
201
188
  "code": "<Editor\n defaultValue=\"This content is read-only. You can select and copy text but cannot modify it.\"\n readOnly\n/>"
202
189
  },
203
190
  {
204
191
  "name": "Custom Toolbar",
205
- "description": "Compound usage with custom toolbar layout and separator",
192
+ "description": "Separators split the controls into labelled clusters.",
206
193
  "code": "<Editor\n placeholder=\"Write your blog post...\"\n onValueChange={(v) => console.log(v)}\n>\n <Editor.Toolbar>\n <Editor.ToolbarGroup aria-label=\"Basic formatting\">\n <Editor.ToolbarButton format=\"bold\" />\n <Editor.ToolbarButton format=\"italic\" />\n </Editor.ToolbarGroup>\n <Editor.Separator />\n <Editor.ToolbarGroup aria-label=\"Advanced formatting\">\n <Editor.ToolbarButton format=\"link\" />\n <Editor.ToolbarButton format=\"code\" />\n <Editor.ToolbarButton format=\"bulletList\" />\n </Editor.ToolbarGroup>\n <Editor.ToolbarGroup aria-label=\"Status\">\n <Editor.StatusIndicator status=\"saving\" />\n </Editor.ToolbarGroup>\n </Editor.Toolbar>\n <Editor.Content />\n <Editor.StatusBar showWordCount showCharCount />\n</Editor>"
207
194
  },
208
195
  {
209
196
  "name": "Full Formatting",
210
- "description": "All format options including headings, blockquote, ordered list, undo/redo",
197
+ "description": "Every opt-in format switched on, at the tallest preset.",
211
198
  "code": "<Editor\n placeholder=\"Write an article...\"\n size=\"lg\"\n>\n <Editor.Toolbar>\n <Editor.ToolbarGroup aria-label=\"History\">\n <Editor.ToolbarButton format=\"undo\" />\n <Editor.ToolbarButton format=\"redo\" />\n </Editor.ToolbarGroup>\n <Editor.Separator />\n <Editor.ToolbarGroup aria-label=\"Headings\">\n <Editor.ToolbarButton format=\"heading1\" />\n <Editor.ToolbarButton format=\"heading2\" />\n <Editor.ToolbarButton format=\"heading3\" />\n </Editor.ToolbarGroup>\n <Editor.Separator />\n <Editor.ToolbarGroup aria-label=\"Text formatting\">\n <Editor.ToolbarButton format=\"bold\" />\n <Editor.ToolbarButton format=\"italic\" />\n <Editor.ToolbarButton format=\"strikethrough\" />\n <Editor.ToolbarButton format=\"code\" />\n </Editor.ToolbarGroup>\n <Editor.Separator />\n <Editor.ToolbarGroup aria-label=\"Block formatting\">\n <Editor.ToolbarButton format=\"bulletList\" />\n <Editor.ToolbarButton format=\"orderedList\" />\n <Editor.ToolbarButton format=\"blockquote\" />\n <Editor.ToolbarButton format=\"link\" />\n </Editor.ToolbarGroup>\n </Editor.Toolbar>\n <Editor.Content />\n <Editor.StatusBar showWordCount showCharCount />\n</Editor>"
212
199
  },
213
200
  {
214
201
  "name": "With Character Limit",
215
- "description": "Editor with maxLength showing character count indicator with warning and error states",
202
+ "description": "The counter warns near 280 characters and turns red past it.",
216
203
  "code": "<Editor\n placeholder=\"Write a tweet-sized message...\"\n maxLength={280}\n size=\"sm\"\n formats={['bold', 'italic', 'link']}\n/>"
217
204
  },
218
205
  {
219
206
  "name": "Small Size",
220
- "description": "Compact editor with sm size preset (120px min-height)",
207
+ "description": "A 120px body with a trimmed toolbar, for tight spaces.",
221
208
  "code": "<Editor\n placeholder=\"Quick note...\"\n size=\"sm\"\n formats={['bold', 'italic', 'code']}\n/>"
222
209
  }
223
210
  ],
@@ -253,11 +240,7 @@
253
240
  "maxLength: number - character limit with visual indicator",
254
241
  "toolbarIcons: Partial<Record<EditorFormat, ReactNode | (state) => ReactNode>> - custom toolbar icons"
255
242
  ],
256
- "a11yRules": [
257
- "A11Y_TOOLBAR_ROLE",
258
- "A11Y_BUTTON_LABEL",
259
- "A11Y_LIVE_REGION"
260
- ]
243
+ "a11yRules": ["A11Y_TOOLBAR_ROLE", "A11Y_BUTTON_LABEL", "A11Y_LIVE_REGION"]
261
244
  },
262
245
  "ai": {
263
246
  "compositionPattern": "compound",
@@ -9,6 +9,8 @@
9
9
  .editor {
10
10
  @include form-group-surface;
11
11
 
12
+ // Component-scoped registered vocabulary: these are declared here as the
13
+ // token source for the editor's size presets, not ad-hoc custom properties.
12
14
  --fui-editor-min-block-sm: 120px;
13
15
  --fui-editor-min-block-md: 200px;
14
16
  --fui-editor-min-block-lg: 400px;
@@ -60,7 +62,7 @@
60
62
  }
61
63
 
62
64
  .toolbar {
63
- border-block-end: var(--fui-stroke-hairline) solid var(--fui-form-group-border, $fui-border);
65
+ border-block-end: var(--fui-stroke-hairline, 1px) solid var(--fui-form-group-border, $fui-border);
64
66
  }
65
67
 
66
68
  .toolbarGroup,
@@ -77,7 +79,7 @@
77
79
  @include action.icon-only("sm");
78
80
  @include target.hit-area("compact");
79
81
 
80
- border: var(--fui-stroke-hairline) solid transparent;
82
+ border: var(--fui-stroke-hairline, 1px) solid transparent;
81
83
  border-radius: var(--fui-radius-sm, $fui-radius-sm);
82
84
  background-color: transparent;
83
85
  color: var(--fui-text-secondary, $fui-text-secondary);
@@ -94,6 +96,10 @@
94
96
  background-color: var(--fui-field-selection-bg, $fui-bg-hover);
95
97
  }
96
98
 
99
+ &:focus-visible {
100
+ @include focus-ring;
101
+ }
102
+
97
103
  &:disabled {
98
104
  cursor: not-allowed;
99
105
  }
@@ -107,13 +113,13 @@
107
113
  border-color: var(--fui-field-selection-border, $fui-color-accent);
108
114
  background-color: var(--fui-field-selection-bg, $fui-bg-hover);
109
115
  color: var(--fui-text-primary, $fui-text-primary);
110
- box-shadow: inset 0 0 0 var(--fui-stroke-hairline)
116
+ box-shadow: inset 0 0 0 var(--fui-stroke-hairline, 1px)
111
117
  color-mix(in srgb, var(--fui-field-selection-border, $fui-color-accent) 55%, transparent);
112
118
  }
113
119
 
114
120
  .separator {
115
- inline-size: var(--fui-stroke-hairline);
116
- block-size: var(--fui-icon-md);
121
+ inline-size: var(--fui-stroke-hairline, 1px);
122
+ block-size: var(--fui-icon-md, $fui-icon-md);
117
123
  margin-inline: layout.gap("xs");
118
124
  background-color: var(--fui-form-group-border, $fui-border);
119
125
  flex-shrink: 0;
@@ -161,14 +167,6 @@
161
167
  @include prose.paragraph;
162
168
  }
163
169
 
164
- p.is-editor-empty:first-child::before {
165
- content: attr(data-placeholder);
166
- float: inline-start;
167
- block-size: 0;
168
- color: var(--fui-text-tertiary, $fui-text-tertiary);
169
- pointer-events: none;
170
- }
171
-
172
170
  @for $level from 1 through 6 {
173
171
  h#{$level} {
174
172
  @include prose.heading($level);
@@ -206,10 +204,33 @@
206
204
  }
207
205
  }
208
206
 
207
+ // TipTap's Placeholder extension is not a dependency, so the empty-document
208
+ // placeholder is driven from the wrapper's own data-placeholder attribute.
209
+ // An empty ProseMirror doc is exactly one paragraph holding a trailing break.
210
+ .contentRich[data-placeholder]:has(
211
+ :global(.tiptap) > p:only-child > br:global(.ProseMirror-trailingBreak)
212
+ ) {
213
+ position: relative;
214
+
215
+ &::before {
216
+ @include typography.role("body-relaxed");
217
+
218
+ content: attr(data-placeholder);
219
+ position: absolute;
220
+ inset-block-start: layout.gap("lg");
221
+ inset-inline-start: layout.gap("lg");
222
+ inset-inline-end: layout.gap("lg");
223
+ color: var(--fui-text-tertiary, $fui-text-tertiary);
224
+ pointer-events: none;
225
+ }
226
+ }
227
+
209
228
  .contentTextarea {
210
229
  @include button-reset;
211
230
  @include typography.role("body-relaxed");
212
231
 
232
+ // button-reset marks pressables select-none; typed text must stay selectable.
233
+ user-select: text;
213
234
  display: block;
214
235
  inline-size: 100%;
215
236
  block-size: 100%;
@@ -234,7 +255,8 @@
234
255
  }
235
256
 
236
257
  .statusBar {
237
- border-block-start: var(--fui-stroke-hairline) solid var(--fui-form-group-border, $fui-border);
258
+ border-block-start: var(--fui-stroke-hairline, 1px) solid
259
+ var(--fui-form-group-border, $fui-border);
238
260
  background-color: color-mix(
239
261
  in srgb,
240
262
  var(--fui-form-group-bg, $fui-bg-secondary) 56%,