@usefragments/ui 1.0.2 → 1.2.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 (326) hide show
  1. package/README.md +16 -16
  2. package/dist/assets/fragments-wordmark.cjs +30 -0
  3. package/dist/assets/fragments-wordmark.d.ts +13 -0
  4. package/dist/assets/fragments-wordmark.d.ts.map +1 -0
  5. package/dist/assets/fragments-wordmark.js +30 -0
  6. package/dist/assets/ui.css +3234 -3116
  7. package/dist/components/Accordion/Accordion.module.scss.cjs +8 -8
  8. package/dist/components/Accordion/Accordion.module.scss.js +8 -8
  9. package/dist/components/Accordion/index.cjs +22 -10
  10. package/dist/components/Accordion/index.d.ts.map +1 -1
  11. package/dist/components/Accordion/index.js +22 -10
  12. package/dist/components/Alert/Alert.module.scss.cjs +13 -13
  13. package/dist/components/Alert/Alert.module.scss.js +13 -13
  14. package/dist/components/AppShell/AppShell.module.scss.cjs +22 -10
  15. package/dist/components/AppShell/AppShell.module.scss.js +22 -10
  16. package/dist/components/AppShell/index.cjs +1 -1
  17. package/dist/components/AppShell/index.js +1 -1
  18. package/dist/components/Avatar/Avatar.module.scss.cjs +13 -13
  19. package/dist/components/Avatar/Avatar.module.scss.js +13 -13
  20. package/dist/components/Badge/Badge.module.scss.cjs +16 -16
  21. package/dist/components/Badge/Badge.module.scss.js +16 -16
  22. package/dist/components/BentoGrid/BentoGrid.module.scss.cjs +14 -14
  23. package/dist/components/BentoGrid/BentoGrid.module.scss.js +14 -14
  24. package/dist/components/Box/Box.module.scss.cjs +152 -152
  25. package/dist/components/Box/Box.module.scss.js +152 -152
  26. package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.cjs +8 -8
  27. package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.js +8 -8
  28. package/dist/components/Button/Button.module.scss.cjs +13 -13
  29. package/dist/components/Button/Button.module.scss.js +13 -13
  30. package/dist/components/Card/Card.module.scss.cjs +17 -17
  31. package/dist/components/Card/Card.module.scss.js +17 -17
  32. package/dist/components/Card/index.d.ts +3 -3
  33. package/dist/components/Card/index.d.ts.map +1 -1
  34. package/dist/components/Chart/Chart.module.scss.cjs +15 -15
  35. package/dist/components/Chart/Chart.module.scss.js +15 -15
  36. package/dist/components/Checkbox/Checkbox.module.scss.cjs +11 -11
  37. package/dist/components/Checkbox/Checkbox.module.scss.js +11 -11
  38. package/dist/components/Chip/Chip.module.scss.cjs +15 -15
  39. package/dist/components/Chip/Chip.module.scss.js +15 -15
  40. package/dist/components/CodeBlock/CodeBlock.module.scss.cjs +21 -21
  41. package/dist/components/CodeBlock/CodeBlock.module.scss.js +21 -21
  42. package/dist/components/Collapsible/Collapsible.module.scss.cjs +10 -10
  43. package/dist/components/Collapsible/Collapsible.module.scss.js +10 -10
  44. package/dist/components/ColorPicker/ColorPicker.module.scss.cjs +14 -14
  45. package/dist/components/ColorPicker/ColorPicker.module.scss.js +14 -14
  46. package/dist/components/Combobox/Combobox.module.scss.cjs +23 -23
  47. package/dist/components/Combobox/Combobox.module.scss.js +23 -23
  48. package/dist/components/Combobox/index.cjs +106 -9
  49. package/dist/components/Combobox/index.d.ts.map +1 -1
  50. package/dist/components/Combobox/index.js +106 -9
  51. package/dist/components/Command/Command.module.scss.cjs +11 -11
  52. package/dist/components/Command/Command.module.scss.js +11 -11
  53. package/dist/components/ConversationList/ConversationList.module.scss.cjs +10 -10
  54. package/dist/components/ConversationList/ConversationList.module.scss.js +10 -10
  55. package/dist/components/DataTable/DataTable.module.scss.cjs +37 -34
  56. package/dist/components/DataTable/DataTable.module.scss.js +37 -34
  57. package/dist/components/DataTable/index.d.ts +3 -1
  58. package/dist/components/DataTable/index.d.ts.map +1 -1
  59. package/dist/components/DatePicker/DatePicker.module.scss.cjs +33 -33
  60. package/dist/components/DatePicker/DatePicker.module.scss.js +33 -33
  61. package/dist/components/DatePicker/index.d.ts +1 -1
  62. package/dist/components/DatePicker/index.d.ts.map +1 -1
  63. package/dist/components/Dialog/Dialog.module.scss.cjs +14 -14
  64. package/dist/components/Dialog/Dialog.module.scss.js +14 -14
  65. package/dist/components/Drawer/Drawer.module.scss.cjs +28 -28
  66. package/dist/components/Drawer/Drawer.module.scss.js +28 -28
  67. package/dist/components/Drawer/index.cjs +20 -3
  68. package/dist/components/Drawer/index.d.ts.map +1 -1
  69. package/dist/components/Drawer/index.js +20 -3
  70. package/dist/components/Editor/Editor.module.scss.cjs +17 -17
  71. package/dist/components/Editor/Editor.module.scss.js +17 -17
  72. package/dist/components/EmptyState/EmptyState.module.scss.cjs +8 -8
  73. package/dist/components/EmptyState/EmptyState.module.scss.js +8 -8
  74. package/dist/components/Field/Field.module.scss.cjs +4 -4
  75. package/dist/components/Field/Field.module.scss.js +4 -4
  76. package/dist/components/Field/index.cjs +10 -9
  77. package/dist/components/Field/index.d.ts +7 -7
  78. package/dist/components/Field/index.d.ts.map +1 -1
  79. package/dist/components/Field/index.js +10 -9
  80. package/dist/components/Fieldset/Fieldset.module.scss.cjs +3 -3
  81. package/dist/components/Fieldset/Fieldset.module.scss.js +3 -3
  82. package/dist/components/Header/Header.module.scss.cjs +44 -29
  83. package/dist/components/Header/Header.module.scss.js +44 -29
  84. package/dist/components/Header/index.cjs +56 -3
  85. package/dist/components/Header/index.d.ts +25 -3
  86. package/dist/components/Header/index.d.ts.map +1 -1
  87. package/dist/components/Header/index.js +56 -3
  88. package/dist/components/Icon/Icon.module.scss.cjs +8 -8
  89. package/dist/components/Icon/Icon.module.scss.js +8 -8
  90. package/dist/components/IconButton/IconButton.module.scss.cjs +8 -8
  91. package/dist/components/IconButton/IconButton.module.scss.js +8 -8
  92. package/dist/components/Image/Image.module.scss.cjs +27 -27
  93. package/dist/components/Image/Image.module.scss.js +27 -27
  94. package/dist/components/Input/Input.module.scss.cjs +19 -19
  95. package/dist/components/Input/Input.module.scss.js +19 -19
  96. package/dist/components/Link/Link.module.scss.cjs +10 -10
  97. package/dist/components/Link/Link.module.scss.js +10 -10
  98. package/dist/components/List/List.module.scss.cjs +19 -19
  99. package/dist/components/List/List.module.scss.js +19 -19
  100. package/dist/components/Listbox/Listbox.module.scss.cjs +8 -8
  101. package/dist/components/Listbox/Listbox.module.scss.js +8 -8
  102. package/dist/components/Loading/Loading.module.scss.cjs +30 -30
  103. package/dist/components/Loading/Loading.module.scss.js +30 -30
  104. package/dist/components/Main/Main.module.scss.cjs +26 -0
  105. package/dist/components/Main/Main.module.scss.js +26 -0
  106. package/dist/components/Main/index.cjs +128 -0
  107. package/dist/components/Main/index.d.ts +22 -0
  108. package/dist/components/Main/index.d.ts.map +1 -0
  109. package/dist/components/Main/index.js +111 -0
  110. package/dist/components/Markdown/Markdown.module.scss.cjs +1 -1
  111. package/dist/components/Markdown/Markdown.module.scss.js +1 -1
  112. package/dist/components/Menu/Menu.module.scss.cjs +14 -14
  113. package/dist/components/Menu/Menu.module.scss.js +14 -14
  114. package/dist/components/Message/Message.module.scss.cjs +18 -18
  115. package/dist/components/Message/Message.module.scss.js +18 -18
  116. package/dist/components/NavigationMenu/NavigationMenu.module.scss.cjs +28 -28
  117. package/dist/components/NavigationMenu/NavigationMenu.module.scss.js +28 -28
  118. package/dist/components/Pagination/Pagination.module.scss.cjs +7 -7
  119. package/dist/components/Pagination/Pagination.module.scss.js +7 -7
  120. package/dist/components/Popover/Popover.module.scss.cjs +10 -10
  121. package/dist/components/Popover/Popover.module.scss.js +10 -10
  122. package/dist/components/Popover/index.cjs +27 -2
  123. package/dist/components/Popover/index.d.ts.map +1 -1
  124. package/dist/components/Popover/index.js +27 -2
  125. package/dist/components/Progress/Progress.module.scss.cjs +25 -25
  126. package/dist/components/Progress/Progress.module.scss.js +25 -25
  127. package/dist/components/Prompt/Prompt.module.scss.cjs +18 -18
  128. package/dist/components/Prompt/Prompt.module.scss.js +18 -18
  129. package/dist/components/RadioGroup/RadioGroup.module.scss.cjs +17 -17
  130. package/dist/components/RadioGroup/RadioGroup.module.scss.js +17 -17
  131. package/dist/components/RadioGroup/index.cjs +2 -0
  132. package/dist/components/RadioGroup/index.d.ts +2 -0
  133. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  134. package/dist/components/RadioGroup/index.js +2 -0
  135. package/dist/components/ScrollArea/ScrollArea.module.scss.cjs +10 -10
  136. package/dist/components/ScrollArea/ScrollArea.module.scss.js +10 -10
  137. package/dist/components/Select/Select.module.scss.cjs +17 -17
  138. package/dist/components/Select/Select.module.scss.js +17 -17
  139. package/dist/components/Separator/Separator.module.scss.cjs +10 -10
  140. package/dist/components/Separator/Separator.module.scss.js +10 -10
  141. package/dist/components/Sidebar/Sidebar.module.scss.cjs +42 -42
  142. package/dist/components/Sidebar/Sidebar.module.scss.js +42 -42
  143. package/dist/components/Skeleton/Skeleton.module.scss.cjs +38 -38
  144. package/dist/components/Skeleton/Skeleton.module.scss.js +38 -38
  145. package/dist/components/Slider/Slider.module.scss.cjs +12 -12
  146. package/dist/components/Slider/Slider.module.scss.js +12 -12
  147. package/dist/components/Table/Table.module.scss.cjs +19 -19
  148. package/dist/components/Table/Table.module.scss.js +19 -19
  149. package/dist/components/TableOfContents/TableOfContents.module.scss.cjs +15 -15
  150. package/dist/components/TableOfContents/TableOfContents.module.scss.js +15 -15
  151. package/dist/components/TableOfContents/index.cjs +22 -42
  152. package/dist/components/TableOfContents/index.d.ts +3 -3
  153. package/dist/components/TableOfContents/index.d.ts.map +1 -1
  154. package/dist/components/TableOfContents/index.js +22 -42
  155. package/dist/components/Tabs/Tabs.module.scss.cjs +12 -12
  156. package/dist/components/Tabs/Tabs.module.scss.js +12 -12
  157. package/dist/components/Text/Text.module.scss.cjs +51 -51
  158. package/dist/components/Text/Text.module.scss.js +51 -51
  159. package/dist/components/Textarea/Textarea.module.scss.cjs +23 -23
  160. package/dist/components/Textarea/Textarea.module.scss.js +23 -23
  161. package/dist/components/Theme/ThemeToggle.module.scss.cjs +6 -6
  162. package/dist/components/Theme/ThemeToggle.module.scss.js +6 -6
  163. package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.cjs +13 -13
  164. package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.js +13 -13
  165. package/dist/components/Toast/Toast.module.scss.cjs +21 -21
  166. package/dist/components/Toast/Toast.module.scss.js +21 -21
  167. package/dist/components/Toggle/Toggle.module.scss.cjs +13 -13
  168. package/dist/components/Toggle/Toggle.module.scss.js +13 -13
  169. package/dist/components/ToggleGroup/ToggleGroup.module.scss.cjs +17 -17
  170. package/dist/components/ToggleGroup/ToggleGroup.module.scss.js +17 -17
  171. package/dist/components/Tooltip/Tooltip.module.scss.cjs +3 -3
  172. package/dist/components/Tooltip/Tooltip.module.scss.js +3 -3
  173. package/dist/data-table.cjs +58 -41
  174. package/dist/data-table.js +59 -41
  175. package/dist/datepicker.cjs +32 -72
  176. package/dist/datepicker.js +32 -72
  177. package/dist/index.cjs +89 -85
  178. package/dist/index.d.ts +2 -0
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +4 -0
  181. package/fragments.json +1 -1
  182. package/package.json +9 -8
  183. package/src/assets/fragments-wordmark.tsx +47 -0
  184. package/src/components/Accordion/index.tsx +13 -3
  185. package/src/components/Alert/Alert.module.scss +15 -2
  186. package/src/components/AppShell/AppShell.module.scss +73 -15
  187. package/src/components/AppShell/index.tsx +1 -1
  188. package/src/components/Button/Button.module.scss +19 -20
  189. package/src/components/Card/Card.module.scss +3 -3
  190. package/src/components/Card/index.tsx +3 -3
  191. package/src/components/Checkbox/Checkbox.contract.json +5 -24
  192. package/src/components/Checkbox/Checkbox.module.scss +4 -2
  193. package/src/components/Chip/Chip.contract.json +11 -28
  194. package/src/components/Chip/Chip.module.scss +21 -45
  195. package/src/components/CodeBlock/CodeBlock.module.scss +2 -7
  196. package/src/components/Combobox/Combobox.contract.json +6 -24
  197. package/src/components/Combobox/Combobox.module.scss +3 -2
  198. package/src/components/Combobox/index.tsx +132 -6
  199. package/src/components/DataTable/DataTable.contract.json +16 -23
  200. package/src/components/DataTable/DataTable.module.scss +31 -8
  201. package/src/components/DataTable/index.tsx +25 -4
  202. package/src/components/DatePicker/index.tsx +32 -84
  203. package/src/components/Drawer/index.tsx +38 -12
  204. package/src/components/Field/index.tsx +35 -35
  205. package/src/components/Header/Header.contract.json +41 -1
  206. package/src/components/Header/Header.module.scss +40 -0
  207. package/src/components/Header/index.tsx +88 -2
  208. package/src/components/IconButton/IconButton.contract.json +120 -0
  209. package/src/components/Listbox/Listbox.module.scss +5 -4
  210. package/src/components/Main/Main.contract.json +79 -0
  211. package/src/components/Main/Main.module.scss +31 -0
  212. package/src/components/Main/index.tsx +124 -0
  213. package/src/components/Menu/Menu.module.scss +8 -10
  214. package/src/components/Popover/index.tsx +34 -2
  215. package/src/components/RadioGroup/RadioGroup.contract.json +13 -27
  216. package/src/components/RadioGroup/index.tsx +4 -0
  217. package/src/components/Select/Select.module.scss +13 -12
  218. package/src/components/Table/Table.module.scss +22 -5
  219. package/src/components/TableOfContents/TableOfContents.contract.json +6 -16
  220. package/src/components/TableOfContents/TableOfContents.module.scss +20 -14
  221. package/src/components/TableOfContents/index.tsx +27 -38
  222. package/src/components/Toast/Toast.module.scss +15 -2
  223. package/src/components/ToggleGroup/ToggleGroup.module.scss +4 -1
  224. package/src/index.ts +4 -0
  225. package/src/styles/globals.scss +13 -10
  226. package/src/tokens/_component-properties.scss +26 -0
  227. package/src/tokens/_computed.scss +22 -4
  228. package/src/tokens/_derive.scss +55 -6
  229. package/src/tokens/_palettes.scss +24 -0
  230. package/src/tokens/_seeds.scss +20 -12
  231. package/src/tokens/_variables.scss +110 -63
  232. package/dist/components/Cloud/DashboardLayoutPrototypes.shared.d.ts +0 -33
  233. package/dist/components/Cloud/DashboardLayoutPrototypes.shared.d.ts.map +0 -1
  234. package/dist/components/Cloud/DashboardLayoutPrototypes.shell.d.ts +0 -11
  235. package/dist/components/Cloud/DashboardLayoutPrototypes.shell.d.ts.map +0 -1
  236. package/dist/components/Cloud/PullRequestsPrototypes.content.d.ts +0 -5
  237. package/dist/components/Cloud/PullRequestsPrototypes.content.d.ts.map +0 -1
  238. package/dist/components/Cloud/PullRequestsPrototypes.detail-panels.d.ts +0 -4
  239. package/dist/components/Cloud/PullRequestsPrototypes.detail-panels.d.ts.map +0 -1
  240. package/dist/components/Cloud/PullRequestsPrototypes.detail.d.ts +0 -3
  241. package/dist/components/Cloud/PullRequestsPrototypes.detail.d.ts.map +0 -1
  242. package/dist/components/Cloud/PullRequestsPrototypes.id-data.d.ts +0 -86
  243. package/dist/components/Cloud/PullRequestsPrototypes.id-data.d.ts.map +0 -1
  244. package/dist/components/Cloud/PullRequestsPrototypes.id-page.d.ts +0 -2
  245. package/dist/components/Cloud/PullRequestsPrototypes.id-page.d.ts.map +0 -1
  246. package/src/components/Accordion/Accordion.stories.tsx +0 -106
  247. package/src/components/Alert/Alert.stories.tsx +0 -119
  248. package/src/components/AppShell/AppShell.stories.tsx +0 -156
  249. package/src/components/Avatar/Avatar.stories.tsx +0 -74
  250. package/src/components/Badge/Badge.stories.tsx +0 -92
  251. package/src/components/BentoGrid/BentoGrid.stories.tsx +0 -98
  252. package/src/components/Box/Box.stories.tsx +0 -150
  253. package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +0 -87
  254. package/src/components/Button/Button.stories.tsx +0 -103
  255. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -97
  256. package/src/components/Card/Card.stories.tsx +0 -144
  257. package/src/components/Chart/Chart.stories.tsx +0 -119
  258. package/src/components/Checkbox/Checkbox.stories.tsx +0 -68
  259. package/src/components/Chip/Chip.stories.tsx +0 -70
  260. package/src/components/Cloud/CloudGovernanceShell.module.scss +0 -88
  261. package/src/components/Cloud/CloudGovernanceShell.stories.tsx +0 -446
  262. package/src/components/Cloud/ControlSizing.module.scss +0 -49
  263. package/src/components/Cloud/ControlSizing.stories.tsx +0 -238
  264. package/src/components/Cloud/DashboardLayoutPrototypes.module.scss +0 -462
  265. package/src/components/Cloud/DashboardLayoutPrototypes.shared.tsx +0 -375
  266. package/src/components/Cloud/DashboardLayoutPrototypes.shell.tsx +0 -147
  267. package/src/components/Cloud/DashboardLayoutPrototypes.stories.tsx +0 -328
  268. package/src/components/Cloud/PullRequestsPrototypes.content.tsx +0 -283
  269. package/src/components/Cloud/PullRequestsPrototypes.detail-panels.tsx +0 -381
  270. package/src/components/Cloud/PullRequestsPrototypes.detail.tsx +0 -204
  271. package/src/components/Cloud/PullRequestsPrototypes.id-data.ts +0 -395
  272. package/src/components/Cloud/PullRequestsPrototypes.id-page.tsx +0 -349
  273. package/src/components/Cloud/PullRequestsPrototypes.stories.tsx +0 -81
  274. package/src/components/CodeBlock/CodeBlock.stories.tsx +0 -147
  275. package/src/components/Collapsible/Collapsible.stories.tsx +0 -94
  276. package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -74
  277. package/src/components/Combobox/Combobox.stories.tsx +0 -133
  278. package/src/components/Command/Command.stories.tsx +0 -102
  279. package/src/components/ConversationList/ConversationList.stories.tsx +0 -93
  280. package/src/components/DataTable/DataTable.stories.tsx +0 -129
  281. package/src/components/DatePicker/DatePicker.stories.tsx +0 -129
  282. package/src/components/Dialog/Dialog.stories.tsx +0 -154
  283. package/src/components/Drawer/Drawer.stories.tsx +0 -144
  284. package/src/components/Editor/Editor.stories.tsx +0 -99
  285. package/src/components/EmptyState/EmptyState.stories.tsx +0 -97
  286. package/src/components/Field/Field.stories.tsx +0 -109
  287. package/src/components/Fieldset/Fieldset.stories.tsx +0 -116
  288. package/src/components/Form/Form.stories.tsx +0 -142
  289. package/src/components/Grid/Grid.stories.tsx +0 -125
  290. package/src/components/Header/Header.stories.tsx +0 -133
  291. package/src/components/Icon/Icon.stories.tsx +0 -80
  292. package/src/components/IconButton/IconButton.stories.tsx +0 -78
  293. package/src/components/Image/Image.stories.tsx +0 -109
  294. package/src/components/Input/Input.stories.tsx +0 -104
  295. package/src/components/Link/Link.stories.tsx +0 -67
  296. package/src/components/List/List.stories.tsx +0 -95
  297. package/src/components/Listbox/Listbox.stories.tsx +0 -81
  298. package/src/components/Loading/Loading.stories.tsx +0 -69
  299. package/src/components/Markdown/Markdown.stories.tsx +0 -75
  300. package/src/components/Menu/Menu.stories.tsx +0 -113
  301. package/src/components/Message/Message.stories.tsx +0 -85
  302. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -161
  303. package/src/components/Pagination/Pagination.stories.tsx +0 -81
  304. package/src/components/Popover/Popover.stories.tsx +0 -152
  305. package/src/components/Progress/Progress.stories.tsx +0 -64
  306. package/src/components/Prompt/Prompt.stories.tsx +0 -93
  307. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -107
  308. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -97
  309. package/src/components/Select/Select.stories.tsx +0 -127
  310. package/src/components/Separator/Separator.stories.tsx +0 -84
  311. package/src/components/Sidebar/Sidebar.stories.tsx +0 -122
  312. package/src/components/Skeleton/Skeleton.stories.tsx +0 -80
  313. package/src/components/Slider/Slider.stories.tsx +0 -73
  314. package/src/components/Stack/Stack.stories.tsx +0 -73
  315. package/src/components/Switch/Switch.stories.tsx +0 -59
  316. package/src/components/Table/Table.stories.tsx +0 -219
  317. package/src/components/TableOfContents/TableOfContents.stories.tsx +0 -120
  318. package/src/components/Tabs/Tabs.stories.tsx +0 -136
  319. package/src/components/Text/Text.stories.tsx +0 -133
  320. package/src/components/Textarea/Textarea.stories.tsx +0 -107
  321. package/src/components/Theme/Theme.stories.tsx +0 -95
  322. package/src/components/ThinkingIndicator/ThinkingIndicator.stories.tsx +0 -85
  323. package/src/components/Toast/Toast.stories.tsx +0 -91
  324. package/src/components/ToggleGroup/ToggleGroup.stories.tsx +0 -114
  325. package/src/components/Tooltip/Tooltip.stories.tsx +0 -95
  326. package/src/components/VisuallyHidden/VisuallyHidden.stories.tsx +0 -78
