@felloinnovations/brand-kit 0.4.0 → 0.5.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 (363) hide show
  1. package/AGENTS.md +198 -24
  2. package/CHANGELOG.md +221 -0
  3. package/README.md +38 -9
  4. package/design-system/01-how-claude-decides.md +26 -17
  5. package/design-system/02-principles.md +11 -6
  6. package/design-system/03-colour.md +135 -47
  7. package/design-system/04-type.md +45 -23
  8. package/design-system/05-space-and-layout.md +175 -52
  9. package/design-system/06-sizing-profiles.md +4 -4
  10. package/design-system/07-scrolling.md +66 -20
  11. package/design-system/08-choosing-components.md +50 -22
  12. package/design-system/09-charts.md +71 -28
  13. package/design-system/10-patterns.md +33 -10
  14. package/design-system/11-page-recipes.md +110 -23
  15. package/design-system/12-content.md +2 -1
  16. package/design-system/13-motion.md +330 -47
  17. package/design-system/14-accessibility.md +47 -24
  18. package/design-system/15-ai-experiences.md +11 -6
  19. package/design-system/16-creativity.md +1 -1
  20. package/design-system/17-decisions.md +367 -1
  21. package/design-system/18-checklist.md +79 -16
  22. package/design-system/19-public-pages.md +6 -4
  23. package/design-system/20-palettes.md +275 -0
  24. package/design-system/README.md +30 -17
  25. package/design-system/components/ActionList/README.md +96 -10
  26. package/design-system/components/ActionList/preview.html +52 -7
  27. package/design-system/components/ActionList/style.css +64 -0
  28. package/design-system/components/ActivityGrid/README.md +38 -2
  29. package/design-system/components/ActivityGrid/preview.html +1 -1
  30. package/design-system/components/ActivityGrid/style.css +35 -0
  31. package/design-system/components/AppShell/README.md +205 -75
  32. package/design-system/components/AppShell/preview.html +339 -58
  33. package/design-system/components/AppShell/style.css +154 -0
  34. package/design-system/components/Avatar/README.md +37 -10
  35. package/design-system/components/Avatar/preview.html +13 -4
  36. package/design-system/components/Avatar/style.css +14 -0
  37. package/design-system/components/Badge/README.md +41 -19
  38. package/design-system/components/Badge/preview.html +13 -10
  39. package/design-system/components/Badge/style.css +23 -0
  40. package/design-system/components/Banner/README.md +30 -9
  41. package/design-system/components/Banner/preview.html +1 -1
  42. package/design-system/components/Banner/style.css +19 -0
  43. package/design-system/components/Breadcrumb/README.md +58 -46
  44. package/design-system/components/Breadcrumb/preview.html +16 -16
  45. package/design-system/components/Breadcrumb/style.css +17 -0
  46. package/design-system/components/Button/README.md +113 -55
  47. package/design-system/components/Button/preview.html +98 -25
  48. package/design-system/components/Button/style.css +86 -0
  49. package/design-system/components/Card/README.md +158 -49
  50. package/design-system/components/Card/preview.html +141 -19
  51. package/design-system/components/Card/style.css +115 -0
  52. package/design-system/components/CardBoard/README.md +58 -37
  53. package/design-system/components/CardBoard/preview.html +26 -29
  54. package/design-system/components/ChatCard/README.md +115 -29
  55. package/design-system/components/ChatCard/preview.html +149 -32
  56. package/design-system/components/ChatCard/style.css +49 -0
  57. package/design-system/components/ChatShell/README.md +116 -0
  58. package/design-system/components/ChatShell/preview.html +201 -0
  59. package/design-system/components/ChatShell/style.css +86 -0
  60. package/design-system/components/ChatTurn/README.md +78 -35
  61. package/design-system/components/ChatTurn/preview.html +60 -28
  62. package/design-system/components/ChatTurn/style.css +50 -0
  63. package/design-system/components/CheckRow/README.md +141 -0
  64. package/design-system/components/CheckRow/preview.html +140 -0
  65. package/design-system/components/CheckRow/style.css +88 -0
  66. package/design-system/components/Checkbox/README.md +58 -22
  67. package/design-system/components/Checkbox/preview.html +112 -50
  68. package/design-system/components/Checkbox/style.css +45 -0
  69. package/design-system/components/Chip/README.md +78 -47
  70. package/design-system/components/Chip/preview.html +29 -4
  71. package/design-system/components/Chip/style.css +17 -0
  72. package/design-system/components/Combobox/README.md +44 -11
  73. package/design-system/components/Combobox/preview.html +35 -12
  74. package/design-system/components/Combobox/style.css +54 -0
  75. package/design-system/components/Composer/README.md +137 -35
  76. package/design-system/components/Composer/preview.html +115 -40
  77. package/design-system/components/Composer/style.css +81 -0
  78. package/design-system/components/ConfirmDialog/README.md +73 -52
  79. package/design-system/components/ConfirmDialog/preview.html +70 -26
  80. package/design-system/components/ConfirmDialog/style.css +5 -0
  81. package/design-system/components/Cover/preview.html +3 -3
  82. package/design-system/components/Cover/style.css +19 -0
  83. package/design-system/components/DateInput/README.md +77 -12
  84. package/design-system/components/DateInput/preview.html +27 -12
  85. package/design-system/components/DateInput/style.css +38 -0
  86. package/design-system/components/Dialog/README.md +112 -44
  87. package/design-system/components/Dialog/preview.html +141 -18
  88. package/design-system/components/Dialog/style.css +74 -0
  89. package/design-system/components/EmptyState/README.md +42 -12
  90. package/design-system/components/EmptyState/preview.html +11 -11
  91. package/design-system/components/EmptyState/style.css +9 -0
  92. package/design-system/components/EntryShell/README.md +73 -48
  93. package/design-system/components/EntryShell/preview.html +60 -27
  94. package/design-system/components/EntryShell/style.css +19 -0
  95. package/design-system/components/FeatureGrid/README.md +61 -39
  96. package/design-system/components/FeatureGrid/preview.html +2 -2
  97. package/design-system/components/FeatureGrid/style.css +20 -0
  98. package/design-system/components/FileUpload/README.md +33 -3
  99. package/design-system/components/FileUpload/preview.html +18 -4
  100. package/design-system/components/FileUpload/style.css +23 -0
  101. package/design-system/components/FilterBar/README.md +114 -0
  102. package/design-system/components/FilterBar/preview.html +82 -0
  103. package/design-system/components/FilterBar/style.css +22 -0
  104. package/design-system/components/Fold/README.md +84 -26
  105. package/design-system/components/Fold/preview.html +77 -34
  106. package/design-system/components/Fold/style.css +48 -0
  107. package/design-system/components/Footer/README.md +62 -39
  108. package/design-system/components/Footer/preview.html +5 -5
  109. package/design-system/components/Footer/style.css +30 -0
  110. package/design-system/components/FunnelBars/README.md +24 -3
  111. package/design-system/components/FunnelBars/preview.html +5 -5
  112. package/design-system/components/FunnelBars/style.css +13 -0
  113. package/design-system/components/GoalBars/README.md +54 -10
  114. package/design-system/components/GoalBars/preview.html +69 -28
  115. package/design-system/components/GoalBars/style.css +51 -0
  116. package/design-system/components/GoalTicks/README.md +74 -58
  117. package/design-system/components/GoalTicks/preview.html +41 -118
  118. package/design-system/components/GoalTicks/style.css +37 -0
  119. package/design-system/components/GoalTubes/README.md +29 -3
  120. package/design-system/components/GoalTubes/preview.html +6 -6
  121. package/design-system/components/GoalTubes/style.css +23 -0
  122. package/design-system/components/Heatmap/README.md +133 -0
  123. package/design-system/components/Heatmap/preview.html +168 -0
  124. package/design-system/components/Heatmap/style.css +119 -0
  125. package/design-system/components/Hero/README.md +58 -40
  126. package/design-system/components/Hero/preview.html +1 -1
  127. package/design-system/components/Hero/style.css +19 -0
  128. package/design-system/components/HoverCard/README.md +114 -0
  129. package/design-system/components/HoverCard/preview.html +107 -0
  130. package/design-system/components/HoverCard/style.css +59 -0
  131. package/design-system/components/IconButton/README.md +69 -38
  132. package/design-system/components/IconButton/preview.html +77 -43
  133. package/design-system/components/IconButton/style.css +45 -0
  134. package/design-system/components/Input/README.md +36 -11
  135. package/design-system/components/Input/preview.html +1 -1
  136. package/design-system/components/Input/style.css +23 -0
  137. package/design-system/components/KanbanBoard/README.md +93 -45
  138. package/design-system/components/KanbanBoard/preview.html +159 -43
  139. package/design-system/components/KanbanBoard/style.css +53 -0
  140. package/design-system/components/Kbd/README.md +25 -9
  141. package/design-system/components/Kbd/preview.html +6 -2
  142. package/design-system/components/Kbd/style.css +9 -0
  143. package/design-system/components/KitButton/README.md +81 -47
  144. package/design-system/components/KitButton/preview.html +35 -13
  145. package/design-system/components/KitButton/style.css +46 -0
  146. package/design-system/components/KitCard/README.md +75 -44
  147. package/design-system/components/KitCard/preview.html +18 -10
  148. package/design-system/components/KitCard/style.css +15 -0
  149. package/design-system/components/KitInput/README.md +54 -39
  150. package/design-system/components/KitInput/preview.html +7 -7
  151. package/design-system/components/KitInput/style.css +23 -0
  152. package/design-system/components/Leaderboard/README.md +76 -49
  153. package/design-system/components/Leaderboard/preview.html +61 -26
  154. package/design-system/components/Leaderboard/style.css +44 -0
  155. package/design-system/components/ListDetail/README.md +222 -0
  156. package/design-system/components/ListDetail/preview.html +213 -0
  157. package/design-system/components/ListDetail/style.css +148 -0
  158. package/design-system/components/LoadBar/README.md +79 -0
  159. package/design-system/components/LoadBar/preview.html +40 -0
  160. package/design-system/components/LoadBar/style.css +17 -0
  161. package/design-system/components/MarketingNav/README.md +76 -42
  162. package/design-system/components/MarketingNav/preview.html +37 -8
  163. package/design-system/components/MarketingNav/style.css +45 -0
  164. package/design-system/components/Matrix/README.md +129 -0
  165. package/design-system/components/Matrix/preview.html +99 -0
  166. package/design-system/components/Matrix/style.css +84 -0
  167. package/design-system/components/Menu/README.md +117 -41
  168. package/design-system/components/Menu/preview.html +85 -23
  169. package/design-system/components/Menu/style.css +61 -0
  170. package/design-system/components/Meter/README.md +39 -4
  171. package/design-system/components/Meter/preview.html +18 -1
  172. package/design-system/components/Meter/style.css +23 -0
  173. package/design-system/components/MetricTile/README.md +237 -0
  174. package/design-system/components/MetricTile/preview.html +241 -0
  175. package/design-system/components/MetricTile/style.css +129 -0
  176. package/design-system/components/Morph/README.md +106 -0
  177. package/design-system/components/Morph/preview.html +103 -0
  178. package/design-system/components/Morph/style.css +31 -0
  179. package/design-system/components/Motion/README.md +164 -0
  180. package/design-system/components/Motion/preview.html +2537 -0
  181. package/design-system/components/NumberInput/README.md +27 -8
  182. package/design-system/components/NumberInput/preview.html +21 -5
  183. package/design-system/components/NumberInput/style.css +34 -0
  184. package/design-system/components/PaceBar/README.md +75 -0
  185. package/design-system/components/PaceBar/preview.html +67 -0
  186. package/design-system/components/PaceBar/style.css +25 -0
  187. package/design-system/components/Page/README.md +57 -18
  188. package/design-system/components/Page/preview.html +15 -17
  189. package/design-system/components/Page/style.css +7 -0
  190. package/design-system/components/PageBar/README.md +90 -34
  191. package/design-system/components/PageBar/preview.html +60 -19
  192. package/design-system/components/PageBar/style.css +35 -0
  193. package/design-system/components/PageHero/README.md +87 -51
  194. package/design-system/components/PageHero/preview.html +35 -6
  195. package/design-system/components/PageHero/style.css +31 -0
  196. package/design-system/components/Pagination/README.md +70 -49
  197. package/design-system/components/Pagination/preview.html +24 -15
  198. package/design-system/components/Pagination/style.css +12 -0
  199. package/design-system/components/Panel/README.md +109 -51
  200. package/design-system/components/Panel/preview.html +118 -20
  201. package/design-system/components/Panel/style.css +51 -0
  202. package/design-system/components/PasswordInput/README.md +50 -18
  203. package/design-system/components/PasswordInput/preview.html +71 -21
  204. package/design-system/components/PasswordInput/style.css +31 -0
  205. package/design-system/components/Plate/README.md +75 -17
  206. package/design-system/components/Plate/preview.html +40 -7
  207. package/design-system/components/Plate/style.css +37 -0
  208. package/design-system/components/Popover/README.md +70 -49
  209. package/design-system/components/Popover/preview.html +44 -22
  210. package/design-system/components/Popover/style.css +41 -0
  211. package/design-system/components/PricingTable/README.md +69 -49
  212. package/design-system/components/PricingTable/preview.html +21 -21
  213. package/design-system/components/PricingTable/style.css +21 -0
  214. package/design-system/components/ProgressPetals/README.md +31 -3
  215. package/design-system/components/ProgressPetals/preview.html +14 -15
  216. package/design-system/components/ProgressPetals/style.css +27 -0
  217. package/design-system/components/README.md +151 -0
  218. package/design-system/components/Radio/README.md +40 -17
  219. package/design-system/components/Radio/preview.html +16 -1
  220. package/design-system/components/Radio/style.css +21 -0
  221. package/design-system/components/RankBar/README.md +29 -2
  222. package/design-system/components/RankBar/preview.html +14 -12
  223. package/design-system/components/RankBar/style.css +18 -0
  224. package/design-system/components/Ring/README.md +61 -11
  225. package/design-system/components/Ring/preview.html +55 -10
  226. package/design-system/components/Ring/style.css +49 -0
  227. package/design-system/components/ScoreHero/README.md +91 -0
  228. package/design-system/components/ScoreHero/preview.html +104 -0
  229. package/design-system/components/ScoreHero/style.css +32 -0
  230. package/design-system/components/Section/README.md +72 -33
  231. package/design-system/components/Section/preview.html +46 -16
  232. package/design-system/components/Section/style.css +18 -0
  233. package/design-system/components/Segmented/README.md +100 -55
  234. package/design-system/components/Segmented/preview.html +107 -26
  235. package/design-system/components/Segmented/style.css +94 -0
  236. package/design-system/components/SegmentedProgress/README.md +64 -0
  237. package/design-system/components/SegmentedProgress/preview.html +69 -0
  238. package/design-system/components/SegmentedProgress/style.css +11 -0
  239. package/design-system/components/Select/README.md +47 -12
  240. package/design-system/components/Select/preview.html +28 -2
  241. package/design-system/components/Select/style.css +22 -0
  242. package/design-system/components/ShareBar/README.md +69 -0
  243. package/design-system/components/ShareBar/preview.html +72 -0
  244. package/design-system/components/ShareBar/style.css +25 -0
  245. package/design-system/components/SideList/README.md +147 -0
  246. package/design-system/components/SideList/preview.html +139 -0
  247. package/design-system/components/SideList/style.css +94 -0
  248. package/design-system/components/Skeleton/README.md +53 -16
  249. package/design-system/components/Skeleton/preview.html +35 -23
  250. package/design-system/components/Skeleton/style.css +17 -0
  251. package/design-system/components/Slider/README.md +95 -0
  252. package/design-system/components/Slider/preview.html +49 -0
  253. package/design-system/components/Slider/style.css +13 -0
  254. package/design-system/components/Split/README.md +112 -0
  255. package/design-system/components/Split/preview.html +105 -0
  256. package/design-system/components/Split/style.css +30 -0
  257. package/design-system/components/Starter/README.md +21 -9
  258. package/design-system/components/Starter/preview.html +5 -5
  259. package/design-system/components/Stat/README.md +64 -43
  260. package/design-system/components/Stat/preview.html +3 -3
  261. package/design-system/components/Stat/style.css +15 -0
  262. package/design-system/components/StatTiles/README.md +88 -44
  263. package/design-system/components/StatTiles/preview.html +142 -71
  264. package/design-system/components/StatTiles/style.css +64 -0
  265. package/design-system/components/StatusLine/README.md +85 -0
  266. package/design-system/components/StatusLine/preview.html +49 -0
  267. package/design-system/components/StatusLine/style.css +14 -0
  268. package/design-system/components/StatusScreen/README.md +49 -35
  269. package/design-system/components/StatusScreen/preview.html +20 -5
  270. package/design-system/components/StatusScreen/style.css +9 -0
  271. package/design-system/components/StepLine/README.md +97 -0
  272. package/design-system/components/StepLine/preview.html +108 -0
  273. package/design-system/components/StepLine/style.css +62 -0
  274. package/design-system/components/Stepper/README.md +35 -13
  275. package/design-system/components/Stepper/style.css +13 -0
  276. package/design-system/components/StreakCalendar/README.md +22 -1
  277. package/design-system/components/StreakCalendar/preview.html +10 -10
  278. package/design-system/components/StreakCalendar/style.css +12 -0
  279. package/design-system/components/SuggestionChip/README.md +87 -0
  280. package/design-system/components/SuggestionChip/preview.html +42 -0
  281. package/design-system/components/SuggestionChip/style.css +20 -0
  282. package/design-system/components/Switch/README.md +44 -24
  283. package/design-system/components/Switch/preview.html +23 -8
  284. package/design-system/components/Switch/style.css +31 -0
  285. package/design-system/components/Table/README.md +129 -58
  286. package/design-system/components/Table/preview.html +106 -72
  287. package/design-system/components/Table/style.css +104 -0
  288. package/design-system/components/Tabs/README.md +71 -46
  289. package/design-system/components/Tabs/preview.html +56 -24
  290. package/design-system/components/Tabs/style.css +44 -0
  291. package/design-system/components/Testimonial/README.md +48 -32
  292. package/design-system/components/Testimonial/preview.html +14 -14
  293. package/design-system/components/Testimonial/style.css +12 -0
  294. package/design-system/components/TextArea/README.md +27 -11
  295. package/design-system/components/TextArea/preview.html +8 -2
  296. package/design-system/components/TextArea/style.css +12 -0
  297. package/design-system/components/ThemeSwitch/README.md +116 -0
  298. package/design-system/components/ThemeSwitch/preview.html +57 -0
  299. package/design-system/components/ThemeSwitch/style.css +6 -0
  300. package/design-system/components/TickRow/README.md +52 -36
  301. package/design-system/components/TickRow/preview.html +64 -41
  302. package/design-system/components/TickRow/style.css +23 -0
  303. package/design-system/components/TickStrip/README.md +95 -0
  304. package/design-system/components/TickStrip/preview.html +88 -0
  305. package/design-system/components/TickStrip/style.css +42 -0
  306. package/design-system/components/Tile/README.md +79 -18
  307. package/design-system/components/Tile/preview.html +91 -40
  308. package/design-system/components/Tile/style.css +36 -0
  309. package/design-system/components/Timeline/README.md +68 -48
  310. package/design-system/components/Timeline/preview.html +27 -15
  311. package/design-system/components/Timeline/style.css +25 -0
  312. package/design-system/components/Toast/README.md +70 -38
  313. package/design-system/components/Toast/preview.html +43 -8
  314. package/design-system/components/Toast/style.css +25 -0
  315. package/design-system/components/Tooltip/README.md +93 -35
  316. package/design-system/components/Tooltip/preview.html +69 -15
  317. package/design-system/components/Tooltip/style.css +78 -0
  318. package/design-system/components/TopBar/README.md +67 -53
  319. package/design-system/components/TopBar/preview.html +14 -27
  320. package/design-system/components/TopBar/style.css +35 -0
  321. package/design-system/components/TopicRail/README.md +108 -0
  322. package/design-system/components/TopicRail/preview.html +58 -0
  323. package/design-system/components/TopicRail/style.css +48 -0
  324. package/design-system/components/TrendBars/README.md +52 -14
  325. package/design-system/components/TrendBars/preview.html +65 -32
  326. package/design-system/components/TrendBars/style.css +25 -0
  327. package/design-system/components/TrendLine/README.md +164 -0
  328. package/design-system/components/TrendLine/preview.html +373 -0
  329. package/design-system/components/TrendLine/style.css +155 -0
  330. package/design-system/components/Well/README.md +64 -22
  331. package/design-system/components/Well/preview.html +14 -14
  332. package/design-system/components/Well/style.css +22 -0
  333. package/design-system/components/_house.css +324 -0
  334. package/design-system/components/bundle.css +4086 -744
  335. package/design-system/tokens.json +1310 -124
  336. package/dist/fello-core.css +2 -2
  337. package/dist/fello.css +6 -1369
  338. package/dist/fello.scoped.css +7 -0
  339. package/dist/index.d.ts +109 -10
  340. package/dist/index.js +781 -96
  341. package/dist/palettes.d.ts +464 -0
  342. package/dist/palettes.js +497 -0
  343. package/dist/scoped.d.ts +3 -0
  344. package/dist/scoped.js +16 -0
  345. package/dist/toast.d.ts +14 -0
  346. package/dist/toast.js +33 -29
  347. package/dist/tokens.d.ts +1686 -62
  348. package/dist/tokens.js +1668 -61
  349. package/package.json +20 -4
  350. package/scripts/check-palette.mjs +295 -0
  351. package/scripts/token-model.mjs +552 -0
  352. package/tokens/_dark.css +173 -0
  353. package/tokens/_palettes.css +46 -0
  354. package/tokens/_product.css +266 -53
  355. package/tokens/_source.hubl.css +39 -19
  356. package/tokens/design-tokens.json +319 -0
  357. package/tokens/palettes.ts +504 -0
  358. package/tokens/shadcn-compat.css +19 -19
  359. package/tokens/shadcn-compat.hsl.css +76 -0
  360. package/tokens/tokens.css +1287 -62
  361. package/tokens/tokens.md +587 -61
  362. package/tokens/tokens.root.css +1293 -62
  363. package/tokens/tokens.ts +1677 -64
