@felloinnovations/brand-kit 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/AGENTS.md +198 -24
  2. package/CHANGELOG.md +197 -0
  3. package/README.md +34 -7
  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 +134 -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 +357 -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 +52 -16
  249. package/design-system/components/Skeleton/preview.html +35 -23
  250. package/design-system/components/Skeleton/style.css +22 -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 +4091 -744
  335. package/design-system/tokens.json +1314 -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 +110 -11
  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 +174 -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 +1292 -62
  361. package/tokens/tokens.md +588 -61
  362. package/tokens/tokens.root.css +1298 -62
  363. package/tokens/tokens.ts +1677 -64
@@ -0,0 +1,12 @@
1
+ /* ---- Testimonial: the kit's quote card, the words then the person; two or three to a row ---- */
2
+ /* A grid of columns at least 280 px wide: a third card that wraps keeps its column's width instead of spanning the row. */
3
+ .ws-testimonial-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(var(--space-9xl) + var(--space-5xl))), 1fr)); gap: var(--layout-col-gap); }
4
+ .ws-testimonial-row > * { min-width: 0; }
5
+ /* A figure: the quote is a blockquote and the person its caption. The person sits at the foot, so a row of cards lines up. */
6
+ .ws-testimonial { display: flex; flex-direction: column; margin: 0; border-radius: var(--ws-radius-control); border: var(--ws-line) solid var(--color-border-default); background: var(--color-surface); padding: var(--space-lg); }
7
+ .ws-testimonial__quote { margin: 0; font-size: var(--font-size-md); line-height: var(--space-lg); color: var(--color-text-primary); }
8
+ .ws-testimonial__who { margin-top: auto; padding-top: var(--space-md); display: flex; align-items: center; gap: var(--space-sm); }
9
+ .ws-testimonial__avatar { width: var(--ws-control-h-md); height: var(--ws-control-h-md); border-radius: var(--radius-full); background: var(--ws-surface-sunk); color: var(--color-text-heading); display: inline-flex; align-items: center; justify-content: center; font-size: var(--font-size-2xs); font-weight: 600; flex-shrink: 0; }
10
+ .ws-testimonial__person { min-width: 0; }
11
+ .ws-testimonial__name { font-size: var(--font-size-sm); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); }
12
+ .ws-testimonial__role { font-size: var(--font-size-2xs); line-height: var(--space-md); color: var(--color-text-muted); }
@@ -13,11 +13,11 @@ Several lines of typed text, drawn exactly as `Input` is: white ground, the fine
13
13
 
14
14
  ## Anatomy
15
15
 
16
- - Box: `--ws-radius-control` (4px) corners, white ground (`--ws-field`), the fine hairline edge, at least 72px tall
16
+ - Box: `--ws-radius-control` (4px) corners, white ground (`--ws-field`), the 0.5 px card edge (`--ws-edge-card`) drawn inside, so a scroller never clips it, at least 72px tall
17
17
  (3 rows by default).
18
18
  - Sides: 12px (`--space-sm`) horizontal, 8px (`--space-xs`) vertical.
19
19
  - Label: 12px medium, `--color-text-body`, above the field.
20
- - Words: 14px, `--color-gray-8`, 20px line height; placeholder `--color-gray-5`.
20
+ - Words: 14 / 20, `--ws-field-ink`; placeholder `--color-text-placeholder` (AA on white).
21
21
  - Message below: as `Input`'s.
22
22
  - Resize: vertical only, so it never grows wider than its column.
23
23
 
@@ -32,24 +32,25 @@ There is one size; `rows` sets the starting height.
32
32
  ## States
33
33
 
34
34
  - **Default (rest):** white ground, fine grey edge, 3 rows tall.