@@ -25,12 +25,26 @@ export type HeaderIconSlot =
25
25
 
26
26
  export type HeaderIcons = Partial<Record<HeaderIconRenderState['slot'], HeaderIconSlot>>;
27
27
 
28
+ export type HeaderNavAlign = 'start' | 'center';
29
+ export type HeaderContainer = 'full' | 'page';
30
+
31
+ export interface HeaderElevatedOnScrollOptions {
32
+ /** Scroll offset before the elevated surface is applied */
33
+ threshold?: number;
34
+ }
35
+
28
36
  export interface HeaderProps extends React.HTMLAttributes<HTMLElement> {
29
37
  children: React.ReactNode;
30
38
  /** Header height (default: '56px') */
31
39
  height?: string;
32
40
  /** Position behavior */
33
41
  position?: 'static' | 'fixed' | 'sticky';
42
+ /** Apply the elevated header surface after scroll */
43
+ elevatedOnScroll?: boolean | HeaderElevatedOnScrollOptions;
44
+ /** Navigation alignment inside the header */
45
+ navAlign?: HeaderNavAlign;
46
+ /** Header content width */
47
+ container?: HeaderContainer;
34
48
  /** Optional icon overrides for internal header controls (mobile trigger + nav menu chevron) */
35
49
  icons?: HeaderIcons;
36
50
  }