@@ -0,0 +1,36 @@
1
+ /* ---- Tile: one card in a bento (an icon disc and a title in its head, its body under), and the product tile row ---- */
2
+ /* Not clipped (K1, K9): a clip squashed the tile in a scroller and cut any menu or tip inside it. */
3
+ .ws-tile { display: flex; flex-direction: column; }
4
+ .ws-tile__head { display: flex; min-height: var(--space-3xl); align-items: center; gap: var(--space-xs); padding: var(--ws-card-padding-lg) var(--ws-card-padding-lg) 0; }
5
+ .ws-tile__head > .ws-section { min-width: 0; }
6
+ .ws-tile__disc { width: var(--space-lg); height: var(--space-lg); }
7
+ .ws-tile__disc svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); color: var(--color-text-heading); }
8
+ .ws-tile__body { display: flex; flex: 1; flex-direction: column; gap: var(--space-xs); padding: var(--space-xxs) var(--ws-card-padding-lg) var(--ws-card-padding-lg); }
9
+ /* Seth's tile figure: 32 / 38 regular, tight tracking, tabular. A figure that is not there yet ("Not connected") is muted. */
10
+ .ws-tile__figure { font-size: var(--ws-text-figure); line-height: var(--ws-leading-figure); font-weight: 400; letter-spacing: var(--ws-tracking-display); color: var(--color-text-heading); font-variant-numeric: tabular-nums; }
11
+ .ws-tile__figure--none { color: var(--color-text-muted); }
12
+ /* In a .ws-board--4: --full takes the whole row; --half two columns once the board has two (40rem). */
13
+ .ws-tile--full { grid-column: 1 / -1; }
14
+ @container (min-width: 40rem) { .ws-tile--half { grid-column: span 2; } }
15
+
16
+ /* The product tile row (issue #9, Seth's first open): what an app can do, 2 or 3 tiles joined on the tray, 1 px in and
17
+ 2 px apart. Each tile is a cream surface (a 24 px line icon, a 14 / 20 title, a 13 / 18 line, 108 tall at least)
18
+ with the card's foot on the grey under it: a door, or the step it waits on. The whole tile is the target. */
19
+ .ws-tiles { display: flex; flex-wrap: wrap; gap: var(--space-3xs); padding: var(--ws-rim); border-radius: var(--ws-radius-card); background: var(--ws-tray); }
20
+ .ws-tiles > li { display: flex; flex: 1 1 0; min-width: min(100%, calc(var(--space-8xl) + var(--space-xs))); }
21
+ .ws-tiles__tile { display: flex; flex: 1; flex-direction: column; min-width: 0; border-radius: var(--ws-radius-card-inner); color: inherit; text-align: left; text-decoration: none; }
22
+ a.ws-tiles__tile, button.ws-tiles__tile { width: 100%; padding: 0; border: 0; background: none; cursor: pointer; transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
23
+ a.ws-tiles__tile:focus-visible, button.ws-tiles__tile:focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
24
+ .ws-tiles__surface { display: flex; flex: 1; flex-direction: column; gap: var(--space-sm); min-height: calc(var(--space-7xl) - var(--space-sm)); padding: var(--space-md); border-radius: var(--ws-radius-card-inner); background: var(--color-bg-page); transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
25
+ .ws-tiles__icon { flex-shrink: 0; width: var(--space-lg); height: var(--space-lg); color: var(--color-text-heading); }
26
+ .ws-tiles__words { display: flex; flex-direction: column; gap: var(--space-3xs); }
27
+ .ws-tiles__title { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); }
28
+ .ws-tiles__line { font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; color: var(--color-text-body); }
29
+ /* Hover darkens the tray under the tile (its foot), the door's words underline; a press tints the cream at once. A
30
+ muted aside in the foot takes the body grey there (the muted grey is under AA on Seth's hover tray). */
31
+ @media (hover: hover) {
32
+ a.ws-tiles__tile:hover, button.ws-tiles__tile:hover { background-color: var(--ws-well-hover); }
33
+ :is(a, button).ws-tiles__tile:hover .ws-card__foot { --color-text-muted: var(--color-text-body); }
34
+ a.ws-tiles__tile:hover .ws-card__foot > :first-child, button.ws-tiles__tile:hover .ws-card__foot > :first-child { text-decoration: underline; }
35
+ }
36
+ a.ws-tiles__tile:active .ws-tiles__surface, button.ws-tiles__tile:active .ws-tiles__surface { background-color: var(--ws-surface-press); transition-duration: var(--ws-duration-instant); }
@@ -7,59 +7,57 @@ A vertical feed of what happened, grouped by day, a coloured dot on a fine line
7
7
 
8
8
  ## Not for
9
9
 
10
- - A sequence of steps still in progress toward an end: use `Stepper`, which shows what is done, current and ahead rather
11
- than a past record.
10
+ - A sequence of steps still in progress toward an end: use `Stepper`.
12
11
  - A list of records to compare or act on: use `Table` or rows in a `Card`.
13
- - A single moment worth calling out inside a chart: use `TrendBars`' own labelled moment instead of a whole timeline.
12
+ - A single moment worth calling out inside a chart: use `TrendBars`' own labelled moment.
14
13
 
15
14
  ## Anatomy
16
15
 
17
- - A vertical line, `--ws-line` (1 px) in `--ws-edge-slot`, running the column's height.
18
- - A dot per entry: 8 px, centred on the line, with a 2 px cream ring so it reads over the line.
19
- - Dot colour: navy for something the person did, `--ws-chart-finished` (teal) for a positive outcome,
20
- `--color-brand-salmon` for something that needs the person, grey (`--color-gray-3`) for something settled with no
21
- action attached.
22
- - An entry: a 14 px navy title (`--color-text-heading`), a 13 px muted meta line under it with the time
23
- (`--ws-text-meta`, `--color-text-muted`).
24
- - Spacing: 12 px between a dot and its words (the line sits in a 16 px left column, the words indent to clear it), 16 px
25
- between entries (`--space-md`), 24 px between day groups.
26
- - A day group: a 12 px eyebrow ("Today", "Yesterday", "Oct 24") above its entries, same style as any group eyebrow.
16
+ - A day: its label in Seth's control words (13 / 18 medium muted, sentence case: "Today", "Yesterday", "Oct 24"), flush
17
+ with the dots, 12 above its entries; days 24 apart.
18
+ - A dot per entry: 8 px, centred on the title's first line, on a 2 px ring of the ground so it reads over the line.
19
+ - The line: 1 px (`--ws-line`) in `--ws-edge-slot`, drawn from each dot's centre to the next dot's centre, so it never
20
+ runs past the last entry.
21
+ - An entry: the title 14 / 20 navy, 20 in (8 for the dot, 12 to the words); the time under it, 2 below, in the meta
22
+ words (`ws-meta`: 13 / 16 muted). Entries 16 apart.
23
+ - Dot tones: navy (`--color-text-heading`) for something the person did, teal (`--ws-chart-finished`) for a positive
24
+ outcome, salmon (`--ws-chart-under-half`) for something that needs the person, grey (`--ws-edge-card`) for something
25
+ settled with no act attached.
27
26
 
28
27
  ## Variants and sizes
29
28
 
30
- | Dot tone | Meaning |
31
- | --- | --- |
32
- | Navy | Something the person did (a call, a move) |
33
- | Teal (`--ws-chart-finished`) | A positive outcome (passed, accepted) |
34
- | Salmon (`--color-brand-salmon`) | Needs the person now |
35
- | Grey (`--color-gray-3`) | Settled, no action was or is needed |
29
+ | Dot tone | Class | Meaning |
30
+ | --- | --- | --- |
31
+ | Navy | `__dot--navy` | Something the person did (a call, a move) |
32
+ | Teal | `__dot--positive` | A positive outcome (passed, accepted) |
33
+ | Salmon | `__dot--needs` | Needs the person now |
34
+ | Grey | `__dot--settled` (or none) | Settled, no act needed |
36
35
 
37
36
  ## States
38
37
 
39
38
  - **Default**: as above.
40
- - **Needs you**: the salmon dot; the entry's own title already says what is needed, so no extra chip repeats it.
41
- - **Empty**: the same card, a sentence ("Nothing here yet") in place of the list; never an empty line with no dots.
42
- - **Loading**: skeleton lines in place of titles, the dots shown as plain grey circles until content arrives.
43
- - **Long title**: wraps to a second line rather than truncating, since a history entry is read once and should say the
44
- whole thing.
45
- - **Many entries**: the feed scrolls inside its card past a comfortable length rather than growing the page; it is never
46
- paginated like `Table`, since a history reads front to back.
39
+ - **Needs you**: the salmon dot; the entry's own title already says what is needed.
40
+ - **An entry that opens something**: the title is a link (`a.ws-timeline__title`, medium), underlined on hover; on
41
+ touch its box grows to 24 without moving anything.
42
+ - **Empty**: the same card, a sentence ("Nothing here yet") in place of the list; never a bare line with no dots.
43
+ - **Loading**: ghost lines where the titles go under the shimmer (`__ghost ws-shimmer`), the dots plain grey;
44
+ still under reduced motion.
45
+ - **Long title**: wraps; a history entry is read once and should say the whole thing.
46
+ - **Many entries**: the feed scrolls inside its card past a comfortable length; it is never paginated.
47
47
 
48
48
  ## Behaviour
49
49
 
50
- - Keyboard: the feed is a plain ordered list (`<ol>`); an entry that opens something (a lead, a call) is a real
51
- link within it.
52
- - Pointer: an actionable entry hovers like any row; a purely informational entry does not react to the pointer.
53
- - Motion: entries rise in on arrival (`ws-rise`), staggered up to six at a time per the system's stagger cap; reduced
54
- motion shows them in place without the rise.
50
+ - Keyboard: a plain ordered list (`<ol>`) per day; an entry that opens something is a real link.
51
+ - Pointer: an informational entry does not react to the pointer.
52
+ - Motion: entries settle in on arrival (the house `ws-settle`: up 6 px out of a 3 px blur over 320 ms, 22 ms apart; set
53
+ `--ws-i` on each). Under reduced motion they are simply there.
55
54
 
56
55
  ## Content
57
56
 
58
57
  - A title states what happened in a plain sentence, past tense, naming who did it ("You called Dana Alvarez", not
59
58
  "Call logged").
60
- - The meta line is the time alone, or the time and a short detail ("10:14", "4:47, 6 minutes"); it never repeats the
61
- title.
62
- - No em dashes; day labels are "Today", "Yesterday", then a date ("Oct 24"), never a full date for the two most recent.
59
+ - The meta line is the time alone, or the time and a short detail ("10:14", "4:47, 6 minutes").
60
+ - Day labels are "Today", "Yesterday", then a date ("Oct 24"). No em dashes.
63
61
 
64
62
  ## Props
65
63
 
@@ -70,20 +68,42 @@ A vertical feed of what happened, grouped by day, a coloured dot on a fine line
70
68
 
71
69
  ## Rules
72
70
 
73
- - **A mark never stands for a state alone**: the dot's tone pairs with the entry's own words, matching the system's rule
74
- that a state always shows with a word as well as a colour (`03-colour.md`, "Never a state by colour alone").
75
- - **Grouped by day, not a bare flat list**: matching the grouping rule that related information sits closer together
76
- and different groups (here, different days) are told apart by a label, not just a gap (`05-space-and-layout.md`,
77
- "Grouping").
78
- - **The hairline is `--ws-edge-slot`**, the same tone used for a day cell's or a chart row's fine edge, since the line is
79
- content structure rather than a card boundary.
80
- - **Source**: Intentional addition, decided from the system (26 Oct 2026): any product needs a plain history of what
81
- happened to one thing, which none of the system's own progress-and-goal charts provide. Derived from the slot-edge
82
- hairline, the four state tones (navy, teal, salmon, grey) used throughout the colour system, and the meta text size
83
- for timestamps.
71
+ - **A mark never stands for a state alone**: the dot's tone pairs with the entry's words.
72
+ - **Grouped by day**, each group named by a label, not just a gap.
73
+ - **The line ends at the last dot**: no tail under the feed.
74
+ - **Sentence case day labels** (D6): no uppercase eyebrow.
84
75
 
85
76
  ## Source
86
77
 
87
- **Derived from**: `--ws-edge-slot` for the line's hairline, the four state tones already defined for colour meaning
88
- (navy, teal, salmon, grey), and `--ws-text-meta` for the time line. **Precedent**: an intentional addition decided
89
- from the system, 26 Oct 2026; no chart in the first product draws a plain activity feed.
78
+ **Derived from**: `--ws-edge-slot` for the line, the four state tones, Seth's control words for the day (D6), North's
79
+ settle motion (D7). **Precedent**: an intentional addition decided from the system, 26 Oct 2026; in 0.5.0 the dot moved
80
+ onto the title's first line (it sat 2 px high) and the settled dot from the near-white `--ws-chart-empty` to the card
81
+ edge grey, which reads on cream and on dark.
82
+
83
+ ## Markup
84
+
85
+ ```html
86
+ <section class="ws-card ws-card--inset ws-timeline" aria-label="Activity">
87
+ <div class="ws-timeline__day">
88
+ <h3 class="ws-timeline__day-label">Today</h3>
89
+ <ol class="ws-timeline__list">
90
+ <li class="ws-timeline__item ws-settle">
91
+ <span class="ws-timeline__dot ws-timeline__dot--needs" aria-hidden="true"></span>
92
+ <a class="ws-timeline__title" href="#priya">Priya Nair's showing link expired</a>
93
+ <p class="ws-meta ws-timeline__meta">10:14</p>
94
+ </li>
95
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 1;">
96
+ <span class="ws-timeline__dot ws-timeline__dot--navy" aria-hidden="true"></span>
97
+ <p class="ws-timeline__title">You called Dana Alvarez</p>
98
+ <p class="ws-meta ws-timeline__meta">9:02, 6 minutes</p>
99
+ </li>
100
+ </ol>
101
+ </div>
102
+ </section>
103
+ ```
104
+
105
+ ## Styles
106
+
107
+ `design-system/components/Timeline/style.css`, in `bundle.css` and `fello.css`. `ws-timeline` on the card is a hook
108
+ for an app's own selectors and tests; the kit gives it no rule (the parts carry the styles). Dark comes from the tokens (the dot's
109
+ ring is `--color-bg-page`, so it matches whatever card it sits on in light, dark or navy).
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Data" height=496 -->
1
+ <!-- @dsCard group="Data" height=600 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -10,49 +10,46 @@
10
10
  <body>
