@sovereignfs/ui 0.54.0 → 0.83.1

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 (277) hide show
  1. package/dist/Accordion.module.css +1 -1
  2. package/dist/Alert.module.css +1 -1
  3. package/dist/AppsLauncher.module.css +96 -0
  4. package/dist/Avatar.module.css +1 -1
  5. package/dist/Badge.module.css +30 -7
  6. package/dist/BalanceChip.module.css +1 -1
  7. package/dist/Button.module.css +18 -2
  8. package/dist/Card.module.css +1 -1
  9. package/dist/CardTile.module.css +181 -0
  10. package/dist/CodeTextarea.module.css +1 -1
  11. package/dist/Collapsible.module.css +1 -1
  12. package/dist/ColorPicker.module.css +132 -0
  13. package/dist/Combobox.module.css +2 -2
  14. package/dist/Command.module.css +1 -1
  15. package/dist/ConfirmDialog.module.css +2 -2
  16. package/dist/ConsentPrompt.module.css +21 -0
  17. package/dist/DatePicker.module.css +1 -1
  18. package/dist/Dialog.module.css +130 -21
  19. package/dist/Drawer.module.css +36 -7
  20. package/dist/Header.module.css +62 -0
  21. package/dist/HeaderFooterLayout.module.css +21 -0
  22. package/dist/IconPicker.module.css +1 -1
  23. package/dist/Input.module.css +1 -1
  24. package/dist/Kbd.module.css +1 -1
  25. package/dist/Markdown.module.css +24 -0
  26. package/dist/Menu.module.css +1 -0
  27. package/dist/Message.module.css +1 -1
  28. package/dist/MessageScroller.module.css +12 -1
  29. package/dist/MobileAppsDrawer.module.css +10 -9
  30. package/dist/MobileFooter.module.css +1 -1
  31. package/dist/MobileHeader.module.css +14 -1
  32. package/dist/NavList.module.css +130 -0
  33. package/dist/NavTabs.module.css +1 -1
  34. package/dist/NotificationsPanel.module.css +258 -0
  35. package/dist/OverlayHeader.module.css +1 -1
  36. package/dist/PageContainer.module.css +62 -0
  37. package/dist/PageHeader.module.css +54 -0
  38. package/dist/PageLayout.module.css +51 -0
  39. package/dist/Popover.module.css +1 -1
  40. package/dist/QuantityStepper.module.css +1 -1
  41. package/dist/Resizable.module.css +3 -3
  42. package/dist/RootLayout.module.css +12 -0
  43. package/dist/SegmentedControl.module.css +1 -1
  44. package/dist/Select.module.css +1 -1
  45. package/dist/Sheet.module.css +4 -1
  46. package/dist/SplitPane.module.css +4 -4
  47. package/dist/StatusBadge.module.css +1 -1
  48. package/dist/StepStrip.module.css +53 -0
  49. package/dist/SuggestionInput.module.css +2 -2
  50. package/dist/SwipableMobileCarousel.module.css +12 -3
  51. package/dist/SwipableMobileCarouselDots.module.css +15 -0
  52. package/dist/SwipeStack.module.css +101 -0
  53. package/dist/SystemBanner.module.css +10 -0
  54. package/dist/Table.module.css +2 -2
  55. package/dist/Tabs.module.css +1 -1
  56. package/dist/TagInput.module.css +2 -2
  57. package/dist/Textarea.module.css +9 -1
  58. package/dist/ThreeColumnLayout.module.css +35 -0
  59. package/dist/Toast.module.css +62 -3
  60. package/dist/Tooltip.module.css +1 -1
  61. package/dist/UserMenu.module.css +90 -0
  62. package/dist/index.d.ts +1047 -45
  63. package/dist/index.js +3908 -1456
  64. package/dist/tokens/primitives.css +11 -0
  65. package/dist/tokens/semantic.css +32 -0
  66. package/dist/tokens/theme-presets.css +33 -0
  67. package/package.json +25 -9
  68. package/src/__tests__/package-json.test.ts +8 -0
  69. package/src/components/Accordion/Accordion.module.css +1 -1
  70. package/src/components/Alert/Alert.module.css +1 -1
  71. package/src/components/AppsLauncher/AppsLauncher.module.css +96 -0
  72. package/src/components/AppsLauncher/AppsLauncher.stories.tsx +58 -0
  73. package/src/components/AppsLauncher/AppsLauncher.tsx +117 -0
  74. package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +52 -0
  75. package/src/components/Avatar/Avatar.module.css +1 -1
  76. package/src/components/Badge/Badge.module.css +30 -7
  77. package/src/components/Badge/Badge.stories.tsx +16 -4
  78. package/src/components/Badge/Badge.tsx +7 -4
  79. package/src/components/Badge/__tests__/Badge.test.tsx +4 -2
  80. package/src/components/BalanceChip/BalanceChip.module.css +1 -1
  81. package/src/components/Button/Button.module.css +18 -2
  82. package/src/components/Card/Card.module.css +1 -1
  83. package/src/components/CardTile/CardTile.module.css +181 -0
  84. package/src/components/CardTile/CardTile.stories.tsx +86 -0
  85. package/src/components/CardTile/CardTile.tsx +128 -0
  86. package/src/components/CardTile/__tests__/CardTile.test.tsx +56 -0
  87. package/src/components/CodeTextarea/CodeTextarea.module.css +1 -1
  88. package/src/components/Collapsible/Collapsible.module.css +1 -1
  89. package/src/components/ColorPicker/ColorPicker.module.css +132 -0
  90. package/src/components/ColorPicker/ColorPicker.stories.tsx +80 -0
  91. package/src/components/ColorPicker/ColorPicker.tsx +157 -0
  92. package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +117 -0
  93. package/src/components/Combobox/Combobox.module.css +2 -2
  94. package/src/components/Command/Command.module.css +1 -1
  95. package/src/components/ConfirmDialog/ConfirmDialog.module.css +2 -2
  96. package/src/components/ConfirmDialog/ConfirmDialog.tsx +28 -2
  97. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +71 -3
  98. package/src/components/ConsentPrompt/ConsentPrompt.module.css +21 -0
  99. package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +31 -0
  100. package/src/components/ConsentPrompt/ConsentPrompt.tsx +66 -0
  101. package/src/components/ContextMenu/ContextMenu.tsx +1 -1
  102. package/src/components/DatePicker/DatePicker.module.css +1 -1
  103. package/src/components/Dialog/Dialog.module.css +130 -21
  104. package/src/components/Dialog/Dialog.stories.tsx +179 -2
  105. package/src/components/Dialog/Dialog.tsx +129 -35
  106. package/src/components/Dialog/__tests__/Dialog.test.tsx +190 -9
  107. package/src/components/DragHandleRow/DragHandleRow.tsx +2 -21
  108. package/src/components/Drawer/Drawer.module.css +36 -7
  109. package/src/components/Drawer/Drawer.tsx +9 -10
  110. package/src/components/Drawer/__tests__/Drawer.test.tsx +33 -6
  111. package/src/components/GripIcon/GripIcon.tsx +27 -0
  112. package/src/components/Header/Header.module.css +62 -0
  113. package/src/components/Header/Header.stories.tsx +452 -0
  114. package/src/components/Header/Header.tsx +102 -0
  115. package/src/components/Header/__tests__/Header.test.tsx +104 -0
  116. package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +21 -0
  117. package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +111 -0
  118. package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +54 -0
  119. package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +58 -0
  120. package/src/components/Icon/icons/arrow-left-right.tsx +23 -0
  121. package/src/components/Icon/icons/bold.tsx +20 -0
  122. package/src/components/Icon/icons/calendar.tsx +4 -4
  123. package/src/components/Icon/icons/carrot.tsx +3 -3
  124. package/src/components/Icon/icons/circle-chevron-left.tsx +21 -0
  125. package/src/components/Icon/icons/code.tsx +21 -0
  126. package/src/components/Icon/icons/copy.tsx +21 -0
  127. package/src/components/Icon/icons/credit-card.tsx +21 -0
  128. package/src/components/Icon/icons/database.tsx +22 -0
  129. package/src/components/Icon/icons/download.tsx +22 -0
  130. package/src/components/Icon/icons/file-text.tsx +24 -0
  131. package/src/components/Icon/icons/folder-closed.tsx +21 -0
  132. package/src/components/Icon/icons/folder-open.tsx +20 -0
  133. package/src/components/Icon/icons/folder.tsx +20 -0
  134. package/src/components/Icon/icons/folders.tsx +21 -0
  135. package/src/components/Icon/icons/hat-glasses.tsx +24 -0
  136. package/src/components/Icon/icons/history.tsx +22 -0
  137. package/src/components/Icon/icons/inbox.tsx +21 -0
  138. package/src/components/Icon/icons/index.ts +161 -1
  139. package/src/components/Icon/icons/italic.tsx +22 -0
  140. package/src/components/Icon/icons/layers.tsx +22 -0
  141. package/src/components/Icon/icons/layout-dashboard.tsx +23 -0
  142. package/src/components/Icon/icons/layout-grid.tsx +23 -0
  143. package/src/components/Icon/icons/link.tsx +21 -0
  144. package/src/components/Icon/icons/list-ordered.tsx +25 -0
  145. package/src/components/Icon/icons/list.tsx +25 -0
  146. package/src/components/Icon/icons/luggage.tsx +24 -0
  147. package/src/components/Icon/icons/map-pin.tsx +21 -0
  148. package/src/components/Icon/icons/minus.tsx +20 -0
  149. package/src/components/Icon/icons/paint-bucket.tsx +23 -0
  150. package/src/components/Icon/icons/panel-left.tsx +21 -0
  151. package/src/components/Icon/icons/pin.tsx +21 -0
  152. package/src/components/Icon/icons/rectangle-ellipsis.tsx +23 -0
  153. package/src/components/Icon/icons/refresh-cw.tsx +23 -0
  154. package/src/components/Icon/icons/rotate-cw.tsx +21 -0
  155. package/src/components/Icon/icons/route.tsx +22 -0
  156. package/src/components/Icon/icons/send.tsx +21 -0
  157. package/src/components/Icon/icons/share-2.tsx +24 -0
  158. package/src/components/Icon/icons/sheet.tsx +24 -0
  159. package/src/components/Icon/icons/square-kanban.tsx +23 -0
  160. package/src/components/Icon/icons/table.tsx +23 -0
  161. package/src/components/Icon/icons/user-round-plus.tsx +23 -0
  162. package/src/components/Icon/icons/users.tsx +23 -0
  163. package/src/components/IconPicker/IconPicker.module.css +1 -1
  164. package/src/components/Input/Input.module.css +1 -1
  165. package/src/components/Input/Input.tsx +8 -2
  166. package/src/components/Kbd/Kbd.module.css +1 -1
  167. package/src/components/Markdown/Markdown.module.css +24 -0
  168. package/src/components/Markdown/Markdown.stories.tsx +10 -0
  169. package/src/components/Markdown/Markdown.tsx +166 -29
  170. package/src/components/Markdown/__tests__/Markdown.test.tsx +144 -0
  171. package/src/components/Menu/Menu.module.css +1 -0
  172. package/src/components/Menu/Menu.tsx +72 -22
  173. package/src/components/Menu/__tests__/Menu.test.tsx +30 -0
  174. package/src/components/Menubar/Menubar.tsx +1 -1
  175. package/src/components/Message/Message.module.css +1 -1
  176. package/src/components/MessageScroller/MessageScroller.module.css +12 -1
  177. package/src/components/MessageScroller/MessageScroller.tsx +12 -0
  178. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +10 -9
  179. package/src/components/MobileFooter/MobileFooter.module.css +1 -1
  180. package/src/components/MobileFooter/MobileFooter.tsx +15 -2
  181. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +58 -0
  182. package/src/components/MobileHeader/MobileHeader.module.css +14 -1
  183. package/src/components/MobileHeader/MobileHeader.tsx +15 -2
  184. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +56 -1
  185. package/src/components/NavList/NavList.module.css +130 -0
  186. package/src/components/NavList/NavList.tsx +136 -0
  187. package/src/components/NavList/__tests__/NavList.test.tsx +109 -0
  188. package/src/components/NavTabs/NavTabs.module.css +1 -1
  189. package/src/components/NotificationsPanel/NotificationsPanel.module.css +258 -0
  190. package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +61 -0
  191. package/src/components/NotificationsPanel/NotificationsPanel.tsx +187 -0
  192. package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +78 -0
  193. package/src/components/OverlayHeader/OverlayHeader.module.css +1 -1
  194. package/src/components/OverlayHeader/OverlayHeader.tsx +19 -4
  195. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +18 -0
  196. package/src/components/PageContainer/PageContainer.module.css +62 -0
  197. package/src/components/PageContainer/PageContainer.tsx +37 -4
  198. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +41 -8
  199. package/src/components/PageHeader/PageHeader.module.css +54 -0
  200. package/src/components/PageHeader/PageHeader.tsx +146 -5
  201. package/src/components/PageHeader/__tests__/PageHeader.test.tsx +103 -0
  202. package/src/components/PageLayout/PageLayout.module.css +51 -0
  203. package/src/components/PageLayout/PageLayout.stories.tsx +73 -0
  204. package/src/components/PageLayout/PageLayout.tsx +51 -0
  205. package/src/components/PageLayout/__tests__/PageLayout.test.tsx +34 -0
  206. package/src/components/Popover/Popover.module.css +1 -1
  207. package/src/components/Popover/Popover.tsx +86 -4
  208. package/src/components/Popover/__tests__/Popover.test.tsx +165 -0
  209. package/src/components/QuantityStepper/QuantityStepper.module.css +1 -1
  210. package/src/components/Resizable/Resizable.module.css +3 -3
  211. package/src/components/RootLayout/RootLayout.module.css +12 -0
  212. package/src/components/RootLayout/RootLayout.stories.tsx +125 -0
  213. package/src/components/RootLayout/RootLayout.tsx +185 -0
  214. package/src/components/RootLayout/__tests__/RootLayout.test.tsx +161 -0
  215. package/src/components/SegmentedControl/SegmentedControl.module.css +1 -1
  216. package/src/components/Select/Select.module.css +1 -1
  217. package/src/components/Sheet/Sheet.module.css +4 -1
  218. package/src/components/Sheet/Sheet.tsx +5 -5
  219. package/src/components/SplitPane/SplitPane.module.css +4 -4
  220. package/src/components/StatusBadge/StatusBadge.module.css +1 -1
  221. package/src/components/StepStrip/StepStrip.module.css +53 -0
  222. package/src/components/StepStrip/StepStrip.tsx +74 -0
  223. package/src/components/SuggestionInput/SuggestionInput.module.css +2 -2
  224. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +12 -3
  225. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +25 -9
  226. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +81 -0
  227. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +15 -0
  228. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +12 -1
  229. package/src/components/SwipeStack/SwipeStack.module.css +101 -0
  230. package/src/components/SwipeStack/SwipeStack.tsx +199 -0
  231. package/src/components/SwipeStack/SwipeStackCard.tsx +22 -0
  232. package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +169 -0
  233. package/src/components/SystemBanner/SystemBanner.module.css +10 -0
  234. package/src/components/Table/Table.module.css +2 -2
  235. package/src/components/Tabs/Tabs.module.css +1 -1
  236. package/src/components/TagInput/TagInput.module.css +2 -2
  237. package/src/components/Textarea/Textarea.module.css +9 -1
  238. package/src/components/Textarea/Textarea.tsx +28 -5
  239. package/src/components/Textarea/__tests__/Textarea.test.tsx +23 -1
  240. package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +35 -0
  241. package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +152 -0
  242. package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +87 -0
  243. package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +78 -0
  244. package/src/components/Toast/Toast.module.css +62 -3
  245. package/src/components/Toast/Toast.stories.tsx +1 -1
  246. package/src/components/Tooltip/Tooltip.module.css +1 -1
  247. package/src/components/UserMenu/UserMenu.module.css +90 -0
  248. package/src/components/UserMenu/UserMenu.stories.tsx +49 -0
  249. package/src/components/UserMenu/UserMenu.tsx +132 -0
  250. package/src/components/UserMenu/__tests__/UserMenu.test.tsx +77 -0
  251. package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +118 -0
  252. package/src/hooks/__tests__/useReorderSensors.test.ts +26 -0
  253. package/src/hooks/__tests__/useSnapCarousel.test.tsx +82 -0
  254. package/src/hooks/__tests__/useSwipeStack.test.tsx +155 -0
  255. package/src/hooks/index.ts +9 -0
  256. package/src/hooks/usePublishShellChromeHeight.ts +96 -0
  257. package/src/hooks/useReorderSensors.ts +88 -0
  258. package/src/hooks/useSnapCarousel.ts +211 -6
  259. package/src/hooks/useSwipeStack.ts +235 -0
  260. package/src/index.ts +61 -1
  261. package/src/overlay-shell.ts +65 -0
  262. package/src/stories/DesignSystemOverview.stories.tsx +617 -11
  263. package/src/stories/GripIcon.stories.tsx +29 -0
  264. package/src/stories/LayoutSystem.stories.tsx +639 -0
  265. package/src/stories/MenuEntries.stories.tsx +86 -0
  266. package/src/stories/NavList.stories.tsx +147 -0
  267. package/src/stories/PageContainer.stories.tsx +52 -7
  268. package/src/stories/PageHeader.stories.tsx +54 -1
  269. package/src/stories/StepStrip.stories.tsx +76 -0
  270. package/src/stories/SwipableMobileCarousel.stories.tsx +58 -0
  271. package/src/stories/SwipeStack.stories.tsx +200 -0
  272. package/src/stories/Textarea.stories.tsx +12 -0
  273. package/src/stories/TokenGallery.stories.tsx +50 -0
  274. package/src/tokens/primitives.css +11 -0
  275. package/src/tokens/semantic.css +32 -0
  276. package/src/tokens/theme-presets.css +33 -0
  277. package/src/tokens/theme-presets.ts +72 -0
