@sixthshift/design-system 0.5.0 → 0.6.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 (412) hide show
  1. package/README.md +132 -87
  2. package/dist/components/Badge/Badge.d.ts +2 -2
  3. package/dist/components/Badge/Badge.js +2 -2
  4. package/dist/components/Button/Button.d.ts +1 -1
  5. package/dist/components/Button/Button.js +1 -1
  6. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  7. package/dist/components/Calendar/Calendar.js +1 -0
  8. package/dist/components/Calendar/Calendar.js.map +1 -1
  9. package/dist/components/Calendar/CalendarView.d.ts +0 -11
  10. package/dist/components/Calendar/CalendarView.d.ts.map +1 -1
  11. package/dist/components/Calendar/CalendarView.js +1 -0
  12. package/dist/components/Calendar/CalendarView.js.map +1 -1
  13. package/dist/components/Calendar/calendar.hooks.d.ts.map +1 -1
  14. package/dist/components/Calendar/calendar.hooks.js +1 -0
  15. package/dist/components/Calendar/calendar.hooks.js.map +1 -1
  16. package/dist/components/Card/Card.d.ts +2 -2
  17. package/dist/components/Card/Card.d.ts.map +1 -1
  18. package/dist/components/Card/Card.js +3 -2
  19. package/dist/components/Card/Card.js.map +1 -1
  20. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  21. package/dist/components/Checkbox/Checkbox.js +1 -0
  22. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  23. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
  24. package/dist/components/CheckboxGroup/CheckboxGroup.js +1 -0
  25. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
  26. package/dist/components/Code/Editor/Editor.d.ts.map +1 -1
  27. package/dist/components/Code/Editor/Editor.js +1 -0
  28. package/dist/components/Code/Editor/Editor.js.map +1 -1
  29. package/dist/components/Code/Workspace/StatusBar.d.ts.map +1 -1
  30. package/dist/components/Code/Workspace/StatusBar.js +1 -0
  31. package/dist/components/Code/Workspace/StatusBar.js.map +1 -1
  32. package/dist/components/Code/Workspace/Toolbar.d.ts.map +1 -1
  33. package/dist/components/Code/Workspace/Toolbar.js +1 -0
  34. package/dist/components/Code/Workspace/Toolbar.js.map +1 -1
  35. package/dist/components/Code/Workspace/Workspace.d.ts.map +1 -1
  36. package/dist/components/Code/Workspace/Workspace.js +1 -0
  37. package/dist/components/Code/Workspace/Workspace.js.map +1 -1
  38. package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
  39. package/dist/components/DatePicker/DatePicker.js +5 -0
  40. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  41. package/dist/components/DatePicker/DateSegments.d.ts.map +1 -1
  42. package/dist/components/DatePicker/DateSegments.js +1 -0
  43. package/dist/components/DatePicker/DateSegments.js.map +1 -1
  44. package/dist/components/DatePicker/datepicker.hooks.d.ts.map +1 -1
  45. package/dist/components/DatePicker/datepicker.hooks.js +1 -0
  46. package/dist/components/DatePicker/datepicker.hooks.js.map +1 -1
  47. package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  48. package/dist/components/DateRangePicker/DateRangePicker.js +1 -0
  49. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  50. package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  51. package/dist/components/DateTimePicker/DateTimePicker.js +5 -0
  52. package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
  53. package/dist/components/DateTimePicker/DateTimeSegments.d.ts.map +1 -1
  54. package/dist/components/DateTimePicker/DateTimeSegments.js +1 -0
  55. package/dist/components/DateTimePicker/DateTimeSegments.js.map +1 -1
  56. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
  57. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +5 -0
  58. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
  59. package/dist/components/FormField/FormField.d.ts +31 -10
  60. package/dist/components/FormField/FormField.d.ts.map +1 -1
  61. package/dist/components/FormField/FormField.js +46 -17
  62. package/dist/components/FormField/FormField.js.map +1 -1
  63. package/dist/components/FormField/index.d.ts +2 -2
  64. package/dist/components/FormField/index.d.ts.map +1 -1
  65. package/dist/components/FormField/index.js +1 -1
  66. package/dist/components/FormField/index.js.map +1 -1
  67. package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
  68. package/dist/components/HoverCard/HoverCard.js +1 -0
  69. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  70. package/dist/components/HoverCard/components/HoverCardContent.d.ts.map +1 -1
  71. package/dist/components/HoverCard/components/HoverCardContent.js +1 -0
  72. package/dist/components/HoverCard/components/HoverCardContent.js.map +1 -1
  73. package/dist/components/HoverCard/components/HoverCardContext.d.ts.map +1 -1
  74. package/dist/components/HoverCard/components/HoverCardContext.js +1 -0
  75. package/dist/components/HoverCard/components/HoverCardContext.js.map +1 -1
  76. package/dist/components/HoverCard/components/HoverCardTrigger.d.ts.map +1 -1
  77. package/dist/components/HoverCard/components/HoverCardTrigger.js +1 -0
  78. package/dist/components/HoverCard/components/HoverCardTrigger.js.map +1 -1
  79. package/dist/components/Message/Message.d.ts +1 -1
  80. package/dist/components/Message/Message.js +1 -1
  81. package/dist/components/Modal/Modal.d.ts +14 -9
  82. package/dist/components/Modal/Modal.d.ts.map +1 -1
  83. package/dist/components/Modal/Modal.js +42 -20
  84. package/dist/components/Modal/Modal.js.map +1 -1
  85. package/dist/components/Modal/components/ModalContext.d.ts.map +1 -1
  86. package/dist/components/Modal/components/ModalContext.js +1 -0
  87. package/dist/components/Modal/components/ModalContext.js.map +1 -1
  88. package/dist/components/Modal/components/ModalHeader.d.ts.map +1 -1
  89. package/dist/components/Modal/components/ModalHeader.js +1 -0
  90. package/dist/components/Modal/components/ModalHeader.js.map +1 -1
  91. package/dist/components/Popover/Popover.d.ts.map +1 -1
  92. package/dist/components/Popover/Popover.js +5 -0
  93. package/dist/components/Popover/Popover.js.map +1 -1
  94. package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
  95. package/dist/components/Popover/components/PopoverBody.js +1 -0
  96. package/dist/components/Popover/components/PopoverBody.js.map +1 -1
  97. package/dist/components/Popover/components/PopoverClose.d.ts.map +1 -1
  98. package/dist/components/Popover/components/PopoverClose.js +1 -0
  99. package/dist/components/Popover/components/PopoverClose.js.map +1 -1
  100. package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
  101. package/dist/components/Popover/components/PopoverContext.js +1 -0
  102. package/dist/components/Popover/components/PopoverContext.js.map +1 -1
  103. package/dist/components/Popover/components/PopoverTrigger.d.ts.map +1 -1
  104. package/dist/components/Popover/components/PopoverTrigger.js +1 -0
  105. package/dist/components/Popover/components/PopoverTrigger.js.map +1 -1
  106. package/dist/components/RadioButton/RadioButton.d.ts.map +1 -1
  107. package/dist/components/RadioButton/RadioButton.js +1 -0
  108. package/dist/components/RadioButton/RadioButton.js.map +1 -1
  109. package/dist/components/RadioButtonGroup/RadioButtonGroup.d.ts.map +1 -1
  110. package/dist/components/RadioButtonGroup/RadioButtonGroup.js +1 -0
  111. package/dist/components/RadioButtonGroup/RadioButtonGroup.js.map +1 -1
  112. package/dist/components/SearchInput/SearchInput.d.ts +10 -7
  113. package/dist/components/SearchInput/SearchInput.d.ts.map +1 -1
  114. package/dist/components/SearchInput/SearchInput.js +11 -6
  115. package/dist/components/SearchInput/SearchInput.js.map +1 -1
  116. package/dist/components/Select/Select.d.ts +6 -0
  117. package/dist/components/Select/Select.d.ts.map +1 -1
  118. package/dist/components/Select/Select.js +9 -3
  119. package/dist/components/Select/Select.js.map +1 -1
  120. package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
  121. package/dist/components/Select/SelectDropdown.js +1 -0
  122. package/dist/components/Select/SelectDropdown.js.map +1 -1
  123. package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
  124. package/dist/components/Select/SelectTrigger.js +5 -1
  125. package/dist/components/Select/SelectTrigger.js.map +1 -1
  126. package/dist/components/Select/useSelectKeyboard.d.ts.map +1 -1
  127. package/dist/components/Select/useSelectKeyboard.js +1 -0
  128. package/dist/components/Select/useSelectKeyboard.js.map +1 -1
  129. package/dist/components/Sheet/Sheet.d.ts.map +1 -1
  130. package/dist/components/Sheet/Sheet.js +23 -9
  131. package/dist/components/Sheet/Sheet.js.map +1 -1
  132. package/dist/components/Sheet/components/SheetContext.d.ts.map +1 -1
  133. package/dist/components/Sheet/components/SheetContext.js +1 -0
  134. package/dist/components/Sheet/components/SheetContext.js.map +1 -1
  135. package/dist/components/Sheet/components/SheetHeader.d.ts.map +1 -1
  136. package/dist/components/Sheet/components/SheetHeader.js +1 -0
  137. package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
  138. package/dist/components/Spinner/Spinner.d.ts +2 -2
  139. package/dist/components/Spinner/Spinner.js +2 -2
  140. package/dist/components/Switch/Switch.d.ts.map +1 -1
  141. package/dist/components/Switch/Switch.js +1 -0
  142. package/dist/components/Switch/Switch.js.map +1 -1
  143. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  144. package/dist/components/Tabs/Tabs.js +1 -0
  145. package/dist/components/Tabs/Tabs.js.map +1 -1
  146. package/dist/components/Tabs/components/TabsContext.d.ts.map +1 -1
  147. package/dist/components/Tabs/components/TabsContext.js +1 -0
  148. package/dist/components/Tabs/components/TabsContext.js.map +1 -1
  149. package/dist/components/Tabs/components/TabsList.d.ts.map +1 -1
  150. package/dist/components/Tabs/components/TabsList.js +1 -0
  151. package/dist/components/Tabs/components/TabsList.js.map +1 -1
  152. package/dist/components/Tabs/components/TabsPanels.d.ts.map +1 -1
  153. package/dist/components/Tabs/components/TabsPanels.js +1 -0
  154. package/dist/components/Tabs/components/TabsPanels.js.map +1 -1
  155. package/dist/components/Tabs/components/TabsTrigger.d.ts.map +1 -1
  156. package/dist/components/Tabs/components/TabsTrigger.js +2 -1
  157. package/dist/components/Tabs/components/TabsTrigger.js.map +1 -1
  158. package/dist/components/TagChip/TagChip.d.ts.map +1 -1
  159. package/dist/components/TagChip/TagChip.js +1 -0
  160. package/dist/components/TagChip/TagChip.js.map +1 -1
  161. package/dist/components/TagInput/TagInput.d.ts +8 -2
  162. package/dist/components/TagInput/TagInput.d.ts.map +1 -1
  163. package/dist/components/TagInput/TagInput.js +8 -5
  164. package/dist/components/TagInput/TagInput.js.map +1 -1
  165. package/dist/components/Textarea/Textarea.d.ts +21 -5
  166. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  167. package/dist/components/Textarea/Textarea.js +31 -5
  168. package/dist/components/Textarea/Textarea.js.map +1 -1
  169. package/dist/components/TimePicker/PeriodSelector.d.ts.map +1 -1
  170. package/dist/components/TimePicker/PeriodSelector.js +1 -0
  171. package/dist/components/TimePicker/PeriodSelector.js.map +1 -1
  172. package/dist/components/TimePicker/TimeColumn.d.ts.map +1 -1
  173. package/dist/components/TimePicker/TimeColumn.js +1 -0
  174. package/dist/components/TimePicker/TimeColumn.js.map +1 -1
  175. package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
  176. package/dist/components/TimePicker/TimePicker.js +5 -0
  177. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  178. package/dist/components/TimePicker/TimeSegments.d.ts.map +1 -1
  179. package/dist/components/TimePicker/TimeSegments.js +1 -0
  180. package/dist/components/TimePicker/TimeSegments.js.map +1 -1
  181. package/dist/components/Toast/Toast.d.ts +16 -2
  182. package/dist/components/Toast/Toast.d.ts.map +1 -1
  183. package/dist/components/Toast/Toast.js +16 -6
  184. package/dist/components/Toast/Toast.js.map +1 -1
  185. package/dist/components/Toggle/Toggle.d.ts +1 -1
  186. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  187. package/dist/components/Toggle/Toggle.js +2 -1
  188. package/dist/components/Toggle/Toggle.js.map +1 -1
  189. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +2 -0
  190. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
  191. package/dist/components/ToggleGroup/ToggleGroupMultiple.js +4 -3
  192. package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
  193. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +2 -0
  194. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
  195. package/dist/components/ToggleGroup/ToggleGroupSingle.js +4 -3
  196. package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
  197. package/dist/components/ToggleGroup/toggleGroup.types.d.ts +7 -0
  198. package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
  199. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  200. package/dist/components/Tooltip/Tooltip.js +1 -0
  201. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  202. package/dist/components/Tooltip/components/TooltipBody.d.ts.map +1 -1
  203. package/dist/components/Tooltip/components/TooltipBody.js +1 -0
  204. package/dist/components/Tooltip/components/TooltipBody.js.map +1 -1
  205. package/dist/components/Tooltip/components/TooltipContext.d.ts.map +1 -1
  206. package/dist/components/Tooltip/components/TooltipContext.js +1 -0
  207. package/dist/components/Tooltip/components/TooltipContext.js.map +1 -1
  208. package/dist/components/Tooltip/components/TooltipTrigger.d.ts.map +1 -1
  209. package/dist/components/Tooltip/components/TooltipTrigger.js +1 -0
  210. package/dist/components/Tooltip/components/TooltipTrigger.js.map +1 -1
  211. package/dist/hooks/useCollapsible.d.ts.map +1 -1
  212. package/dist/hooks/useCollapsible.js +1 -0
  213. package/dist/hooks/useCollapsible.js.map +1 -1
  214. package/dist/hooks/useControllableState.d.ts.map +1 -1
  215. package/dist/hooks/useControllableState.js +1 -0
  216. package/dist/hooks/useControllableState.js.map +1 -1
  217. package/dist/hooks/useDebouncedCallback.d.ts.map +1 -1
  218. package/dist/hooks/useDebouncedCallback.js +1 -0
  219. package/dist/hooks/useDebouncedCallback.js.map +1 -1
  220. package/dist/hooks/useDebouncedState.d.ts.map +1 -1
  221. package/dist/hooks/useDebouncedState.js +1 -0
  222. package/dist/hooks/useDebouncedState.js.map +1 -1
  223. package/dist/hooks/useDeviceFormFactor.d.ts.map +1 -1
  224. package/dist/hooks/useDeviceFormFactor.js +1 -0
  225. package/dist/hooks/useDeviceFormFactor.js.map +1 -1
  226. package/dist/hooks/useLocalStorage.d.ts.map +1 -1
  227. package/dist/hooks/useLocalStorage.js +1 -0
  228. package/dist/hooks/useLocalStorage.js.map +1 -1
  229. package/dist/hooks/useMergedFloatingRef.d.ts.map +1 -1
  230. package/dist/hooks/useMergedFloatingRef.js +1 -0
  231. package/dist/hooks/useMergedFloatingRef.js.map +1 -1
  232. package/dist/hooks/usePresence.d.ts.map +1 -1
  233. package/dist/hooks/usePresence.js +1 -0
  234. package/dist/hooks/usePresence.js.map +1 -1
  235. package/dist/hooks/useStack.d.ts.map +1 -1
  236. package/dist/hooks/useStack.js +34 -10
  237. package/dist/hooks/useStack.js.map +1 -1
  238. package/dist/hooks/useTheme.d.ts.map +1 -1
  239. package/dist/hooks/useTheme.js +1 -0
  240. package/dist/hooks/useTheme.js.map +1 -1
  241. package/dist/internal/PickerField.d.ts.map +1 -1
  242. package/dist/internal/PickerField.js +1 -0
  243. package/dist/internal/PickerField.js.map +1 -1
  244. package/dist/internal/SegmentedField.d.ts.map +1 -1
  245. package/dist/internal/SegmentedField.js +1 -0
  246. package/dist/internal/SegmentedField.js.map +1 -1
  247. package/dist/internal/escapeLayers.d.ts +12 -0
  248. package/dist/internal/escapeLayers.d.ts.map +1 -0
  249. package/dist/internal/escapeLayers.js +48 -0
  250. package/dist/internal/escapeLayers.js.map +1 -0
  251. package/dist/lib/ErrorBoundary.d.ts.map +1 -1
  252. package/dist/lib/ErrorBoundary.js +1 -0
  253. package/dist/lib/ErrorBoundary.js.map +1 -1
  254. package/dist/lib/contexts/ComponentsContext/ComponentsContext.d.ts.map +1 -1
  255. package/dist/lib/contexts/ComponentsContext/ComponentsContext.js +1 -0
  256. package/dist/lib/contexts/ComponentsContext/ComponentsContext.js.map +1 -1
  257. package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts +9 -4
  258. package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts.map +1 -1
  259. package/dist/lib/contexts/OverlayContext/OverlayContext.js +25 -12
  260. package/dist/lib/contexts/OverlayContext/OverlayContext.js.map +1 -1
  261. package/dist/lib/contexts/OverlayContext/ToastStack.d.ts +20 -0
  262. package/dist/lib/contexts/OverlayContext/ToastStack.d.ts.map +1 -0
  263. package/dist/lib/contexts/OverlayContext/ToastStack.js +45 -0
  264. package/dist/lib/contexts/OverlayContext/ToastStack.js.map +1 -0
  265. package/dist/lib/contexts/OverlayContext/hooks/useModal.d.ts.map +1 -1
  266. package/dist/lib/contexts/OverlayContext/hooks/useModal.js +1 -0
  267. package/dist/lib/contexts/OverlayContext/hooks/useModal.js.map +1 -1
  268. package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts +27 -10
  269. package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts.map +1 -1
  270. package/dist/lib/contexts/OverlayContext/hooks/useToast.js +31 -49
  271. package/dist/lib/contexts/OverlayContext/hooks/useToast.js.map +1 -1
  272. package/dist/lib/contexts/OverlayContext/index.d.ts +2 -0
  273. package/dist/lib/contexts/OverlayContext/index.d.ts.map +1 -1
  274. package/dist/lib/contexts/OverlayContext/index.js +2 -0
  275. package/dist/lib/contexts/OverlayContext/index.js.map +1 -1
  276. package/dist/lib/contexts/OverlayContext/toastStore.d.ts +68 -0
  277. package/dist/lib/contexts/OverlayContext/toastStore.d.ts.map +1 -0
  278. package/dist/lib/contexts/OverlayContext/toastStore.js +69 -0
  279. package/dist/lib/contexts/OverlayContext/toastStore.js.map +1 -0
  280. package/dist/lib/withErrorBoundary.d.ts.map +1 -1
  281. package/dist/lib/withErrorBoundary.js +1 -0
  282. package/dist/lib/withErrorBoundary.js.map +1 -1
  283. package/dist/lib/withSuspenseAndErrorBoundary.d.ts.map +1 -1
  284. package/dist/lib/withSuspenseAndErrorBoundary.js +1 -0
  285. package/dist/lib/withSuspenseAndErrorBoundary.js.map +1 -1
  286. package/dist/{theme/schema.d.ts → theming/vocabulary.d.ts} +4 -4
  287. package/dist/theming/vocabulary.d.ts.map +1 -0
  288. package/dist/{theme/schema.js → theming/vocabulary.js} +4 -4
  289. package/dist/theming/vocabulary.js.map +1 -0
  290. package/package.json +18 -6
  291. package/src/components/Badge/Badge.tsx +2 -2
  292. package/src/components/Button/Button.tsx +1 -1
  293. package/src/{theme/recipes/button.css → components/Button/button.recipe.css} +2 -2
  294. package/src/components/Calendar/Calendar.tsx +2 -0
  295. package/src/components/Calendar/CalendarView.tsx +2 -0
  296. package/src/components/Calendar/calendar.hooks.ts +2 -0
  297. package/src/components/Card/Card.tsx +4 -2
  298. package/src/components/Checkbox/Checkbox.tsx +2 -0
  299. package/src/components/CheckboxGroup/CheckboxGroup.tsx +2 -0
  300. package/src/components/Code/Editor/Editor.tsx +2 -0
  301. package/src/components/Code/Workspace/StatusBar.tsx +2 -0
  302. package/src/components/Code/Workspace/Toolbar.tsx +2 -0
  303. package/src/components/Code/Workspace/Workspace.tsx +2 -0
  304. package/src/components/DatePicker/DatePicker.tsx +7 -0
  305. package/src/components/DatePicker/DateSegments.tsx +2 -0
  306. package/src/components/DatePicker/datepicker.hooks.ts +2 -0
  307. package/src/components/DateRangePicker/DateRangePicker.tsx +2 -0
  308. package/src/components/DateTimePicker/DateTimePicker.tsx +7 -1
  309. package/src/components/DateTimePicker/DateTimeSegments.tsx +2 -0
  310. package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +7 -1
  311. package/src/components/FormField/FormField.tsx +94 -42
  312. package/src/components/FormField/index.ts +2 -2
  313. package/src/components/HoverCard/HoverCard.tsx +2 -0
  314. package/src/components/HoverCard/components/HoverCardContent.tsx +2 -0
  315. package/src/components/HoverCard/components/HoverCardContext.tsx +2 -0
  316. package/src/components/HoverCard/components/HoverCardTrigger.tsx +2 -0
  317. package/src/components/Message/Message.tsx +1 -1
  318. package/src/components/Modal/Modal.tsx +77 -51
  319. package/src/components/Modal/components/ModalContext.tsx +2 -0
  320. package/src/components/Modal/components/ModalHeader.tsx +2 -0
  321. package/src/components/Popover/Popover.tsx +7 -0
  322. package/src/components/Popover/components/PopoverBody.tsx +2 -0
  323. package/src/components/Popover/components/PopoverClose.tsx +2 -0
  324. package/src/components/Popover/components/PopoverContext.tsx +2 -0
  325. package/src/components/Popover/components/PopoverTrigger.tsx +2 -0
  326. package/src/components/RadioButton/RadioButton.tsx +2 -0
  327. package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +2 -0
  328. package/src/components/SearchInput/SearchInput.tsx +15 -8
  329. package/src/components/Select/Select.tsx +24 -1
  330. package/src/components/Select/SelectDropdown.tsx +2 -0
  331. package/src/components/Select/SelectTrigger.tsx +5 -0
  332. package/src/components/Select/useSelectKeyboard.ts +2 -0
  333. package/src/components/Sheet/Sheet.tsx +49 -34
  334. package/src/components/Sheet/components/SheetContext.tsx +2 -0
  335. package/src/components/Sheet/components/SheetHeader.tsx +2 -0
  336. package/src/components/Spinner/Spinner.tsx +2 -2
  337. package/src/components/Switch/Switch.tsx +2 -0
  338. package/src/components/Tabs/Tabs.tsx +2 -0
  339. package/src/components/Tabs/components/TabsContext.tsx +2 -0
  340. package/src/components/Tabs/components/TabsList.tsx +2 -0
  341. package/src/components/Tabs/components/TabsPanels.tsx +2 -0
  342. package/src/components/Tabs/components/TabsTrigger.tsx +3 -1
  343. package/src/{theme/recipes/tabs.css → components/Tabs/tabs.recipe.css} +1 -1
  344. package/src/components/TagChip/TagChip.tsx +2 -0
  345. package/src/components/TagInput/TagInput.tsx +15 -6
  346. package/src/components/Textarea/Textarea.tsx +42 -6
  347. package/src/{theme/recipes/textarea.css → components/Textarea/textarea.recipe.css} +1 -1
  348. package/src/components/TimePicker/PeriodSelector.tsx +2 -0
  349. package/src/components/TimePicker/TimeColumn.tsx +2 -0
  350. package/src/components/TimePicker/TimePicker.tsx +7 -0
  351. package/src/components/TimePicker/TimeSegments.tsx +2 -0
  352. package/src/components/Toast/Toast.tsx +22 -6
  353. package/src/components/Toggle/Toggle.tsx +3 -1
  354. package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +6 -0
  355. package/src/components/ToggleGroup/ToggleGroupSingle.tsx +6 -0
  356. package/src/components/ToggleGroup/toggleGroup.types.ts +7 -0
  357. package/src/components/Tooltip/Tooltip.tsx +2 -0
  358. package/src/components/Tooltip/components/TooltipBody.tsx +2 -0
  359. package/src/components/Tooltip/components/TooltipContext.tsx +2 -0
  360. package/src/components/Tooltip/components/TooltipTrigger.tsx +2 -0
  361. package/src/hooks/useCollapsible.ts +2 -0
  362. package/src/hooks/useControllableState.ts +2 -0
  363. package/src/hooks/useDebouncedCallback.ts +2 -0
  364. package/src/hooks/useDebouncedState.ts +2 -0
  365. package/src/hooks/useDeviceFormFactor.ts +2 -0
  366. package/src/hooks/useLocalStorage.ts +2 -0
  367. package/src/hooks/useMergedFloatingRef.ts +2 -0
  368. package/src/hooks/usePresence.ts +2 -0
  369. package/src/hooks/useStack.ts +35 -12
  370. package/src/hooks/useTheme.ts +2 -0
  371. package/src/internal/PickerField.tsx +2 -0
  372. package/src/internal/SegmentedField.tsx +2 -0
  373. package/src/internal/escapeLayers.ts +53 -0
  374. package/src/lib/ErrorBoundary.tsx +2 -0
  375. package/src/lib/contexts/ComponentsContext/ComponentsContext.tsx +2 -0
  376. package/src/lib/contexts/OverlayContext/OverlayContext.tsx +42 -26
  377. package/src/lib/contexts/OverlayContext/ToastStack.tsx +71 -0
  378. package/src/lib/contexts/OverlayContext/hooks/useModal.tsx +2 -0
  379. package/src/lib/contexts/OverlayContext/hooks/useToast.ts +30 -73
  380. package/src/lib/contexts/OverlayContext/index.ts +2 -0
  381. package/src/lib/contexts/OverlayContext/toastStore.ts +138 -0
  382. package/src/lib/withErrorBoundary.tsx +2 -0
  383. package/src/lib/withSuspenseAndErrorBoundary.tsx +2 -0
  384. package/src/theme/linen/index.css +11 -0
  385. package/src/theme/linen/palette.css +87 -0
  386. package/src/theme/linen/theme.css +371 -0
  387. package/src/theming/tailwind.css +356 -0
  388. package/src/{theme/schema.ts → theming/vocabulary.ts} +3 -3
  389. package/dist/theme/index.d.ts +0 -9
  390. package/dist/theme/index.d.ts.map +0 -1
  391. package/dist/theme/index.js +0 -8
  392. package/dist/theme/index.js.map +0 -1
  393. package/dist/theme/schema.d.ts.map +0 -1
  394. package/dist/theme/schema.js.map +0 -1
  395. package/src/theme/index.ts +0 -39
  396. package/src/theme/recipes/index.css +0 -28
  397. package/src/theme/tokens.css +0 -824
  398. /package/src/{theme/recipes/badge.css → components/Badge/badge.recipe.css} +0 -0
  399. /package/src/{theme/recipes/card.css → components/Card/card.recipe.css} +0 -0
  400. /package/src/{theme/recipes/checkbox.css → components/Checkbox/checkbox.recipe.css} +0 -0
  401. /package/src/{theme/recipes/field.css → components/Field/field.recipe.css} +0 -0
  402. /package/src/{theme/recipes/input.css → components/Input/input.recipe.css} +0 -0
  403. /package/src/{theme/recipes/message.css → components/Message/message.recipe.css} +0 -0
  404. /package/src/{theme/recipes/modal.css → components/Modal/modal.recipe.css} +0 -0
  405. /package/src/{theme/recipes/radio-button.css → components/RadioButton/radio-button.recipe.css} +0 -0
  406. /package/src/{theme/recipes/search-input.css → components/SearchInput/search-input.recipe.css} +0 -0
  407. /package/src/{theme/recipes/select.css → components/Select/select.recipe.css} +0 -0
  408. /package/src/{theme/recipes/sheet.css → components/Sheet/sheet.recipe.css} +0 -0
  409. /package/src/{theme/recipes/spinner.css → components/Spinner/spinner.recipe.css} +0 -0
  410. /package/src/{theme/recipes/switch.css → components/Switch/switch.recipe.css} +0 -0
  411. /package/src/{theme/recipes/tag-chip.css → components/TagChip/tag-chip.recipe.css} +0 -0
  412. /package/src/{theme/recipes/toggle.css → components/Toggle/toggle.recipe.css} +0 -0