11
11
  <div class="ws-stage ws-stage--grey">
12
12
 
13
- <div style="width: 360px; max-width: 100%;">
14
- <section class="ws-card ws-card--inset ws-timeline" aria-label="Activity">
13
+ <section class="ws-card ws-card--inset ws-timeline" aria-label="Activity" style="width: 380px;">
15
14
  <div class="ws-timeline__day">
16
- <h3 class="ws-eyebrow ws-timeline__day-label">Today</h3>
15
+ <h3 class="ws-timeline__day-label">Today</h3>
17
16
  <ol class="ws-timeline__list">
18
- <li class="ws-timeline__item ws-rise">
17
+ <li class="ws-timeline__item ws-settle">
19
18
  <span class="ws-timeline__dot ws-timeline__dot--needs" aria-hidden="true"></span>
20
- <p class="ws-timeline__title">Priya Nair's showing link expired</p>
19
+ <a class="ws-timeline__title" href="#priya">Priya Nair's showing link expired before she opened it</a>
21
20
  <p class="ws-meta ws-timeline__meta">10:14</p>
22
21
  </li>
23
- <li class="ws-timeline__item ws-rise" style="animation-delay: calc(var(--ws-stagger) * 1);">
22
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 1;">
24
23
  <span class="ws-timeline__dot ws-timeline__dot--navy" aria-hidden="true"></span>
