@sixthshift/design-system 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/README.md +132 -87
  2. package/dist/components/Badge/Badge.d.ts +12 -4
  3. package/dist/components/Badge/Badge.d.ts.map +1 -1
  4. package/dist/components/Badge/Badge.js +8 -6
  5. package/dist/components/Badge/Badge.js.map +1 -1
  6. package/dist/components/Button/Button.d.ts +26 -3
  7. package/dist/components/Button/Button.d.ts.map +1 -1
  8. package/dist/components/Button/Button.js +14 -5
  9. package/dist/components/Button/Button.js.map +1 -1
  10. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  11. package/dist/components/Calendar/Calendar.js +1 -0
  12. package/dist/components/Calendar/Calendar.js.map +1 -1
  13. package/dist/components/Calendar/CalendarView.d.ts +0 -11
  14. package/dist/components/Calendar/CalendarView.d.ts.map +1 -1
  15. package/dist/components/Calendar/CalendarView.js +1 -0
  16. package/dist/components/Calendar/CalendarView.js.map +1 -1
  17. package/dist/components/Calendar/calendar.hooks.d.ts.map +1 -1
  18. package/dist/components/Calendar/calendar.hooks.js +1 -0
  19. package/dist/components/Calendar/calendar.hooks.js.map +1 -1
  20. package/dist/components/Card/Card.d.ts +2 -2
  21. package/dist/components/Card/Card.d.ts.map +1 -1
  22. package/dist/components/Card/Card.js +3 -2
  23. package/dist/components/Card/Card.js.map +1 -1
  24. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  25. package/dist/components/Checkbox/Checkbox.js +1 -0
  26. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  27. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
  28. package/dist/components/CheckboxGroup/CheckboxGroup.js +1 -0
  29. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
  30. package/dist/components/Code/Editor/Editor.d.ts.map +1 -1
  31. package/dist/components/Code/Editor/Editor.js +1 -0
  32. package/dist/components/Code/Editor/Editor.js.map +1 -1
  33. package/dist/components/Code/Workspace/StatusBar.d.ts.map +1 -1
  34. package/dist/components/Code/Workspace/StatusBar.js +1 -0
  35. package/dist/components/Code/Workspace/StatusBar.js.map +1 -1
  36. package/dist/components/Code/Workspace/Toolbar.d.ts.map +1 -1
  37. package/dist/components/Code/Workspace/Toolbar.js +1 -0
  38. package/dist/components/Code/Workspace/Toolbar.js.map +1 -1
  39. package/dist/components/Code/Workspace/Workspace.d.ts.map +1 -1
  40. package/dist/components/Code/Workspace/Workspace.js +1 -0
  41. package/dist/components/Code/Workspace/Workspace.js.map +1 -1
  42. package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
  43. package/dist/components/DatePicker/DatePicker.js +7 -1
  44. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  45. package/dist/components/DatePicker/DateSegments.d.ts.map +1 -1
  46. package/dist/components/DatePicker/DateSegments.js +1 -0
  47. package/dist/components/DatePicker/DateSegments.js.map +1 -1
  48. package/dist/components/DatePicker/datepicker.hooks.d.ts.map +1 -1
  49. package/dist/components/DatePicker/datepicker.hooks.js +1 -0
  50. package/dist/components/DatePicker/datepicker.hooks.js.map +1 -1
  51. package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  52. package/dist/components/DateRangePicker/DateRangePicker.js +1 -0
  53. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  54. package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  55. package/dist/components/DateTimePicker/DateTimePicker.js +7 -1
  56. package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
  57. package/dist/components/DateTimePicker/DateTimeSegments.d.ts.map +1 -1
  58. package/dist/components/DateTimePicker/DateTimeSegments.js +1 -0
  59. package/dist/components/DateTimePicker/DateTimeSegments.js.map +1 -1
  60. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
  61. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +7 -1
  62. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
  63. package/dist/components/FormField/FormField.d.ts +31 -10
  64. package/dist/components/FormField/FormField.d.ts.map +1 -1
  65. package/dist/components/FormField/FormField.js +46 -17
  66. package/dist/components/FormField/FormField.js.map +1 -1
  67. package/dist/components/FormField/index.d.ts +2 -2
  68. package/dist/components/FormField/index.d.ts.map +1 -1
  69. package/dist/components/FormField/index.js +1 -1
  70. package/dist/components/FormField/index.js.map +1 -1
  71. package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
  72. package/dist/components/HoverCard/HoverCard.js +4 -0
  73. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  74. package/dist/components/HoverCard/components/HoverCardContent.d.ts +16 -2
  75. package/dist/components/HoverCard/components/HoverCardContent.d.ts.map +1 -1
  76. package/dist/components/HoverCard/components/HoverCardContent.js +4 -3
  77. package/dist/components/HoverCard/components/HoverCardContent.js.map +1 -1
  78. package/dist/components/HoverCard/components/HoverCardContext.d.ts +2 -0
  79. package/dist/components/HoverCard/components/HoverCardContext.d.ts.map +1 -1
  80. package/dist/components/HoverCard/components/HoverCardContext.js +1 -0
  81. package/dist/components/HoverCard/components/HoverCardContext.js.map +1 -1
  82. package/dist/components/HoverCard/components/HoverCardTrigger.d.ts.map +1 -1
  83. package/dist/components/HoverCard/components/HoverCardTrigger.js +1 -0
  84. package/dist/components/HoverCard/components/HoverCardTrigger.js.map +1 -1
  85. package/dist/components/Message/Message.d.ts +5 -1
  86. package/dist/components/Message/Message.d.ts.map +1 -1
  87. package/dist/components/Message/Message.js +3 -3
  88. package/dist/components/Message/Message.js.map +1 -1
  89. package/dist/components/Modal/Modal.d.ts +26 -9
  90. package/dist/components/Modal/Modal.d.ts.map +1 -1
  91. package/dist/components/Modal/Modal.js +46 -21
  92. package/dist/components/Modal/Modal.js.map +1 -1
  93. package/dist/components/Modal/components/ModalContext.d.ts.map +1 -1
  94. package/dist/components/Modal/components/ModalContext.js +1 -0
  95. package/dist/components/Modal/components/ModalContext.js.map +1 -1
  96. package/dist/components/Modal/components/ModalHeader.d.ts.map +1 -1
  97. package/dist/components/Modal/components/ModalHeader.js +1 -0
  98. package/dist/components/Modal/components/ModalHeader.js.map +1 -1
  99. package/dist/components/Popover/Popover.d.ts +3 -1
  100. package/dist/components/Popover/Popover.d.ts.map +1 -1
  101. package/dist/components/Popover/Popover.js +8 -0
  102. package/dist/components/Popover/Popover.js.map +1 -1
  103. package/dist/components/Popover/components/PopoverBody.d.ts +16 -2
  104. package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
  105. package/dist/components/Popover/components/PopoverBody.js +4 -3
  106. package/dist/components/Popover/components/PopoverBody.js.map +1 -1
  107. package/dist/components/Popover/components/PopoverClose.d.ts.map +1 -1
  108. package/dist/components/Popover/components/PopoverClose.js +1 -0
  109. package/dist/components/Popover/components/PopoverClose.js.map +1 -1
  110. package/dist/components/Popover/components/PopoverContext.d.ts +2 -0
  111. package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
  112. package/dist/components/Popover/components/PopoverContext.js +1 -0
  113. package/dist/components/Popover/components/PopoverContext.js.map +1 -1
  114. package/dist/components/Popover/components/PopoverTrigger.d.ts.map +1 -1
  115. package/dist/components/Popover/components/PopoverTrigger.js +1 -0
  116. package/dist/components/Popover/components/PopoverTrigger.js.map +1 -1
  117. package/dist/components/RadioButton/RadioButton.d.ts.map +1 -1
  118. package/dist/components/RadioButton/RadioButton.js +1 -0
  119. package/dist/components/RadioButton/RadioButton.js.map +1 -1
  120. package/dist/components/RadioButtonGroup/RadioButtonGroup.d.ts.map +1 -1
  121. package/dist/components/RadioButtonGroup/RadioButtonGroup.js +1 -0
  122. package/dist/components/RadioButtonGroup/RadioButtonGroup.js.map +1 -1
  123. package/dist/components/SearchInput/SearchInput.d.ts +10 -7
  124. package/dist/components/SearchInput/SearchInput.d.ts.map +1 -1
  125. package/dist/components/SearchInput/SearchInput.js +11 -6
  126. package/dist/components/SearchInput/SearchInput.js.map +1 -1
  127. package/dist/components/Select/Select.d.ts +6 -0
  128. package/dist/components/Select/Select.d.ts.map +1 -1
  129. package/dist/components/Select/Select.js +11 -4
  130. package/dist/components/Select/Select.js.map +1 -1
  131. package/dist/components/Select/SelectDropdown.d.ts +3 -1
  132. package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
  133. package/dist/components/Select/SelectDropdown.js +3 -2
  134. package/dist/components/Select/SelectDropdown.js.map +1 -1
  135. package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
  136. package/dist/components/Select/SelectTrigger.js +5 -1
  137. package/dist/components/Select/SelectTrigger.js.map +1 -1
  138. package/dist/components/Select/useSelectKeyboard.d.ts.map +1 -1
  139. package/dist/components/Select/useSelectKeyboard.js +1 -0
  140. package/dist/components/Select/useSelectKeyboard.js.map +1 -1
  141. package/dist/components/Sheet/Sheet.d.ts +12 -0
  142. package/dist/components/Sheet/Sheet.d.ts.map +1 -1
  143. package/dist/components/Sheet/Sheet.js +26 -10
  144. package/dist/components/Sheet/Sheet.js.map +1 -1
  145. package/dist/components/Sheet/components/SheetContext.d.ts.map +1 -1
  146. package/dist/components/Sheet/components/SheetContext.js +1 -0
  147. package/dist/components/Sheet/components/SheetContext.js.map +1 -1
  148. package/dist/components/Sheet/components/SheetHeader.d.ts.map +1 -1
  149. package/dist/components/Sheet/components/SheetHeader.js +1 -0
  150. package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
  151. package/dist/components/Spinner/Spinner.d.ts +2 -2
  152. package/dist/components/Spinner/Spinner.js +2 -2
  153. package/dist/components/Switch/Switch.d.ts.map +1 -1
  154. package/dist/components/Switch/Switch.js +1 -0
  155. package/dist/components/Switch/Switch.js.map +1 -1
  156. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  157. package/dist/components/Tabs/Tabs.js +1 -0
  158. package/dist/components/Tabs/Tabs.js.map +1 -1
  159. package/dist/components/Tabs/components/TabsContext.d.ts.map +1 -1
  160. package/dist/components/Tabs/components/TabsContext.js +1 -0
  161. package/dist/components/Tabs/components/TabsContext.js.map +1 -1
  162. package/dist/components/Tabs/components/TabsList.d.ts.map +1 -1
  163. package/dist/components/Tabs/components/TabsList.js +1 -0
  164. package/dist/components/Tabs/components/TabsList.js.map +1 -1
  165. package/dist/components/Tabs/components/TabsPanels.d.ts.map +1 -1
  166. package/dist/components/Tabs/components/TabsPanels.js +1 -0
  167. package/dist/components/Tabs/components/TabsPanels.js.map +1 -1
  168. package/dist/components/Tabs/components/TabsTrigger.d.ts.map +1 -1
  169. package/dist/components/Tabs/components/TabsTrigger.js +2 -1
  170. package/dist/components/Tabs/components/TabsTrigger.js.map +1 -1
  171. package/dist/components/TagChip/TagChip.d.ts.map +1 -1
  172. package/dist/components/TagChip/TagChip.js +1 -0
  173. package/dist/components/TagChip/TagChip.js.map +1 -1
  174. package/dist/components/TagInput/TagInput.d.ts +8 -2
  175. package/dist/components/TagInput/TagInput.d.ts.map +1 -1
  176. package/dist/components/TagInput/TagInput.js +8 -5
  177. package/dist/components/TagInput/TagInput.js.map +1 -1
  178. package/dist/components/Textarea/Textarea.d.ts +21 -5
  179. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  180. package/dist/components/Textarea/Textarea.js +31 -5
  181. package/dist/components/Textarea/Textarea.js.map +1 -1
  182. package/dist/components/TimePicker/PeriodSelector.d.ts.map +1 -1
  183. package/dist/components/TimePicker/PeriodSelector.js +1 -0
  184. package/dist/components/TimePicker/PeriodSelector.js.map +1 -1
  185. package/dist/components/TimePicker/TimeColumn.d.ts.map +1 -1
  186. package/dist/components/TimePicker/TimeColumn.js +1 -0
  187. package/dist/components/TimePicker/TimeColumn.js.map +1 -1
  188. package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
  189. package/dist/components/TimePicker/TimePicker.js +7 -1
  190. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  191. package/dist/components/TimePicker/TimeSegments.d.ts.map +1 -1
  192. package/dist/components/TimePicker/TimeSegments.js +1 -0
  193. package/dist/components/TimePicker/TimeSegments.js.map +1 -1
  194. package/dist/components/Toast/Toast.d.ts +16 -2
  195. package/dist/components/Toast/Toast.d.ts.map +1 -1
  196. package/dist/components/Toast/Toast.js +17 -7
  197. package/dist/components/Toast/Toast.js.map +1 -1
  198. package/dist/components/Toggle/Toggle.d.ts +5 -1
  199. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  200. package/dist/components/Toggle/Toggle.js +4 -3
  201. package/dist/components/Toggle/Toggle.js.map +1 -1
  202. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +3 -0
  203. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
  204. package/dist/components/ToggleGroup/ToggleGroupMultiple.js +4 -3
  205. package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
  206. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +3 -0
  207. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
  208. package/dist/components/ToggleGroup/ToggleGroupSingle.js +4 -3
  209. package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
  210. package/dist/components/ToggleGroup/toggleGroup.types.d.ts +13 -0
  211. package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
  212. package/dist/components/Tooltip/Tooltip.d.ts +3 -1
  213. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  214. package/dist/components/Tooltip/Tooltip.js +4 -0
  215. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  216. package/dist/components/Tooltip/components/TooltipBody.d.ts +16 -2
  217. package/dist/components/Tooltip/components/TooltipBody.d.ts.map +1 -1
  218. package/dist/components/Tooltip/components/TooltipBody.js +4 -3
  219. package/dist/components/Tooltip/components/TooltipBody.js.map +1 -1
  220. package/dist/components/Tooltip/components/TooltipContext.d.ts +2 -0
  221. package/dist/components/Tooltip/components/TooltipContext.d.ts.map +1 -1
  222. package/dist/components/Tooltip/components/TooltipContext.js +1 -0
  223. package/dist/components/Tooltip/components/TooltipContext.js.map +1 -1
  224. package/dist/components/Tooltip/components/TooltipTrigger.d.ts.map +1 -1
  225. package/dist/components/Tooltip/components/TooltipTrigger.js +1 -0
  226. package/dist/components/Tooltip/components/TooltipTrigger.js.map +1 -1
  227. package/dist/hooks/useCollapsible.d.ts.map +1 -1
  228. package/dist/hooks/useCollapsible.js +1 -0
  229. package/dist/hooks/useCollapsible.js.map +1 -1
  230. package/dist/hooks/useControllableState.d.ts.map +1 -1
  231. package/dist/hooks/useControllableState.js +1 -0
  232. package/dist/hooks/useControllableState.js.map +1 -1
  233. package/dist/hooks/useDebouncedCallback.d.ts.map +1 -1
  234. package/dist/hooks/useDebouncedCallback.js +1 -0
  235. package/dist/hooks/useDebouncedCallback.js.map +1 -1
  236. package/dist/hooks/useDebouncedState.d.ts.map +1 -1
  237. package/dist/hooks/useDebouncedState.js +1 -0
  238. package/dist/hooks/useDebouncedState.js.map +1 -1
  239. package/dist/hooks/useDeviceFormFactor.d.ts.map +1 -1
  240. package/dist/hooks/useDeviceFormFactor.js +1 -0
  241. package/dist/hooks/useDeviceFormFactor.js.map +1 -1
  242. package/dist/hooks/useLocalStorage.d.ts.map +1 -1
  243. package/dist/hooks/useLocalStorage.js +1 -0
  244. package/dist/hooks/useLocalStorage.js.map +1 -1
  245. package/dist/hooks/useMergedFloatingRef.d.ts.map +1 -1
  246. package/dist/hooks/useMergedFloatingRef.js +1 -0
  247. package/dist/hooks/useMergedFloatingRef.js.map +1 -1
  248. package/dist/hooks/usePresence.d.ts.map +1 -1
  249. package/dist/hooks/usePresence.js +1 -0
  250. package/dist/hooks/usePresence.js.map +1 -1
  251. package/dist/hooks/useStack.d.ts.map +1 -1
  252. package/dist/hooks/useStack.js +34 -10
  253. package/dist/hooks/useStack.js.map +1 -1
  254. package/dist/hooks/useTheme.d.ts.map +1 -1
  255. package/dist/hooks/useTheme.js +1 -0
  256. package/dist/hooks/useTheme.js.map +1 -1
  257. package/dist/internal/PickerField.d.ts.map +1 -1
  258. package/dist/internal/PickerField.js +1 -0
  259. package/dist/internal/PickerField.js.map +1 -1
  260. package/dist/internal/SegmentedField.d.ts.map +1 -1
  261. package/dist/internal/SegmentedField.js +1 -0
  262. package/dist/internal/SegmentedField.js.map +1 -1
  263. package/dist/internal/brandScope.d.ts +25 -0
  264. package/dist/internal/brandScope.d.ts.map +1 -0
  265. package/dist/internal/brandScope.js +37 -0
  266. package/dist/internal/brandScope.js.map +1 -0
  267. package/dist/internal/escapeLayers.d.ts +12 -0
  268. package/dist/internal/escapeLayers.d.ts.map +1 -0
  269. package/dist/internal/escapeLayers.js +48 -0
  270. package/dist/internal/escapeLayers.js.map +1 -0
  271. package/dist/lib/ErrorBoundary.d.ts.map +1 -1
  272. package/dist/lib/ErrorBoundary.js +1 -0
  273. package/dist/lib/ErrorBoundary.js.map +1 -1
  274. package/dist/lib/contexts/ComponentsContext/ComponentsContext.d.ts.map +1 -1
  275. package/dist/lib/contexts/ComponentsContext/ComponentsContext.js +1 -0
  276. package/dist/lib/contexts/ComponentsContext/ComponentsContext.js.map +1 -1
  277. package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts +9 -4
  278. package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts.map +1 -1
  279. package/dist/lib/contexts/OverlayContext/OverlayContext.js +25 -12
  280. package/dist/lib/contexts/OverlayContext/OverlayContext.js.map +1 -1
  281. package/dist/lib/contexts/OverlayContext/ToastStack.d.ts +20 -0
  282. package/dist/lib/contexts/OverlayContext/ToastStack.d.ts.map +1 -0
  283. package/dist/lib/contexts/OverlayContext/ToastStack.js +45 -0
  284. package/dist/lib/contexts/OverlayContext/ToastStack.js.map +1 -0
  285. package/dist/lib/contexts/OverlayContext/hooks/useModal.d.ts.map +1 -1
  286. package/dist/lib/contexts/OverlayContext/hooks/useModal.js +1 -0
  287. package/dist/lib/contexts/OverlayContext/hooks/useModal.js.map +1 -1
  288. package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts +27 -10
  289. package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts.map +1 -1
  290. package/dist/lib/contexts/OverlayContext/hooks/useToast.js +31 -49
  291. package/dist/lib/contexts/OverlayContext/hooks/useToast.js.map +1 -1
  292. package/dist/lib/contexts/OverlayContext/index.d.ts +2 -0
  293. package/dist/lib/contexts/OverlayContext/index.d.ts.map +1 -1
  294. package/dist/lib/contexts/OverlayContext/index.js +2 -0
  295. package/dist/lib/contexts/OverlayContext/index.js.map +1 -1
  296. package/dist/lib/contexts/OverlayContext/toastStore.d.ts +68 -0
  297. package/dist/lib/contexts/OverlayContext/toastStore.d.ts.map +1 -0
  298. package/dist/lib/contexts/OverlayContext/toastStore.js +69 -0
  299. package/dist/lib/contexts/OverlayContext/toastStore.js.map +1 -0
  300. package/dist/lib/withErrorBoundary.d.ts.map +1 -1
  301. package/dist/lib/withErrorBoundary.js +1 -0
  302. package/dist/lib/withErrorBoundary.js.map +1 -1
  303. package/dist/lib/withSuspenseAndErrorBoundary.d.ts.map +1 -1
  304. package/dist/lib/withSuspenseAndErrorBoundary.js +1 -0
  305. package/dist/lib/withSuspenseAndErrorBoundary.js.map +1 -1
  306. package/dist/{theme/schema.d.ts → theming/vocabulary.d.ts} +4 -4
  307. package/dist/theming/vocabulary.d.ts.map +1 -0
  308. package/dist/{theme/schema.js → theming/vocabulary.js} +4 -4
  309. package/dist/theming/vocabulary.js.map +1 -0
  310. package/package.json +18 -6
  311. package/src/components/Badge/Badge.tsx +12 -6
  312. package/src/components/Button/Button.tsx +25 -5
  313. package/src/{theme/recipes/button.css → components/Button/button.recipe.css} +2 -2
  314. package/src/components/Calendar/Calendar.tsx +2 -0
  315. package/src/components/Calendar/CalendarView.tsx +2 -0
  316. package/src/components/Calendar/calendar.hooks.ts +2 -0
  317. package/src/components/Card/Card.tsx +4 -2
  318. package/src/components/Checkbox/Checkbox.tsx +2 -0
  319. package/src/components/CheckboxGroup/CheckboxGroup.tsx +2 -0
  320. package/src/components/Code/Editor/Editor.tsx +2 -0
  321. package/src/components/Code/Workspace/StatusBar.tsx +2 -0
  322. package/src/components/Code/Workspace/Toolbar.tsx +2 -0
  323. package/src/components/Code/Workspace/Workspace.tsx +2 -0
  324. package/src/components/DatePicker/DatePicker.tsx +10 -0
  325. package/src/components/DatePicker/DateSegments.tsx +2 -0
  326. package/src/components/DatePicker/datepicker.hooks.ts +2 -0
  327. package/src/components/DateRangePicker/DateRangePicker.tsx +2 -0
  328. package/src/components/DateTimePicker/DateTimePicker.tsx +10 -1
  329. package/src/components/DateTimePicker/DateTimeSegments.tsx +2 -0
  330. package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +10 -1
  331. package/src/components/FormField/FormField.tsx +94 -42
  332. package/src/components/FormField/index.ts +2 -2
  333. package/src/components/HoverCard/HoverCard.tsx +5 -0
  334. package/src/components/HoverCard/components/HoverCardContent.tsx +13 -3
  335. package/src/components/HoverCard/components/HoverCardContext.tsx +4 -0
  336. package/src/components/HoverCard/components/HoverCardTrigger.tsx +2 -0
  337. package/src/components/Message/Message.tsx +27 -23
  338. package/src/components/Modal/Modal.tsx +88 -51
  339. package/src/components/Modal/components/ModalContext.tsx +2 -0
  340. package/src/components/Modal/components/ModalHeader.tsx +2 -0
  341. package/src/components/Popover/Popover.tsx +10 -0
  342. package/src/components/Popover/components/PopoverBody.tsx +13 -3
  343. package/src/components/Popover/components/PopoverClose.tsx +2 -0
  344. package/src/components/Popover/components/PopoverContext.tsx +4 -0
  345. package/src/components/Popover/components/PopoverTrigger.tsx +2 -0
  346. package/src/components/RadioButton/RadioButton.tsx +2 -0
  347. package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +2 -0
  348. package/src/components/SearchInput/SearchInput.tsx +15 -8
  349. package/src/components/Select/Select.tsx +27 -2
  350. package/src/components/Select/SelectDropdown.tsx +6 -0
  351. package/src/components/Select/SelectTrigger.tsx +5 -0
  352. package/src/components/Select/useSelectKeyboard.ts +2 -0
  353. package/src/components/Sheet/Sheet.tsx +59 -34
  354. package/src/components/Sheet/components/SheetContext.tsx +2 -0
  355. package/src/components/Sheet/components/SheetHeader.tsx +2 -0
  356. package/src/components/Spinner/Spinner.tsx +2 -2
  357. package/src/components/Switch/Switch.tsx +2 -0
  358. package/src/components/Tabs/Tabs.tsx +2 -0
  359. package/src/components/Tabs/components/TabsContext.tsx +2 -0
  360. package/src/components/Tabs/components/TabsList.tsx +2 -0
  361. package/src/components/Tabs/components/TabsPanels.tsx +2 -0
  362. package/src/components/Tabs/components/TabsTrigger.tsx +3 -1
  363. package/src/{theme/recipes/tabs.css → components/Tabs/tabs.recipe.css} +1 -1
  364. package/src/components/TagChip/TagChip.tsx +2 -0
  365. package/src/components/TagInput/TagInput.tsx +15 -6
  366. package/src/components/Textarea/Textarea.tsx +42 -6
  367. package/src/{theme/recipes/textarea.css → components/Textarea/textarea.recipe.css} +1 -1
  368. package/src/components/TimePicker/PeriodSelector.tsx +2 -0
  369. package/src/components/TimePicker/TimeColumn.tsx +2 -0
  370. package/src/components/TimePicker/TimePicker.tsx +10 -0
  371. package/src/components/TimePicker/TimeSegments.tsx +2 -0
  372. package/src/components/Toast/Toast.tsx +26 -6
  373. package/src/components/Toggle/Toggle.tsx +20 -3
  374. package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +8 -1
  375. package/src/components/ToggleGroup/ToggleGroupSingle.tsx +8 -0
  376. package/src/components/ToggleGroup/toggleGroup.types.ts +13 -0
  377. package/src/components/Tooltip/Tooltip.tsx +5 -0
  378. package/src/components/Tooltip/components/TooltipBody.tsx +13 -3
  379. package/src/components/Tooltip/components/TooltipContext.tsx +4 -0
  380. package/src/components/Tooltip/components/TooltipTrigger.tsx +2 -0
  381. package/src/hooks/useCollapsible.ts +2 -0
  382. package/src/hooks/useControllableState.ts +2 -0
  383. package/src/hooks/useDebouncedCallback.ts +2 -0
  384. package/src/hooks/useDebouncedState.ts +2 -0
  385. package/src/hooks/useDeviceFormFactor.ts +2 -0
  386. package/src/hooks/useLocalStorage.ts +2 -0
  387. package/src/hooks/useMergedFloatingRef.ts +2 -0
  388. package/src/hooks/usePresence.ts +2 -0
  389. package/src/hooks/useStack.ts +35 -12
  390. package/src/hooks/useTheme.ts +2 -0
  391. package/src/internal/PickerField.tsx +2 -0
  392. package/src/internal/SegmentedField.tsx +2 -0
  393. package/src/internal/brandScope.ts +39 -0
  394. package/src/internal/escapeLayers.ts +53 -0
  395. package/src/lib/ErrorBoundary.tsx +2 -0
  396. package/src/lib/contexts/ComponentsContext/ComponentsContext.tsx +2 -0
  397. package/src/lib/contexts/OverlayContext/OverlayContext.tsx +42 -26
  398. package/src/lib/contexts/OverlayContext/ToastStack.tsx +71 -0
  399. package/src/lib/contexts/OverlayContext/hooks/useModal.tsx +2 -0
  400. package/src/lib/contexts/OverlayContext/hooks/useToast.ts +30 -73
  401. package/src/lib/contexts/OverlayContext/index.ts +2 -0
  402. package/src/lib/contexts/OverlayContext/toastStore.ts +138 -0
  403. package/src/lib/withErrorBoundary.tsx +2 -0
  404. package/src/lib/withSuspenseAndErrorBoundary.tsx +2 -0
  405. package/src/theme/linen/index.css +11 -0
  406. package/src/theme/linen/palette.css +87 -0
  407. package/src/theme/linen/theme.css +371 -0
  408. package/src/theming/tailwind.css +356 -0
  409. package/src/{theme/schema.ts → theming/vocabulary.ts} +3 -3
  410. package/dist/theme/index.d.ts +0 -9
  411. package/dist/theme/index.d.ts.map +0 -1
  412. package/dist/theme/index.js +0 -8
  413. package/dist/theme/index.js.map +0 -1
  414. package/dist/theme/schema.d.ts.map +0 -1
  415. package/dist/theme/schema.js.map +0 -1
  416. package/src/theme/index.ts +0 -39
  417. package/src/theme/recipes/index.css +0 -28
  418. package/src/theme/tokens.css +0 -824
  419. /package/src/{theme/recipes/badge.css → components/Badge/badge.recipe.css} +0 -0
  420. /package/src/{theme/recipes/card.css → components/Card/card.recipe.css} +0 -0
  421. /package/src/{theme/recipes/checkbox.css → components/Checkbox/checkbox.recipe.css} +0 -0
  422. /package/src/{theme/recipes/field.css → components/Field/field.recipe.css} +0 -0
  423. /package/src/{theme/recipes/input.css → components/Input/input.recipe.css} +0 -0
  424. /package/src/{theme/recipes/message.css → components/Message/message.recipe.css} +0 -0
  425. /package/src/{theme/recipes/modal.css → components/Modal/modal.recipe.css} +0 -0
  426. /package/src/{theme/recipes/radio-button.css → components/RadioButton/radio-button.recipe.css} +0 -0
  427. /package/src/{theme/recipes/search-input.css → components/SearchInput/search-input.recipe.css} +0 -0
  428. /package/src/{theme/recipes/select.css → components/Select/select.recipe.css} +0 -0
  429. /package/src/{theme/recipes/sheet.css → components/Sheet/sheet.recipe.css} +0 -0
  430. /package/src/{theme/recipes/spinner.css → components/Spinner/spinner.recipe.css} +0 -0
  431. /package/src/{theme/recipes/switch.css → components/Switch/switch.recipe.css} +0 -0
  432. /package/src/{theme/recipes/tag-chip.css → components/TagChip/tag-chip.recipe.css} +0 -0
  433. /package/src/{theme/recipes/toggle.css → components/Toggle/toggle.recipe.css} +0 -0
