@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,21 +1,16 @@
1
1
  {
2
2
  "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
3
  "name": "EmptyState",
4
- "description": "Placeholder for empty content areas. Provides context, guidance, and actions when no data is available.",
4
+ "description": "Explains why an area is blank and offers the next step.",
5
5
  "category": "feedback",
6
- "tags": [
7
- "empty",
8
- "placeholder",
9
- "no-data",
10
- "zero-state",
11
- "blank-slate"
12
- ],
6
+ "tags": ["empty", "placeholder", "no-data", "zero-state", "blank-slate"],
13
7
  "status": "stable",
14
8
  "sourcePath": "src/components/EmptyState/index.tsx",
15
9
  "exportName": "EmptyState",
16
10
  "propsSummary": [
17
11
  "children: node (required)",
18
- "size: sm|md|lg (default: md)"
12
+ "size: sm|md|lg (default: md)",
13
+ "variant: plain|outlined (default: plain)"
19
14
  ],
20
15
  "props": {
21
16
  "children": {
@@ -28,31 +23,33 @@
28
23
  "description": "Size variant",
29
24
  "default": "md",
30
25
  "required": false,
31
- "values": [
32
- "sm",
33
- "md",
34
- "lg"
35
- ]
26
+ "values": ["sm", "md", "lg"]
27
+ },
28
+ "variant": {
29
+ "type": "enum",
30
+ "description": "Frame style. `outlined` draws a dashed hairline around the reserved region; `plain` leaves framing to the surrounding surface.",
31
+ "default": "plain",
32
+ "required": false,
33
+ "values": ["plain", "outlined"]
36
34
  }
37
35
  },
38
36
  "usage": {
39
37
  "when": [
40
- "Empty lists, tables, or search results",
41
- "New user onboarding (no content yet)",
42
- "Filtered views with no matches",
43
- "Error states where content failed to load"
38
+ "Lists, tables, or search results with nothing to show",
39
+ "First-run screens before any content exists",
40
+ "Filtered views that matched nothing"
44
41
  ],
45
42
  "whenNot": [
46
- "Loading states (use skeleton or spinner)",
47
- "Error messages with retry (use Alert)",
48
- "Temporary messages (use Toast)"
43
+ "Content still loading (use Skeleton)",
44
+ "Failures that need a retry (use Alert)",
45
+ "Transient confirmations (use Toast)"
49
46
  ],
50
47
  "guidelines": [
51
- "Always explain why the area is empty",
52
- "Provide a clear action to resolve the empty state",
53
- "Use appropriate icons to reinforce the message",
54
- "Keep messaging positive and actionable",
55
- "EmptyState compound sub-components forward DOM props for ids, aria attributes, and handlers"
48
+ "Say why the area is empty, not just that it is",
49
+ "Give one clear action out of the state",
50
+ "Keep to two actions at most, primary first",
51
+ "Match the icon to the cause \u2014 search, inbox, folder",
52
+ "Use size=\"sm\" inline and size=\"lg\" for full-page states"
56
53
  ],
57
54
  "accessibility": [
58
55
  "Empty state content is accessible to screen readers",
@@ -62,27 +59,27 @@
62
59
  "examples": [
63
60
  {
64
61
  "name": "Default",
65
- "description": "Basic empty state with action",
62
+ "description": "First-run state: nothing exists yet, so offer the create action.",
66
63
  "code": "<EmptyState>\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>No projects yet</EmptyState.Title>\n <EmptyState.Description>Get started by creating your first project.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Project</Button>\n </EmptyState.Actions>\n</EmptyState>"
67
64
  },
68
65
  {
69
66
  "name": "No Results",
70
- "description": "Empty search results",
67
+ "description": "A filter or query matched nothing \u2014 offer a way back.",
71
68
  "code": "<EmptyState>\n <EmptyState.Icon><SearchIcon /></EmptyState.Icon>\n <EmptyState.Title>No results found</EmptyState.Title>\n <EmptyState.Description>Try adjusting your search terms or filters.</EmptyState.Description>\n <EmptyState.Actions>\n <Button variant=\"secondary\">Clear Filters</Button>\n </EmptyState.Actions>\n</EmptyState>"
72
69
  },
73
70
  {
74
71
  "name": "With Secondary Action",
75
- "description": "Empty state with two actions",
72
+ "description": "One primary action plus a quieter alternative.",
76
73
  "code": "<EmptyState>\n <EmptyState.Icon><InboxIcon /></EmptyState.Icon>\n <EmptyState.Title>Inbox is empty</EmptyState.Title>\n <EmptyState.Description>You have no new messages.</EmptyState.Description>\n <EmptyState.Actions>\n <Button>Compose Message</Button>\n <Button variant=\"secondary\">View Archive</Button>\n </EmptyState.Actions>\n</EmptyState>"
77
74
  },
78
75
  {
79
76
  "name": "Small",
80
- "description": "Compact empty state for inline use",
77
+ "description": "Compact size for inline panels; no icon, no action.",
81
78
  "code": "<EmptyState size=\"sm\">\n <EmptyState.Title>No items</EmptyState.Title>\n <EmptyState.Description>Add items to see them here.</EmptyState.Description>\n</EmptyState>"
82
79
  },
83
80
  {
84
81
  "name": "Large",
85
- "description": "Prominent empty state for full-page use",
82
+ "description": "Full-page size for a workspace or onboarding screen.",
86
83
  "code": "<EmptyState size=\"lg\">\n <EmptyState.Icon><FolderIcon /></EmptyState.Icon>\n <EmptyState.Title>Welcome to your workspace</EmptyState.Title>\n <EmptyState.Description>\n This is where your projects will appear. Create your first project to get started.\n </EmptyState.Description>\n <EmptyState.Actions>\n <Button>Create Your First Project</Button>\n </EmptyState.Actions>\n</EmptyState>"
87
84
  }
88
85
  ],
@@ -104,21 +101,12 @@
104
101
  "Sub-components: EmptyState.Icon, EmptyState.Title, EmptyState.Description, EmptyState.Actions",
105
102
  "Compound sub-components forward DOM props to their rendered elements"
106
103
  ],
107
- "a11yRules": [
108
- "A11Y_EMPTY_STATE_CONTENT"
109
- ]
104
+ "a11yRules": ["A11Y_EMPTY_STATE_CONTENT"]
110
105
  },
111
106
  "ai": {
112
107
  "compositionPattern": "compound",
113
- "subComponents": [
114
- "Icon",
115
- "Title",
116
- "Description",
117
- "Actions"
118
- ],
119
- "requiredChildren": [
120
- "Title"
121
- ],
108
+ "subComponents": ["Icon", "Title", "Description", "Actions"],
109
+ "requiredChildren": ["Title"],
122
110
  "commonPatterns": [
123
111
  "<EmptyState><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description></EmptyState>",
124
112
  "<EmptyState><EmptyState.Icon>{icon}</EmptyState.Icon><EmptyState.Title>{title}</EmptyState.Title><EmptyState.Description>{description}</EmptyState.Description><EmptyState.Actions><Button>{action}</Button></EmptyState.Actions></EmptyState>"
@@ -42,6 +42,14 @@
42
42
  @include feedback.empty-state("lg");
43
43
  }
44
44
 
45
+ // Reserved-but-empty region: a dashed hairline says the space belongs to
46
+ // content that has not arrived, without claiming the weight of a real card.
47
+ .outlined {
48
+ justify-content: center;
49
+ border: var(--fui-stroke-hairline, 1px) dashed var(--fui-border-default, $fui-border-default);
50
+ border-radius: var(--fui-card-radius, var(--fui-radius-lg, $fui-radius-lg));
51
+ }
52
+
45
53
  .icon {
46
54
  display: flex;
47
55
  align-items: center;
@@ -1,7 +1,7 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import * as React from 'react';
4
- import styles from './EmptyState.module.scss';
3
+ import * as React from "react";
4
+ import styles from "./EmptyState.module.scss";
5
5
 
6
6
  // ============================================
7
7
  // Types
@@ -9,7 +9,12 @@ import styles from './EmptyState.module.scss';
9
9
 
10
10
  export interface EmptyStateProps extends React.HTMLAttributes<HTMLDivElement> {
11
11
  children: React.ReactNode;
12
- size?: 'sm' | 'md' | 'lg';
12
+ size?: "sm" | "md" | "lg";
13
+ /** `outlined` draws the dashed hairline that marks a reserved-but-empty
14
+ * region. Default `plain` keeps the state inside whatever already frames it
15
+ * (a Card, a table body) so the frame is never doubled.
16
+ * @default "plain" */
17
+ variant?: "plain" | "outlined";
13
18
  }
14
19
 
15
20
  export interface EmptyStateIconProps extends React.HTMLAttributes<HTMLDivElement> {
@@ -33,7 +38,7 @@ export interface EmptyStateActionsProps extends React.HTMLAttributes<HTMLDivElem
33
38
  // ============================================
34
39
 
35
40
  interface EmptyStateContextValue {
36
- size: 'sm' | 'md' | 'lg';
41
+ size: "sm" | "md" | "lg";
37
42
  }
38
43
 
39
44
  const EmptyStateContext = React.createContext<EmptyStateContextValue | null>(null);
@@ -41,7 +46,7 @@ const EmptyStateContext = React.createContext<EmptyStateContextValue | null>(nul
41
46
  function useEmptyStateContext() {
42
47
  const context = React.useContext(EmptyStateContext);
43
48
  if (!context) {
44
- throw new Error('EmptyState compound components must be used within an EmptyState');
49
+ throw new Error("EmptyState compound components must be used within an EmptyState");
45
50
  }
46
51
  return context;
47
52
  }
@@ -52,45 +57,65 @@ function useEmptyStateContext() {
52
57
 
53
58
  function EmptyStateRoot({
54
59
  children,
55
- size = 'md',
60
+ size = "md",
61
+ variant = "plain",
56
62
  className,
57
63
  ...htmlProps
58
64
  }: EmptyStateProps) {
59
- const classes = [styles.emptyState, styles[size], className]
65
+ const classes = [
66
+ styles.emptyState,
67
+ styles[size],
68
+ variant === "outlined" ? styles.outlined : null,
69
+ className,
70
+ ]
60
71
  .filter(Boolean)
61
- .join(' ');
72
+ .join(" ");
62
73
 
63
74
  const contextValue: EmptyStateContextValue = { size };
64
75
 
65
76
  return (
66
77
  <EmptyStateContext.Provider value={contextValue}>
67
- <div {...htmlProps} className={classes}>{children}</div>
78
+ <div {...htmlProps} className={classes}>
79
+ {children}
80
+ </div>
68
81
  </EmptyStateContext.Provider>
69
82
  );
70
83
  }
71
84
 
72
85
  function EmptyStateIcon({ children, className, ...htmlProps }: EmptyStateIconProps) {
73
- const classes = [styles.icon, className].filter(Boolean).join(' ');
74
- return <div {...htmlProps} className={classes}>{children}</div>;
86
+ const classes = [styles.icon, className].filter(Boolean).join(" ");
87
+ return (
88
+ <div {...htmlProps} className={classes}>
89
+ {children}
90
+ </div>
91
+ );
75
92
  }
76
93
 
77
94
  function EmptyStateTitle({ children, className, ...htmlProps }: EmptyStateTitleProps) {
78
- const classes = [styles.title, className].filter(Boolean).join(' ');
79
- return <h3 {...htmlProps} className={classes}>{children}</h3>;
95
+ const classes = [styles.title, className].filter(Boolean).join(" ");
96
+ return (
97
+ <h3 {...htmlProps} className={classes}>
98
+ {children}
99
+ </h3>
100
+ );
80
101
  }
81
102
 
82
- function EmptyStateDescription({
83
- children,
84
- className,
85
- ...htmlProps
86
- }: EmptyStateDescriptionProps) {
87
- const classes = [styles.description, className].filter(Boolean).join(' ');
88
- return <p {...htmlProps} className={classes}>{children}</p>;
103
+ function EmptyStateDescription({ children, className, ...htmlProps }: EmptyStateDescriptionProps) {
104
+ const classes = [styles.description, className].filter(Boolean).join(" ");
105
+ return (
106
+ <p {...htmlProps} className={classes}>
107
+ {children}
108
+ </p>
109
+ );
89
110
  }
90
111
 
91
112
  function EmptyStateActions({ children, className, ...htmlProps }: EmptyStateActionsProps) {
92
- const classes = [styles.actions, className].filter(Boolean).join(' ');
93
- return <div {...htmlProps} className={classes}>{children}</div>;
113
+ const classes = [styles.actions, className].filter(Boolean).join(" ");
114
+ return (
115
+ <div {...htmlProps} className={classes}>
116
+ {children}
117
+ </div>
118
+ );
94
119
  }
95
120
 
96
121
  // ============================================
@@ -1,17 +1,9 @@
1
1
  {
2
2
  "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
3
  "name": "Field",
4
- "description": "Compositional form field wrapper providing validation, labels, descriptions, and error messages. Use for advanced form needs beyond baked-in Input/Textarea props.",
5
- "category": "forms",
6
- "tags": [
7
- "form",
8
- "field",
9
- "validation",
10
- "label",
11
- "error",
12
- "input",
13
- "accessible"
14
- ],
4
+ "description": "Composes labels, descriptions, validation, and errors around a form control.",
5
+ "category": "inputs",
6
+ "tags": ["form", "field", "validation", "label", "error", "input", "accessible"],
15
7
  "status": "stable",
16
8
  "sourcePath": "src/components/Field/index.tsx",
17
9
  "exportName": "Field",
@@ -54,11 +46,7 @@
54
46
  "type": "enum",
55
47
  "description": "When to trigger validation",
56
48
  "required": false,
57
- "values": [
58
- "onSubmit",
59
- "onBlur",
60
- "onChange"
61
- ]
49
+ "values": ["onSubmit", "onBlur", "onChange"]
62
50
  },
63
51
  "validationDebounceTime": {
64
52
  "type": "number",
@@ -68,42 +56,47 @@
68
56
  },
69
57
  "usage": {
70
58
  "when": [
71
- "You need granular validation with match-based error messages",
72
- "Custom form controls need accessible labels and descriptions",
73
- "Server-side errors need to be distributed to specific fields",
74
- "You need dirty/touched tracking or custom validation logic"
59
+ "One error message per failure reason, not one catch-all",
60
+ "A custom control needs a real label and description",
61
+ "Server errors must land on the field that caused them",
62
+ "You need dirty and touched tracking"
75
63
  ],
76
64
  "whenNot": [
77
- "Simple inputs with basic label and helper text (use Input with label prop)",
78
- "Standalone selects or textareas with built-in error display"
65
+ "A plain input with a label and helper text (use Input's own props)",
66
+ "A Select or Textarea whose built-in error display is enough"
79
67
  ],
80
68
  "guidelines": [
81
- "Always provide a Field.Label for accessibility",
82
- "Wrap any form control in Field.Control to connect it to the field context",
83
- "Use match prop on Field.Error for granular native validation messages",
84
- "Wrap in Form to enable server-side error distribution by field name"
69
+ "Every Field gets a Field.Label",
70
+ "Wrap the control in Field.Control so it joins the field context",
71
+ "Give each Field.Error a match so the message fits the failure",
72
+ "Nest inside Form to route server errors by field name"
85
73
  ],
86
74
  "accessibility": [
87
- "Label automatically linked to control via aria-labelledby",
88
- "Description linked via aria-describedby",
89
- "Error messages announced to screen readers",
90
- "Supports data-disabled and data-invalid attributes for styling"
75
+ "Label links to the control via aria-labelledby",
76
+ "Description links via aria-describedby",
77
+ "Errors are announced when they appear",
78
+ "data-disabled and data-invalid are available for styling"
91
79
  ]
92
80
  },
93
81
  "examples": [
94
82
  {
95
83
  "name": "Single field",
96
- "description": "A single field with label, control, and description",
84
+ "description": "Label, control and description wired together automatically.",
97
85
  "code": "<Field name=\"email\">\n <Field.Label>Email address</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Description>We will never share your email.</Field.Description>\n</Field>"
98
86
  },
99
87
  {
100
88
  "name": "Two-column layout",
101
- "description": "Fields arranged in a two-column grid",
89
+ "description": "Grid places two short fields side by side and one full-width.",
102
90
  "code": "<Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n <Field.Error match=\"typeMismatch\">Enter a valid email address</Field.Error>\n </Field>\n </Grid.Item>\n</Grid>"
103
91
  },
92
+ {
93
+ "name": "Invalid",
94
+ "description": "invalid marks the field failed and reveals Field.Error.",
95
+ "code": "<Field name=\"username\" invalid>\n <Field.Label>Username</Field.Label>\n <Field.Control>\n <Input value=\"ada lovelace\" error />\n </Field.Control>\n <Field.Error match>Usernames cannot contain spaces</Field.Error>\n</Field>"
96
+ },
104
97
  {
105
98
  "name": "Custom validation",
106
- "description": "Field with custom validate function",
99
+ "description": "validate runs on change and feeds Field.Error.",
107
100
  "code": "<Field\n name=\"age\"\n validate={(value) => {\n const num = Number(value);\n if (isNaN(num) || num < 18) return 'Must be 18 or older';\n return null;\n }}\n validationMode=\"onChange\"\n validationDebounceTime={500}\n>\n <Field.Label>Age</Field.Label>\n <Field.Control>\n <Input type=\"number\" placeholder=\"18\" />\n </Field.Control>\n <Field.Description>You must be at least 18 years old.</Field.Description>\n <Field.Error match=\"customError\" />\n</Field>"
108
101
  }
109
102
  ],
@@ -132,22 +125,11 @@
132
125
  "Field.Control: wraps any form component (Input, Textarea, etc.)",
133
126
  "Field.Error match: valueMissing|typeMismatch|customError|... - granular errors"
134
127
  ],
135
- "a11yRules": [
136
- "A11Y_FIELD_LABEL",
137
- "A11Y_FIELD_ERROR",
138
- "A11Y_FIELD_DESCRIPTION"
139
- ]
128
+ "a11yRules": ["A11Y_FIELD_LABEL", "A11Y_FIELD_ERROR", "A11Y_FIELD_DESCRIPTION"]
140
129
  },
141
130
  "ai": {
142
131
  "compositionPattern": "compound",
143
- "subComponents": [
144
- "Label",
145
- "Control",
146
- "Description",
147
- "Error",
148
- "Validity",
149
- "Required"
150
- ]
132
+ "subComponents": ["Label", "Control", "Description", "Error", "Validity", "Required"]
151
133
  },
152
134
  "provenance": {
153
135
  "source": "migrated",
@@ -140,7 +140,11 @@ function FieldValidity({ children }: FieldValidityProps) {
140
140
 
141
141
  function FieldRequired({ children = "*", className, ...htmlProps }: FieldRequiredProps) {
142
142
  return (
143
- <span {...htmlProps} className={[styles.required, className].filter(Boolean).join(" ")} aria-hidden>
143
+ <span
144
+ {...htmlProps}
145
+ className={[styles.required, className].filter(Boolean).join(" ")}
146
+ aria-hidden
147
+ >
144
148
  {children}
145
149
  </span>
146
150
  );
@@ -1,22 +1,13 @@
1
1
  {
2
2
  "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
3
  "name": "Fieldset",
4
- "description": "Groups related form fields with an accessible legend. Use to organize forms into logical sections.",
5
- "category": "forms",
6
- "tags": [
7
- "form",
8
- "fieldset",
9
- "group",
10
- "legend",
11
- "accessible"
12
- ],
4
+ "description": "Groups related form controls under an accessible legend.",
5
+ "category": "inputs",
6
+ "tags": ["form", "fieldset", "group", "legend", "accessible"],
13
7
  "status": "stable",
14
8
  "sourcePath": "src/components/Fieldset/index.tsx",
15
9
  "exportName": "Fieldset",
16
- "propsSummary": [
17
- "children: node (required)",
18
- "disabled: boolean"
19
- ],
10
+ "propsSummary": ["children: node (required)", "disabled: boolean"],
20
11
  "props": {
21
12
  "children": {
22
13
  "type": "node",
@@ -31,45 +22,42 @@
31
22
  },
32
23
  "usage": {
33
24
  "when": [
34
- "Grouping related fields in a form (e.g., address, personal info)",
35
- "Disabling a group of fields together",
36
- "Providing an accessible group label for screen readers"
37
- ],
38
- "whenNot": [
39
- "Generic visual grouping (use Card)",
40
- "Single field wrapping (use Field)"
25
+ "Fields that belong to one subject: address, billing, profile",
26
+ "Locking a whole section at once",
27
+ "Screen readers should hear the group name before each field"
41
28
  ],
29
+ "whenNot": ["Grouping for looks alone (use Card)", "Wrapping one control (use Field)"],
42
30
  "guidelines": [
43
- "Always include a Fieldset.Legend for accessibility",
44
- "Use disabled prop to disable all fields within the group",
45
- "Use Grid inside Fieldset for multi-column layouts",
46
- "Fieldset.Legend forwards DOM props for ids, aria attributes, and custom data hooks"
31
+ "Every Fieldset gets a Fieldset.Legend",
32
+ "disabled on the Fieldset locks every control inside it",
33
+ "Put a Grid inside for multi-column layouts",
34
+ "Fieldset.Legend forwards DOM props for ids, ARIA, and data hooks"
47
35
  ],
48
36
  "accessibility": [
49
- "Renders semantic fieldset element",
50
- "Legend provides accessible group label",
51
- "Disabled state propagates to all child fields"
37
+ "Renders a real fieldset element",
38
+ "Legend names the group",
39
+ "Disabled cascades to every child field"
52
40
  ]
53
41
  },
54
42
  "examples": [
55
43
  {
56
44
  "name": "Two-column layout",
57
- "description": "Fieldset with Grid for side-by-side fields",
45
+ "description": "A Grid inside the legend box pairs short fields on one row.",
58
46
  "code": "<Fieldset>\n <Fieldset.Legend>Personal Information</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"firstName\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lastName\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input placeholder=\"Doe\" />\n </Field.Control>\n </Field>\n <Grid.Item colSpan=\"full\">\n <Field name=\"email\">\n <Field.Label>Email</Field.Label>\n <Field.Control>\n <Input type=\"email\" placeholder=\"jane@example.com\" />\n </Field.Control>\n </Field>\n </Grid.Item>\n </Grid>\n</Fieldset>"
59
47
  },
60
48
  {
61
49
  "name": "Mixed controls",
62
- "description": "Fieldset with textarea, select, and checkbox",
50
+ "description": "Textarea, select and checkbox share one spacing rhythm.",
63
51
  "code": "<Fieldset>\n <Fieldset.Legend>Preferences</Fieldset.Legend>\n <Field name=\"bio\">\n <Field.Label>Bio</Field.Label>\n <Field.Control>\n <Textarea placeholder=\"Tell us about yourself\" rows={3} />\n </Field.Control>\n <Field.Description>Brief description for your profile.</Field.Description>\n </Field>\n <Field name=\"role\">\n <Field.Label>Role</Field.Label>\n <Field.Control>\n <Select placeholder=\"Select a role\">\n <Select.Trigger />\n <Select.Content>\n <Select.Item value=\"admin\">Admin</Select.Item>\n <Select.Item value=\"editor\">Editor</Select.Item>\n <Select.Item value=\"viewer\">Viewer</Select.Item>\n </Select.Content>\n </Select>\n </Field.Control>\n </Field>\n <Field name=\"newsletter\">\n <Field.Control>\n <Checkbox label=\"Subscribe to newsletter\" />\n </Field.Control>\n </Field>\n</Fieldset>"
64
52
  },
65
53
  {
66
54
  "name": "With Description",
67
- "description": "Fieldset with descriptive helper text below the legend",
55
+ "description": "One sentence under the legend covers the whole group.",
68
56
  "code": "<Fieldset>\n <Fieldset.Legend>Notification Settings</Fieldset.Legend>\n <Fieldset.Description>Choose how you want to be notified about updates.</Fieldset.Description>\n <Field name=\"emailNotif\">\n <Field.Control>\n <Checkbox label=\"Email notifications\" />\n </Field.Control>\n </Field>\n <Field name=\"smsNotif\">\n <Field.Control>\n <Checkbox label=\"SMS notifications\" />\n </Field.Control>\n </Field>\n</Fieldset>"
69
57
  },
70
58
  {
71
59
  "name": "Disabled",
72
- "description": "Disabled fieldset prevents interaction with all children",
60
+ "description": "One prop on the wrapper dims and locks every control inside.",
73
61
  "code": "<Fieldset disabled>\n <Fieldset.Legend>Locked Section</Fieldset.Legend>\n <Grid columns={2} gap=\"md\">\n <Field name=\"lockedFirst\">\n <Field.Label>First Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Jane\" />\n </Field.Control>\n </Field>\n <Field name=\"lockedLast\">\n <Field.Label>Last Name</Field.Label>\n <Field.Control>\n <Input defaultValue=\"Doe\" />\n </Field.Control>\n </Field>\n </Grid>\n <Field name=\"lockedCheck\">\n <Field.Control>\n <Checkbox label=\"Cannot toggle\" defaultChecked />\n </Field.Control>\n </Field>\n</Fieldset>"
74
62
  }
75
63
  ],
@@ -97,16 +85,11 @@
97
85
  "Fieldset.Legend forwards DOM props",
98
86
  "Fieldset.Description: helper text below the legend"
99
87
  ],
100
- "a11yRules": [
101
- "A11Y_FIELDSET_LEGEND"
102
- ]
88
+ "a11yRules": ["A11Y_FIELDSET_LEGEND"]
103
89
  },
104
90
  "ai": {
105
91
  "compositionPattern": "compound",
106
- "subComponents": [
107
- "Legend",
108
- "Description"
109
- ]
92
+ "subComponents": ["Legend", "Description"]
110
93
  },
111
94
  "provenance": {
112
95
  "source": "migrated",
@@ -1,6 +1,6 @@
1
- @use '../../tokens/variables' as *;
2
- @use '../../tokens/mixins' as *;
3
- @use '../../recipes/typography';
1
+ @use "../../tokens/variables" as *;
2
+ @use "../../tokens/mixins" as *;
3
+ @use "../../recipes/typography";
4
4
 
5
5
  .root {
6
6
  @include form-group-surface;
@@ -14,6 +14,13 @@
14
14
  &[data-disabled] {
15
15
  opacity: 0.5;
16
16
  }
17
+
18
+ // Legend and description carry their own block margins, so spacing is added
19
+ // only between the remaining rows. Without this, sibling controls that render
20
+ // a single line (a bare Checkbox or Switch inside a Field) sit flush together.
21
+ > :not(.legend):not(.description) + :not(.legend):not(.description) {
22
+ margin-block-start: var(--fui-raw-space-16, 16px);
23
+ }
17
24
  }
18
25
 
19
26
  .legend {