25
24
  <p class="ws-timeline__title">You called Dana Alvarez</p>
26
25
  <p class="ws-meta ws-timeline__meta">9:02, 6 minutes</p>
27
26
  </li>
28
27
  </ol>
29
28
  </div>
30
-
31
29
  <div class="ws-timeline__day">
32
- <h3 class="ws-eyebrow ws-timeline__day-label">Yesterday</h3>
30
+ <h3 class="ws-timeline__day-label">Yesterday</h3>
33
31
  <ol class="ws-timeline__list">
34
- <li class="ws-timeline__item ws-rise" style="animation-delay: calc(var(--ws-stagger) * 2);">
32
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 2;">
35
33
  <span class="ws-timeline__dot ws-timeline__dot--positive" aria-hidden="true"></span>
36
34
  <p class="ws-timeline__title">Sam Okafor confirmed the showing</p>
37
35
  <p class="ws-meta ws-timeline__meta">4:47</p>
38
36
  </li>
39
- <li class="ws-timeline__item ws-rise" style="animation-delay: calc(var(--ws-stagger) * 3);">
37
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 3;">
40
38
  <span class="ws-timeline__dot ws-timeline__dot--navy" aria-hidden="true"></span>
41
39
  <p class="ws-timeline__title">You moved Marco Diaz to New lead</p>