@@ -5,6 +5,7 @@ import { Avatar } from '../components/Avatar/Avatar';
5
5
  import { Badge } from '../components/Badge/Badge';
6
6
  import { Button } from '../components/Button/Button';
7
7
  import { Card } from '../components/Card/Card';
8
+ import { CardTile, CardTileGrid, NewCardTile } from '../components/CardTile/CardTile';
8
9
  import { Dialog } from '../components/Dialog/Dialog';
9
10
  import { Drawer } from '../components/Drawer/Drawer';
10
11
  import { EmptyState } from '../components/EmptyState/EmptyState';
@@ -15,6 +16,7 @@ import { FormField } from '../components/FormField/FormField';
15
16
  import { Icon } from '../components/Icon/Icon';
16
17
  import type { IconName } from '../components/Icon/Icon';
17
18
  import { IconPicker } from '../components/IconPicker/IconPicker';
19
+ import { ColorPicker } from '../components/ColorPicker/ColorPicker';
18
20
  import { QuantityStepper } from '../components/QuantityStepper/QuantityStepper';
19
21
  import { CheckableListRow } from '../components/CheckableListRow/CheckableListRow';
20
22
  import { Input } from '../components/Input/Input';
@@ -22,21 +24,32 @@ import { CodeTextarea } from '../components/CodeTextarea/CodeTextarea';
22
24
  import { Textarea } from '../components/Textarea/Textarea';