@@ -1,10 +1,19 @@
1
+ "use client";
2
+
1
3
  import { FloatingPortal, type FloatingPortalProps } from "@floating-ui/react";
2
4
  import { type StackItem, useStack } from "@sixthshift/design-system/hooks";
3
5
  import { createContext, type FunctionComponent, type PropsWithChildren, useContext, useEffect, useMemo } from "react";
6
+ import { hasOpenEscapeLayer } from "../../../internal/escapeLayers";
7
+ import { ToastStack } from "./ToastStack";
8
+ import { toastStore as defaultToastStore, type ToastStore } from "./toastStore";
4
9
 
5
10
  type OverlayContextProps = {
6
11
  modal?: FloatingPortalProps["root"];
7
12
  toast?: FloatingPortalProps["root"];
13
+ /** The toast stack to render. Default: the app's one, which `toast()` opens onto. Hand in your own for a second bundle or a test. */
14
+ toasts?: ToastStore;
15
+ /** Merged over the toast stack's container classes, so an app can move it (above a bottom bar, into a corner). */
16
+ toastClassName?: string;
8
17
  };
9
18
 
10
19
  /** Stack item for overlays - component is a self-contained wrapper */
@@ -18,10 +27,13 @@ type OverlayStackItem = StackItem & {
18
27
  };