35
- - **Typing (focus):** the edge turns mid blue and the kit's focus halo shows, exactly as `Input`'s, so focus never reads
36
- as an error.
37
- - **Error:** the edge turns salmon and a message rises in below (`ws-arrive`) with a warning icon, in `--ws-word-needs`.
38
- - **Disabled:** not editable; shown at reduced emphasis, the existing words still visible.
39
- - **With placeholder:** grey-5 placeholder, never the field's only label.
35
+ - **Hover (a mouse only):** the edge darkens (#AAA49D, North's outlined controls).
36
+ - **Typing (focus):** the kit's focus ring, 2 px navy, 2 px out, over the field's own ground; it never reads as an error
37
+ (the error is the salmon's step, the ring is navy).
38
+ - **Error:** a 1 px edge in the salmon's AA step and a message rises in below (`ws-arrive`), as `Input`'s.
39
+ - **Disabled:** the sunk cream ground with muted words, no resize; the existing words still visible.
40
+ - **With placeholder:** the AA placeholder grey, never the field's only label.
40
41
  - **Empty:** the rest state with the placeholder, if given.
41
42
  - **Long label:** the field's own label wraps; the typed words wrap and the box grows (or scrolls, by drag) rather than
42
43
  clip.
43
44
  - **Narrow:** always `width: 100%` of its column; only the height is resizable, by the person dragging its corner.
44
45
  - **Touch:** the field keeps its padding; there is no separate touch height since its content, not a fixed control
45
- height, decides its size.
46
+ height, decides its size. Its words grow to 16 / 24, so a phone does not zoom the page into it on focus.
47
+ - **Dark:** as `Input`'s.
46
48
 
47
49
  ## Behaviour
48
50
 
49
51
  - Keyboard: a native `<textarea>`; Tab moves to and from it, Enter inserts a new line (it does not submit a form).
50
52
  - Pointer / touch: a drag handle at the bottom-right corner resizes the height (`resize: vertical`).
51
- - Motion: border colour, background and shadow transition over `--ws-duration-instant` on `--ws-ease-soft`; an error
52
- message rises in over `--ws-duration-gentle`; nothing animates under `prefers-reduced-motion: reduce`.
53
+ - Motion: the edge over the hover beat on `--ws-ease-soft`; an error message rises in; still under reduced motion.
53
54
 
54
55
  ## Content
55
56
 
@@ -80,4 +81,19 @@ There is one size; `rows` sets the starting height.
80
81
  ## Source
81
82
 
82
83
  **Derived from**: the system's rule that a field without a kit equivalent is drawn to match `Input` exactly, including
83
- its mid-blue (never salmon) focus ring (21 Oct 2026). **Precedent**: the first product built on the system.
84
+ its focus ring, never salmon (21 Oct 2026); 0.5.0 takes `Input`'s inside edge, hover and navy ring. **Precedent**: the first
85
+ product built on the system.
86
+
87
+ ## Markup
88
+
89
+ ```html
90
+ <div class="ws-field">
91
+ <label class="ws-label" for="opener">Opener for Nellie</label>
92
+ <textarea class="ws-textarea" id="opener" rows="3" aria-describedby="opener-msg"></textarea>
93
+ <p class="ws-field-msg" id="opener-msg">Shown to the lead as a text</p>
94
+ </div>
95
+ ```
96
+
97
+ ## Styles
98
+
99
+ `design-system/components/TextArea/style.css`: `ws-textarea` (and `--typing`).
@@ -9,7 +9,7 @@
9
9
  </head>
10
10
  <body>
11
11
  <div class="ws-stage">
12
- <div style="display: grid; grid-template-columns: repeat(2, minmax(var(--space-9xl), 1fr)); gap: var(--ws-gap-component); width: 100%;">
12
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: var(--ws-gap-component); width: 100%;">
13
13
 
14
14
  <div class="ws-field">
15
15
  <span class="ws-muted">Rest, with a hint</span>
@@ -19,11 +19,17 @@
19
19
  </div>
20
20
 
21
21
  <div class="ws-field">
22
- <span class="ws-muted">Typing (focus), with placeholder</span>
22
+ <span class="ws-muted">Typing (focus)</span>
23
23
  <label class="ws-label" for="t-focus">Notes on this call</label>
24
24
  <textarea class="ws-textarea ws-textarea--typing" id="t-focus" rows="3" placeholder="What stood out, and what to try next time" autofocus>She asks five direct questions, then</textarea>
25
25
  </div>
26
26
 
27
+ <div class="ws-field">
28
+ <span class="ws-muted">Empty: only the placeholder shows</span>
29
+ <label class="ws-label" for="t-empty">Notes for next time</label>
30
+ <textarea class="ws-textarea" id="t-empty" rows="3" placeholder="What stood out, and what to try next time"></textarea>
31
+ </div>
32
+
27
33
  <div class="ws-field">
28
34
  <span class="ws-muted">Error, rising in</span>
29
35
  <label class="ws-label" for="t-err">Reason for the hold</label>
@@ -0,0 +1,12 @@
1
+ /* ---- TextArea: the house's multi-line field, restated (0.5.0) so the house's Fields copy can go: Input's ground, edge,
2
+ hover, focus ring and error, 8 / 12 inside, 14 / 20 words, at least 72 tall, resized by height only. ---- */
3
+ .ws-textarea { display: block; width: 100%; min-width: 0; min-height: calc(var(--space-4xl) + var(--space-xs)); padding: var(--space-xs) var(--space-sm); border: 0; border-radius: var(--ws-radius-control); background: var(--ws-field); box-shadow: var(--ws-shadow-hairline-in); color: var(--ws-field-ink); font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); resize: vertical; transition: box-shadow var(--ws-duration-hover) var(--ws-ease-soft); }
4
+ @media (hover: hover) { .ws-textarea:not(:disabled, [aria-invalid="true"]):hover { box-shadow: inset 0 0 0 var(--ws-hairline) var(--ws-edge-hover); } }
5
+ .ws-textarea::placeholder { color: var(--color-text-placeholder); }
6
+ .ws-textarea:focus-visible { background: var(--ws-field); }
7
+ .ws-textarea[aria-invalid="true"] { box-shadow: inset 0 0 0 var(--ws-line) var(--ws-word-needs); }
8
+ .ws-textarea:disabled { background: var(--ws-surface-sunk); color: var(--color-text-muted); cursor: not-allowed; resize: none; }
9
+ /* The typing state drawn still: the focus ring a real focus draws. */
10
+ .ws-textarea--typing { outline: var(--ws-focus-width) solid var(--ws-focus-color); outline-offset: var(--ws-focus-offset); }
11
+ /* Touch: 16 / 24 words, so a phone does not zoom the page into the field (iOS zooms any field under 16 px). */
12
+ @media (pointer: coarse) { .ws-textarea { font-size: var(--ws-text-value); line-height: var(--space-lg); } }
@@ -0,0 +1,116 @@
1
+ The person's pick of System, Light or Dark, at the foot of the app's nav, kept in their browser and set before the page
2
+ paints.
3
+
4
+ ## Use it when
5
+
6
+ - An app offers the dark theme (D12: dark is opt-in) and a person may want it fixed, or following their computer.
7
+
8
+ ## Not for
9
+
10
+ - A page or an artifact that only follows the computer: set `<html data-theme="system">` and offer no switch.
11
+ - A per-card or per-chart look: the theme is the whole app's.
12
+
13
+ ## Anatomy
14
+
15
+ - The word "Theme" (12 / 16 muted, `ws-theme-switch__label`) at the left, the switch at the right, 8 apart, 8 / 8 / 4
16
+ inside (it sits at the foot of the nav).
17
+ - The switch: a `Segmented --sm` of three icon radios, each 28 by 24 with a 16 px icon: System (a screen), Light (a sun),
18
+ Dark (a moon). The chosen one is the navy act with its words colour (`--ws-on-act`).
19
+ - The group is `role="radiogroup"` named by the word; each item is a native radio with an `aria-label` and a `title`.
20
+
21
+ ## Variants and sizes
22
+
23
+ One size (`Segmented --sm`).
24
+
25
+ ## States
26
+
27
+ - **System (the default):** follows the computer, and changes with it.
28
+ - **Light / Dark:** fixed until changed.
29
+ - **Hover (a mouse only):** an item takes the navy wash.
30
+ - **Focus:** the kit's ring drawn inside the item.
31
+ - **Switching:** for two frames every transition is off (`ws-theme-switching` on `<html>`), so every surface turns at
32
+ once instead of each on its own beat.
33
+ - **No storage (a private window):** the pick holds for this page only.
34
+ - **Touch:** each item is a 40 px target.
35
+ - **Dark:** the switch itself takes the dark values like everything else.
36
+
37
+ ## Behaviour
38
+
39
+ - Native radios: Tab reaches the group, the arrow keys move the pick.
40
+ - A script in `<head>`, before the page paints, reads the pick from `localStorage` (`fello-theme`), sets
41
+ `<html data-theme="system|light|dark">` and the browser bar's colour (`<meta name="theme-color">` from the page's
42
+ `--ws-page`), and listens to the computer while on System. Picking System removes the key. Storage is wrapped in
43
+ try/catch. Another tab's pick follows through the `storage` event.
44
+
45
+ ## Content
46
+
47
+ - The word is "Theme"; the items' names are "System", "Light", "Dark".
48
+ - No em dashes.
49
+
50
+ ## Props
51
+
52
+ | Name | Type | Meaning |
53
+ | --- | --- | --- |
54
+ | `storageKey` | `string` | the `localStorage` key, default `fello-theme` |
55
+
56
+ ## Rules
57
+
58
+ - Dark is opt-in: an app that renders no switch and sets no `data-theme` stays light.
59
+ - The head script runs before paint, so a page never flashes the wrong theme.
60
+ - System is the default and removes the stored pick.
61
+
62
+ ## Source
63
+
64
+ **Derived from**: gtm-ai-impact's switch (public/ds-dark.css:181-188, public/theme.js:1-85): the three icon items at the
65
+ foot of the nav, the two-frame `ws-theme-switching`, the try/catch, the theme-color meta; drawn here with native radios
66
+ (the arrow keys come free) and the kit's `data-theme="system"`, so the CSS follows the computer without the script.
67
+
68
+ ## Markup
69
+
70
+ ```html
71
+ <!-- In <head>, after the stylesheet: sets the theme before the page paints. -->
72
+ <script>
73
+ (function () {
74
+ var KEY = 'fello-theme', root = document.documentElement, mq = matchMedia('(prefers-color-scheme: dark)');
75
+ function stored() { try { var v = localStorage.getItem(KEY); return v === 'light' || v === 'dark' ? v : 'system'; } catch (e) { return 'system'; } }
76
+ function paintMeta() {
77
+ var meta = document.querySelector('meta[name="theme-color"]');
78
+ if (meta) meta.content = getComputedStyle(root).getPropertyValue('--ws-page').trim();
79
+ }
80
+ function apply(pick, animate) {
81
+ if (animate) root.classList.add('ws-theme-switching');
82
+ root.dataset.theme = pick;
83
+ paintMeta();
84
+ if (animate) requestAnimationFrame(function () { requestAnimationFrame(function () { root.classList.remove('ws-theme-switching'); }); });
85
+ document.querySelectorAll('input[name="ws-theme"]').forEach(function (r) { r.checked = r.value === pick; });
86
+ }
87
+ apply(stored(), false);
88
+ mq.addEventListener('change', function () { if (stored() === 'system') paintMeta(); });
89
+ addEventListener('storage', function (e) { if (e.key === KEY) apply(stored(), true); });
90
+ document.addEventListener('DOMContentLoaded', function () {
91
+ apply(stored(), false);
92
+ document.addEventListener('change', function (e) {
93
+ var r = e.target;
94
+ if (r.name !== 'ws-theme') return;
95
+ try { r.value === 'system' ? localStorage.removeItem(KEY) : localStorage.setItem(KEY, r.value); } catch (err) {}
96
+ apply(r.value, true);
97
+ });
98
+ });
99
+ })();
100
+ </script>
101
+
102
+ <!-- At the foot of the nav. -->
103
+ <div class="ws-theme-switch" role="radiogroup" aria-labelledby="theme-label">
104
+ <span class="ws-theme-switch__label" id="theme-label">Theme</span>
105
+ <span class="ws-segmented ws-segmented--sm">
106
+ <label class="ws-segmented__item ws-segmented__item--icon" title="System"><input type="radio" name="ws-theme" value="system" aria-label="System" checked><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="3" width="12" height="8" rx="1"/><path d="M6 14h4M8 11v3"/></svg></label>
107
+ <label class="ws-segmented__item ws-segmented__item--icon" title="Light"><input type="radio" name="ws-theme" value="light" aria-label="Light"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="8" r="2.5"/><path d="M8 1.5v1.5M8 13v1.5M14.5 8H13M3 8H1.5M12.6 3.4l-1 1M4.4 11.6l-1 1M12.6 12.6l-1-1M4.4 4.4l-1-1"/></svg></label>
108
+ <label class="ws-segmented__item ws-segmented__item--icon" title="Dark"><input type="radio" name="ws-theme" value="dark" aria-label="Dark"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.5 9.5A5.5 5.5 0 1 1 6.5 2.5a4.5 4.5 0 0 0 7 7Z"/></svg></label>
109
+ </span>
110
+ </div>
111
+ ```
112
+
113
+ ## Styles
114
+
115
+ `design-system/components/ThemeSwitch/style.css`: `ws-theme-switch` and `__label`; the switch is `Segmented`'s `--sm`
116
+ with `__item--icon` items holding native radios. `ws-theme-switching` is the house's.
@@ -0,0 +1,57 @@
1
+ <!-- @dsCard group="Navigation" height=250 -->
2
+ <!doctype html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>ThemeSwitch</title>
7
+ <link rel="stylesheet" href="../../tokens.css">
8
+ <link rel="stylesheet" href="../bundle.css">
9
+ </head>
10
+ <body>
11
+ <div class="ws-stage ws-stage--column">
12
+
13
+ <div class="ws-stack" style="width: 232px; max-width: 100%;">
14
+ <span class="ws-muted">At the foot of the nav: System chosen, so the page follows the computer</span>
15
+ <div class="ws-theme-switch" role="radiogroup" aria-labelledby="theme-label">
16
+ <span class="ws-theme-switch__label" id="theme-label">Theme</span>
17
+ <span class="ws-segmented ws-segmented--sm">
18
+ <label class="ws-segmented__item ws-segmented__item--icon" title="System">
19
+ <input type="radio" name="ws-theme" value="system" aria-label="System" checked>
20
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="3" width="12" height="8" rx="1"/><path d="M6 14h4M8 11v3"/></svg>
21
+ </label>
22
+ <label class="ws-segmented__item ws-segmented__item--icon" title="Light">
23
+ <input type="radio" name="ws-theme" value="light" aria-label="Light">
24
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="8" r="2.5"/><path d="M8 1.5v1.5M8 13v1.5M14.5 8H13M3 8H1.5M12.6 3.4l-1 1M4.4 11.6l-1 1M12.6 12.6l-1-1M4.4 4.4l-1-1"/></svg>
25
+ </label>
26
+ <label class="ws-segmented__item ws-segmented__item--icon" title="Dark">
27
+ <input type="radio" name="ws-theme" value="dark" aria-label="Dark">
28
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.5 9.5A5.5 5.5 0 1 1 6.5 2.5a4.5 4.5 0 0 0 7 7Z"/></svg>
29
+ </label>
30
+ </span>
31
+ </div>
32
+ </div>
33
+
34
+ <p class="ws-meta" style="max-width: 420px;">Pick Light or Dark here to see the preview change; System follows the computer, and the choice is kept in this browser.</p>
35
+
36
+ </div>
37
+ <script>
38
+ /* The switch's wiring (the head script in the README sets the theme before paint; this preview has no head script, so it
39
+ only keeps the radios and the page in step). */
40
+ (function () {
41
+ var KEY = 'fello-theme', root = document.documentElement;
42
+ function stored() { try { var v = localStorage.getItem(KEY); return v === 'light' || v === 'dark' ? v : 'system'; } catch (e) { return 'system'; } }
43
+ var pick = stored();
44
+ root.dataset.theme = pick; // 'system' too: a page that sets nothing stays light (D12)
45
+ document.querySelectorAll('input[name="ws-theme"]').forEach(function (r) {
46
+ r.checked = r.value === pick;
47
+ r.addEventListener('change', function () {
48
+ try { r.value === 'system' ? localStorage.removeItem(KEY) : localStorage.setItem(KEY, r.value); } catch (e) {}
49
+ root.classList.add('ws-theme-switching');
50
+ root.dataset.theme = r.value;
51
+ requestAnimationFrame(function () { requestAnimationFrame(function () { root.classList.remove('ws-theme-switching'); }); });
52
+ });
53
+ });
54
+ })();
55
+ </script>
56
+ </body>
57
+ </html>
@@ -0,0 +1,6 @@
1
+ /* ---- ThemeSwitch: System, Light or Dark (D12), from gtm-ai-impact's switch (ds-dark.css:181-188): the word "Theme" in
2
+ the muted words and a small Segmented of three icon radios (System, Light, Dark), the chosen one the navy act. It
3
+ sits at the foot of the app's nav. The head script in its README sets <html data-theme> before the page paints. ---- */
4
+ .ws-theme-switch { display: flex; align-items: center; justify-content: space-between; gap: var(--space-xs); min-width: 0; padding: var(--space-xs) var(--space-xs) var(--space-xxs); }
5
+ .ws-theme-switch__label { font-size: var(--ws-text-dense); line-height: var(--space-md); color: var(--color-text-muted); }
6
+ .ws-theme-switch > .ws-segmented { flex-shrink: 0; }
@@ -1,67 +1,83 @@
1
- One row of ticks for a count out of a small whole, each done tick carrying its stretch of the cards' one salmon-to-teal gradient.
1
+ One row of fixed-size ticks for a count out of a small whole: the done ticks in one tone, or each its stretch of the gradient.
2
2
 