23
25
  import { StatusBadge } from '../components/StatusBadge/StatusBadge';
24
26
  import { SplitPane } from '../components/SplitPane/SplitPane';
27
+ import { ThreeColumnLayout } from '../components/ThreeColumnLayout/ThreeColumnLayout';
28
+ import { HeaderFooterLayout } from '../components/HeaderFooterLayout/HeaderFooterLayout';
29
+ import { RootLayout } from '../components/RootLayout/RootLayout';
30
+ import { PageLayout } from '../components/PageLayout/PageLayout';
25
31
  import { TagInput } from '../components/TagInput/TagInput';
26
32
  import { SuggestionInput } from '../components/SuggestionInput/SuggestionInput';
33
+ import { AppsLauncher } from '../components/AppsLauncher/AppsLauncher';
34
+ import { Header } from '../components/Header/Header';
27
35
  import { MobileAppsDrawer } from '../components/MobileAppsDrawer/MobileAppsDrawer';
28
36
  import { MobileFooter } from '../components/MobileFooter/MobileFooter';
29
37
  import { MobileHeader } from '../components/MobileHeader/MobileHeader';
38
+ import { NavList } from '../components/NavList/NavList';
30
39
  import { NavTabs } from '../components/NavTabs/NavTabs';
40
+ import { NotificationsPanel } from '../components/NotificationsPanel/NotificationsPanel';
31
41
  import { PageHeader } from '../components/PageHeader/PageHeader';
32
42
  import { PageContainer } from '../components/PageContainer/PageContainer';
33
43
  import { Popover } from '../components/Popover/Popover';
44
+ import { UserMenu } from '../components/UserMenu/UserMenu';
34
45
  import { ResponsiveSurface } from '../components/ResponsiveSurface/ResponsiveSurface';
35
46
  import { SwipableMobileCarousel } from '../components/SwipableMobileCarousel/SwipableMobileCarousel';
36
47
  import { SwipableMobileCarouselSlide } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlide';
37
48
  import { SwipableMobileCarouselSlideHeader } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader';
38
49
  import { SwipableMobileCarouselSlideBody } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody';
39
50
  import { SwipableMobileCarouselDots } from '../components/SwipableMobileCarouselDots/SwipableMobileCarouselDots';
51
+ import { SwipeStack } from '../components/SwipeStack/SwipeStack';
52
+ import { SwipeStackCard } from '../components/SwipeStack/SwipeStackCard';
40
53
  import { SegmentedControl } from '../components/SegmentedControl/SegmentedControl';
41
54
  import { Select } from '../components/Select/Select';
42
55
  import { Spinner } from '../components/Spinner/Spinner';