19
28
 
20
29
  type OverlayContextType = {
21
- modalRoot?: FloatingPortalProps["root"];
30
+ // `undefined` spelled out rather than an optional `?:` — the context value
31
+ // below always sets the key, and `exactOptionalPropertyTypes` treats "absent"
32
+ // and "present but undefined" as different types.
33
+ modalRoot: FloatingPortalProps["root"] | undefined;
22
34
  modalStack: ReturnType<typeof useStack<OverlayStackItem>>;
23
- toastRoot?: FloatingPortalProps["root"];
24
- toastStack: ReturnType<typeof useStack<OverlayStackItem>>;
35
+ toastRoot: FloatingPortalProps["root"] | undefined;
36
+ toastStore: ToastStore;
25
37
  };
26
38
 
27
39
  /**
@@ -35,18 +47,28 @@ const rootProp = (root: FloatingPortalProps["root"] | undefined) => (root === un
35
47
  const OverlayContext = createContext<OverlayContextType>(undefined as unknown as OverlayContextType);
36
48
  export const useOverlayContext = () => useContext(OverlayContext);
37
49
 
38
- export const OverlayProvider = ({ modal: modalRoot, toast: toastRoot, children }: PropsWithChildren<OverlayContextProps>) => {
39
- // The roots pass through unresolved, deliberately. Defaulting them to
40
- // `document.body` here read the DOM during render, which threw the whole
41
- // tree under SSR — and it bought nothing: `FloatingPortal` already falls
42
- // back to `document.body` when no `root` is given, on the client, where a
43
- // body exists. Both portals below are behind a non-empty stack, and both
44
- // stacks start empty, so nothing portals on the server either way.
50
+ export const OverlayProvider = ({
51
+ modal: modalRoot,
52
+ toast: toastRoot,
53
+ toasts: toastStore = defaultToastStore,
54
+ toastClassName,
55
+ children,
56
+ }: PropsWithChildren<OverlayContextProps>) => {
57
+ // The roots pass through unresolved, deliberately. `"use client"` makes this a
58
+ // Client Component, but a Client Component is still rendered once on the
59
+ // server — defaulting to `document.body` here read the DOM at render scope and
60
+ // threw "document is not defined" on the first App Router request, which
61
+ // src/testing/stories.ssr.test.tsx and src/exports.ssr.test.tsx now catch. It
62
+ // bought nothing either: `FloatingPortal` already falls back to
63
+ // `document.body` when no `root` is given, and does it in an effect, on the
64
+ // client, where a body exists. Both portals below are behind a non-empty
65
+ // stack, and both stacks start empty, so nothing portals on the server anyway.
66
+ //
67
+ // Modals are a `useStack` here; toasts are a store outside React, so that
68
+ // `toast()` works from code that is not a component.
45
69
  const modalStack = useStack<OverlayStackItem>([]);
46
- const toastStack = useStack<OverlayStackItem>([]);
47
70
 
48
71
  const [modals] = modalStack;
49
- const [toasts] = toastStack;
50
72
 
51
73
  // Global escape key handler - closes topmost modal
52
74
  useEffect(() => {
@@ -54,6 +76,10 @@ export const OverlayProvider = ({ modal: modalRoot, toast: toastRoot, children }
54
76
 
55
77
  const handleEscape = (event: KeyboardEvent) => {
56
78
  if (event.key === "Escape") {
79
+ // A transient overlay open above the modal (a Select dropdown, a
80
+ // Popover, a picker calendar) consumes this Escape via its own
81
+ // dismiss handling — closing the modal too would double-fire.
82
+ if (hasOpenEscapeLayer()) return;
57
83
  const topModal = modals.at(-1);
58
84
  topModal?.onClose?.();
59
85
  }
@@ -69,9 +95,9 @@ export const OverlayProvider = ({ modal: modalRoot, toast: toastRoot, children }
69
95
  modalRoot,
70
96
  modalStack,
71
97
  toastRoot,
72
- toastStack,
98
+ toastStore,
73
99
  }),
74
- [modalRoot, modalStack, toastRoot, toastStack]
100
+ [modalRoot, modalStack, toastRoot, toastStore]
75
101
  );
76
102
 
77
103
  return (
@@ -87,18 +113,8 @@ export const OverlayProvider = ({ modal: modalRoot, toast: toastRoot, children }
87
113
  </FloatingPortal>
88
114
  )}
89
115
 
90
- {/* Toast stack - rendered in portal */}
91
- {toasts.length > 0 && (
92
- <FloatingPortal {...rootProp(toastRoot)}>
93
- <div className="pointer-events-none fixed bottom-6 left-1/2 z-toast flex -translate-x-1/2 flex-col-reverse items-center gap-3">
94
- {toasts.map(({ id, component: Component, onClose, ...props }) => (
95
- <div key={id} className="pointer-events-auto">
96
- <Component onClose={onClose} {...props} />
97
- </div>
98
- ))}
99
- </div>
100
- </FloatingPortal>
101
- )}
116
+ {/* Toast stack - portals itself, and only while it holds something */}
117
+ <ToastStack store={toastStore} className={toastClassName} {...rootProp(toastRoot)} />
102
118
  </OverlayContext.Provider>