@@ -39,6 +53,8 @@ export interface HeaderBrandProps extends React.HTMLAttributes<HTMLElement> {
39
53
  children: React.ReactNode;
40
54
  /** Link destination */
41
55
  href?: string;
56
+ /** Render as child element (polymorphic) */
57
+ asChild?: boolean;
42
58
  }
43
59
 
44
60
  export interface HeaderNavProps extends React.HTMLAttributes<HTMLElement> {
@@ -101,6 +117,10 @@ export interface HeaderMobileNavProps {
101
117
  className?: string;
102
118
  }
103
119
 
120
+ export interface HeaderMobileNavActionsProps extends React.HTMLAttributes<HTMLDivElement> {
121
+ children: React.ReactNode;
122
+ }
123
+
104
124
  // ============================================
105
125
  // Internal Context
106
126
  // ============================================
@@ -175,17 +195,37 @@ function HeaderRoot({
175
195
  children,
176
196
  height = '56px',
177
197
  position = 'static',
198
+ elevatedOnScroll = false,
199
+ navAlign = 'start',
200
+ container = 'full',
178
201
  icons,
179
202
  className,
180
203
  style: styleProp,
181
204
  ...htmlProps
182
205
  }: HeaderProps) {
183
206
  const [mobileOpen, setMobileOpen] = React.useState(false);
207
+ const [scrolled, setScrolled] = React.useState(false);
208
+ const shouldElevateOnScroll = Boolean(elevatedOnScroll);
209
+ const scrollThreshold =
210
+ typeof elevatedOnScroll === 'object' ? (elevatedOnScroll.threshold ?? 16) : 16;
211
+
212
+ React.useEffect(() => {
213
+ if (!shouldElevateOnScroll) return;
214
+
215
+ const updateScrolled = () => setScrolled(window.scrollY > scrollThreshold);
216
+ updateScrolled();
217
+ window.addEventListener('scroll', updateScrolled, { passive: true });
218
+ return () => window.removeEventListener('scroll', updateScrolled);
219
+ }, [scrollThreshold, shouldElevateOnScroll]);
184
220
 
185
221
  const classes = [
186
222
  styles.header,
187
223
  position === 'fixed' && styles.fixed,
188
224
  position === 'sticky' && styles.sticky,
225
+ shouldElevateOnScroll && styles.elevatedOnScroll,
226
+ shouldElevateOnScroll && scrolled && styles.scrolled,
227
+ navAlign === 'center' && styles.navCentered,
228
+ container === 'page' && styles.containerPage,
189
229
  className,
190
230
  ].filter(Boolean).join(' ');
191
231
 
@@ -202,7 +242,13 @@ function HeaderRoot({
202
242
  return (
203
243
  <HeaderContext.Provider value={contextValue}>
204
244
  <HeaderIconContext.Provider value={icons}>
205
- <header {...htmlProps} className={classes} style={style} data-position={position}>
245
+ <header
246
+ {...htmlProps}
247
+ className={classes}
248
+ style={style}
249
+ data-position={position}
250
+ data-scrolled={shouldElevateOnScroll ? scrolled : undefined}
251
+ >
206
252
  <div className={styles.container}>
207
253
  {children}
208
254
  </div>
@@ -215,9 +261,30 @@ function HeaderRoot({
215
261
  /**
216
262
  * Header.Brand - Logo/brand slot
217
263
  */
218
- function HeaderBrand({ children, href, className, ...htmlProps }: HeaderBrandProps) {
264
+ function HeaderBrand({
265
+ children,
266
+ href,
267
+ asChild = false,
268
+ className,
269
+ ...htmlProps
270
+ }: HeaderBrandProps) {
219
271
  const classes = [styles.brand, className].filter(Boolean).join(' ');
220
272
 
273
+ if (asChild && React.isValidElement(children)) {
274
+ const childProps = children.props as {
275
+ className?: string;
276
+ onClick?: React.MouseEventHandler<HTMLElement>;
277
+ };
278
+ const { onClick, ...restHtmlProps } = htmlProps as React.HTMLAttributes<HTMLElement>;
279
+
280
+ return React.cloneElement(children, {
281
+ ...restHtmlProps,
282
+ ...(href ? { href } : {}),
283
+ className: [classes, childProps.className].filter(Boolean).join(' '),
284
+ onClick: onClick ? composeEventHandlers(childProps.onClick, onClick) : childProps.onClick,
285
+ } as React.HTMLAttributes<HTMLElement>);
286
+ }
287
+
221
288
  if (href) {
222
289
  return (
223
290
  <a {...htmlProps} href={href} className={classes}>
@@ -604,6 +671,23 @@ function HeaderMobileNavLink({
604
671
  );
605
672
  }
606
673
 
674
+ /**
675
+ * Header.MobileNavActions - Action row inside the mobile drawer
676
+ */
677
+ function HeaderMobileNavActions({
678
+ children,
679
+ className,
680
+ ...htmlProps
681
+ }: HeaderMobileNavActionsProps) {
682
+ const classes = [styles.mobileNavActions, className].filter(Boolean).join(' ');
683
+
684
+ return (
685
+ <div {...htmlProps} className={classes}>
686
+ {children}
687
+ </div>
688
+ );
689
+ }
690
+
607
691
  /**
608
692
  * Header.SkipLink - Skip to main content link (accessibility)
609
693
  */
@@ -641,6 +725,7 @@ export const Header = Object.assign(HeaderRoot, {
641
725
  SkipLink: HeaderSkipLink,
642
726
  MobileNav: HeaderMobileNav,
643
727
  MobileNavLink: HeaderMobileNavLink,
728
+ MobileNavActions: HeaderMobileNavActions,
644
729
  });
645
730
 
646
731
  export {
@@ -657,4 +742,5 @@ export {
657
742
  HeaderSkipLink,
658
743
  HeaderMobileNav,
659
744
  HeaderMobileNavLink,
745
+ HeaderMobileNavActions,
660
746
  };
@@ -0,0 +1,120 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "IconButton",
4
+ "description": "Compact square button for icon-only actions in dense toolbars, top bars, and row controls.",
5
+ "category": "forms",
6
+ "tags": ["action", "button", "icon", "toolbar", "interactive"],
7
+ "status": "stable",
8
+ "sourcePath": "src/components/IconButton/index.tsx",
9
+ "exportName": "IconButton",
10
+ "propsSummary": [
11
+ "children: node (required)",
12
+ "variant: ghost|subtle|outlined (default: ghost)",
13
+ "size: sm|md|lg (default: md)",
14
+ "pressed: boolean",
15
+ "aria-label: string",
16
+ "aria-labelledby: string"
17
+ ],
18
+ "props": {
19
+ "children": {
20
+ "type": "node",
21
+ "description": "Icon element rendered inside the button",
22
+ "required": true
23
+ },
24
+ "variant": {
25
+ "type": "enum",
26
+ "description": "Visual treatment for the icon-only action",
27
+ "default": "ghost",
28
+ "required": false,
29
+ "values": ["ghost", "subtle", "outlined"]
30
+ },
31
+ "size": {
32
+ "type": "enum",
33
+ "description": "Control size aligned with adjacent fields and toolbar actions",
34
+ "default": "md",
35
+ "required": false,
36
+ "values": ["sm", "md", "lg"]
37
+ },
38
+ "pressed": {
39
+ "type": "boolean",
40
+ "description": "Marks a toggle-style action as pressed and sets aria-pressed",
41
+ "required": false
42
+ },
43
+ "aria-label": {
44
+ "type": "string",
45
+ "description": "Accessible action name when no labelled-by relationship is available",
46
+ "required": false
47
+ },
48
+ "aria-labelledby": {
49
+ "type": "string",
50
+ "description": "ID reference for an external accessible action label",
51
+ "required": false
52
+ }
53
+ },
54
+ "usage": {
55
+ "when": [
56
+ "Compact icon-only actions in toolbars or top bars",
57
+ "Row actions where a text button would be too wide",
58
+ "Toggle-style icon actions with a visible pressed state"
59
+ ],
60
+ "whenNot": [
61
+ "The action needs a visible text label (use Button)",
62
+ "The control changes a persistent boolean setting (use Switch)",
63
+ "The icon is decorative and not interactive (use Icon)"
64
+ ],
65
+ "guidelines": [
66
+ "Always provide aria-label or aria-labelledby",
67
+ "Use ghost for ordinary toolbar actions and outlined when more separation is needed",
68
+ "Use pressed only when the button represents a persistent toggle state"
69
+ ],
70
+ "accessibility": [
71
+ "Every icon-only button must have an accessible name",
72
+ "The accessible name should describe the action, not the icon",
73
+ "Pressed state must be exposed with aria-pressed"
74
+ ]
75
+ },
76
+ "examples": [
77
+ {
78
+ "name": "Toolbar action",
79
+ "description": "A named icon-only toolbar action",
80
+ "code": "<IconButton aria-label=\"Add item\">\n <PlusIcon aria-hidden />\n</IconButton>"
81
+ },
82
+ {
83
+ "name": "Pressed state",
84
+ "description": "A toggle-style action with its state exposed",
85
+ "code": "import { PushPin as PinIcon } from '@phosphor-icons/react';\n\n<IconButton aria-label=\"Pin item\" pressed>\n <PinIcon aria-hidden />\n</IconButton>"
86
+ }
87
+ ],
88
+ "relations": [
89
+ {
90
+ "component": "Button",
91
+ "relationship": "sibling",
92
+ "note": "Use Button when the action should have a visible text label or broader layout variants"
93
+ },
94
+ {
95
+ "component": "Icon",
96
+ "relationship": "complementary",
97
+ "note": "Icon supplies the visual glyph rendered inside IconButton"
98
+ }
99
+ ],
100
+ "contract": {
101
+ "propsSummary": [
102
+ "children: ReactNode - icon element (required)",
103
+ "variant: ghost|subtle|outlined - visual treatment",
104
+ "size: sm|md|lg - square control size",
105
+ "pressed: boolean - toggle state exposed with aria-pressed",
106
+ "aria-label or aria-labelledby - required accessible name"
107
+ ],
108
+ "a11yRules": ["A11Y_BTN_LABEL", "A11Y_BTN_FOCUS", "A11Y_TARGET_SIZE_MIN"]
109
+ },
110
+ "ai": {
111
+ "compositionPattern": "compound",
112
+ "subComponents": ["Root"]
113
+ },
114
+ "provenance": {
115
+ "source": "migrated",
116
+ "verified": false,
117
+ "frameworkSupport": "native",
118
+ "extractedAt": "2026-07-14T00:00:00.000Z"
119
+ }
120
+ }
@@ -1,5 +1,5 @@
1
- @use '../../tokens/variables' as *;
2
- @use '../../tokens/mixins' as *;
1
+ @use "../../tokens/variables" as *;
2
+ @use "../../tokens/mixins" as *;
3
3
 
4
4
  // ============================================
5
5
  // Listbox container
@@ -10,7 +10,7 @@
10
10
  @include popup-container;
11
11
 
12
12
  // Item height derived from text-base font + vertical padding (matches Select/Combobox)
13
- --_item-h: calc(
13
+ --_listbox-item-h: calc(
14
14
  var(--fui-font-size-sm, #{$fui-font-size-sm}) *
15
15
  var(--fui-line-height-normal, #{$fui-line-height-normal}) +
16
16
  var(--fui-space-2, #{$fui-space-2}) * 2
@@ -19,7 +19,8 @@
19
19
  min-width: 12rem;
20
20
  // Show N items + half-peek scroll hint (default 4.5 items)
21
21
  max-height: calc(
22
- var(--_item-h) * var(--fui-select-max-items, 4.5) + var(--fui-space-1, #{$fui-space-1}) * 2
22
+ var(--_listbox-item-h) * var(--fui-select-max-items, 4.5) +
23
+ var(--fui-space-1, #{$fui-space-1}) * 2
23
24
  );
24
25
  overflow-y: auto;
25
26
  border-color: var(--fui-form-group-border, $fui-border);
@@ -0,0 +1,79 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Main",
4
+ "description": "Canonical page composition owning gutter, measure, and vertical rhythm.",
5
+ "category": "layout",
6
+ "tags": ["main", "page", "layout", "compound"],
7
+ "status": "stable",
8
+ "sourcePath": "src/components/Main/index.tsx",
9
+ "exportName": "Main",
10
+ "propsSummary": [
11
+ "children: node (required)",
12
+ "measure: full|narrow (default: full)",
13
+ "as: semantic element (default: main)"
14
+ ],
15
+ "props": {
16
+ "children": {
17
+ "type": "node",
18
+ "description": "Page regions composed from Main.Header, Main.Description, Main.Content, and Main.Footer",
19
+ "required": true
20
+ },
21
+ "measure": {
22
+ "type": "enum",
23
+ "description": "Maximum width applied to the page composition",
24
+ "default": "full",
25
+ "required": false,
26
+ "values": ["full", "narrow"]
27
+ },
28
+ "as": {
29
+ "type": "enum",
30
+ "description": "Semantic HTML element rendered by the root",
31
+ "default": "main",
32
+ "required": false,
33
+ "values": [
34
+ "div",
35
+ "section",
36
+ "nav",
37
+ "article",
38
+ "aside",
39
+ "header",
40
+ "footer",
41
+ "main",
42
+ "ul",
43
+ "ol"
44
+ ]
45
+ }
46
+ },
47
+ "usage": {
48
+ "when": ["Composing a page header, description, content, and footer"],
49
+ "whenNot": ["Application shell navigation (use AppShell)"],
50
+ "guidelines": [
51
+ "Use one Main gutter owner per page",
52
+ "Compose page regions with Main.Header, Main.Description, Main.Content, and Main.Footer"
53
+ ],
54
+ "accessibility": [
55
+ "Use the default main element unless an existing shell already owns the main landmark"
56
+ ]
57
+ },
58
+ "examples": [
59
+ {
60
+ "name": "Full Measure",
61
+ "description": "Page composition that uses the full available canvas",
62
+ "code": "<Main measure=\"full\">\n <Main.Header>Page statement</Main.Header>\n <Main.Description>Supporting page context.</Main.Description>\n <Main.Content>Page content</Main.Content>\n <Main.Footer>Page actions</Main.Footer>\n</Main>"
63
+ },
64
+ {
65
+ "name": "Narrow Measure",
66
+ "description": "Readable page composition constrained to the canonical 800px measure",
67
+ "code": "<Main measure=\"narrow\">\n <Main.Header>Settings</Main.Header>\n <Main.Description>Manage the workspace contract.</Main.Description>\n <Main.Content>Settings content</Main.Content>\n <Main.Footer>Save changes</Main.Footer>\n</Main>"
68
+ }
69
+ ],
70
+ "ai": {
71
+ "compositionPattern": "compound",
72
+ "subComponents": ["Header", "Description", "Content", "Footer"]
73
+ },
74
+ "provenance": {
75
+ "source": "manual",
76
+ "verified": true,
77
+ "frameworkSupport": "native"
78
+ }
79
+ }
@@ -0,0 +1,31 @@
1
+ @use "../../tokens/variables" as *;
2
+
3
+ $fui-main-measure-narrow: 57.143rem !default;
4
+
5
+ .root {
6
+ box-sizing: border-box;
7
+ width: 100%;
8
+ min-width: 0;
9
+ min-height: 100%;
10
+ margin-inline: auto;
11
+ padding: var(--fui-space-3, $fui-space-3);
12
+ }
13
+
14
+ .full {
15
+ max-width: none;
16
+ }
17
+
18
+ .narrow {
19
+ max-width: $fui-main-measure-narrow;
20
+ }
21
+
22
+ .header,
23
+ .description,
24
+ .content,
25
+ .footer {
26
+ min-width: 0;
27
+ }
28
+
29
+ .description {
30
+ max-width: 68ch;
31
+ }
@@ -0,0 +1,124 @@
1
+ import * as React from "react";
2
+ import { Stack, type StackProps } from "../Stack";
3
+ import styles from "./Main.module.scss";
4
+
5
+ export type MainMeasure = "full" | "narrow";
6
+
7
+ export interface MainProps extends Omit<StackProps, "as" | "children" | "direction" | "gap"> {
8
+ as?: StackProps["as"];
9
+ children: React.ReactNode;
10
+ /** Maximum readable width for the page content. */
11
+ measure?: MainMeasure;
12
+ }
13
+
14
+ export type MainRegionProps = StackProps;
15
+
16
+ function joinClasses(...classes: Array<string | false | undefined>) {
17
+ return classes.filter(Boolean).join(" ");
18
+ }
19
+
20
+ const MainRoot = React.forwardRef<HTMLElement, MainProps>(function MainRoot(
21
+ { as = "main", children, className, measure = "full", ...htmlProps },
22
+ ref
23
+ ) {
24
+ return (
25
+ <Stack
26
+ {...htmlProps}
27
+ ref={ref}
28
+ as={as}
29
+ direction="column"
30
+ gap="lg"
31
+ className={joinClasses(
32
+ styles.root,
33
+ measure === "narrow" ? styles.narrow : styles.full,
34
+ className
35
+ )}
36
+ data-main-measure={measure}
37
+ >
38
+ {children}
39
+ </Stack>
40
+ );
41
+ });
42
+
43
+ function MainHeader({
44
+ as = "header",
45
+ direction = "column",
46
+ gap = "sm",
47
+ className,
48
+ ...props
49
+ }: MainRegionProps) {
50
+ return (
51
+ <Stack
52
+ {...props}
53
+ as={as}
54
+ direction={direction}
55
+ gap={gap}
56
+ className={joinClasses(styles.header, className)}
57
+ />
58
+ );
59
+ }
60
+
61
+ function MainDescription({
62
+ as = "div",
63
+ direction = "column",
64
+ gap = "xs",
65
+ className,
66
+ ...props
67
+ }: MainRegionProps) {
68
+ return (
69
+ <Stack
70
+ {...props}
71
+ as={as}
72
+ direction={direction}
73
+ gap={gap}
74
+ className={joinClasses(styles.description, className)}
75
+ />
76
+ );
77
+ }
78
+
79
+ function MainContent({
80
+ as = "div",
81
+ direction = "column",
82
+ gap = "lg",
83
+ className,
84
+ ...props
85
+ }: MainRegionProps) {
86
+ return (
87
+ <Stack
88
+ {...props}
89
+ as={as}
90
+ direction={direction}
91
+ gap={gap}
92
+ className={joinClasses(styles.content, className)}
93
+ />
94
+ );
95
+ }
96
+
97
+ function MainFooter({
98
+ as = "footer",
99
+ direction = "row",
100
+ gap = "sm",
101
+ justify = "end",
102
+ wrap = true,
103
+ className,
104
+ ...props
105
+ }: MainRegionProps) {
106
+ return (
107
+ <Stack
108
+ {...props}
109
+ as={as}
110
+ direction={direction}
111
+ gap={gap}
112
+ justify={justify}
113
+ wrap={wrap}
114
+ className={joinClasses(styles.footer, className)}
115
+ />
116
+ );
117
+ }
118
+
119
+ export const Main = Object.assign(MainRoot, {
120
+ Header: MainHeader,
121
+ Description: MainDescription,
122
+ Content: MainContent,
123
+ Footer: MainFooter,
124
+ });
@@ -8,6 +8,7 @@ $fui-arrow-size: 10px !default;
8
8
  .positioner {
9
9
  z-index: 52;
10
10
  outline: none;
11
+ pointer-events: auto;
11
12
  }
12
13
 
13
14
  // Popup container
@@ -19,23 +20,21 @@ $fui-arrow-size: 10px !default;
19
20
  margin: 0;
20
21
  min-width: 12rem;
21
22
 
22
- // Animation
23
- opacity: 0;
24
- transform: scale(0.95);
23
+ // Menus must be fully hit-testable as soon as they open. A fade/scale
24
+ // entrance can let fast clicks pass through to page links under the portal.
25
+ opacity: 1;
26
+ transform: none;
25
27
  transform-origin: var(--transform-origin);
26
- transition:
27
- opacity var(--fui-transition-fast, $fui-transition-fast),
28
- transform var(--fui-transition-fast, $fui-transition-fast);
29
28
 
30
29
  &[data-open] {
31
30
  opacity: 1;
32
- transform: scale(1);
31
+ transform: none;
33
32
  }
34
33
 
35
34
  &[data-starting-style],
36
35
  &[data-ending-style] {
37
- opacity: 0;
38
- transform: scale(0.95);
36
+ opacity: 1;
37
+ transform: none;
39
38
  }
40
39
  }
41
40
 
@@ -204,7 +203,6 @@ $fui-arrow-size: 10px !default;
204
203
 
205
204
  @media (prefers-reduced-motion: reduce) {
206
205
  .popup {
207
- transition: none;
208
206
  transform: none;
209
207
 
210
208
  &[data-starting-style],
@@ -110,6 +110,28 @@ function CloseIcon() {
110
110
  );
111
111
  }
112
112
 
113
+ // ============================================
114
+ // Helpers
115
+ // ============================================
116
+
117
+ /**
118
+ * Base UI's button-like triggers default `nativeButton` to `true`. When an
119
+ * `asChild` trigger renders something other than a native `<button>` (an
120
+ * anchor, or a component rendered `as="a"`), that default is wrong and Base UI
121
+ * warns that native button semantics were removed. Resolve the correct value
122
+ * from the child so the trigger stays honest and the warning goes away.
123
+ */
124
+ function resolveNativeButton(child: React.ReactElement): boolean {
125
+ const type = child.type;
126
+ // Intrinsic elements: only `<button>` is a native button.
127
+ if (typeof type === 'string') return type === 'button';
128
+ // Custom components render a native `<button>` by default; treat anchors
129
+ // (via `as="a"` or an `href`) as non-native.
130
+ const props = (child.props ?? {}) as Record<string, unknown>;
131
+ if (props.as === 'a' || props.href != null) return false;
132
+ return true;
133
+ }
134
+
113
135
  // ============================================
114
136
  // Components
115
137
  // ============================================
@@ -139,7 +161,12 @@ function PopoverTrigger({ children, asChild, className, ...htmlProps }: PopoverT
139
161
  throw new Error('Popover.Trigger with asChild requires a single valid React element child.');
140
162
  }
141
163
  return (
142
- <BasePopover.Trigger {...htmlProps} className={className} render={children as React.ReactElement}>
164
+ <BasePopover.Trigger
165
+ {...htmlProps}
166
+ nativeButton={resolveNativeButton(children as React.ReactElement)}
167
+ className={className}
168
+ render={children as React.ReactElement}
169
+ >
143
170
  {null}
144
171
  </BasePopover.Trigger>
145
172
  );
@@ -240,7 +267,12 @@ function PopoverClose({ children, asChild, className, ...htmlProps }: PopoverClo
240
267
  throw new Error('Popover.Close with asChild requires a single valid React element child.');
241
268
  }
242
269
  return (
243
- <BasePopover.Close {...htmlProps} className={className} render={children as React.ReactElement}>
270
+ <BasePopover.Close
271
+ {...htmlProps}
272
+ nativeButton={resolveNativeButton(children as React.ReactElement)}
273
+ className={className}
274
+ render={children as React.ReactElement}
275
+ >
244
276
  {null}
245
277
  </BasePopover.Close>
246
278
  );