3
3
  **Use it when**
4
4
 
5
5
  - A list has a count out of a whole beside it: issues done, pieces used, goals met, a chapter's steps.
6
- - The count sits inside a row (a `GoalTicks` breakdown row, a course's chapter, a list card) rather than standing as a card's own headline figure.
7
- - Several of these rows sit together and should read as one family, each carrying a different stretch of the same gradient (`tickSpan`).
6
+ - The count sits inside a row (a `GoalTicks` breakdown row, a stat tile, a list card) rather than standing as a card's
7
+ own headline figure.
8
+ - A small count should read one tick a unit ("10 need a reply").
8
9
 
9
10
  **Not for**
10
11
 
12
+ - A share that fills the width (a score, 40 or 50 ticks): use `TickStrip`.
11
13
  - A card's one big number and its own strip: use `GoalTicks`.
12
14
  - Comparing rows against each other by length: use `GoalBars`.
13
15
  - An ordered sequence of steps: use `Stepper`.
14
- - A ring or an arc share: use `Ring`.
15
16
 
16
17
  **Anatomy**
17
18
 
18
- - Up to 14 ticks (`MAX_ROW_TICKS`), each `calc(--space-xs + --space-xxs/4)` wide (10 px) and `calc(--space-md + --space-xxs/2)` tall (18 px), `--radius-xs` (2 px) corners, `--space-xxs` (4 px) apart.
19
- - A done tick's colour comes from `along(p)`: a `color-mix` between `--ws-chart-under-half` (salmon) and `--ws-chart-past-half` (purple) for the first half of its span, and between `--ws-chart-past-half` and `--ws-chart-finished` (teal) for the second half.
20
- - An empty tick is `--color-bg-page` with a 1 px `--ws-edge-slot` inset edge, the same look as `GoalTicks`' own empty ticks.
21
- - `span` (`[from, to]`, each 0 to 1) picks the stretch of the one gradient this row carries; `tickSpan(n)` hands back the nth of a small set of rows' stretch, as `GoalTicks`' three rows use it.
19
+ - Up to 14 ticks (20 in `--fine` and `--tall`), one a unit, 1 px corners (`--ws-radius-bar`).
20
+ - A done tick is `--tone` (set on the row; teal `--ws-chart-finished` by default), or carries its own colour inline
21
+ for the gradient stretch (a `color-mix` along salmon, purple, teal, so a set of rows reads as one run).
22
+ - An empty tick is the plain track (`--ws-track`), no edge (Seth).
23
+ - The row shrinks with its column: each tick gives way down to 2 px, so a narrow tile never cuts a tick and a narrow row
24
+ never squeezes its label.
22
25
 
23
- **Variants and sizes**
26
+ | Size | Tick | Gap | Seth's use |
27
+ | --- | --- | --- | --- |
28
+ | default | 10 x 18 | 4 | a goal's breakdown, a tile's count |
29
+ | `--fine` | 6 x 18 | 2 | a first-open card's small counts |
30
+ | `--tall` | 10 x 28 | 3 | "Need a reply" beside a 32 px figure, in the alert tone |
24
31
 
25
- | Variant | What changes |
26
- | --- | --- |
27
- | `span` default `[0, 1]` | The row runs the full gradient, salmon to teal |
28
- | `span = tickSpan(0\|1\|2)` | A narrower stretch, so several rows read as one continuous run across them |
29
- | `of` above 14 | Scales: the done count is drawn as its share of 14 slots, not drawn one tick a unit |
32
+ - The line (`.ws-tick-row__line`): a 96 px label (14/20 navy), 12, the row, 12, the count (16/20 semibold, tabular).
33
+ The count takes the rest of the line and wraps there, so a sentence after the figure ("2.9 of 4 · bar 2.7, steady")
34
+ never squeezes the ticks or runs off the card; the ticks give way only when the count's longest word no longer fits.
35
+ Join the figure with no-break spaces (`3&nbsp;of&nbsp;5`) so it stays on one line.
30
36
 
31
37
  **States**
32
38
 
33
- - Default: ticks rise from their foot (`ws-grow-up`) in order, each delayed by its share of `--ws-sweep`.
34
- - Empty: `value` is 0, every tick the empty cream; a real zero, never hidden.
35
- - Full: `value` equals `of`, every tick lit through to the span's end colour.
36
- - Disabled / error / hover / focus / pressed / selected: do not apply; the row is decorative, not a control.
37
- - Reduced motion: every tick is simply in place, no rise.
39
+ - Default: the done ticks in their tone, the rest the track.
40
+ - Draw (`--draw`): ticks rise from their foot one after another over the card's 900 ms draw, each on
41
+ `--ws-ease-settle`. Set `--i` on each tick and `--n` on the row.
42
+ - Empty: `value` is 0, every tick the track; a real zero, never hidden.
43
+ - Full: every tick lit.
44
+ - Reduced motion: every tick in place, no rise.
45
+ - Hover, focus, pressed, selected, disabled: do not apply; the row is a picture, not a control.
38
46
 
39
47
  **Behaviour**
40
48
 
41
- - Entirely decorative (`aria-hidden`): say the figure in words beside it ("3 of 5", "4 of 6") for a screen reader, since the ticks carry no `aria-label` of their own.
42
- - Motion: `ws-grow-up`, scaling up from the foot, each tick delayed by `sweepDelay(i, n)` so the row fills first to last over `--ws-sweep`; still with reduced motion.
49
+ - Always `aria-hidden="true"`: say the count in words beside it ("3 of 5", "10") for a screen reader.
43
50
  - No pointer or keyboard behaviour.
44
51
 
45
52
  **Content**
46
53
 
47
- - Say the count in words beside the row ("3 of 5 met", "14"), never let the ticks alone carry the number.
48
- - Keep the row's own label short; it sits to the ticks' left in a list, not wrapped.
49
-
50
- **Props**
51
-
52
- | Name | Type | Meaning |
53
- | --- | --- | --- |
54
- | `value` | `number` | Units done |
55
- | `of` | `number` | The whole the row counts against |
56
- | `span` | `[number, number]` | Which stretch of the one gradient this row's done ticks carry (default `[0, 1]`) |
54
+ - Say the count in words beside the row ("3 of 5 met", "14"); the ticks never carry the number alone.
55
+ - Keep the label short; it sits to the left of the ticks, not wrapped.
57
56
 
58
57
  **Rules**
59
58
 
60
- - Counts out of a whole are tick rows; a score is the goal card, comparisons are goal bars.
61
- - Marks keep the system's exact colours; this row never needs the AA step itself because it draws no words, but anything placed beside it does.
62
- - Never an axis or a grid where a short row of ticks says it plainer.
59
+ - Counts out of a small whole are tick rows; a score that fills the width is a tick strip; a goal is the goal card.
60
+ - Marks keep the system's exact colours. The row draws no words, but anything beside it takes the AA word step.
61
+ - One tone a row, or one stretch of the gradient; never both in a row.
63
62
 
64
63
  **Source**
65
64
 
66
- **Derived from**: the system's data-tone gradient, split across a small set of rows with `tickSpan` so several rows
67
- read as one continuous run. **Precedent**: the first product built on the system.
65
+ **Derived from**: the system's data-tone gradient; the solid tone, the fine and tall sizes, the 1 px corners and the
66
+ plain empty tick from Seth's first open (282:892) and Review inbox (313:2711), issue #7. **Precedent**: Ignite's
67
+ `TickRow` (`fine`, `tall`, `color`).
68
+
69
+ **Markup**
70
+
71
+ ```html
72
+ <div class="ws-tick-row__line">
73
+ <span class="ws-tick-row__label">Goals met</span>
74
+ <span class="ws-tick-row" aria-hidden="true">
75
+ <span class="ws-tick-row__tick"></span>
76
+ <span class="ws-tick-row__tick"></span>
77
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
78
+ </span>
79
+ <span class="ws-tick-row__count">2&nbsp;<span class="ws-muted">of&nbsp;3</span></span>
80
+ </div>
81
+ ```
82
+
83
+ **Styles**: `TickRow/style.css`, in `bundle.css` and `fello.css` as `.ws-tick-row`. Every value is a token.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Progress" height=152 -->
1
+ <!-- @dsCard group="Progress" height=560 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -8,86 +8,109 @@
8
8
  <link rel="stylesheet" href="../bundle.css">
9
9
  </head>
10
10
  <body>
11
- <div class="ws-stage">
11
+ <div class="ws-stage ws-stage--column">
12
12
 
13
13
  <div class="ws-stack">
14
- <span class="ws-muted">A count out of a whole, the default span: "3 of 5 met"</span>
14
+ <span class="ws-muted">Default: one solid tone, a tick a unit, drawn in on first paint ("3 of 5 met")</span>
15
15
  <div class="ws-tick-row__line">
16
16
  <span class="ws-tick-row__label">Goals met</span>
17
- <span class="ws-tick-row" aria-hidden="true">
18
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 0%, var(--ws-chart-under-half)); animation-delay: calc(var(--ws-sweep) * 0 / 2);"></span>
19
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 100%, var(--ws-chart-under-half)); animation-delay: calc(var(--ws-sweep) * 1 / 2);"></span>
20
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 100%, var(--ws-chart-past-half)); animation-delay: calc(var(--ws-sweep) * 2 / 2);"></span>
17
+ <span class="ws-tick-row ws-tick-row--draw" style="--n: 5;" aria-hidden="true">
18
+ <span class="ws-tick-row__tick" style="--i: 0;"></span>
19
+ <span class="ws-tick-row__tick" style="--i: 1;"></span>
20
+ <span class="ws-tick-row__tick" style="--i: 2;"></span>
21
21
  <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