@@ -1,7 +1,10 @@
1
+ "use client";
2
+
1
3
  import { autoUpdate, flip, offset, type Placement, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
2
4
  import { useControllableState } from "@sixthshift/design-system/hooks";
3
5
  import type * as React from "react";
4
6
  import { useId } from "react";
7
+ import { useEscapeLayer } from "../../internal/escapeLayers";
5
8
  import { PopoverBody } from "./components/PopoverBody";
6
9
  import { PopoverClose } from "./components/PopoverClose";
7
10
  import { PopoverContext } from "./components/PopoverContext";
@@ -42,6 +45,10 @@ const PopoverRoot = ({ open: controlledOpen, onOpenChange, defaultOpen = false,
42
45
  const dismiss = useDismiss(context);
43
46
  const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
44
47
 
48
+ // While open, an Escape press dismisses this popover and must not also
49
+ // close a Modal/Sheet underneath it.
50
+ useEscapeLayer(open);
51
+
45
52
  const id = useId();
46
53
  const contentId = `popover-content-${id}`;
47
54
  // `Popover.Body` is a `role="dialog"`, and a dialog with no accessible name is
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { FloatingPortal } from "@floating-ui/react";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import * as React from "react";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import * as React from "react";
2
4
  import { Slot } from "../../../internal/Slot";
3
5
  import { usePopoverContext } from "./PopoverContext";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { createContext, useContext } from "react";
2
4
 
3
5
  export type PopoverContextValue = {
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import * as React from "react";
2
4
  import { Slot } from "../../../internal/Slot";
3
5
  import { usePopoverContext } from "./PopoverContext";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { Label } from "@sixthshift/design-system/label";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import * as React from "react";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { useControllableState } from "@sixthshift/design-system/hooks";
2
4
  import { RadioButton } from "@sixthshift/design-system/radio-button";
3
5
  import { cn } from "@sixthshift/design-system/utils";
@@ -1,11 +1,14 @@
1
+ "use client";
2
+
1
3
  import { Input } from "@sixthshift/design-system/input";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import { Search, X } from "lucide-react";
4
6
  import * as React from "react";
5
7
 
6
- export type SearchInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> & {
8
+ export type SearchInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> & {
7
9
  value: string;
8
- onChange: (value: string) => void;
10
+ /** Called with the input's string value on every change. The native `onChange(event)` also fires, unchanged. */
11
+ onValueChange: (value: string) => void;
9
12
  onClear?: () => void;
10
13
  /** Accessible name for the clear button — it is icon-only. */
11
14
  clearLabel?: string;
@@ -17,17 +20,18 @@ export type SearchInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>,
17
20
  *
18
21
  * Wraps `Input`, using its `iconLeft`/`iconRight` slots, rather than
19
22
  * reimplementing the field. Always controlled — `value` is required and
20
- * there is no `defaultValue`/uncontrolled mode. `onChange` receives the
21
- * string value directly, not the change event. Clearing calls `onClear` if
22
- * provided, otherwise calls `onChange("")`.
23
+ * there is no `defaultValue`/uncontrolled mode. `onValueChange` receives the
24
+ * string value directly; the native `onChange` keeps its event signature and
25
+ * fires too if passed. Clearing calls `onClear` if provided, otherwise calls
26
+ * `onValueChange("")` — note a programmatic clear dispatches no native event.
23
27
  */
24
28
  const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
25
- ({ className, value, onChange, onClear, clearLabel = "Clear search", ...props }, ref) => {
29
+ ({ className, value, onValueChange, onChange, onClear, clearLabel = "Clear search", ...props }, ref) => {
26
30
  const handleClear = () => {
27
31
  if (onClear) {
28
32
  onClear();
29
33
  } else {
30
- onChange("");
34
+ onValueChange("");
31
35
  }
32
36
  };
33
37
 
@@ -36,7 +40,10 @@ const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
36
40
  ref={ref}
37
41
  type="text"
38
42
  value={value}
39
- onChange={(e) => onChange(e.target.value)}
43
+ onChange={(e) => {
44
+ onValueChange(e.target.value);
45
+ onChange?.(e);
46
+ }}
40
47
  iconLeft={<Search />}
41
48
  iconRight={
42
49
  value ? (
@@ -1,6 +1,9 @@
1
+ "use client";
2
+
1
3
  import { autoUpdate, flip, offset, shift, size, useFloating } from "@floating-ui/react";
2
4
  import { useControllableState } from "@sixthshift/design-system/hooks";
3
5
  import { forwardRef, type HTMLAttributes, type ReactElement, type Ref, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
6
+ import { useEscapeLayer } from "../../internal/escapeLayers";
4
7
  import { SelectDropdown, selectOptionId } from "./SelectDropdown";
5
8
  import { SelectTriggerButton, SelectTriggerSearch } from "./SelectTrigger";
6
9
  import { useSelectKeyboard } from "./useSelectKeyboard";
@@ -19,6 +22,12 @@ type SelectBaseProps<T extends string = string> = Omit<HTMLAttributes<HTMLElemen
19
22
  placeholder?: string;
20
23
  searchable?: boolean;
21
24
  clearable?: boolean;
25
+ /** Input name for native form submission. Selected value(s) are mirrored into hidden `<input>`s, `${name}[]` in multiple mode. */
26
+ name?: string;
27
+ /** The `form` attribute for the hidden input(s), for a Select rendered outside its `<form>`. */
28
+ form?: string;
29
+ /** Marks the combobox `aria-required`. Constraint validation is the caller's job — the mirrored inputs are hidden. */
30
+ required?: boolean;
22
31
  };
23
32
 
24
33
  type SelectSingleProps<T extends string = string> = SelectBaseProps<T> & {
@@ -54,6 +63,9 @@ const SelectRoot = forwardRef(function SelectRoot<T extends string = string>(pro
54
63
  placeholder = "Select...",
55
64
  searchable = false,
56
65
  clearable = false,
66
+ name,
67
+ form,
68
+ required = false,
57
69
  ...restProps
58
70
  } = props;
59
71
 
@@ -244,6 +256,10 @@ const SelectRoot = forwardRef(function SelectRoot<T extends string = string>(pro
244
256
  }
245
257
  }, [highlightedIndex, open]);
246
258
 
259
+ // While open, an Escape press closes the dropdown and must not also close
260
+ // a Modal/Sheet this Select is rendered inside.
261
+ useEscapeLayer(open);
262
+
247
263
  // Close on outside click
248
264
  useEffect(() => {
249
265
  if (!open) return;
@@ -266,7 +282,8 @@ const SelectRoot = forwardRef(function SelectRoot<T extends string = string>(pro
266
282
  const activeOptionId = open && highlightedIndex >= 0 && highlightedIndex < filteredOptions.length ? selectOptionId(listboxId, highlightedIndex) : undefined;
267
283
 
268
284
  // Strip mode from DOM props
269
- const { mode: _, value: _v, defaultValue: _dv, onValueChange: _oc, ...htmlProps } = restProps as Record<string, unknown>;
285
+ const { mode: _, value: _v, defaultValue: _dv, onValueChange: _oc, ...strippedProps } = restProps as Record<string, unknown>;
286
+ const htmlProps = required ? { "aria-required": true, ...strippedProps } : strippedProps;
270
287
 
271
288
  // `role="listbox"` requires an accessible name of its own, and the trigger
272
289
  // can't supply one: its label is the current *value*, and in searchable mode
@@ -311,6 +328,12 @@ const SelectRoot = forwardRef(function SelectRoot<T extends string = string>(pro
311
328
  />
312
329
  )}
313
330
 
331
+ {/* Hidden inputs mirror the selection for native form submission — same
332
+ contract as DatePicker: rendered inline (not portalled) so they sit
333
+ inside the surrounding <form> unless `form` points elsewhere. */}
334
+ {name && !isMultiple && singleValue && <input type="hidden" name={name} value={singleValue} {...(form ? { form } : {})} />}
335
+ {name && isMultiple && multiValue.map((v) => <input key={v} type="hidden" name={`${name}[]`} value={v} {...(form ? { form } : {})} />)}
336
+
314
337
  {open && !collapsed && (
315
338
  <SelectDropdown
316
339
  setFloating={refs.setFloating}
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { FloatingPortal } from "@floating-ui/react";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import { Check } from "lucide-react";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import { ChevronDown, X } from "lucide-react";
3
5
  import type { HTMLAttributes, Ref } from "react";
@@ -55,6 +57,9 @@ export const SelectTriggerButton = ({
55
57
  className
56
58
  )}
57
59
  title={collapsed ? displayLabel : undefined}
60
+ // The APG select-only combobox: a button-behaving element announced as
61
+ // a combobox, which also admits aria-required — a plain button doesn't.
62
+ role="combobox"
58
63
  aria-haspopup="listbox"
59
64
  aria-expanded={open}
60
65
  // The listbox unmounts when closed, so only reference it while it exists.
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { useCallback } from "react";
2
4
  import type { SelectOption } from "./Select";
3
5
 
@@ -1,7 +1,10 @@
1
- import { FloatingFocusManager, useDismiss, useFloating, useInteractions, useRole } from "@floating-ui/react";
1
+ "use client";
2
+
3
+ import { FloatingFocusManager, FloatingPortal, useDismiss, useFloating, useInteractions, useRole } from "@floating-ui/react";
2
4
  import { useMergedFloatingRef, usePresence } from "@sixthshift/design-system/hooks";
3
5
  import { cn } from "@sixthshift/design-system/utils";
4
6
  import { forwardRef, type HTMLAttributes, type ReactNode, useCallback, useEffect, useId, useMemo, useState } from "react";
7
+ import { hasOpenEscapeDialog, hasOpenEscapeLayer } from "../../internal/escapeLayers";
5
8
  import { SheetBody, SheetContext, SheetFooter, SheetHeader } from "./components";
6
9
 
7
10
  // =============================================================================
@@ -78,8 +81,14 @@ const SheetRoot = forwardRef<HTMLDivElement, SheetProps>(
78
81
 
79
82
  const { refs, context } = useFloating({
80
83
  open,
81
- onOpenChange: (nextOpen) => {
82
- if (!nextOpen) requestClose();
84
+ onOpenChange: (nextOpen, _event, reason) => {
85
+ if (nextOpen) return;
86
+ // The sheet is non-modal, so overlays above it keep their own Escape
87
+ // handling: a transient layer (Select dropdown, Popover, picker)
88
+ // consumes the press, and an open Modal owns it. Only a bare Escape
89
+ // — nothing stacked above — closes the sheet.
90
+ if (reason === "escape-key" && (hasOpenEscapeLayer() || hasOpenEscapeDialog())) return;
91
+ requestClose();
83
92
  },
84
93
  });
85
94
 
@@ -114,37 +123,43 @@ const SheetRoot = forwardRef<HTMLDivElement, SheetProps>(
114
123
  const isExiting = state === "exiting";
115
124
 
116
125
  return (
117
- <FloatingFocusManager context={context} modal={false}>
118
- <div
119
- ref={mergedRef}
120
- // Explicit, though `getFloatingProps` also supplies it from `useRole`:
121
- // the ARIA attributes below are only valid on a dialog, and static
122
- // analysis cannot see a role that arrives through a spread. Matches Modal.
123
- role="dialog"
124
- aria-label={ariaLabel}
125
- aria-labelledby={labelledBy}
126
- aria-describedby={ariaDescribedBy}
127
- tabIndex={-1}
128
- data-state={state}
129
- data-side={side}
130
- className={cn(
131
- "sheet fixed top-0 bottom-0 z-sheet flex flex-col overflow-hidden bg-(--sheet-bg) outline-hidden",
132
- "border-(color:--sheet-border) shadow-lg",
133
- side === "right" ? "right-0 border-l" : "left-0 border-r",
134
- sizeClasses[size],
135
- "max-sm:inset-x-0",
136
- isEntering && side === "right" && "animate-slide-right-in",
137
- isExiting && side === "right" && "animate-slide-right-out",
138
- isEntering && side === "left" && "animate-slide-left-in",
139
- isExiting && side === "left" && "animate-slide-left-out",
140
- className
141
- )}
142
- style={style}
143
- {...getFloatingProps({})}
144
- >
145
- <SheetContext.Provider value={sheetContextValue}>{children}</SheetContext.Provider>
146
- </div>
147
- </FloatingFocusManager>
126
+ // Self-portalled for the same reason as Modal: `position: fixed` inside
127
+ // a transformed/filtered ancestor would anchor (and clip) the sheet to
128
+ // that ancestor instead of the viewport. `FloatingPortal` preserves tab
129
+ // order around the trigger for non-modal focus management.
130
+ <FloatingPortal>
131
+ <FloatingFocusManager context={context} modal={false}>
132
+ <div
133
+ ref={mergedRef}
134
+ // Explicit, though `getFloatingProps` also supplies it from `useRole`:
135
+ // the ARIA attributes below are only valid on a dialog, and static
136
+ // analysis cannot see a role that arrives through a spread. Matches Modal.
137
+ role="dialog"
138
+ aria-label={ariaLabel}
139
+ aria-labelledby={labelledBy}
140
+ aria-describedby={ariaDescribedBy}
141
+ tabIndex={-1}
142
+ data-state={state}
143
+ data-side={side}
144
+ className={cn(
145
+ "sheet fixed top-0 bottom-0 z-sheet flex flex-col overflow-hidden bg-(--sheet-bg) outline-hidden",
146
+ "border-(color:--sheet-border) shadow-lg",
147
+ side === "right" ? "right-0 border-l" : "left-0 border-r",
148
+ sizeClasses[size],
149
+ "max-sm:inset-x-0",
150
+ isEntering && side === "right" && "animate-slide-right-in",
151
+ isExiting && side === "right" && "animate-slide-right-out",
152
+ isEntering && side === "left" && "animate-slide-left-in",
153
+ isExiting && side === "left" && "animate-slide-left-out",
154
+ className
155
+ )}
156
+ style={style}
157
+ {...getFloatingProps({})}
158
+ >
159
+ <SheetContext.Provider value={sheetContextValue}>{children}</SheetContext.Provider>
160
+ </div>
161
+ </FloatingFocusManager>
162
+ </FloatingPortal>
148
163
  );
149
164
  }
150
165
  );
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { createContext, type KeyboardEvent, type MouseEvent, type PropsWithChildren, useContext, useMemo } from "react";
2
4
 
3
5
  export type OnClose = (event?: MouseEvent<Element> | KeyboardEvent<Element>) => void;
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import { X } from "lucide-react";
3
5
  import * as React from "react";
@@ -8,7 +8,7 @@ import * as React from "react";
8
8
  * The colour used to be `text-fg-subtle`, a semantic token named directly in
9
9
  * the class string — the one thing a consumer could not do was recolour a
10
10
  * spinner without fighting `className` against it. `--spinner-fg` in
11
- * src/theme/recipes/spinner.css is now that seam: a consumer overrides the
11
+ * src/components/Spinner/spinner.recipe.css is now that seam: a consumer overrides the
12
12
  * variable, scoped to whatever subtree they like, instead of overriding a
13
13
  * class.
14
14
  */
@@ -40,7 +40,7 @@ export type SpinnerProps = React.SVGAttributes<SVGElement> & VariantProps<typeof
40
40
  * live region) if the loading state needs to be announced.
41
41
  *
42
42
  * Colour reads the `--spinner-fg` component token
43
- * (src/theme/recipes/spinner.css) rather than a class name, so a consumer
43
+ * (src/components/Spinner/spinner.recipe.css) rather than a class name, so a consumer
44
44
  * can recolour a spinner scoped to a subtree without fighting `className`.
45
45
  */
46
46
  const Spinner = React.forwardRef<SVGSVGElement, SpinnerProps>(({ className, size, ...props }, ref) => (
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { useControllableState } from "@sixthshift/design-system/hooks";
2
4
  import { Label } from "@sixthshift/design-system/label";
3
5
  import { cn } from "@sixthshift/design-system/utils";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { useControllableState } from "@sixthshift/design-system/hooks";
2
4
  import type * as React from "react";
3
5
  import { useId } from "react";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { createContext, type ReactNode, useContext } from "react";
2
4
 
3
5
  export type TabItem = {
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import type * as React from "react";
3
5
  import { forwardRef, useCallback, useRef } from "react";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import { forwardRef } from "react";
3
5
  import { useTabsContext } from "./TabsContext";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { Badge } from "@sixthshift/design-system/badge";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import { cva } from "class-variance-authority";
@@ -9,7 +11,7 @@ import { type TabItem, useTabsContext } from "./TabsContext";
9
11
  *
10
12
  * Colour reads `--tabs-trigger-bg` / `--tabs-trigger-fg` component tokens
11
13
  * (each with a `-hovered` state) whose values are decided by
12
- * src/theme/recipes/tabs.css. That file is the mapping from `selected` to a
14
+ * src/components/Tabs/tabs.recipe.css. That file is the mapping from `selected` to a
13
15
  * semantic token — the layer that used to be the two branches of a `cva`
14
16
  * `selected` variant here, compiled into class-name literals and unreachable
15
17
  * from outside. Nothing in this file names a colour, which is the point: the
@@ -7,7 +7,7 @@
7
7
  * data, so a consumer can re-point a cell or scope a change to a subtree.
8
8
  *
9
9
  * The grammar is `--tabs-trigger-{context}[-{state}]` — the same `context`
10
- * and `state` words the semantic layer uses (src/theme/schema.ts). `selected`
10
+ * and `state` words the semantic layer uses (src/theming/vocabulary.ts). `selected`
11
11
  * never appears in a token name: it selects, via the `data-selected`
12
12
  * attribute below. Putting it in the name (`--tabs-trigger-bg-selected`)
13
13
  * would restore the combinatorial explosion this layer exists to remove.
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { Badge } from "@sixthshift/design-system/badge";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import { X } from "lucide-react";
@@ -1,32 +1,40 @@
1
+ "use client";
2
+
1
3
  import { TagChip } from "@sixthshift/design-system/tag-chip";
2
4
  import { cn } from "@sixthshift/design-system/utils";
3
5
  import { forwardRef, type KeyboardEvent, useState } from "react";
4
6
 
5
7
  export type TagInputProps = {
6
8
  value: string[];
7
- onChange: (tags: string[]) => void;
9
+ onValueChange: (tags: string[]) => void;
8
10
  placeholder?: string;
9
11
  id?: string;
10
12
  className?: string;
13
+ /** Input name for native form submission. Each tag is mirrored into a hidden `<input name="${name}[]">`. */
14
+ name?: string;
15
+ /** The `form` attribute for the hidden inputs, for a TagInput rendered outside its `<form>`. */
16
+ form?: string;
11
17
  };
12
18
 
13
19
  /**
14
20
  * Token input for tags: existing tags render as removable `TagChip`s, typing
15
21
  * plus Enter or comma commits a new one, Backspace on an empty field removes
16
22
  * the last. Duplicates are ignored. Controlled only — there is no
17
- * `defaultValue`, the parent always owns `value`.
23
+ * `defaultValue`, the parent always owns `value` and receives changes via
24
+ * `onValueChange`. With `name` set, each tag is mirrored into a hidden
25
+ * `<input name="${name}[]">` for native form submission.
18
26
  *
19
27
  * The chrome matches `Input` (same border/focus tokens) so it sits naturally
20
28
  * among other form fields; the field has no visible label of its own, so
21
29
  * give it an accessible name via a `<label htmlFor={id}>` (pass `id`) or
22
30
  * `aria-label`.
23
31
  */
24
- export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onChange, placeholder = "Add a tag…", id, className }, ref) => {
32
+ export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onValueChange, placeholder = "Add a tag…", id, className, name, form }, ref) => {
25
33
  const [draft, setDraft] = useState("");
26
34
 
27
35
  const commit = () => {
28
36
  const tag = draft.trim();
29
- if (tag && !value.includes(tag)) onChange([...value, tag]);
37
+ if (tag && !value.includes(tag)) onValueChange([...value, tag]);
30
38
  setDraft("");
31
39
  };
32
40
 
@@ -35,7 +43,7 @@ export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onCh
35
43
  e.preventDefault();
36
44
  commit();
37
45
  } else if (e.key === "Backspace" && draft === "" && value.length > 0) {
38
- onChange(value.slice(0, -1));
46
+ onValueChange(value.slice(0, -1));
39
47
  }
40
48
  };
41
49
 
@@ -48,8 +56,9 @@ export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onCh
48
56
  )}
49
57
  >
50
58
  {value.map((tag) => (
51
- <TagChip key={tag} tag={tag} onRemove={() => onChange(value.filter((t) => t !== tag))} />
59
+ <TagChip key={tag} tag={tag} onRemove={() => onValueChange(value.filter((t) => t !== tag))} />
52
60
  ))}
61
+ {name && value.map((tag) => <input key={tag} type="hidden" name={`${name}[]`} value={tag} {...(form ? { form } : {})} />)}
53
62
  <input
54
63
  id={id}
55
64
  value={draft}
@@ -1,28 +1,64 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import * as React from "react";
5
+ import type { WritableRefObject } from "../../internal/types";
3
6
 
4
- export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
7
+ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
8
+ /**
9
+ * Grows the textarea to fit its content instead of scrolling internally.
10
+ * Off by default — a fixed box that scrolls is still correct for e.g. a
11
+ * bounded comment field. `rows` still sets the starting height.
12
+ */
13
+ autosize?: boolean;
14
+ };
5
15
 
6
16
  /**
7
17
  * Multi-line text input for longer free-form text.
8
18
  *
9
19
  * A thin styled wrapper around `<textarea>` — no custom props beyond
10
- * `React.TextareaHTMLAttributes`, no auto-resize, and no maximum-length UI of
20
+ * `autosize` and `React.TextareaHTMLAttributes`, and no maximum-length UI of
11
21
  * its own. Height comes from a `min-h-[60px]` default plus whatever `rows`
12
- * or `className` the caller passes; growing with content is the caller's
13
- * responsibility. Controlled or uncontrolled exactly like a native textarea.
22
+ * or `className` the caller passes. With `autosize`, that starting height
23
+ * grows with content instead; without it, growing with content is the
24
+ * caller's responsibility. Controlled or uncontrolled exactly like a native
25
+ * textarea.
14
26
  *
15
27
  * Meant to be wrapped by `FormField` for label, description and validation
16
28
  * wiring.
17
29
  */
18
- const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ className, ...props }, ref) => {
30
+ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ className, autosize = false, onInput, value, ...props }, ref) => {
31
+ const innerRef = React.useRef<HTMLTextAreaElement | null>(null);
32
+
33
+ const resize = React.useCallback(() => {
34
+ const el = innerRef.current;
35
+ if (!el) return;
36
+ el.style.height = "auto";
37
+ el.style.height = `${el.scrollHeight}px`;
38
+ }, []);
39
+
40
+ // biome-ignore lint/correctness/useExhaustiveDependencies: value only triggers the resize, it isn't read here
41
+ React.useLayoutEffect(() => {
42
+ if (autosize) resize();
43
+ }, [autosize, resize, value]);
44
+
19
45
  return (
20
46
  <textarea
47
+ value={value}
21
48
  className={cn(
22
49
  "textarea border-(color:--textarea-border) focus-visible:ring-(color:--textarea-ring) flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs placeholder:text-(--textarea-placeholder-fg) focus-visible:outline-hidden focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50",
50
+ autosize && "resize-none overflow-hidden",
23
51
  className
24
52
  )}
25
- ref={ref}
53
+ ref={(node) => {
54
+ innerRef.current = node;
55
+ if (typeof ref === "function") ref(node);
56
+ else if (ref) (ref as WritableRefObject<HTMLTextAreaElement | null>).current = node;
57
+ }}
58
+ onInput={(event) => {
59
+ if (autosize) resize();
60
+ onInput?.(event);
61
+ }}
26
62
  {...props}
27
63
  />
28
64
  );
@@ -5,7 +5,7 @@
5
5
  * button.css's header for why `@layer components` is load-bearing.
6
6
  *
7
7
  * Textarea's background is literal `bg-transparent` in the markup, not a
8
- * semantic token today — there is nothing in tier 2 to point a `--textarea-bg`
8
+ * semantic token today — there is nothing in the semantic layer to point a `--textarea-bg`
9
9
  * at, so no such token is introduced here. Border, placeholder and focus ring
10
10
  * are the tokens that existed as semantic classes before this file, and are
11
11
  * the ones made overridable.
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import type { TimePeriod } from "./timepicker.types";
3
5
 
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cn } from "@sixthshift/design-system/utils";
2
4
  import { useEffect, useRef } from "react";
3
5
 
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
2
4
  import { useControllableState } from "@sixthshift/design-system/hooks";
3
5
  import { cn } from "@sixthshift/design-system/utils";
@@ -6,6 +8,7 @@ import * as React from "react";
6
8
  import { useCallback, useId, useMemo, useState } from "react";
7
9
  import { fromISOTime, fromISOTimeOrUndefined, type Temporal, toISOTimeOrUndefined } from "../../date-time";
8
10
  import { PickerField } from "../../internal";
11
+ import { useEscapeLayer } from "../../internal/escapeLayers";
9
12
  import { Button } from "../Button";
10
13
  import { Separator } from "../Separator";
11
14
  import { PeriodSelector } from "./PeriodSelector";
@@ -241,6 +244,10 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
241
244
 
242
245
  const click = useClick(context);
243
246
  const dismiss = useDismiss(context);
247
+
248
+ // While open, an Escape press closes this picker's popover and must not
249
+ // also close a Modal/Sheet it is rendered inside.
250
+ useEscapeLayer(open);
244
251
  const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
245
252
 
246
253
  // IDs for accessibility
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import type { Temporal } from "../../date-time";
2
4
  import { SegmentedField, type SegmentSpec, type SegmentValues } from "../../internal";
3
5
  import { parsedToTemporal, temporalTimeToISO, to12Hour, to24Hour } from "./timepicker.hooks";