42
40
  <p class="ws-meta ws-timeline__meta">2:10</p>
43
41
  </li>
44
- <li class="ws-timeline__item ws-rise" style="animation-delay: calc(var(--ws-stagger) * 4);">
42
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 4;">
45
43
  <span class="ws-timeline__dot ws-timeline__dot--settled" aria-hidden="true"></span>
46
44
  <p class="ws-timeline__title">Nellie Park's offer expired, unanswered</p>
47
45
  <p class="ws-meta ws-timeline__meta">11:30</p>
48
46
  </li>
49
47
  </ol>
50
48
  </div>
51
-
52
49
  <div class="ws-timeline__day">
53
- <h3 class="ws-eyebrow ws-timeline__day-label">Oct 24</h3>
50
+ <h3 class="ws-timeline__day-label">Oct 24</h3>
54
51
  <ol class="ws-timeline__list">
55
- <li class="ws-timeline__item ws-rise" style="animation-delay: calc(var(--ws-stagger) * 5);">
52
+ <li class="ws-timeline__item ws-settle" style="--ws-i: 5;">
56
53
  <span class="ws-timeline__dot ws-timeline__dot--navy" aria-hidden="true"></span>
57
54
  <p class="ws-timeline__title">Jo Whitfield accepted the offer</p>