103
119
  );
104
120
  };
@@ -0,0 +1,71 @@
1
+ "use client";
2
+
3
+ import { FloatingPortal, type FloatingPortalProps } from "@floating-ui/react";
4
+ import { Toast } from "@sixthshift/design-system/toast";
5
+ import { cn } from "@sixthshift/design-system/utils";
6
+ import { useCallback, useEffect, useSyncExternalStore } from "react";
7
+ import { toastStore as defaultStore, type ToastRecord, type ToastStore } from "./toastStore";
8
+
9
+ const EMPTY: readonly ToastRecord[] = [];
10
+
11
+ /** The store's stack, re-rendering the caller as it changes. Empty during server rendering. */
12
+ export function useToasts(store: ToastStore = defaultStore): readonly ToastRecord[] {
13
+ return useSyncExternalStore(store.subscribe, store.snapshot, () => EMPTY);
14
+ }
15
+
16
+ /**
17
+ * One toast in the stack: the dismissal timer lives here, not in the store,
18
+ * so the store stays free of the DOM. Expiry and the X button take the same
19
+ * path — `open` flips false, `Toast` plays its exit, and `onClose` drops the
20
+ * record once the animation ends.
21
+ */
22
+ function ToastItem({ record, store }: { record: ToastRecord; store: ToastStore }) {
23
+ const { id, duration, closing } = record;
24
+ // `duration` is the stack's to act on, not the toast's to render.
25
+ const { component: Component = Toast, duration: _duration, ...props } = record.options;
26
+
27
+ useEffect(() => {
28
+ if (duration <= 0 || closing) return;
29
+ const timer = setTimeout(() => store.close(id), duration);
30
+ return () => clearTimeout(timer);
31
+ }, [id, duration, closing, store]);
32
+
33
+ const onClose = useCallback(() => store.remove(id), [store, id]);
34
+
35
+ return (
36
+ <div className="pointer-events-auto" data-toast-id={id} data-toast-intent={props.intent ?? "neutral"}>
37
+ <Component {...props} standalone={false} open={!closing} onClose={onClose} />
38
+ </div>
39
+ );
40
+ }
41
+
42
+ export type ToastStackProps = {
43
+ /** The stack to render. Default: the app's one, which `toast()` opens onto. */
44
+ store?: ToastStore | undefined;
45
+ /** Portal root (default: `document.body`). */
46
+ root?: FloatingPortalProps["root"] | undefined;
47
+ /** Merged over the container's classes, so an app can move the stack (above a bottom bar, to a corner). */
48
+ className?: string | undefined;
49
+ };
50
+
51
+ /** The container's own classes: bottom centre, newest at the bottom, click-through between toasts. */
52
+ export const TOAST_STACK_CLASS = "pointer-events-none fixed bottom-6 left-1/2 z-toast flex -translate-x-1/2 flex-col-reverse items-center gap-3";
53
+
54
+ /**
55
+ * The open toasts, portalled and positioned. `OverlayProvider` renders one;
56
+ * render it yourself only when there is no provider to host it.
57
+ */
58
+ export function ToastStack({ store = defaultStore, root, className }: ToastStackProps) {
59
+ const toasts = useToasts(store);
60
+ if (toasts.length === 0) return null;
61
+ // `root` omitted rather than passed as `undefined`: see OverlayContext's `rootProp`.
62
+ return (
63
+ <FloatingPortal {...(root === undefined ? {} : { root })}>
64
+ <div className={cn(TOAST_STACK_CLASS, className)} data-toast-stack="" data-count={toasts.length}>
65
+ {toasts.map((record) => (
66
+ <ToastItem key={record.id} record={record} store={store} />
67
+ ))}
68
+ </div>
69
+ </FloatingPortal>
70
+ );
71
+ }
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { ModalContextProvider, type ModalProps, type OnClose } from "@sixthshift/design-system/modal";
2
4
  import { type ComponentType, type ReactNode, Suspense, useCallback, useId, useRef } from "react";