@@ -60,6 +73,7 @@ import {
60
73
  import { Alert } from '../components/Alert/Alert';
61
74
  import { Breadcrumb } from '../components/Breadcrumb/Breadcrumb';
62
75
  import { LegalLinks } from '../components/LegalLinks/LegalLinks';
76
+ import { ConsentPrompt } from '../components/ConsentPrompt/ConsentPrompt';
63
77
  import { Markdown } from '../components/Markdown/Markdown';
64
78
  import { Pagination } from '../components/Pagination/Pagination';
65
79
  import { Kbd } from '../components/Kbd/Kbd';
@@ -87,11 +101,13 @@ import { NavigationMenu } from '../components/NavigationMenu/NavigationMenu';
87
101
  import { Menubar } from '../components/Menubar/Menubar';
88
102
  import { Collapsible } from '../components/Collapsible/Collapsible';
89
103
  import { DragHandleRow } from '../components/DragHandleRow/DragHandleRow';
104
+ import { GripIcon } from '../components/GripIcon/GripIcon';
105
+ import { StepStrip, type StepStripItem } from '../components/StepStrip/StepStrip';
90
106
  import { FileDropzone } from '../components/FileDropzone/FileDropzone';
91
107
  import { OverlayHeader } from '../components/OverlayHeader/OverlayHeader';
92
108
  import { Sheet } from '../components/Sheet/Sheet';
93
109
  import { ConfirmDialog } from '../components/ConfirmDialog/ConfirmDialog';
94
- import { Menu } from '../components/Menu/Menu';
110
+ import { Menu, MenuEntries } from '../components/Menu/Menu';
95
111
  import { Calendar } from '../components/Calendar/Calendar';
96
112
  import { DatePicker } from '../components/DatePicker/DatePicker';
97
113
  import { CurrencyInput } from '../components/CurrencyInput/CurrencyInput';
@@ -251,6 +267,8 @@ const COLOR_GROUPS: Array<{
251
267
  { token: '--sv-color-text-on-accent', name: 'text-on-accent' },
252
268
  { token: '--sv-color-text-on-error', name: 'text-on-error' },
253
269
  { token: '--sv-color-text-on-success', name: 'text-on-success' },
270
+ { token: '--sv-color-text-on-light-fill', name: 'text-on-light-fill' },
271
+ { token: '--sv-color-text-on-dark-fill', name: 'text-on-dark-fill' },
254
272
  ],
255
273
  },
256
274
  {
@@ -261,6 +279,12 @@ const COLOR_GROUPS: Array<{
261
279
  { token: '--sv-color-border-strong', name: 'border-strong' },
262
280
  ],
263
281
  },