58
55
  <p class="ws-meta ws-timeline__meta">3:55</p>
@@ -60,6 +57,21 @@
60
57
  </ol>
61
58
  </div>
62
59
  </section>
60
+
61
+ <div class="ws-stack ws-stack--component" style="width: 300px;">
62
+ <section class="ws-card ws-card--inset ws-timeline" aria-busy="true" aria-label="Activity, loading">
63
+ <div class="ws-timeline__day">
64
+ <h3 class="ws-timeline__day-label">Today</h3>
65
+ <ol class="ws-timeline__list">
66
+ <li class="ws-timeline__item"><span class="ws-timeline__dot" aria-hidden="true"></span><div class="ws-timeline__ghost ws-shimmer" style="width: 80%;"></div></li>
67
+ <li class="ws-timeline__item"><span class="ws-timeline__dot" aria-hidden="true"></span><div class="ws-timeline__ghost ws-shimmer" style="width: 60%;"></div></li>
68
+ <li class="ws-timeline__item"><span class="ws-timeline__dot" aria-hidden="true"></span><div class="ws-timeline__ghost ws-shimmer" style="width: 70%;"></div></li>
69
+ </ol>
70
+ </div>
71
+ </section>
72
+ <section class="ws-card ws-card--inset ws-timeline" aria-label="Activity, empty">
73
+ <p class="ws-body">Nothing here yet. Calls, showings and offers for Priya show up as they happen.</p>
74
+ </section>
63
75
  </div>
64
76
 
65
77
  </div>
@@ -0,0 +1,25 @@
1
+ /* ---- Timeline: what happened, grouped by day, a dot per entry on one fine line that runs from the first dot to the last ---- */
2
+ .ws-timeline__day + .ws-timeline__day { margin-top: var(--space-lg); }
3
+ /* The day: Seth's control words, 13 / 18 medium muted, sentence case, flush with the dots. */
4
+ .ws-timeline__day-label { margin-bottom: var(--space-sm); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; color: var(--color-text-muted); }
5
+ /* Words start 12 past the 8 px dot (20 in); the line is drawn per entry, dot centre to the next dot's centre, so it never
6
+ runs past the last entry. */
7
+ .ws-timeline__list { display: flex; flex-direction: column; gap: var(--space-md); padding-left: calc(var(--space-xs) + var(--space-sm)); }
8
+ .ws-timeline__item { position: relative; }
9
+ .ws-timeline__item:not(:last-child)::before { content: ""; position: absolute; left: calc((var(--space-xs) + var(--space-sm)) * -1 + (var(--space-xs) - var(--ws-line)) / 2); top: calc(var(--ws-leading-row) / 2); bottom: calc((var(--space-md) + var(--ws-leading-row) / 2) * -1); width: var(--ws-line); background: var(--ws-edge-slot); }
10
+ /* The dot: 8 px, centred on the title's first line, on a 2 px ring of the ground so it reads over the line. */
11
+ .ws-timeline__dot { position: absolute; z-index: 1; left: calc((var(--space-xs) + var(--space-sm)) * -1); top: calc((var(--ws-leading-row) - var(--space-xs)) / 2); width: var(--space-xs); height: var(--space-xs); border-radius: var(--radius-full); background: var(--ws-edge-card); box-shadow: 0 0 0 var(--ws-ring) var(--color-bg-page); }
12
+ .ws-timeline__dot--navy { background: var(--color-text-heading); }
13
+ .ws-timeline__dot--positive { background: var(--ws-chart-finished); }
14
+ .ws-timeline__dot--needs { background: var(--ws-chart-under-half); }
15
+ .ws-timeline__dot--settled { background: var(--ws-edge-card); }
16
+ .ws-timeline__title { font-size: var(--ws-text-body); line-height: var(--ws-leading-row); color: var(--color-text-heading); }
17
+ .ws-timeline__meta { margin-top: var(--space-3xs); }
18
+ /* An entry that opens something: the title is a link, underlined on hover, focus the house ring. */
19
+ a.ws-timeline__title { display: block; font-weight: 500; text-decoration: none; }
20
+ @media (hover: hover) { a.ws-timeline__title:hover { text-decoration: underline; text-underline-offset: var(--space-3xs); } }
21
+ /* On touch the link's box grows to 24 without moving a thing. */
22
+ @media (pointer: coarse) { a.ws-timeline__title { padding-block: var(--space-3xs); margin-block: calc(var(--space-3xs) * -1); } }
23
+ /* Loading: ghost lines where the titles go (add ws-shimmer), the dots plain. */
24
+ .ws-timeline__ghost { display: block; height: calc(var(--space-xs) + var(--space-3xs)); margin-block: calc((var(--ws-leading-row) - var(--space-xs) - var(--space-3xs)) / 2); border-radius: var(--ws-radius-bar); background: var(--ws-track); }
25
+ .ws-timeline__ghost.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
@@ -1,72 +1,104 @@
1
- A brief, passing confirmation that something happened in the background, drawn by the kit's own `Toaster` (sonner).
1
+ A receipt that passes: something finished in the background, said in one line, with at most one act. Seth's navy pill.
2
2
 
3
3
  ## Use it when
4
4
 
5
- - Something just finished in the background and the person should know, briefly, without being blocked ("Draft saved", "Lead archived").
6
- - An action offers a short-lived "Undo" ("Removed from the pipeline, Undo"), with its own few seconds before it is gone.
5
+ - Something just finished and the person should know, briefly, without being stopped ("Draft saved").
6
+ - An action offers a short-lived Undo ("Removed from the pipeline. Undo").
7
7
 
8
8
  ## Not for
9
9
 
10
- - An error the person must act on: put it beside the field or action it belongs to (`ws-field-msg--error`, `ws-needs`), never in a toast, since a toast can be missed or dismissed before it is read.
11
- - Essential information the person needs to keep seeing: that lives on the page or in the chat, never only in a toast that disappears.
12
- - A question needing an answer: use `Dialog`.
10
+ - An error the person must act on: put it beside the field or act it belongs to (`ws-field-msg--error`), never in a
11
+ toast, which can be missed.
12
+ - Anything the person needs to keep seeing: that lives on the page or in the chat.
13
+ - A question that needs an answer: use `Dialog`.
13
14
 
14
15
  ## Anatomy
15
16
 