3
5
  import { useOverlayContext } from "../OverlayContext";
@@ -1,80 +1,37 @@
1
- import type { StackItem } from "@sixthshift/design-system/hooks";
2
- import { Toast, type ToastProps } from "@sixthshift/design-system/toast";
3
- import { type FunctionComponent, useCallback, useEffect, useId, useRef } from "react";
4
- import { useOverlayContext } from "../OverlayContext";
5
-
6
- // Default auto-dismiss duration in milliseconds
7
- const DEFAULT_DURATION = 5000;
8
-
9
- // Native replacements for lodash functions
10
- const isFunction = (value: unknown): value is FunctionComponent<ToastProps> => typeof value === "function";
11
-
12
- const isPlainObject = (value: unknown): value is ToastPropsWithDuration => typeof value === "object" && value !== null && !Array.isArray(value);
1
+ "use client";
13
2
 
14
- type ToastPropsWithDuration = Omit<ToastProps, "onClose"> & {
15
- /** Auto-dismiss duration in ms. Set to 0 to disable. Default: 5000 */
16
- duration?: number;
17
- };
3
+ import { useCallback } from "react";
4
+ import { useOverlayContext } from "../OverlayContext";
5
+ import { toastStore as defaultStore, type ToastOptions } from "../toastStore";
18
6
 