282
+ {
283
+ label: 'Shadow',
284
+ usage:
285
+ 'High-contrast shadow color for theme presets with hard offset shadows (RFC 0094). Unused by the default theme.',
286
+ tokens: [{ token: '--sv-color-shadow-strong', name: 'shadow-strong' }],
287
+ },
264
288
  {
265
289
  label: 'Accent',
266
290
  usage:
@@ -390,6 +414,7 @@ function ColorGroup({
390
414
  // ---------------------------------------------------------------------------
391
415
 
392
416
  const TYPE_SCALE: Array<{ token: string; label: string; note: string }> = [
417
+ { token: '--sv-font-size-3xl', label: '3xl — 32px', note: 'Document title style' },
393
418
  { token: '--sv-font-size-2xl', label: '2xl — 24px', note: 'Page titles' },
394
419
  { token: '--sv-font-size-xl', label: 'xl — 20px', note: 'Section headings' },
395
420
  { token: '--sv-font-size-lg', label: 'lg — 18px', note: 'Sub-headings' },
@@ -398,6 +423,11 @@ const TYPE_SCALE: Array<{ token: string; label: string; note: string }> = [
398
423
  { token: '--sv-font-size-caption', label: 'caption — 13px', note: 'Secondary / supporting copy' },
399
424
  { token: '--sv-font-size-xs', label: 'xs — 12px', note: 'Mono identifiers, badges' },
400
425
  { token: '--sv-font-size-label', label: 'label — 11px', note: 'All-caps section labels' },
426
+ {
427
+ token: '--sv-font-size-2xs',
428
+ label: '2xs — 10px',
429
+ note: 'Badge size="xs" — smallest badge tier',
430
+ },
401
431
  ];
402
432
 
403
433
  // ---------------------------------------------------------------------------
@@ -832,6 +862,24 @@ function MenuDemo() {
832
862
  );
833
863
  }
834
864
 
865
+ function MenuEntriesDemo() {
866
+ return (
867
+ <div style={{ width: '100%', maxWidth: 240 }}>
868
+ <MenuEntries
869
+ items={[
870
+ { type: 'label', label: 'Sort by' },
871
+ { label: 'Manual', checked: true },
872
+ { label: 'Title', checked: false },
873
+ { type: 'separator' },
874
+ { label: 'Rename', icon: 'pencil' },
875
+ { label: 'Delete', icon: 'trash-2', destructive: true },
876
+ ]}
877
+ onSelect={() => {}}
878
+ />
879
+ </div>
880
+ );
881
+ }
882
+
835
883
  function CalendarDemo() {
836
884
  const [value, setValue] = useState<Date | null>(new Date());
837
885
  return (
@@ -958,6 +1006,51 @@ function FileDropzoneDemo() {
958
1006
  );
959
1007
  }
960
1008
 
1009
+ interface StepStripDemoStop extends StepStripItem {
1010
+ label: string;
1011
+ sublabel: string;
1012
+ }
1013
+
1014
+ const STEP_STRIP_DEMO_STOPS: StepStripDemoStop[] = [
1015
+ { id: 'lisbon', label: 'Lisbon', sublabel: 'Aug 26 – 28' },
1016
+ { id: 'porto', label: 'Porto', sublabel: 'Aug 28 – 30' },
1017
+ ];
1018
+
1019
+ function StepStripDemo() {
1020
+ const [activeId, setActiveId] = useState('lisbon');
1021
+ return (
1022
+ <StepStrip
1023
+ items={STEP_STRIP_DEMO_STOPS}
1024
+ activeId={activeId}
1025
+ aria-label="Trip stops"
1026
+ onAdd={() => undefined}
1027
+ addLabel="Add a stop"
1028
+ renderItem={(stop, { isActive }) => (
1029
+ <button
1030
+ type="button"
1031
+ onClick={() => setActiveId(stop.id)}
1032
+ style={{
1033
+ boxSizing: 'border-box',
1034
+ minWidth: '150px',
1035
+ padding: 'var(--sv-space-3) var(--sv-space-4)',
1036
+ borderRadius: 'var(--sv-radius-lg)',
1037
+ border: `1px solid ${isActive ? 'var(--sv-color-text-primary)' : 'var(--sv-color-border)'}`,
1038
+ background: isActive
1039
+ ? 'var(--sv-color-text-primary)'
1040
+ : 'var(--sv-color-surface-raised)',
1041
+ color: isActive ? 'var(--sv-color-surface)' : 'var(--sv-color-text-primary)',
1042
+ cursor: 'pointer',
1043
+ textAlign: 'left',
1044
+ }}
1045
+ >
1046
+ <div style={{ fontWeight: 600, fontSize: 'var(--sv-font-size-sm)' }}>{stop.label}</div>
1047
+ <div style={{ fontSize: 'var(--sv-font-size-xs)', opacity: 0.8 }}>{stop.sublabel}</div>
1048
+ </button>
1049
+ )}
1050
+ />
1051
+ );
1052
+ }
1053
+
961
1054
  function ResponsiveSurfaceDemo() {
962
1055
  return (
963
1056
  <div
@@ -1052,6 +1145,48 @@ function SwipableMobileCarouselDotsDemo() {
1052
1145
  );
1053
1146
  }
1054
1147
 
1148
+ const SWIPE_STACK_DEMO_CARDS = [
1149
+ { id: 'water-plants', title: 'Water the plants' },
1150
+ { id: 'standup', title: 'Team standup · 9:30am' },
1151
+ { id: 'groceries', title: 'Buy groceries' },
1152
+ ];
1153
+
1154
+ function SwipeStackDemo() {
1155
+ return (
1156
+ <div style={{ height: 260, maxWidth: 320 }}>
1157
+ <SwipeStack
1158
+ aria-label="Today's agenda"
1159
+ directions={{
1160
+ up: { label: 'Done', icon: 'check' },
1161
+ down: { label: 'Defer', icon: 'history' },
1162
+ }}
1163
+ onSwipe={() => {}}
1164
+ >
1165
+ {SWIPE_STACK_DEMO_CARDS.map((card) => (
1166
+ <SwipeStackCard key={card.id} cardId={card.id}>
1167
+ <div
1168
+ style={{
1169
+ height: '100%',
1170
+ boxSizing: 'border-box',
1171
+ display: 'flex',
1172
+ alignItems: 'center',
1173
+ justifyContent: 'center',
1174
+ padding: 'var(--sv-space-4)',
1175
+ fontFamily: ff,
1176
+ fontWeight: 'var(--sv-font-weight-semibold)',
1177
+ color: 'var(--sv-color-text-primary)',
1178
+ textAlign: 'center',
1179
+ }}
1180
+ >
1181
+ {card.title}
1182
+ </div>
1183
+ </SwipeStackCard>
1184
+ ))}
1185
+ </SwipeStack>
1186
+ </div>
1187
+ );
1188
+ }
1189
+
1055
1190
  function IconPickerDemo() {
1056
1191
  const [value, setValue] = useState<IconName | null>('banana');
1057
1192
  const options: IconName[] = [
@@ -1077,6 +1212,26 @@ function IconPickerDemo() {
1077
1212
  );
1078
1213
  }
1079
1214
 
1215
+ function ColorPickerDemo() {
1216
+ const [value, setValue] = useState<string | null>('#b5c9e8');
1217
+ const swatches = [
1218
+ { label: 'Sky', value: '#b5c9e8' },
1219
+ { label: 'Sage', value: '#c9e0c4' },
1220
+ { label: 'Sand', value: '#e8d3b5' },
1221
+ { label: 'Clay', value: '#e0c4c4' },
1222
+ { label: 'Lilac', value: '#d8c4e0' },
1223
+ ];
1224
+ return (
1225
+ <ColorPicker
1226
+ swatches={swatches}
1227
+ value={value}
1228
+ onChange={setValue}
1229
+ allowNone
1230
+ aria-label="Board color"
1231
+ />
1232
+ );
1233
+ }
1234
+
1080
1235
  function SuggestionInputDemo() {
1081
1236
  const [value, setValue] = useState('ban');
1082
1237
  const options = ['Bananas', 'Banana bread mix']
@@ -1728,7 +1883,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
1728
1883
  <section style={{ marginBottom: 'var(--sv-space-12)' }}>
1729
1884
  <SectionHeader
1730
1885
  title="Component gallery"
1731
- subtitle="All 74 components — click each story in the sidebar for the full API, variants, and controls."
1886
+ subtitle="All 77 components — click each story in the sidebar for the full API, variants, and controls."
1732
1887
  />
1733
1888
 
1734
1889
  <div style={{ marginBottom: 'var(--sv-space-6)' }}>
@@ -1766,7 +1921,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
1766
1921
  <ComponentCard
1767
1922
  name="Badge"
1768
1923
  importLine="import { Badge } from '@sovereignfs/ui';"
1769
- usage="Compact label for roles (role), lifecycle states (status), and type/version tags (mono). sm/md/lg sizes; ALL CAPS by default, or uppercase={false} for title case. RSC-safe."
1924
+ usage="Compact label for roles (role), lifecycle states (status), and type/version tags (mono). xs/sm/md/lg sizes; ALL CAPS by default, or uppercase={false} for title case. RSC-safe."
1770
1925
  >
1771
1926
  <Badge variant="role">Admin</Badge>
1772
1927
  <Badge variant="status" status="active">
@@ -1779,6 +1934,9 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
1779
1934
  <Badge variant="role" size="lg" uppercase={false}>
1780
1935
  Owner
1781
1936
  </Badge>
1937
+ <Badge variant="status" status="active" size="xs">
1938
+ Connected
1939
+ </Badge>
1782
1940
  </ComponentCard>
1783
1941
 
1784
1942
  {/* StatusBadge */}
@@ -1854,6 +2012,15 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
1854
2012
  <IconPickerDemo />
1855
2013
  </ComponentCard>
1856
2014
 
2015
+ {/* ColorPicker */}
2016
+ <ComponentCard
2017
+ name="ColorPicker"
2018
+ importLine="import { ColorPicker } from '@sovereignfs/ui';"
2019
+ usage="Curated swatch suggestions plus a native color-input trigger for picking any color — not just the curated set."
2020
+ >
2021
+ <ColorPickerDemo />
2022
+ </ComponentCard>
2023
+
1857
2024
  {/* QuantityStepper */}
1858
2025
  <ComponentCard
1859
2026
  name="QuantityStepper"
@@ -1927,7 +2094,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
1927
2094
  <ComponentCard
1928
2095
  name="Icon"
1929
2096
  importLine="import { Icon } from '@sovereignfs/ui';"
1930
- usage="SVG icon primitive. 52 bundled icons. Decorative: aria-hidden. Meaningful: aria-label. Three sizes: sm, md, lg."
2097
+ usage="SVG icon primitive. 96 bundled icons. Decorative: aria-hidden. Meaningful: aria-label. Three sizes: sm, md, lg."
1931
2098
  >
1932
2099
  {(
1933
2100
  [
@@ -2010,6 +2177,15 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2010
2177
  <MenuDemo />
2011
2178
  </ComponentCard>
2012
2179
 
2180
+ {/* MenuEntries */}
2181
+ <ComponentCard
2182
+ name="MenuEntries"
2183
+ importLine="import { MenuEntries } from '@sovereignfs/ui';"
2184
+ usage='The <ul role="menu"> item list itself, factored out of Menu so other adaptive-surface components (ContextMenu, Menubar) can render the exact same items/destructive/checked/icon markup inside their own positioning shell instead of re-deriving it. No panel chrome of its own — the background/border/shadow around it belongs to whichever surface hosts it.'
2185
+ >
2186
+ <MenuEntriesDemo />
2187
+ </ComponentCard>
2188
+
2013
2189
  {/* Calendar */}
2014
2190
  <ComponentCard
2015
2191
  name="Calendar"
@@ -2045,7 +2221,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2045
2221
  <ComponentCard
2046
2222
  name="Toast"
2047
2223
  importLine="import { ToastProvider, useToast } from '@sovereignfs/ui';"
2048
- usage="Fixed top-right notification stack. Wrap app in ToastProvider; call useToast().show() imperatively. Six categories."
2224
+ usage="Fixed top-right on desktop, bottom-center on mobile. Wrap app in ToastProvider; call useToast().show() imperatively. Six categories."
2049
2225
  >
2050
2226
  <ToastProvider>
2051
2227
  <ToastDemo />
@@ -2066,6 +2242,38 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2066
2242
  </div>
2067
2243
  </ComponentCard>
2068
2244
 
2245
+ {/* CardTile */}
2246
+ <ComponentCard
2247
+ name="CardTile"
2248
+ importLine="import { CardTile, CardTileGrid, NewCardTile } from '@sovereignfs/ui';"
2249
+ usage="A colored/iconed banner over a footer label, for a grid of navigable top-level entities (projects, boards). Card can't express this — its padding always wraps the whole box, with no bleed slot for a full-width banner. Not link-aware; wrap each tile in the host router's own link component. Pair with NewCardTile for the grid's 'add new' affordance. The icon variant below swaps the card chrome for a plain Finder-style icon + label, for entities that read as a single glyph + name (e.g. a folder)."
2250
+ >
2251
+ <CardTileGrid minTileWidth={140}>
2252
+ <CardTile banner={<Icon name="folder" size="lg" aria-hidden={true} />}>
2253
+ Q4 Planning
2254
+ </CardTile>
2255
+ <CardTile bannerColor="#c7d8ff">Marketing site</CardTile>
2256
+ <NewCardTile label="New project" />
2257
+ </CardTileGrid>
2258
+ <div style={{ marginTop: 'var(--sv-space-4)' }}>
2259
+ <CardTileGrid dense minTileWidth={100}>
2260
+ <CardTile
2261
+ variant="icon"
2262
+ banner={<Icon name="folder-closed" size="lg" aria-hidden={true} />}
2263
+ >
2264
+ Handbook
2265
+ </CardTile>
2266
+ <CardTile
2267
+ variant="icon"
2268
+ banner={<Icon name="folder-closed" size="lg" aria-hidden={true} />}
2269
+ >
2270
+ Q4 Planning
2271
+ </CardTile>
2272
+ <NewCardTile variant="icon" label="New" />
2273
+ </CardTileGrid>
2274
+ </div>
2275
+ </ComponentCard>
2276
+
2069
2277
  {/* FormField */}
2070
2278
  <ComponentCard
2071
2279
  name="FormField"
@@ -2144,11 +2352,186 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2144
2352
  />
2145
2353
  </ComponentCard>
2146
2354
 
2355
+ {/* ThreeColumnLayout */}
2356
+ <ComponentCard
2357
+ name="ThreeColumnLayout"
2358
+ importLine="import { ThreeColumnLayout } from '@sovereignfs/ui';"
2359
+ usage="Sidebar + main + optional detail column, for list-app shells (Tasks, Shopper). Purely positional — pass 2 children for sidebar+main, or 3 for sidebar+main+detail; the third is simply omitted when nothing is selected."
2360
+ >
2361
+ <div style={{ width: '100%', height: '220px' }}>
2362
+ <ThreeColumnLayout sidebarWidth={120} detailWidth={140}>
2363
+ <div
2364
+ style={{
2365
+ padding: 'var(--sv-space-3)',
2366
+ fontFamily: ffm,
2367
+ fontSize: 'var(--sv-font-size-xs)',
2368
+ color: 'var(--sv-color-text-primary)',
2369
+ }}
2370
+ >
2371
+ Sidebar
2372
+ </div>
2373
+ <div
2374
+ style={{
2375
+ padding: 'var(--sv-space-3)',
2376
+ fontFamily: ffm,
2377
+ fontSize: 'var(--sv-font-size-xs)',
2378
+ color: 'var(--sv-color-text-primary)',
2379
+ }}
2380
+ >
2381
+ Main
2382
+ </div>
2383
+ <div
2384
+ style={{
2385
+ padding: 'var(--sv-space-3)',
2386
+ fontFamily: ffm,
2387
+ fontSize: 'var(--sv-font-size-xs)',
2388
+ color: 'var(--sv-color-text-primary)',
2389
+ }}
2390
+ >
2391
+ Detail
2392
+ </div>
2393
+ </ThreeColumnLayout>
2394
+ </div>
2395
+ </ComponentCard>
2396
+
2397
+ {/* HeaderFooterLayout */}
2398
+ <ComponentCard
2399
+ name="HeaderFooterLayout"
2400
+ importLine="import { HeaderFooterLayout } from '@sovereignfs/ui';"
2401
+ usage="Header + main + optional footer, both fixed-height and independently optional; main always claims the remaining height. The vertical counterpart to ThreeColumnLayout."
2402
+ >
2403
+ <div style={{ width: '100%', height: '220px' }}>
2404
+ <HeaderFooterLayout
2405
+ headerHeight={36}
2406
+ footerHeight={36}
2407
+ header={
2408
+ <div
2409
+ style={{
2410
+ display: 'flex',
2411
+ alignItems: 'center',
2412
+ justifyContent: 'center',
2413
+ height: '100%',
2414
+ fontFamily: ffm,
2415
+ fontSize: 'var(--sv-font-size-xs)',
2416
+ color: 'var(--sv-color-text-primary)',
2417
+ }}
2418
+ >
2419
+ Header
2420
+ </div>
2421
+ }
2422
+ footer={
2423
+ <div
2424
+ style={{
2425
+ display: 'flex',
2426
+ alignItems: 'center',
2427
+ justifyContent: 'center',
2428
+ height: '100%',
2429
+ fontFamily: ffm,
2430
+ fontSize: 'var(--sv-font-size-xs)',
2431
+ color: 'var(--sv-color-text-primary)',
2432
+ }}
2433
+ >
2434
+ Footer
2435
+ </div>
2436
+ }
2437
+ >
2438
+ <div
2439
+ style={{
2440
+ padding: 'var(--sv-space-3)',
2441
+ fontFamily: ffm,
2442
+ fontSize: 'var(--sv-font-size-xs)',
2443
+ color: 'var(--sv-color-text-primary)',
2444
+ }}
2445
+ >
2446
+ Main (scrolls)
2447
+ </div>
2448
+ </HeaderFooterLayout>
2449
+ </div>
2450
+ </ComponentCard>
2451
+
2452
+ {/* RootLayout */}
2453
+ <ComponentCard
2454
+ name="RootLayout"
2455
+ importLine="import { RootLayout } from '@sovereignfs/ui';"
2456
+ usage="The root-level layout a plugin's page tree sits in. variant='sidebar' is web-only (sidebar + main); variant='shell' is mobile-only (header + main + footer) — same children, different fork per breakpoint via ResponsiveSurface. Shown here: variant='header', identical on both breakpoints."
2457
+ >
2458
+ <div style={{ width: '100%', height: '160px' }}>
2459
+ <RootLayout variant="header" headerHeight={32}>
2460
+ <div
2461
+ style={{
2462
+ display: 'flex',
2463
+ alignItems: 'center',
2464
+ justifyContent: 'center',
2465
+ height: '100%',
2466
+ fontFamily: ffm,
2467
+ fontSize: 'var(--sv-font-size-xs)',
2468
+ color: 'var(--sv-color-text-primary)',
2469
+ }}
2470
+ >
2471
+ Header
2472
+ </div>
2473
+ <div
2474
+ style={{
2475
+ padding: 'var(--sv-space-3)',
2476
+ fontFamily: ffm,
2477
+ fontSize: 'var(--sv-font-size-xs)',
2478
+ color: 'var(--sv-color-text-primary)',
2479
+ }}
2480
+ >
2481
+ Main
2482
+ </div>
2483
+ </RootLayout>
2484
+ </div>
2485
+ </ComponentCard>
2486
+
2487
+ {/* PageLayout */}
2488
+ <ComponentCard
2489
+ name="PageLayout"
2490
+ importLine="import { PageLayout } from '@sovereignfs/ui';"
2491
+ usage="A single page's content area, nested inside RootLayout's main slot. No padding by default (opt in via padding, same scale as PageContainer). The optional header is page-specific — a board title/toolbar, not the app-level header."
2492
+ >
2493
+ <div
2494
+ style={{
2495
+ width: '100%',
2496
+ height: '160px',
2497
+ border: '1px solid var(--sv-color-border)',
2498
+ }}
2499
+ >
2500
+ <PageLayout
2501
+ padding="sm"
2502
+ header={
2503
+ <div
2504
+ style={{
2505
+ padding: 'var(--sv-space-2) var(--sv-space-3)',
2506
+ borderBottom: '1px solid var(--sv-color-border)',
2507
+ fontFamily: ffm,
2508
+ fontSize: 'var(--sv-font-size-xs)',
2509
+ fontWeight: 600,
2510
+ color: 'var(--sv-color-text-primary)',
2511
+ }}
2512
+ >
2513
+ Page header
2514
+ </div>
2515
+ }
2516
+ >
2517
+ <div
2518
+ style={{
2519
+ fontFamily: ffm,
2520
+ fontSize: 'var(--sv-font-size-xs)',
2521
+ color: 'var(--sv-color-text-primary)',
2522
+ }}
2523
+ >
2524
+ Page content
2525
+ </div>
2526
+ </PageLayout>
2527
+ </div>
2528
+ </ComponentCard>
2529
+
2147
2530
  {/* PageHeader */}
2148
2531
  <ComponentCard
2149
2532
  name="PageHeader"
2150
2533
  importLine="import { PageHeader } from '@sovereignfs/ui';"
2151
- usage="Plugin page top section. Title + optional description + right-side action slot. Replaces the hand-rolled .pageHeader pattern in every plugin."
2534
+ usage="Plugin page top section. Title + optional description + right-side action slot. Replaces the hand-rolled .pageHeader pattern in every plugin. An optional `icon` renders before the title text on both breakpoints. On mobile, description drops out and onBack/onMenuClick add an optional back button and vertical-ellipsis menu trigger."
2152
2535
  >
2153
2536
  <div style={{ width: '100%' }}>
2154
2537
  <PageHeader
@@ -2163,10 +2546,10 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2163
2546
  <ComponentCard
2164
2547
  name="PageContainer"
2165
2548
  importLine="import { PageContainer } from '@sovereignfs/ui';"
2166
- usage="Constrains and centers a plugin's main content width (sm/md/lg/full). Adds no padding of its own — the runtime shell already pads plugin content. Use instead of local container CSS in a plugin's layout."
2549
+ usage="The wrapper every plugin page renders through. Supplies the page gutter (padding: none/sm/md/lg, default md — the runtime shell no longer pads plugin content) and constrains width (maxWidth: sm/md/lg/full, default full). Use instead of declaring padding or max-width in a plugin's own CSS."
2167
2550
  >
2168
2551
  <div style={{ width: '100%', background: 'var(--sv-color-surface-sunken)' }}>
2169
- <PageContainer maxWidth="sm">
2552
+ <PageContainer maxWidth="sm" padding="md">
2170
2553
  <div
2171
2554
  style={{
2172
2555
  background: 'var(--sv-color-surface-raised)',
@@ -2175,12 +2558,150 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2175
2558
  padding: 'var(--sv-space-4)',
2176
2559
  }}
2177
2560
  >
2178
- maxWidth=&quot;sm&quot;
2561
+ maxWidth=&quot;sm&quot; padding=&quot;md&quot;
2179
2562
  </div>
2180
2563
  </PageContainer>
2181
2564
  </div>
2182
2565
  </ComponentCard>
2183
2566
 
2567
+ {/* Header */}
2568
+ <ComponentCard
2569
+ name="Header"
2570
+ importLine="import { Header } from '@sovereignfs/ui';"
2571
+ usage="The web top-bar header for shell: minimal plugins that own their whole viewport (no platform sidebar). Brand badge + optional active plugin on the left; launcher (AppsLauncher), notifications (NotificationsPanel), and avatarMenu (UserMenu) on the right — all real, shared, independently clickable components. Presentational only — see Components/Header for the mobile counterpart (MobileHeader) shown side by side."
2572
+ >
2573
+ <Header
2574
+ instanceName="Sovereign"
2575
+ homeHref="/launcher"
2576
+ plugin={{
2577
+ // The plugin icon is 28px — the same size as the brand
2578
+ // badge next to it, not a smaller inline glyph.
2579
+ name: 'Notes',
2580
+ icon: (
2581
+ <span
2582
+ aria-hidden="true"
2583
+ style={{
2584
+ display: 'inline-flex',
2585
+ alignItems: 'center',
2586
+ justifyContent: 'center',
2587
+ width: 28,
2588
+ height: 28,
2589
+ }}
2590
+ >
2591
+ <span style={{ display: 'inline-flex', transform: 'scale(1.15)' }}>
2592
+ <Icon name="file" size="lg" aria-hidden />
2593
+ </span>
2594
+ </span>
2595
+ ),
2596
+ href: '/notes',
2597
+ }}
2598
+ launcher={
2599
+ <AppsLauncher
2600
+ items={[
2601
+ {
2602
+ key: 'home',
2603
+ icon: <Icon name="house" size="md" aria-hidden />,
2604
+ label: 'Home',
2605
+ href: '/launcher',
2606
+ },
2607
+ {
2608
+ key: 'notes',
2609
+ icon: <Icon name="file" size="md" aria-hidden />,
2610
+ label: 'Notes',
2611
+ href: '/notes',
2612
+ },
2613
+ ]}
2614
+ />
2615
+ }
2616
+ notifications={<NotificationsPanel items={[]} unreadCount={0} />}
2617
+ avatarMenu={
2618
+ <UserMenu
2619
+ name="Kasun Benthara"
2620
+ email="kasun@openfs.io"
2621
+ items={[
2622
+ { label: 'Account', icon: 'user', href: '/account' },
2623
+ { label: 'Sign out', icon: 'log-out', destructive: true, onSelect: () => {} },
2624
+ ]}
2625
+ size="sm"
2626
+ />
2627
+ }
2628
+ />
2629
+ </ComponentCard>
2630
+
2631
+ {/* AppsLauncher */}
2632
+ <ComponentCard
2633
+ name="AppsLauncher"
2634
+ importLine="import { AppsLauncher } from '@sovereignfs/ui';"
2635
+ usage="The desktop 'Apps' switcher — a 28px grid trigger opening a Popover tile grid. The desktop counterpart to MobileAppsDrawer: same items shape (key/icon/label/href/onClick), different chrome. Presentational only — items are supplied already resolved; loading/error are separate props."
2636
+ >
2637
+ <AppsLauncher
2638
+ items={[
2639
+ {
2640
+ key: 'home',
2641
+ icon: <Icon name="house" size="md" aria-hidden />,
2642
+ label: 'Home',
2643
+ href: '/launcher',
2644
+ },
2645
+ {
2646
+ key: 'console',
2647
+ icon: <Icon name="layout-dashboard" size="md" aria-hidden />,
2648
+ label: 'Console',
2649
+ href: '/console',
2650
+ },
2651
+ {
2652
+ key: 'notes',
2653
+ icon: <Icon name="file" size="md" aria-hidden />,
2654
+ label: 'Notes',
2655
+ href: '/notes',
2656
+ },
2657
+ ]}
2658
+ />
2659
+ </ComponentCard>
2660
+
2661
+ {/* NotificationsPanel */}
2662
+ <ComponentCard
2663
+ name="NotificationsPanel"
2664
+ importLine="import { NotificationsPanel } from '@sovereignfs/ui';"
2665
+ usage="The bell trigger + dropdown, generalized from the runtime shell's own NotificationBell — title/Mark all read/Clear all/close, then category-icon + title + time + unread-dot + dismiss rows. Pure presentation: no fetch/SSE/mark-read logic of its own; the consumer supplies already-resolved items and wires onOpen/onDismiss/onMarkAllRead/onClearAll."
2666
+ >
2667
+ <NotificationsPanel
2668
+ items={[
2669
+ {
2670
+ id: '1',
2671
+ icon: <Icon name="layers" size="sm" aria-hidden />,
2672
+ title: 'Added to a project',
2673
+ timeLabel: '2d ago',
2674
+ read: false,
2675
+ onDismiss: () => {},
2676
+ },
2677
+ ]}
2678
+ unreadCount={1}
2679
+ onMarkAllRead={() => {}}
2680
+ onClearAll={() => {}}
2681
+ />
2682
+ </ComponentCard>
2683
+
2684
+ {/* UserMenu */}
2685
+ <ComponentCard
2686
+ name="UserMenu"
2687
+ importLine="import { UserMenu } from '@sovereignfs/ui';"
2688
+ usage="The account avatar trigger + dropdown, generalized from the runtime shell's own AccountMenu — accent-filled avatar, a name/email header block, then a plain item list. Presentational only: no auth/session logic — items carry their own onSelect and/or href (e.g. a real 'Sign out' item just does whatever the consuming app's sign-out requires)."
2689
+ >
2690
+ <UserMenu
2691
+ name="Kasun Benthara"
2692
+ email="kasun@openfs.io"
2693
+ items={[
2694
+ { label: 'Account', icon: 'user', href: '/account' },
2695
+ {
2696
+ label: 'Preferences',
2697
+ icon: 'sliders-horizontal',
2698
+ href: '/account/preferences',
2699
+ },
2700
+ { label: 'Sign out', icon: 'log-out', destructive: true, onSelect: () => {} },
2701
+ ]}
2702
+ />
2703
+ </ComponentCard>
2704
+
2184
2705
  {/* MobileHeader */}
2185
2706
  <ComponentCard
2186
2707
  name="MobileHeader"
@@ -2348,6 +2869,42 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2348
2869
  </div>
2349
2870
  </ComponentCard>
2350
2871
 
2872
+ {/* NavList */}
2873
+ <ComponentCard
2874
+ name="NavList"
2875
+ importLine="import { NavList } from '@sovereignfs/ui';"
2876
+ usage='Vertical list of icon+label rows, optionally grouped under section headers. static: active row highlighted, no chevron — a persistent sidebar. drilldown: trailing chevron on every row, no active state — a native-Settings-app style index. density="compact" (static only) shrinks row height for a short, always-visible list. Framework-agnostic like NavTabs; supply active/renderLink from the consumer.'
2877
+ >
2878
+ <div style={{ width: '100%', maxWidth: 220 }}>
2879
+ <NavList
2880
+ variant="static"
2881
+ aria-label="Example sections"
2882
+ groups={[
2883
+ {
2884
+ id: 'overview',
2885
+ items: [
2886
+ {
2887
+ id: 'overview',
2888
+ label: 'Overview',
2889
+ href: '#',
2890
+ icon: 'layout-dashboard',
2891
+ active: true,
2892
+ },
2893
+ ],
2894
+ },
2895
+ {
2896
+ id: 'people',
2897
+ label: 'People',
2898
+ items: [
2899
+ { id: 'users', label: 'Users', href: '#', icon: 'users' },
2900
+ { id: 'groups', label: 'Groups', href: '#', icon: 'layers' },
2901
+ ],
2902
+ },
2903
+ ]}
2904
+ />
2905
+ </div>
2906
+ </ComponentCard>
2907
+
2351
2908
  {/* Tooltip */}
2352
2909
  <ComponentCard
2353
2910
  name="Tooltip"
@@ -2519,15 +3076,31 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2519
3076
  <LegalLinks />
2520
3077
  </ComponentCard>
2521
3078
 
3079
+ {/* ConsentPrompt */}
3080
+ <ComponentCard
3081
+ name="ConsentPrompt"
3082
+ importLine="import { ConsentPrompt } from '@sovereignfs/ui';"
3083
+ usage="Consent screen shown before one plugin is allowed to read another plugin's data (RFC 0002 data grants) or connect to an external service on the user's behalf. description should come from the provider's own manifest declaration, never caller-supplied copy."
3084
+ >
3085
+ <ConsentPrompt
3086
+ consumerName="Ledger"
3087
+ providerName="Finance Tracker"
3088
+ contract="expenses"
3089
+ description="Monthly expense totals by category, no transaction-level detail."
3090
+ onAllow={() => {}}
3091
+ onDeny={() => {}}
3092
+ />
3093
+ </ComponentCard>
3094
+
2522
3095
  {/* Markdown */}
2523
3096
  <ComponentCard
2524
3097
  name="Markdown"
2525
3098
  importLine="import { Markdown } from '@sovereignfs/ui';"
2526
- usage="Renders a constrained markdown subset (headings, paragraphs, bold/italic/code, links, lists, blockquotes) as Typography-based React elements — no HTML string injection. Built for first-party long-form content pages (privacy policy, terms of service), not arbitrary or user-supplied markdown."
3099
+ usage="Renders a constrained markdown subset (headings, paragraphs, bold/italic/code, links, ordered and unordered lists, fenced code blocks, blockquotes) as Typography-based React elements — no HTML string injection. Built for first-party long-form content and model-generated replies; still not a full CommonMark parser (no tables, images, or nested blocks)."
2527
3100
  >
2528
3101
  <Markdown
2529
3102
  content={
2530
- '## Heading\n\nA paragraph with **bold** and a [link](/privacy).\n\n- One\n- Two'
3103
+ '## Heading\n\nA paragraph with **bold** and a [link](/privacy).\n\n- One\n- Two\n\n1. First\n2. Second\n\n```ts\nconst a = 1;\n```'
2531
3104
  }
2532
3105
  />
2533
3106
  </ComponentCard>
@@ -2962,6 +3535,26 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2962
3535
  </div>
2963
3536
  </ComponentCard>
2964
3537
 
3538
+ {/* GripIcon */}
3539
+ <ComponentCard
3540
+ name="GripIcon"
3541
+ importLine="import { GripIcon } from '@sovereignfs/ui';"
3542
+ usage="Six-dot drag-handle icon, sized via `size` (default 14). No baked-in pointer-events or color — DragHandleRow uses it internally; a floating, absolutely-positioned handle can use it directly."
3543
+ >
3544
+ <div style={{ color: 'var(--sv-color-text-muted)' }}>
3545
+ <GripIcon />
3546
+ </div>
3547
+ </ComponentCard>
3548
+
3549
+ {/* StepStrip */}
3550
+ <ComponentCard
3551
+ name="StepStrip"
3552
+ importLine="import { StepStrip } from '@sovereignfs/ui';"
3553
+ usage="Horizontal connected-chip strip (a route/itinerary sequence) with an optional trailing add chip. Purely presentational — renderItem owns each chip's content, click handling, and any drag-reorder wiring (attach dnd-kit's useSortable the same way DragHandleRow's handleProps expects it)."
3554
+ >
3555
+ <StepStripDemo />
3556
+ </ComponentCard>
3557
+
2965
3558
  {/* FileDropzone */}
2966
3559
  <ComponentCard
2967
3560
  name="FileDropzone"
@@ -2997,6 +3590,15 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
2997
3590
  >
2998
3591
  <SwipableMobileCarouselDotsDemo />
2999
3592
  </ComponentCard>
3593
+
3594
+ {/* SwipeStack */}
3595
+ <ComponentCard
3596
+ name="SwipeStack"
3597
+ importLine="import { SwipeStack, SwipeStackCard } from '@sovereignfs/ui';"
3598
+ usage="Triage one card at a time by dragging left/right/up/down, plus an always-visible fallback button per configured direction wired to the identical commit path. Every direction is independently optional and has no baked-in meaning — the caller supplies label/icon and reacts to onSwipe; once triggered a direction removes the card for good, there is no reversible 'go back'."
3599
+ >
3600
+ <SwipeStackDemo />
3601
+ </ComponentCard>
3000
3602
  </div>
3001
3603
  </section>
3002
3604
 
@@ -3110,6 +3712,10 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
3110
3712
  <li>
3111
3713
  Use <code style={{ fontFamily: ffm }}>--sv-shadow-*</code> for elevation
3112
3714
  </li>
3715
+ <li>
3716
+ Use <code style={{ fontFamily: ffm }}>--sv-border-width-hairline</code> instead of
3717
+ a literal border width (RFC 0094)
3718
+ </li>
3113
3719
  </ul>
3114
3720
  </div>
3115
3721
  <div