16
- - The kit's own `Toaster` (`@felloinnovations/brand-kit/toast`, built on sonner): a white card, 1 px solid `--color-border-default` edge, `--radius-sm` (4 px) corners, `--shadow-card-hover` lift.
17
- - A title line (14 px, `--font-size-sm`, medium, navy `--color-text-heading`) and an optional description line under it (12 px, `--font-size-2xs`, muted `--color-text-muted`).
18
- - An optional close control and an optional action button (styled through `actionButtonStyle`/`cancelButtonStyle`), both token-coloured.
19
- - Positioned bottom right on a desktop, sat over the chat's composer corner; spans the foot above the tab bar on a phone.
17
+ - The pill (`ws-toast`): the act's navy (`--ws-inverse`) with its words (`--ws-on-inverse`, 12.71:1); the brand navy and white in dark, 8 / 14 inside,
18
+ 18 px corners (North's toast), the pop drop (`--ws-shadow-pop`). One line is 34 tall, a true pill; a second line
19
+ keeps the same corners. Never wider than its column.
20
+ - Icon (`ws-toast__icon`): 16 px, before the words, 12 apart; a tick for a receipt. Centred on one line; with a
21
+ detail it sits on the title's line (1 above and below it), as a menu's icon does.
22
+ - Words (`ws-toast__body`): the title (`ws-toast__title`, 13 / 18 medium), and at most one detail under it, 2 apart
23
+ (`ws-toast__description`, 13 / 18 in the act's words at 76%, 8.0:1).
24
+ - Act (`ws-toast__action`): 13 / 18 semibold words that act, underlined, never a second fill. On touch it is 40 tall
25
+ and reaches into the pill's padding, so the pill stays 40.
20
26
 
21
27
  ## Variants and sizes
22
28
 
23
29
  | Kind | Look |
24
30
  | --- | --- |
25
- | Plain confirmation | Title only, or title plus a short description |
26
- | With an action | Adds one button (such as "Undo"), styled through `actionButtonStyle`, kept a quiet navy in the reference implementation rather than the kit's default salmon |
31
+ | Receipt | Tick and title, one line |
32
+ | With an act | Adds one act at the end ("Undo", "View") |
33
+ | With a detail | Title and one detail line; the icon sits on the title's line, the act centred beside both |
27
34
 
28
35
  ## States
29
36
 
30
- - **Entering**: the kit's own sonner entrance (a slide and fade), not a product-specific motion.
31
- - **Shown**: sits over the page's corner for sonner's default duration, stacking above any other toast already showing.
32
- - **Dismissing**: swipe-to-dismiss (sonner's own gesture) or its own timer; leaves the same way it arrived, reversed.
33
- - **With an action**: pressing the action both performs it and dismisses the toast.
37
+ - **Entering** (North's chat toast, js@685658): it slides up 8 px out of .96 (`--ws-open-scale-toast`) and settles on
38
+ the settle spring (`--ws-spring-settle`, .32 / .1).
39
+ - **Shown**: for the toaster's time, stacking over any other toast.
40
+ - **Leaving** (`data-leaving`): fades 4 px down over `--ws-duration-exit` (120 ms), faster than it came; remove it
41
+ 120 ms later.
42
+ - **Act hover**: its underline thickens to 2 px, for pointers that hover.
43
+ - **Act pressed**: does the act and leaves.
44
+ - **Focus**: the act's ring turns to its words' colour, so it shows on the navy.
45
+ - **Dark**: the pill keeps the brand navy and white words; the pop shadow carries a faint light rim so it lifts off
46
+ the dark page (D12).
34
47
 
35
48
  ## Behaviour
36
49
 
37
- - Keyboard: sonner renders its stack in an `aria-live` region; a focused toast's action and close are reachable by Tab while it is present.
38
- - Pointer: a swipe or drag dismisses it; the close control, if shown, dismisses it on click.
39
- - Touch: swipe-to-dismiss is the primary touch interaction; sonner handles this without extra code.
40
- - Motion: entirely the kit's own (sonner's built-in transitions); the reference implementation only overrides colours, border, radius and shadow through `toastOptions`, never the motion itself.
41
- - Reduced motion: follows sonner's own reduced-motion handling, not a product override.
50
+ - Keyboard: the toaster keeps its stack in an `aria-live` region (`role="status"`); a toast's act is reachable by Tab
51
+ while it is there.
52
+ - Pointer and touch: swipe or its own timer dismisses it; the act is 40 tall on touch.
53
+ - Motion: in the kit's `Toaster` (sonner) the toaster moves it; `ws-toast` carries the same motion for a page without
54
+ sonner.
55
+ - Reduced motion: it appears and goes in place.
56
+ - The preview's last stack is live: press Save the draft.
42
57
 
43
58
  ## Content
44
59
 
45
60
  - The title says what happened, in the past tense, briefly ("Draft saved", not "Saving your draft").
46
- - A description, if any, adds the one relevant detail (who or what), never repeating the title.
47
- - No em dash; sentence case.
48
- - Never used for something the person must act on: a toast's words are a receipt, not a request.
61
+ - A detail adds the one fact that matters (who or what), never a repeat of the title.
62
+ - The act is one short verb.
63
+ - Never something the person must act on: a toast is a receipt, not a request.
49
64
 
50
65
  ## Props
51
66
 
52
- `Toaster` takes the kit's own `ToasterProps` (from sonner): `position`, `toastOptions` (its `style`, `actionButtonStyle`, `cancelButtonStyle`, `classNames`), and the rest of sonner's API. The reference implementation's own usage sets:
67
+ `Toaster` takes sonner's `ToasterProps`: `position`, `toastOptions` (`style`, `actionButtonStyle`, `classNames`) and the
68
+ rest of sonner's API. The skin to give it, so it matches `ws-toast`:
53
69
 
54
- | Name | Value | Meaning |
55
- | --- | --- | --- |
56
- | `position` | `"bottom-right"` | Where the stack sits on a desktop. |
57
- | `mobileOffset` | `{ bottom: 'calc(var(--space-6xl) + var(--space-xs))' }` | Clears the phone's tab bar. |
58
- | `toastOptions.style` | white background, `--color-border-default` edge, `--radius-sm`, `--shadow-card-hover` | The kit's own skin, kept whole. |
59
- | `toastOptions.actionButtonStyle.background` | `--color-brand-navy` | The reference implementation's one change: the action is a quiet navy, never the kit's default salmon, since salmon is reserved for the one primary act of a screen. |
70
+ | Name | Value |
71
+ | --- | --- |
72
+ | `toastOptions.style` | `background: var(--ws-inverse)`, `color: var(--ws-on-inverse)`, no border, `border-radius: calc(var(--space-md) + var(--space-3xs))`, `box-shadow: var(--ws-shadow-pop)`, `padding: var(--space-xs) var(--space-sm-plus)`, `font-size: var(--ws-text-control)` |
73
+ | `toastOptions.actionButtonStyle` | `background: none`, `color: var(--color-white)`, `font-weight: 600`, `text-decoration: underline` |
74
+ | `mobileOffset` | `{ bottom: 'calc(var(--space-6xl) + var(--space-xs))' }`, clear of a phone's tab bar |
60
75
 
61
76
  ## Rules
62
77
 
63
- - "Style only" (the kit owns sonner's behaviour: stacking, swipe-to-dismiss, the `aria-live` region); the product never re-implements the toast mechanics itself.
64
- - Never for an error the person must act on (the system's own rule: salmon and red are never used for a toast's own words; an error lives where the problem is, not in a passing toast).
65
- - The action button is quiet navy, not the kit's default salmon, because salmon is reserved for the one primary act of a screen.
66
- - **Contradiction found, not resolved**: a brief for this preview once described a cream card lifted, 8 px corners, a 14 px navy line, a 12 px muted line and an x icon button. Neither the kit's own `Toaster` nor the reference implementation's override matches this: both draw a white card, 4 px corners, a card-hover lift with a 1 px solid border, and neither configures a close ("x") button at all. This preview and README follow the actual code, since code is truth.
78
+ - Style only: the toaster owns stacking, swipe and the `aria-live` region; the product never rewrites them.
79
+ - Never for an error.
80
+ - One act at most, and it is words, never a second fill.
81
+ - Navy, Seth's (North css:679): this replaces the white card with a 1 px border (logged in 17-decisions.md).
67
82
 
68
83
  ## Source
69
84
 
70
- **Derived from**: the kit's own `Toaster` (sonner), restyled only in its colours, border, radius and shadow; the one
71
- additional change is a quiet navy action button in place of the kit's default salmon. **Precedent**: the first
72
- product built on the system.
85
+ **Derived from**: Seth's North toast (style1.css:679: navy pill, 8 / 14 inside, 18 px corners, white words, a
86
+ `0 10px 24px -12px` drop; js: in from y 8 and .96 on the settle spring, out to y 4), the kit's `Toaster` (sonner) and
87
+ the geometry check (the act under 40 on touch). **Precedent**: the first product built on the system.
88
+
89
+ ## Markup
90
+
91
+ ```html
92
+ <div class="ws-toast" role="status">
93
+ <svg class="ws-toast__icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
94
+ <div class="ws-toast__body">
95
+ <p class="ws-toast__title">Removed from the pipeline</p>
96
+ </div>
97
+ <button type="button" class="ws-toast__action">Undo</button>
98
+ </div>
99
+ ```
100
+
101
+ ## Styles
102
+
103
+ `Toast/style.css`, built into `bundle.css` and `fello.css`. Tokens only; the pill stays navy in dark, its rim comes with the page.
104
+ `src/components/toast.tsx` (the `Toaster`) must carry the same skin; until it does, the React toast is the old white card.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Overlays" height=140 -->
1
+ <!-- @dsCard group="Overlays" height=150 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -10,22 +10,23 @@
10
10
  <body>
11
11
  <div class="ws-stage ws-stage--grey">
12
12
 
13
- <div class="ws-stack">
14
- <span class="ws-muted">A static toast as the kit and the reference implementation draw it (sonner, style only, no close icon)</span>
15
- <div style="width: 300px; max-width: 100%;">
13
+ <div class="ws-stack" style="width: 360px;">
14
+ <span class="ws-muted">A receipt: the tick and one line, a navy pill</span>
15
+ <div class="ws-cluster">
16
16
  <div class="ws-toast" role="status">
17
+ <svg class="ws-toast__icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
17
18
  <div class="ws-toast__body">
18
19
  <p class="ws-toast__title">Draft saved</p>
19
- <p class="ws-toast__description">Priya Nair's follow-up is ready to send.</p>
20
20
  </div>
21
21
  </div>
22
22
  </div>
23
23
  </div>
24
24
 
25
- <div class="ws-stack">
26
- <span class="ws-muted">With an action: the action is a quiet navy, never the kit's default salmon</span>
27
- <div style="width: 300px; max-width: 100%;">
25
+ <div class="ws-stack" style="width: 360px;">
26
+ <span class="ws-muted">With its one act: words that act, never a second fill</span>
27
+ <div class="ws-cluster">
28
28
  <div class="ws-toast" role="status">
29
+ <svg class="ws-toast__icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
29
30
  <div class="ws-toast__body">
30
31
  <p class="ws-toast__title">Removed from the pipeline</p>
31
32
  </div>
@@ -34,6 +35,40 @@
34
35
  </div>
35
36
  </div>
36
37
 
38
+ <div class="ws-stack" style="width: 360px;">
39
+ <span class="ws-muted">A title and the one detail; long words wrap, the act sits beside them</span>
40
+ <div class="ws-toast" role="status">
41
+ <svg class="ws-toast__icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
42
+ <div class="ws-toast__body">
43
+ <p class="ws-toast__title">Sent to Google Chat</p>
44
+ <p class="ws-toast__description">Priya Nair's follow-up is with Dana and the two agents who referred her.</p>
45
+ </div>
46
+ <button type="button" class="ws-toast__action">View</button>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="ws-stack" style="width: 360px;" data-live>
51
+ <span class="ws-muted">Live: press Save. The toast slides up out of .96 on the settle spring, stays 3 s, then fades 4 px down over .12 s, faster than it came</span>
52
+ <button type="button" class="ws-btn ws-btn--secondary" id="toast-live-go" style="align-self: flex-start;">Save the draft</button>
53
+ <div class="ws-cluster" id="toast-live" style="min-height: var(--space-2xl);" aria-live="polite"></div>
54
+ </div>
55
+ <script>
56
+ (() => {
57
+ const slot = document.getElementById('toast-live');
58
+ let timer = 0;
59
+ document.getElementById('toast-live-go').addEventListener('click', () => {
60
+ clearTimeout(timer);
61
+ slot.replaceChildren();
62
+ const toast = document.createElement('div');
63
+ toast.className = 'ws-toast';
64
+ toast.setAttribute('role', 'status');
65
+ toast.innerHTML = '<svg class="ws-toast__icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg><div class="ws-toast__body"><p class="ws-toast__title">Draft saved</p></div>';
66
+ slot.append(toast);
67
+ timer = setTimeout(() => { toast.setAttribute('data-leaving', ''); timer = setTimeout(() => toast.remove(), 120); }, 3000);
68
+ });
69
+ })();
70
+ </script>
71
+
37
72
  </div>
38
73
  </body>
39
74
  </html>
@@ -0,0 +1,25 @@
1
+ /* ---- Toast: a receipt that passes, Seth's navy pill (North css:679): a tick, 13 px words, at most one quiet act ---- */
2
+ /* The act and its words in light (--ws-inverse: a palette's act), the brand navy and white in dark (D12: a floating navy message keeps the navy; in dark the pop shadow
3
+ carries its faint light rim). One line is a pill (18 px corners on a 34 px line); a second line keeps the same corners. */
4
+ .ws-toast { --ws-toast-radius: calc(var(--space-md) + var(--space-3xs)); /* North's 18 */ display: flex; align-items: center; gap: var(--space-sm); max-width: 100%; padding: var(--space-xs) var(--space-sm-plus); border-radius: var(--ws-toast-radius); background: var(--ws-inverse); color: var(--ws-on-inverse); box-shadow: var(--ws-shadow-pop); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); }
5
+ .ws-toast__icon { flex-shrink: 0; width: var(--ws-icon); height: var(--ws-icon); }
6
+ /* With a detail the tick belongs to the title: it sits on the title's line, as a menu's icon does; the act stays centred. */
7
+ .ws-toast:has(.ws-toast__description) > .ws-toast__icon { align-self: flex-start; margin-block: calc((var(--ws-leading-control) - var(--ws-icon)) / 2); }
8
+ .ws-toast__body { display: flex; flex: 1; flex-direction: column; gap: var(--space-3xs); min-width: 0; }
9
+ .ws-toast__title { font-weight: 500; color: inherit; }
10
+ /* North's quiet words on navy: its words at 76% (8.0:1 on the navy, in either theme). */
11
+ .ws-toast__description { color: color-mix(in srgb, var(--ws-on-inverse) 76%, transparent); }
12
+ /* The one act: words that act, underlined, never a second fill; under a pointer the underline thickens to 2 px. The
13
+ focus ring turns to the words' colour so it shows on the navy. On touch it is 40 tall and reaches into the pill's padding, so the pill stays 40. */
14
+ .ws-toast__action { flex-shrink: 0; padding: 0 var(--space-xxs); margin-inline: calc(var(--space-xxs) * -1); border: 0; border-radius: var(--ws-radius-control); background: none; color: var(--ws-on-inverse); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 600; text-decoration: underline; text-underline-offset: var(--space-3xs); cursor: pointer; }
15
+ .ws-toast__action:focus-visible { outline-color: var(--ws-on-inverse); }
16
+ @media (hover: hover) { .ws-toast__action:hover { text-decoration-thickness: var(--ws-focus-width); } }
17
+ @media (pointer: coarse) { .ws-toast__action { margin-block: calc(var(--space-xs) * -1); } }
18
+ /* Motion (D7, North's chat toast, js@685658: from y 8 and scale .96 on the settle spring .32 / .1, "Messages and steps
19
+ settle"): it slides up out of .96 and settles; it leaves by fading 4 px down over .12 s, faster than it came. */
20
+ @keyframes ws-toast-in { from { opacity: 0; transform: translateY(var(--space-xs)) scale(var(--ws-open-scale-toast)); } }
21
+ @keyframes ws-toast-out { to { opacity: 0; transform: translateY(var(--ws-nudge)); } }
22
+ @media (prefers-reduced-motion: no-preference) {
23
+ .ws-toast { animation: ws-toast-in var(--ws-spring-settle-duration) var(--ws-spring-settle) backwards; }
24
+ .ws-toast[data-leaving] { animation: ws-toast-out var(--ws-duration-exit) var(--ws-ease-exit) forwards; pointer-events: none; }
25
+ }