22
22
  <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
23
23
  </span>
24
- <span class="ws-tick-row__count">3 <span class="ws-muted">of 5</span></span>
24
+ <span class="ws-tick-row__count">3&nbsp;<span class="ws-muted">of&nbsp;5</span></span>
25
25
  </div>
26
26
  </div>
27
27
 
28
28
  <div class="ws-stack">
29
- <span class="ws-muted">The first of a set of rows (`tickSpan(0)`): salmon toward violet</span>
29
+ <span class="ws-muted">Tall, in the alert tone: Seth's "Need a reply" (10 x 28, 3 apart)</span>
30
30
  <div class="ws-tick-row__line">
31
- <span class="ws-tick-row__label">Cold calls</span>
32
- <span class="ws-tick-row" aria-hidden="true">
33
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 0%, var(--ws-chart-under-half));"></span>
34
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 23%, var(--ws-chart-under-half));"></span>
35
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 45%, var(--ws-chart-under-half));"></span>
36
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 68%, var(--ws-chart-under-half));"></span>
37
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
38
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
31
+ <span class="ws-tick-row__label">Need a reply</span>
32
+ <span class="ws-tick-row ws-tick-row--tall" style="--tone: var(--ws-chart-alert);" aria-hidden="true">
33
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
34
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
39
35
  </span>