19
7
  /**
20
- * Toast stack item - extends base StackItem with component and additional props
21
- * that are passed through to the Toast component in OverlayContext
8
+ * Open toasts on the provider's stack, with the content decided at the moment
9
+ * of opening: an error's message, a count, whatever the action produced.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const { openToast } = useToast();
14
+ *
15
+ * async function save() {
16
+ * try {
17
+ * await api.save();
18
+ * openToast({ intent: "success", title: "Saved" });
19
+ * } catch (error) {
20
+ * openToast({ intent: "danger", title: "Could not save", children: String(error) });
21
+ * }
22
+ * }
23
+ * ```
24
+ *
25
+ * Outside any provider this opens on the app's default stack, which is also
26
+ * what the plain `toast()` export uses, so code that is not a component — a
27
+ * store, a callback from a service worker — has the same door.
22
28
  */
23
- type ToastStackItem = StackItem & {
24
- component: FunctionComponent<ToastProps>;
25
- onClose?: () => void;
26
- } & Partial<Omit<ToastProps, "onClose">>;
27
-
28
- export const useToast = (args: ToastPropsWithDuration | FunctionComponent<ToastProps>) => {
29
- const {
30
- toastStack: [, dispatch],
31
- } = useOverlayContext();
32
-
33
- const id = useId();
34
-
35
- const customComponent = isFunction(args) ? args : null;
36
- const props = isPlainObject(args) ? args : ({} as ToastPropsWithDuration);
37
- const { duration = DEFAULT_DURATION, ...toastPropsRaw } = props;
38
-
39
- const closeToast = useCallback(() => {
40
- dispatch({ type: "remove", id, transition: { duration: 300 } });
41
- }, [dispatch, id]);
42
-
43
- // `openToast` has to be both referentially stable — callers put it in effect
44
- // dependency arrays — and able to see the current props. A ref refreshed after
45
- // every render gives both.
46
- //
47
- // It previously memoised the props object against JSON.stringify(props) as a
48
- // cache key. JSON.stringify silently drops function-valued properties, so a
49
- // changed `onAction` whose serialisable fields were identical did not
50
- // invalidate the key, and `openToast` kept firing the stale closure.
51
- const latest = useRef({ customComponent, toastProps: toastPropsRaw, duration });
52
- useEffect(() => {
53
- latest.current = { customComponent, toastProps: toastPropsRaw, duration };
54
- });
55
-
56
- const openToast = useCallback(() => {
57
- const { customComponent: component, toastProps, duration: autoDismiss } = latest.current;
58
-
59
- dispatch({
60
- type: "push",
61
- item: {
62
- id,
63
- component: component ?? Toast,
64
- onClose: closeToast,
65
- standalone: false, // OverlayContext handles positioning
66
- ...toastProps,
67
- } as ToastStackItem,
68
- });
29
+ export const useToast = () => {
30
+ const store = useOverlayContext()?.toastStore ?? defaultStore;
69
31
 
70
- // Auto-dismiss if duration is set
71
- if (autoDismiss > 0) {
72
- setTimeout(closeToast, autoDismiss);
73
- }
74
- }, [dispatch, id, closeToast]);
32
+ const openToast = useCallback((options: ToastOptions) => store.open(options), [store]);
33
+ const closeToast = useCallback((id: string) => store.close(id), [store]);
34
+ const closeAllToasts = useCallback(() => store.clear(), [store]);
75
35
 
76
- return {
77
- openToast,
78
- closeToast,
79
- };
36
+ return { openToast, closeToast, closeAllToasts };
80
37
  };
@@ -4,3 +4,5 @@ export { Modal } from "@sixthshift/design-system/modal";
4
4
  export * from "./hooks/useModal";
5
5
  export * from "./hooks/useToast";
6
6
  export * from "./OverlayContext";
7
+ export { TOAST_STACK_CLASS, ToastStack, type ToastStackProps, useToasts } from "./ToastStack";
8
+ export * from "./toastStore";
@@ -0,0 +1,138 @@
1
+ import type { ToastProps } from "@sixthshift/design-system/toast";
2
+ import type { FunctionComponent } from "react";
3
+
4
+ // =============================================================================
5
+ // Types
6
+ // =============================================================================
7
+
8
+ /** What a caller passes to open a toast: the `Toast`'s own props, plus how long it stays. */
9
+ export type ToastOptions = Omit<ToastProps, "onClose" | "open" | "standalone" | "root"> & {
10
+ /**
11
+ * Milliseconds until the toast dismisses itself. `0` keeps it until it is
12
+ * dismissed by hand. Default: `0` for `intent="danger"` (a failure usually
13
+ * carries a message worth reading, and often a retry), `5000` otherwise.
14
+ */
15
+ duration?: number;
16
+ /** Render this instead of `Toast`. It receives `ToastProps` and must honour `open` and `onClose` as `Toast` does. */
17
+ component?: FunctionComponent<ToastProps>;
18
+ };
19
+
20
+ /** One toast as the stack holds it. */
21
+ export type ToastRecord = {
22
+ id: string;
23
+ options: ToastOptions;
24
+ /** The resolved lifetime, in ms; `0` sticks. */
25
+ duration: number;
26
+ /** Playing its exit; removed once the animation ends. */
27
+ closing: boolean;
28
+ };
29
+
30
+ /** What `open` hands back: the toast's id, and a way to close it early. */
31
+ export type ToastHandle = { id: string; close: () => void };
32
+
33
+ /**
34
+ * The stack of open toasts, with subscribers. No DOM and no timers: the
35
+ * `ToastStack` that renders it owns dismissal timing, and `Toast` owns the
36
+ * exit animation. Plain functions, so a toast can be opened from anywhere —
37
+ * an event handler, a store, a service-worker callback — not only from a
38
+ * component.
39
+ */
40
+ export type ToastStore = {
41
+ /** Register a listener; returns the unsubscribe. */
42
+ subscribe: (listener: () => void) => () => void;
43
+ /** The current stack, oldest first. Reference-stable until it changes, as `useSyncExternalStore` needs. */
44
+ snapshot: () => readonly ToastRecord[];
45
+ /** Add a toast. Past `max`, the oldest is dropped at once. */
46
+ open: (options: ToastOptions) => ToastHandle;
47
+ /** Begin a toast's exit. It leaves the stack when `remove` is called, which `Toast` does after its animation. */
48
+ close: (id: string) => void;
49
+ /** Drop a toast at once. */
50
+ remove: (id: string) => void;
51
+ /** Begin every toast's exit. */
52
+ clear: () => void;
53
+ };
54
+
55
+ export type ToastStoreOptions = {
56
+ /** How many toasts show at once; the oldest falls off. Default: 3 — a short stack reads on a phone. */
57
+ max?: number;
58
+ /** Ids in open order. Injectable so a test can name them. */
59
+ newId?: () => string;
60
+ };
61
+
62
+ // =============================================================================
63
+ // Defaults
64
+ // =============================================================================
65
+
66
+ export const DEFAULT_TOAST_DURATION = 5000;
67
+ export const DEFAULT_MAX_TOASTS = 3;
68
+
69
+ /** The lifetime an intent gets when none is given: failures stay, everything else expires. */
70
+ export function defaultToastDuration(intent: ToastOptions["intent"]): number {
71
+ return intent === "danger" ? 0 : DEFAULT_TOAST_DURATION;
72
+ }
73
+
74
+ let opened = 0;
75
+ const nextId = () => `toast-${++opened}`;
76
+
77
+ // =============================================================================
78
+ // Store
79
+ // =============================================================================
80
+
81
+ const EMPTY: readonly ToastRecord[] = [];
82
+
83
+ export function createToastStore({ max = DEFAULT_MAX_TOASTS, newId = nextId }: ToastStoreOptions = {}): ToastStore {
84
+ let toasts: readonly ToastRecord[] = EMPTY;
85
+ const listeners = new Set<() => void>();
86
+
87
+ const set = (next: readonly ToastRecord[]) => {
88
+ toasts = next.length === 0 ? EMPTY : next;
89
+ for (const listener of [...listeners]) listener();
90
+ };
91
+
92
+ const close = (id: string) => {
93
+ const record = toasts.find((toast) => toast.id === id);
94
+ if (record === undefined || record.closing) return;
95
+ set(toasts.map((toast) => (toast === record ? { ...toast, closing: true } : toast)));
96
+ };
97
+
98
+ return {
99
+ subscribe(listener) {
100
+ listeners.add(listener);
101
+ return () => void listeners.delete(listener);
102
+ },
103
+ snapshot: () => toasts,
104
+ open(options) {
105
+ const id = newId();
106
+ const record: ToastRecord = { id, options, duration: options.duration ?? defaultToastDuration(options.intent), closing: false };
107
+ set([...toasts, record].slice(-max));
108
+ return { id, close: () => close(id) };
109
+ },
110
+ close,
111
+ remove(id) {
112
+ const next = toasts.filter((toast) => toast.id !== id);
113
+ if (next.length !== toasts.length) set(next);
114
+ },
115
+ clear() {
116
+ if (toasts.every((toast) => toast.closing)) return;
117
+ set(toasts.map((toast) => ({ ...toast, closing: true })));
118
+ },
119
+ };
120
+ }
121
+
122
+ /** The app's one stack: what `OverlayProvider` renders unless handed another. */
123
+ export const toastStore = createToastStore();
124
+
125
+ /** Open a toast on the app's stack, from anywhere. Returns its id and a way to close it early. */
126
+ export function toast(options: ToastOptions): ToastHandle {
127
+ return toastStore.open(options);
128
+ }
129
+
130
+ /** Begin a toast's exit on the app's stack. */
131
+ export function closeToast(id: string): void {
132
+ toastStore.close(id);
133
+ }
134
+
135
+ /** Begin every toast's exit on the app's stack. */
136
+ export function closeAllToasts(): void {
137
+ toastStore.clear();
138
+ }
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import type { ComponentType, ReactNode } from "react";
2
4
  import { ErrorBoundary, type ErrorFallbackProps } from "./ErrorBoundary";
3
5
 
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import type { ComponentType, ReactNode } from "react";
2
4
  import { Suspense } from "react";
3
5
  import { ErrorBoundary, type ErrorFallbackProps } from "./ErrorBoundary";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Linen — the exported artifact (`@sixthshift/design-system/themes/linen.css`).
3
+ * The system's one theme, consolidated from the plans/10 exploration (was
4
+ * "02 Hue-anchored"; the six alternatives live at the `themes-exploration` tag).
5
+ * Plain CSS composition, no build step. A theme is exactly two imports: its
6
+ * own tokens, plus the theme-independent system (recipes, Tailwind config),
7
+ * which theming/tailwind.css composes.
8
+ */
9
+
10
+ @import "./theme.css"; /* imports ./palette.css itself */
11
+ @import "../../theming/tailwind.css"; /* imports every component's *.recipe.css itself */
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Linen — the palette: the authoring convention behind theme.css, not a
3
+ * layer. Referenced only by theme.css; not API for consumers.
4
+ *
5
+ * Thesis: One temperature runs through everything, the grey included. Warm
6
+ * here — hue ~70 across the board, so the page reads as woven cloth
7
+ * rather than blue-grey screen. Named for the warm off-white ground
8
+ * a canvas is made of before anything is painted on it: a surface
9
+ * with a temperature of its own, not a blank.
10
+ * Kin: Radix (sand, sage, olive), IBM Carbon warm grey
11
+ *
12
+ * Family names are this theme's own — a palette's names are part of its
13
+ * premise. theme.css points every semantic token at them.
14
+ */
15
+
16
+ :root {
17
+ --theme-name: "Linen";
18
+ --theme-version: "1.0.0";
19
+
20
+ /* sand (neutral) */
21
+ --color-sand-50: #f9f9f9;
22
+ --color-sand-100: #efeeed;
23
+ --color-sand-200: #dfdddb;
24
+ --color-sand-300: #c6c4c0;
25
+ --color-sand-400: #a19e9a;
26
+ --color-sand-500: #736f6b;
27
+ --color-sand-600: #5e5a55;
28
+ --color-sand-700: #484440;
29
+ --color-sand-800: #302d2a;
30
+ --color-sand-900: #1d1b19;
31
+ --color-sand-950: #0c0b09;
32
+
33
+ /* blue (accent) */
34
+ --color-blue-50: #f6f9fe;
35
+ --color-blue-100: #e6effd;
36
+ --color-blue-200: #cddff9;
37
+ --color-blue-300: #abc6ee;
38
+ --color-blue-400: #7ca0d5;
39
+ --color-blue-500: #4771ae;
40
+ --color-blue-600: #315a97;
41
+ --color-blue-700: #25487c;
42
+ --color-blue-800: #1b375f;
43
+ --color-blue-900: #122746;
44
+ --color-blue-950: #09172c;
45
+
46
+ /* green */
47
+ --color-green-50: #f6faf6;
48
+ --color-green-100: #e7f2e8;
49
+ --color-green-200: #cee4d0;
50
+ --color-green-300: #accfb0;
51
+ --color-green-400: #7dac83;
52
+ --color-green-500: #467f50;
53
+ --color-green-600: #2e693a;
54
+ --color-green-700: #23552d;
55
+ --color-green-800: #194121;
56
+ --color-green-900: #102e16;
57
+ --color-green-950: #081c0c;
58
+
59
+ /* amber */
60
+ --color-amber-50: #fdf8f3;
61
+ --color-amber-100: #f9ecdf;
62
+ --color-amber-200: #f1d9bf;
63
+ --color-amber-300: #e1bd94;
64
+ --color-amber-400: #c4945b;
65
+ --color-amber-500: #9a620b;
66
+ --color-amber-600: #7e4f00;
67
+ --color-amber-700: #663f00;
68
+ --color-amber-800: #4e2f00;
69
+ --color-amber-900: #392100;
70
+ --color-amber-950: #241300;
71
+
72
+ /* red */
73
+ --color-red-50: #fff7f6;
74
+ --color-red-100: #ffe9e5;
75
+ --color-red-200: #fed1c9;
76
+ --color-red-300: #f5b1a5;
77
+ --color-red-400: #dc8274;
78
+ --color-red-500: #b24b3d;
79
+ --color-red-600: #9b3225;
80
+ --color-red-700: #7f251b;
81
+ --color-red-800: #611c13;
82
+ --color-red-900: #47120c;
83
+ --color-red-950: #2d0906;
84
+
85
+ --font-sans: Inter Variable, ui-sans-serif, system-ui, sans-serif;
86
+ --font-mono: JetBrains Mono Variable, ui-monospace, monospace;
87
+ }