40
- <span class="ws-tick-row__count">4 <span class="ws-muted">of 6</span></span>
36
+ <span class="ws-tick-row__count">10</span>
41
37
  </div>
42
38
  </div>
43
39
 
44
40
  <div class="ws-stack">
45
- <span class="ws-muted">The second (`tickSpan(1)`): violet toward blue</span>
41
+ <span class="ws-muted">Fine (6 x 18, 2 apart), in purple: 12 of 20 seats used</span>
46
42
  <div class="ws-tick-row__line">
47
- <span class="ws-tick-row__label">Live transfers</span>
48
- <span class="ws-tick-row" aria-hidden="true">
49
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 73%, var(--ws-chart-under-half));"></span>
50
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 84%, var(--ws-chart-under-half));"></span>
51
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-past-half) 96%, var(--ws-chart-under-half));"></span>
52
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 7%, var(--ws-chart-past-half));"></span>
53
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
54
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
43
+ <span class="ws-tick-row__label">Seats used</span>
44
+ <span class="ws-tick-row ws-tick-row--fine" style="--tone: var(--ws-chart-past-half);" aria-hidden="true">
45
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
46
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
47
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
48
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
49
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
55
50
  </span>
56
- <span class="ws-tick-row__count">4 <span class="ws-muted">of 6</span></span>
51
+ <span class="ws-tick-row__count">12&nbsp;<span class="ws-muted">of&nbsp;20</span></span>
57
52
  </div>
58
53
  </div>
59
54
 
60
55
  <div class="ws-stack">
61
- <span class="ws-muted">The third (`tickSpan(2)`): deep blue</span>
56
+ <span class="ws-muted">The gradient stretch: a set of rows that read as one run (each tick carries its own colour)</span>
57
+ <div class="ws-tick-row__line">
58
+ <span class="ws-tick-row__label">Cold calls</span>
59
+ <span class="ws-tick-row" aria-hidden="true">
60
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-past-half) 0%, var(--ws-chart-under-half));"></span>
61
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-past-half) 23%, var(--ws-chart-under-half));"></span>
62
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-past-half) 45%, var(--ws-chart-under-half));"></span>
63
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-past-half) 68%, var(--ws-chart-under-half));"></span>
64
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
65
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
66
+ </span>
67
+ <span class="ws-tick-row__count">4&nbsp;<span class="ws-muted">of&nbsp;6</span></span>
68
+ </div>
62
69
  <div class="ws-tick-row__line">
63
70
  <span class="ws-tick-row__label">Follow-ups</span>
64
71
  <span class="ws-tick-row" aria-hidden="true">
65
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 13%, var(--ws-chart-past-half));"></span>
66
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 18%, var(--ws-chart-past-half));"></span>
67
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 22%, var(--ws-chart-past-half));"></span>
68
- <span class="ws-tick-row__tick ws-grow-up" style="background-color: color-mix(in srgb, var(--ws-chart-finished) 27%, var(--ws-chart-past-half));"></span>
72
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-finished) 13%, var(--ws-chart-past-half));"></span>
73
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-finished) 40%, var(--ws-chart-past-half));"></span>
74
+ <span class="ws-tick-row__tick" style="background: color-mix(in srgb, var(--ws-chart-finished) 70%, var(--ws-chart-past-half));"></span>
75
+ <span class="ws-tick-row__tick" style="background: var(--ws-chart-finished);"></span>
69
76
  <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
70
77
  <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
71
78
  </span>
72
- <span class="ws-tick-row__count">4 <span class="ws-muted">of 6</span></span>
79
+ <span class="ws-tick-row__count">4&nbsp;<span class="ws-muted">of&nbsp;6</span></span>
73
80
  </div>
74
81
  </div>
75
82
 
76
83
  <div class="ws-stack">
77
- <span class="ws-muted">Empty: nothing done yet</span>
84
+ <span class="ws-muted">Empty: nothing done yet, a real zero, never hidden</span>
78
85
  <div class="ws-tick-row__line">
79
86
  <span class="ws-tick-row__label">Nudges sent</span>
80
87
  <span class="ws-tick-row" aria-hidden="true">
81
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
82
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
83
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
84
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
85
- <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
88
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
89
+ </span>
90
+ <span class="ws-tick-row__count">0&nbsp;<span class="ws-muted">of&nbsp;5</span></span>
91
+ </div>
92
+ </div>
93
+
94
+ <div class="ws-stack" style="width: 340px; max-width: 100%;">
95
+ <span class="ws-muted">A long count: the words wrap beside the row, the ticks keep their size</span>
96
+ <div class="ws-tick-row__line">
97
+ <span class="ws-tick-row__label">Follow-ups</span>
98
+ <span class="ws-tick-row" aria-hidden="true">
99
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
86
100
  </span>
87
- <span class="ws-tick-row__count">0 <span class="ws-muted">of 5</span></span>
101
+ <span class="ws-tick-row__count">2.9&nbsp;<span class="ws-muted">of&nbsp;4 &middot; bar 2.7, at or above the bar &middot; steady</span></span>
88
102
  </div>
89
103
  </div>
90
104
 
105
+ <div class="ws-stack" style="width: 120px; max-width: 100%;">
106
+ <span class="ws-muted">A 120 px column: 14 ticks give way instead of being cut</span>
107
+ <span class="ws-tick-row" aria-hidden="true">
108
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
109
+ <span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span><span class="ws-tick-row__tick"></span>
110
+ <span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span><span class="ws-tick-row__tick ws-tick-row__tick--empty"></span>
111
+ </span>
112
+ </div>
113
+
91
114
  </div>
92
115
  </body>
93
116
  </html>