@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
@@ -15,30 +15,45 @@ A quiet block set apart inside a card: the cream a shade darker, for a card's fa
15
15
 
16
16
  ## Anatomy
17
17
 
18
- - Background: `--ws-surface-sunk` (the cream 95% mixed with gray-8, `#f3f1ef`), a shade darker than the card's own `--color-bg-page`.
19
- - Corners: `--ws-radius-card` (8 px), the same ladder step as the card that holds it.
20
- - Inside: `--ws-card-padding` (12 px) on every side.
21
- - No edge, no shadow: a plate is a ground, not a bordered box.
18
+ - Ground: `--ws-surface-sunk` (#F3F1EF), a shade darker than the card's cream. Corners `--ws-radius-card` (8 px).
19
+ - Inside: Seth's 14 px top and bottom, 16 px at the sides (`--space-sm-plus`, `--space-md`). No edge, no shadow.
20
+ - Facts (`ws-plate__fact`): label and value on one line, 16 px apart, the label on the value's first line (baseline),
21
+ the value at the end in navy semibold with tabular figures. A long value wraps under its own first line; the label
22
+ never wraps. Rows 4 px apart.
23
+ - Stats (`ws-plate__stats`): label over value, 2 px apart: the label 13 / 18 medium in `--color-text-muted`
24
+ (`ws-plate__label`), the value 15 / 22 semibold navy (`ws-plate__value`); pairs 32 px apart, wrapping 8 px under.
25
+ - A title (`ws-plate__title`): 14 / 20 semibold navy, for the thing the stats are about (a search, a place). Stats
26
+ right under it sit 16 px down (Seth 301:2084), in a body that is an 8 px `ws-stack`.
27
+ - A foot (`ws-plate__foot`, Seth's search result plate): the plate shows 1 px of its sunk cream round a body
28
+ (`ws-plate__body`, 14 / 16 inside) and a cream foot under a 0.5 px divider, 12 / 16 inside, 7 px bottom corners;
29
+ 13 / 18 medium navy words and a 16 px chevron at the end. A foot that opens something is an `a.ws-plate__foot`.
30
+ - A track (`ws-plate__track`): 12 px tall, 2 px corners, the empty part in navy at 8 % (the load bar's track; the tray grey all but vanished on the sunk plate), the fill (`ws-plate__fill`, its width the share done) in teal.
31
+ - The draft (`ws-plate--draft`, Seth's inbox reply 313): the sunk cream inside a 1 px tray rim, 20 px inside, its parts
32
+ 12 px apart. Its head (`ws-plate__head`, 8 apart): the agent's 20 px face (an `svg`), a 15 / 22 semibold title
33
+ (`ws-section`) that takes the room, and a 13 / 18 word act (`ws-btn ws-btn--text`, "Edit"); then the words (`ws-body`).
22
34
 
23
35
  ## Variants and sizes
24
36
 
25
37
  | Use | What sits inside |
26
38
  | --- | --- |
27
- | Facts plate | Label and value rows, each row's label muted (`ws-muted`), its value navy and medium |
28
- | Track plate | A progress bar or strip, with a caption line under it |
29
-
30
- Both variants share the same 8 px corners and 12 px padding; only the content differs.
39
+ | Facts plate | Label and value rows |
40
+ | Stats plate | A title, then label-over-value pairs, optionally a foot |
41
+ | Track plate | A progress track with a caption under it |
42
+ | Draft (`--draft`) | Something the agent wrote for the person to use: a head (face, title, Edit), then the draft |
31
43
 
32
44
  ## States
33
45
 
34
- - **Default**: the sunk ground, static.
35
- - **Hover** (when a plate doubles as a row's ground, such as a menu item or a well's row): the surface can step further to `--ws-surface-press` under a press, so a tap answers on touch.
36
- - **Empty**: a plate with nothing to show is not drawn; the card either omits the plate or, if the whole card has no data, the card itself is left out.
37
- - **Narrow**: the plate has no width of its own; it fills whatever room its card gives it and its rows wrap or truncate as the card does.
46
+ - **Default**: the sunk ground, still.
47
+ - **Foot hover** (a pointer that hovers): a faint navy wash on the foot and its words underline; **pressed**: a
48
+ stronger wash at once; **focus**: the 2 px navy ring drawn inside the foot.
49
+ - **Long words**: a value wraps under its own first line, the label stays put; a stat pair wraps to a new line.
50
+ - **Empty**: a plate with nothing to show is not drawn.
51
+ - **Narrow**: the plate fills its card; stats wrap.
52
+ - **Dark**: the ground, the foot and the divider follow the theme.
38
53
 
39
54
  ## Behaviour
40
55
 
41
- - Keyboard and pointer: a plate is a passive ground, not an interactive element; anything pressable inside it (a row, a link) carries its own focus and hover states.
56
+ - Keyboard and pointer: a plate is a passive ground; only its foot, when it is a link, takes focus.
42
57
  - Touch: no special handling; it is not itself a 40 px control.
43
58
  - Motion: a track plate's fill can grow in with `ws-grow` (`--ws-duration-calm`, scales from the left); the plate's own ground never animates.
44
59
  - Reduced motion: a growing track shows at its final width immediately.
@@ -65,7 +80,50 @@ Plate has no dedicated component in the first product built on the system: it is
65
80
 
66
81
  ## Source
67
82
 
68
- - **Derived from**: the system's sunk-surface and plate rules ("its facts are on a plate," never grey holding
69
- white rows) and the `--ws-surface-sunk` token.
70
- - **Precedent**: the first product built on the system, where the pattern lives inline wherever a card needs it
71
- rather than as a single `Plate.tsx`.
83
+ - **Derived from**: Seth's search result plate (Grow 301:2080 to 301:2093: the 1 px sunk rim, the 14 / 16 body, the cream
84
+ foot, label-over-value stats) and the system's plate rule ("its facts are on a plate"). K17 (Revenue OS): facts on
85
+ the baseline.
86
+ - **Precedent**: the first product built on the system.
87
+
88
+ ## Markup
89
+
90
+ ```html
91
+ <div class="ws-plate">
92
+ <div class="ws-plate__body ws-stack">
93
+ <p class="ws-plate__title">Chagrin Falls, OH</p>
94
+ <div class="ws-plate__stats">
95
+ <div class="ws-plate__stat"><span class="ws-plate__label">Found</span><span class="ws-plate__value">5 of 9</span></div>
96
+ <div class="ws-plate__stat"><span class="ws-plate__label">Top three</span><span class="ws-plate__value">0 of 9</span></div>
97
+ </div>
98
+ </div>
99
+ <a class="ws-plate__foot" href="/map">
100
+ <span>See it on the map</span>
101
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6.6 5.2L9.4 8l-2.8 2.8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
102
+ </a>
103
+ </div>
104
+
105
+ <div class="ws-plate">
106
+ <div class="ws-plate__fact"><span class="ws-muted">Source</span><span class="ws-body ws-plate__value">Referral</span></div>
107
+ </div>
108
+
109
+ <div class="ws-plate ws-plate--draft">
110
+ <div class="ws-plate__head">
111
+ <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 16.5V9l6.5-5.5L16.5 9v7.5Z"/><path d="M8 16.5v-4h4v4"/></svg>
112
+ <p class="ws-section">Grow drafted a reply in your voice</p>
113
+ <button type="button" class="ws-btn ws-btn--text">Edit</button>
114
+ </div>
115
+ <p class="ws-body">Thank you both! It was a pleasure helping you price it right.</p>
116
+ </div>
117
+
118
+ <div class="ws-plate ws-stack">
119
+ <div class="ws-plate__track"><div class="ws-plate__fill" style="width: 65%;"></div></div>
120
+ <p class="ws-muted">26 of 40 calls, nine days early</p>
121
+ </div>
122
+ ```
123
+
124
+ ## Styles
125
+
126
+ The ground and corners are the house's `.ws-plate`; `Plate/style.css` sets Seth's insets and adds the facts, stats,
127
+ title, foot, track and the draft. Tokens: `--ws-surface-sunk`, `--space-sm-plus`, `--ws-rim`, `--ws-divider`,
128
+ `--ws-radius-card-inner`, `--ws-text-control`, `--ws-text-section`, `--ws-hover-faint`, `--ws-ink`, `--ws-tray`,
129
+ `--ws-card-inset`, `--ws-icon-lg`.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Cards" height=228 -->
1
+ <!-- @dsCard group="Cards" height=555 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -8,10 +8,9 @@
8
8
  <link rel="stylesheet" href="../bundle.css">
9
9
  </head>
10
10
  <body>
11
- <div class="ws-stage ws-stage--grey">
12
-
13
- <div class="ws-stack" style="width: 300px; max-width: 100%;">
14
- <span class="ws-muted">A plate of facts inside a card</span>
11
+ <div class="ws-stage">
12
+ <div class="ws-stack" style="width: 300px;">
13
+ <span class="ws-muted">Facts: label and value rows; a long value wraps under its own line</span>
15
14
  <div class="ws-card ws-card--pad-md ws-stack ws-stack--loose">
16
15
  <h3 class="ws-section">This lead</h3>
17
16
  <div class="ws-plate">
@@ -25,13 +24,33 @@
25
24
  </div>
26
25
  <div class="ws-plate__fact">
27
26
  <span class="ws-muted">Next step</span>
28
- <span class="ws-body ws-plate__value">Call Priya Nair</span>
27
+ <span class="ws-body ws-plate__value">Call Priya Nair about the Oak Street offer</span>
29
28
  </div>
30
29
  </div>
31
30
  </div>
32
31
  </div>
33
32
 
34
- <div class="ws-stack" style="width: 300px; max-width: 100%;">
33
+ <div class="ws-stack" style="width: 380px;">
34
+ <span class="ws-muted">Stats with a foot (Seth's search result plate)</span>
35
+ <div class="ws-card ws-card--pad-md ws-stack ws-stack--loose">
36
+ <h3 class="ws-section">Buyers near you see you in 5 of 9 spots</h3>
37
+ <div class="ws-plate">
38
+ <div class="ws-plate__body ws-stack">
39
+ <p class="ws-plate__title">Chagrin Falls, OH: &ldquo;real estate agent in chagrin falls, oh&rdquo;</p>
40
+ <div class="ws-plate__stats">
41
+ <div class="ws-plate__stat"><span class="ws-plate__label">Found</span><span class="ws-plate__value">5 of 9</span></div>
42
+ <div class="ws-plate__stat"><span class="ws-plate__label">Top three</span><span class="ws-plate__value">0 of 9</span></div>
43
+ </div>
44
+ </div>
45
+ <a class="ws-plate__foot" href="#" onclick="return false;">
46
+ <span>See it on the map</span>
47
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6.6 5.2L9.4 8l-2.8 2.8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
48
+ </a>
49
+ </div>
50
+ </div>
51
+ </div>
52
+
53
+ <div class="ws-stack" style="width: 300px;">
35
54
  <span class="ws-muted">A plate as a track (a goal's progress)</span>
36
55
  <div class="ws-card ws-card--pad-md ws-stack ws-stack--loose">
37
56
  <h3 class="ws-section">October goal</h3>
@@ -42,6 +61,20 @@
42
61
  </div>
43
62
  </div>
44
63
 
64
+ <div class="ws-stack" style="width: 440px; max-width: 100%;">
65
+ <span class="ws-muted">A draft (Seth's inbox reply): the tray rim round the sunk cream, the agent's face, Edit</span>
66
+ <div class="ws-card ws-card--pad-md ws-stack ws-stack--loose">
67
+ <h3 class="ws-section">&ldquo;Knew the market inside out and got us a great price.&rdquo;</h3>
68
+ <div class="ws-plate ws-plate--draft">
69
+ <div class="ws-plate__head">
70
+ <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 16.5V9l6.5-5.5L16.5 9v7.5Z"/><path d="M8 16.5v-4h4v4"/></svg>
71
+ <p class="ws-section">Grow drafted a reply in your voice</p>
72
+ <button type="button" class="ws-btn ws-btn--text">Edit</button>
73
+ </div>
74
+ <p class="ws-body">Thank you both! It was a pleasure helping you price it right, and I&rsquo;m so glad it came together the way you hoped. Enjoy the next chapter.</p>
75
+ </div>
76
+ </div>
77
+ </div>
45
78
  </div>
46
79
  </body>
47
80
  </html>
@@ -0,0 +1,37 @@
1
+ /* ---- Plate: a card's facts set apart on the sunk cream (Seth's facts plate): label and value rows, stats, a track, a foot ---- */
2
+ /* Seth's plate is 14 / 16 inside (the house had 12 all round). */
3
+ .ws-plate { padding: var(--space-sm-plus) var(--space-md); }
4
+ /* A plate with a foot: the sunk cream shows 1 px round a body and a cream foot (Seth's search result plate, 301:2080). */
5
+ .ws-plate:has(> .ws-plate__foot) { padding: var(--ws-rim); }
6
+ .ws-plate__body { padding: var(--space-sm-plus) var(--space-md); }
7
+ .ws-plate__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-xs); padding: var(--space-sm) var(--space-md); border-top: var(--ws-divider); border-radius: 0 0 var(--ws-radius-card-inner) var(--ws-radius-card-inner); background: var(--color-bg-page); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; color: var(--color-text-heading); }
8
+ a.ws-plate__foot { text-decoration: none; transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
9
+ @media (hover: hover) { a.ws-plate__foot:hover { background-image: linear-gradient(var(--ws-hover-faint), var(--ws-hover-faint)); } a.ws-plate__foot:hover > :first-child { text-decoration: underline; } }
10
+ a.ws-plate__foot:active { background-image: linear-gradient(var(--ws-hover), var(--ws-hover)); }
11
+ a.ws-plate__foot:focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
12
+ .ws-plate__foot > svg { flex-shrink: 0; width: var(--ws-icon); height: var(--ws-icon); }
13
+ /* Label and value rows: the label on the value's first line (a wrapped value never strands its label mid-way, K17),
14
+ 16 apart, the value at the end. */
15
+ .ws-plate__fact { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); }
16
+ .ws-plate__fact > :first-child { flex-shrink: 0; }
17
+ .ws-plate__fact + .ws-plate__fact { margin-top: var(--space-xxs); }
18
+ .ws-plate__value { font-weight: 600; color: var(--color-text-heading); text-align: right; font-variant-numeric: tabular-nums; }
19
+ /* Stats: label over value (13 / 18 medium muted over 15 / 22 semibold navy, 2 apart), pairs 32 apart, wrapping. */
20
+ .ws-plate__stats { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-xl); }
21
+ /* Under a plate's title the stats sit 16 down (Seth 301:2084): 8 more than the body's 8 px stack. */
22
+ .ws-plate__title + .ws-plate__stats { padding-top: var(--space-xs); }
23
+ .ws-plate__stat { display: flex; flex-direction: column; gap: var(--space-3xs); }
24
+ .ws-plate__label { font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; color: var(--color-text-muted); }
25
+ .ws-plate__stat > .ws-plate__value { font-size: var(--ws-text-section); line-height: var(--ws-leading-section); text-align: left; }
26
+ /* A goal's track on the plate: the empty track in navy at 8 % (the load bar's track), 2 px corners (Seth's 12 px
27
+ segments). The tray grey was 1.04:1 on the sunk plate, so the track's end, the goal, did not show. */
28
+ .ws-plate__track { height: var(--space-sm); border-radius: var(--ws-radius-chip); background: color-mix(in srgb, var(--ws-ink) 8%, transparent); overflow: hidden; }
29
+ .ws-plate__fill { height: 100%; border-radius: var(--ws-radius-chip); background: var(--color-stat-positive); transform-origin: left; }
30
+ /* A plate's own title (a search query, a named fact): 14 / 20 semibold navy. */
31
+ .ws-plate__title { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 600; color: var(--color-text-heading); }
32
+ /* The draft (Seth's inbox reply, 313): the sunk cream inside the 1 px tray rim, 20 inside, its parts 12 apart. Its
33
+ head: the agent's 20 px face, a 15 / 22 title that takes the room (ws-section) and a 13 / 18 word act (Edit). */
34
+ .ws-plate--draft { display: flex; flex-direction: column; gap: var(--space-sm); padding: var(--ws-card-inset); border: var(--ws-rim) solid var(--ws-tray); }
35
+ .ws-plate__head { display: flex; align-items: center; gap: var(--space-xs); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; }
36
+ .ws-plate__head > svg { flex-shrink: 0; width: var(--ws-icon-lg); height: var(--ws-icon-lg); color: var(--color-text-heading); }
37
+ .ws-plate__head > .ws-section { flex: 1; min-width: 0; }
@@ -1,85 +1,106 @@
1
- A small lifted card of content, anchored to a control, for the one time a tooltip is too thin and a dialog is too much.
1
+ A small lifted card beside its control, for the time a tooltip is too thin and a dialog is too much.
2
2
 
3
3
  ## Use it when
4
4
 
5
5
  - A control needs to show a short piece of content (a note, a small field) without leaving the page or blocking it.
6
- - An icon button's result belongs right where it was pressed, not in a panel or a dialog.
7
- - A quick, optional one-field form (renaming something, adding a quick note) fits in a few lines.
6
+ - An icon button's answer belongs right where it was pressed ("Why this call is flagged").
7
+ - A quick, optional one-field form fits in a few lines (renaming a list, a short note).
8
8
 
9
9
  ## Not for
10
10
 
11
- - A one-word label on hover or focus: use `Tooltip`; a popover is never the only place a label lives.
12
- - A short blocking task the person must resolve before continuing: use `Dialog`.
11
+ - A control's name on hover: use `Tooltip`.
12
+ - What a chart mark holds: use `HoverCard`.
13
13
  - A list of actions: use `Menu`.
14
- - A thing's full detail opened from the chat: use `Panel`.
14
+ - A task the person must finish before going on: use `Dialog`.
15
+ - A thing's full detail: use `Panel`.
15
16
 
16
17
  ## Anatomy
17
18
 
18
- - Panel: `ws-menu`'s shell (cream `--color-bg-page`, `--ws-radius-card` corners, `--ws-shadow-lift`), with `--space-sm`
19
- (12 px) padding instead of `Menu`'s own 4 px row padding, since a popover holds a block of content, not a tight list
20
- of 32 px action rows.
21
- - Title: 14 px navy medium (weight 500, `--color-text-heading`). This is not `row-title` (14/20, weight 600): the brief
22
- calls for "medium," and `row-title`'s role is a row's name, not a popover's heading, so this is its own 14 px/500
23
- treatment.
24
- - Body: `.ws-body` (14 px regular, `--color-text-body`).
25
- - Optional field and one small primary button, styled exactly as `Input` and `Button`.
26
- - No arrow pointing at the anchor: a plain floating card, offset a small gap from the control that opened it.
19
+ - The card (`ws-popover`): `--ws-raised` ground, 8 px corners (`--ws-radius-card`), the 0.5 px hairline and the pop drop
20
+ (`--ws-shadow-hairline`, `--ws-shadow-pop`), 12 px inside, its parts 8 apart. As wide as its words, from 200 up to
21
+ 300 (North's pop), never wider than the window less 32; never taller than the window less 32, its own scroll past
22
+ that.
23
+ - Title (`ws-popover__title`): 14 / 20 medium navy.
24
+ - Body: `.ws-body`, 14 / 20.
25
+ - Form (`ws-popover__form`): one field and one small primary act on the right, 8 apart, as `Input` and `Button`.
26
+ - No arrow: a plain card, 8 from its control.
27
27
 
28
28
  ## Variants and sizes
29
29
 
30
- | Variant | What it holds |
30
+ | Class | Where |
31
31
  | --- | --- |
32
- | Note | a title and a line or two of body words |
33
- | Small form | a title, one field, one small primary button |
34
-
35
- There is one size; the panel's width fits its content, roughly 220 to 280 px.
32
+ | `ws-popover` | Under its control, right edges flush, growing from the top right |
33
+ | `ws-popover ws-popover--above` | Over its control, growing from the bottom right |
36
34
 
37
35
  ## States
38
36
 
39
- - **Closed:** not rendered.
40
- - **Open:** lifted on `--ws-shadow-lift`, anchored under or beside its control.
41
- - **Focus:** focus moves into the panel when it opens (to its first focusable element) and returns to the anchor
42
- control when it closes, as `Dialog`'s own focus-trap-and-return behaviour, though a popover is lighter than a dialog
43
- and uses no scrim.
44
- - **Disabled:** not applicable to the panel itself; a disabled field or button inside it follows its own component's
45
- rule.
37
+ - **Closed**: not shown.
38
+ - **Opening** (North js@620042 and js@556550): it grows out of the corner it hangs from, 4 px toward its control and
39
+ .97 (`--ws-open-scale`), on the settle spring (`--ws-spring-settle`, .32 / .1); `--above` (or `data-side="top"` from
40
+ an app that places it) turns the nudge and the corner round. As `Menu`: a native popover by `@starting-style`, where
41
+ the browser places it by anchor the nudge rides on the margin so a flip turns it too, one the app mounts plays
42
+ `ws-popover-in`.
43
+ - **Open**: anchored 8 from its control.
44
+ - **Focus**: focus moves to its first field when it opens (give that field `autofocus`: a native popover does not move
45
+ focus by itself, it only puts its content next in the Tab order) and back to the control when it closes.
46
+ - **Leaving** (`data-leaving`, or a native popover closing): it goes back into its corner, fading, over
47
+ `--ws-duration-exit` (120 ms) on `--ws-ease-exit`, faster than it came; a close mid-entrance turns back from where
48
+ it is.
49
+ - **Long words**: they wrap at 300.
46
50
 
47
51
  ## Behaviour
48
52
 
49
- - Keyboard: Escape closes it and returns focus to the anchor, exactly as `Menu`'s and `Dialog`'s own dismiss rule; Tab
50
- cycles through the panel's own focusable content while open.
51
- - Pointer: an outside click closes it, the same `useDismiss` pattern `Menu` uses and the same scrim-click logic `Dialog`
52
- uses, without a scrim.
53
- - Motion: the panel rises in on `--ws-duration-gentle` on `--ws-ease-soft`, exactly as `Menu`'s own entrance.
54
- - Reduced motion: it appears without the rise.
53
+ - Placement (K9): as `Menu`. Open it in the top layer with the native `popover` attribute and its control's
54
+ `popovertarget`; where the browser places by anchor it hangs 8 under (or over, with `--above`), right edges flush,
55
+ capped to that side and scrolling inside (never over its control), flips when less than 200 px fits, and centres in
56
+ the window when it is wider than either side of its control (a phone). In a React app, portal it with `flip` and
57
+ `shift`; a scoped app's portal root carries `class="fello"`.
58
+ - Keyboard: `popover="auto"` closes on Escape and on a press outside, and focus goes back to the control; Tab moves
59
+ through its own content.
60
+ - Touch: it opens on a tap of its control; its field and act are 40 tall.
61
+ - Reduced motion: it appears and goes at once; so does a browser without `@starting-style` or `linear()`.
62
+ - The preview's last stack is live: press either button.
55
63
 
56
64
  ## Content
57
65
 
58
66
  - The title is a short phrase, sentence case, no colon.
59
- - Body words are brief; a popover is not the place for a paragraph.
60
- - No em dashes.
67
+ - Body words are brief: a popover is not the place for a paragraph.
61
68
 
62
69
  ## Props
63
70
 
64
71
  | Name | Type | Meaning |
65
72
  | --- | --- | --- |
66
- | `open` | `boolean` | whether it is shown |
67
- | `onClose` | `() => void` | fires on Escape or an outside click |
68
- | `anchorRef` | `RefObject` | the control it is positioned against |
69
- | `title` | `string` | the 14 px heading |
70
- | `children` | `ReactNode` | the body content |
73
+ | `open` | `boolean` | Whether it is shown. |
74
+ | `onClose` | `() => void` | Fires on Escape or a press outside. |
75
+ | `anchorRef` | `RefObject` | The control it is placed against. |
76
+ | `side` | `"below"` \| `"above"` | Which side it opens on; it flips when there is no room. Default `below`. |
77
+ | `title` | `string` | The 14 px title. |
78
+ | `children` | `ReactNode` | The body. |
71
79
 
72
80
  ## Rules
73
81
 
74
- - Built on `ws-menu`'s exact shell, with one difference: 12 px panel padding instead of `Menu`'s 4 px, since `Menu` is a
75
- list of tight action rows and `Popover` is a block of content.
76
- - No arrow, per spec; the panel is a plain floating card.
77
- - Dismissal and focus-return follow `Menu`'s `useDismiss` and `Dialog`'s focus-trap precedent, without a scrim, since a
78
- popover is not a blocking task.
82
+ - It floats, so it has the pop drop; never a lift on a card.
83
+ - No scrim: it does not block the page.
84
+ - Dismissal and focus return follow `Menu`.
79
85
 
80
86
  ## Source
81
87
 
82
- Intentional addition, decided from the system (26 Oct 2026): 08-choosing-components.md draws `Tooltip` ("a short tip on
83
- hover or focus... never the only place a label lives") below this weight and `Dialog` ("a short blocking task") above
84
- it, leaving the middle case, lifted content that is not blocking and not label-only, undocumented. Built on `Menu`'s
85
- `ws-menu` shell and dismiss behaviour, and `Dialog`'s focus-trap-and-return rule.
88
+ **Derived from**: Seth's North pop (style1.css:87: 300 wide, 8 px corners, the 0.5 px edge, `0 12px 32px -16px` drop,
89
+ 8 under its trigger, right-aligned, origin at that corner; pickers open from y 4 or -4, js@556550) and Revenue OS K9.
90
+ **Precedent**: an intentional addition, decided from the system (26 Oct 2026), between `Tooltip` and `Dialog`.
91
+
92
+ ## Markup
93
+
94
+ ```html
95
+ <button type="button" class="ws-icon-btn ws-icon-btn--outline" aria-label="Why this call is flagged" popovertarget="flag-note">
96
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="6"/><path d="M8 7.3v3.4M8 5.3v.01"/></svg>
97
+ </button>
98
+ <div id="flag-note" class="ws-popover" role="dialog" aria-labelledby="flag-note-title" popover>
99
+ <p class="ws-popover__title" id="flag-note-title">Why this call is flagged</p>
100
+ <p class="ws-body">Priya has not had a cold call logged in nine days.</p>
101
+ </div>
102
+ ```
103
+
104
+ ## Styles
105
+
106
+ `Popover/style.css`, built into `bundle.css` and `fello.css`. Tokens only, so it turns dark with the page.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Feedback" height=212 -->
1
+ <!-- @dsCard group="Feedback" height=240 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -9,36 +9,58 @@
9
9
  </head>
10
10
  <body>
11
11
  <div class="ws-stage ws-stage--grey">
12
- <div class="ws-cluster ws-cluster--start" style="gap: calc(var(--ws-gap-component) * 3);">
13
12
 
14
- <div class="ws-stack">
15
- <span class="ws-muted">Open above an icon button: a short note, no arrow</span>
16
- <div class="ws-stack ws-stack--tight" style="width: 240px;">
17
- <div class="ws-popover" role="dialog" aria-labelledby="pop-note-title">
18
- <p class="ws-popover__title" id="pop-note-title">Why this call is flagged</p>
19
- <p class="ws-body">Priya has not had a cold call logged in nine days.</p>
20
- </div>
21
- <div><button type="button" class="ws-icon-btn ws-icon-btn--outline" aria-label="Why this call is flagged">
22
- <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6"/><path d="M8 7.3v3.4M8 5.3v.01"/></svg>
23
- </button></div>
13
+ <div class="ws-stack" style="width: 300px;">
14
+ <span class="ws-muted">A note, above its icon button: 8 apart, right edges flush</span>
15
+ <div class="ws-stack" style="align-items: flex-end; gap: var(--space-xs);">
16
+ <div class="ws-popover ws-popover--above" role="dialog" aria-labelledby="pop-note-title">
17
+ <p class="ws-popover__title" id="pop-note-title">Why this call is flagged</p>
18
+ <p class="ws-body">Priya has not had a cold call logged in nine days.</p>
24
19
  </div>
20
+ <button type="button" class="ws-icon-btn ws-icon-btn--outline" aria-label="Why this call is flagged" aria-expanded="true">
21
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6"/><path d="M8 7.3v3.4M8 5.3v.01"/></svg>
22
+ </button>
25
23
  </div>
24
+ </div>
26
25
 
27
- <div class="ws-stack">
28
- <span class="ws-muted">Open with a small form: 12 px inside, one field, one small primary act</span>
29
- <div class="ws-stack ws-stack--tight" style="width: 240px;">
30
- <div class="ws-popover" role="dialog" aria-labelledby="pop-form-title">
31
- <p class="ws-popover__title" id="pop-form-title">Rename this list</p>
32
- <div class="ws-popover__form">
33
- <input class="ws-input" value="This week's follow-ups" aria-label="List name">
34
- <button type="button" class="ws-btn ws-btn--primary">Save</button>
35
- </div>
26
+ <div class="ws-stack" style="width: 300px;">
27
+ <span class="ws-muted">A small form, under its button: one field, one small primary act</span>
28
+ <div class="ws-stack" style="align-items: flex-end; gap: var(--space-xs);">
29
+ <button type="button" class="ws-btn ws-btn--secondary" aria-expanded="true">This week's follow-ups</button>
30
+ <div class="ws-popover" role="dialog" aria-labelledby="pop-form-title">
31
+ <p class="ws-popover__title" id="pop-form-title">Rename this list</p>
32
+ <div class="ws-popover__form">
33
+ <input class="ws-input" value="This week's follow-ups" aria-label="List name">
34
+ <button type="button" class="ws-btn ws-btn--primary">Save</button>
36
35
  </div>
37
- <div><button type="button" class="ws-btn ws-btn--secondary">This week's follow-ups</button></div>
38
36
  </div>
39
37
  </div>
38
+ </div>
39
+
40
+ <div class="ws-stack" style="width: 300px;">
41
+ <span class="ws-muted">Longer words wrap at 300; the popover never runs past the window</span>
42
+ <div class="ws-popover" role="dialog" aria-labelledby="pop-long-title">
43
+ <p class="ws-popover__title" id="pop-long-title">How the score is worked out</p>
44
+ <p class="ws-body">Each of the six checks counts the same. A check we could not run is left out, so it never pulls the score down.</p>
45
+ </div>
46
+ </div>
40
47
 
48
+ <div class="ws-stack" style="width: 300px;" data-live>
49
+ <span class="ws-muted">Live: press either. Each grows out of the corner it hangs from, toward its control, on the settle spring, and goes back faster (Escape or a press outside)</span>
50
+ <div class="ws-cluster">
51
+ <button type="button" class="ws-btn ws-btn--secondary" popovertarget="pop-live" aria-haspopup="dialog">How it is scored</button>
52
+ <button type="button" class="ws-btn ws-btn--secondary" popovertarget="pop-live-up" aria-haspopup="dialog">Above</button>
53
+ </div>
54
+ <div id="pop-live" class="ws-popover" popover role="dialog" aria-labelledby="pop-live-title">
55
+ <p class="ws-popover__title" id="pop-live-title">How the score is worked out</p>
56
+ <p class="ws-body">Each of the six checks counts the same.</p>
57
+ </div>
58
+ <div id="pop-live-up" class="ws-popover ws-popover--above" popover role="dialog" aria-labelledby="pop-live-up-title">
59
+ <p class="ws-popover__title" id="pop-live-up-title">Opened above its control</p>
60
+ <p class="ws-body">It grows up out of its bottom corner.</p>
61
+ </div>
41
62
  </div>
63
+
42
64
  </div>
43
65
  </body>
44
66
  </html>
@@ -0,0 +1,41 @@
1
+ /* ---- Popover: a short note or a small form lifted beside its control, Seth's North pop: 8 px corners on the hairline and
2
+ the pop drop, 12 px inside, opened in the top layer and kept on screen ---- */
3
+ /* As wide as its words up to 300 (North's pop) and never past the window (K9), its own scroll past its height. It grows
4
+ from the corner it hangs from: the top right, 8 under its control (North P1). */
5
+ .ws-popover { display: flex; flex-direction: column; gap: var(--space-xs); width: max-content; min-width: var(--space-9xl); max-width: min(var(--ws-float-width), calc(100vw - var(--space-xl))); max-height: calc(100dvh - var(--space-xl)); overflow-y: auto; overscroll-behavior: contain; z-index: var(--z-dropdown); padding: var(--space-sm); border: 0; border-radius: var(--ws-radius-card); background: var(--ws-raised); color: var(--color-text-body); box-shadow: var(--ws-shadow-hairline), var(--ws-shadow-pop); transform-origin: top right; }
6
+ .ws-popover__title { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); }
7
+ .ws-popover__form { display: flex; flex-direction: column; gap: var(--space-xs); }
8
+ .ws-popover__form > .ws-btn { align-self: flex-end; }
9
+ /* The top layer (K9): see Menu. It hangs 8 under its control (over it, with --above), right edges flush; a tall one is
10
+ capped to that side and scrolls inside, never over its control; it flips only when less than 200 px fits, and
11
+ centres in the window when it is wider than either side of its control. */
12
+ .ws-popover[popover]:not(:popover-open) { display: none; }
13
+ @supports (position-area: block-end) {
14
+ .ws-popover[popover] { inset: auto; margin: var(--space-xs) 0; position-area: block-end span-inline-start; justify-self: end; position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline, --ws-popover-wide, --ws-popover-wide flip-block; max-height: calc(100% - var(--space-xs) * 2); min-height: calc-size(max-content, min(size, var(--space-9xl))); }
15
+ .ws-popover--above[popover] { position-area: block-start span-inline-start; transform-origin: bottom right; }
16
+ }
17
+ @position-try --ws-popover-wide { position-area: block-end span-all; justify-self: center; }
18
+ /* Motion (D7, North js@620042 and js@556550: from 4 px toward its control and scale .97 on the settle spring .32 / .1,
19
+ out the same way over .12 s): as Menu. It grows out of the corner it hangs from and goes back into it, faster;
20
+ --above (or data-side="top" from an app that places it) turns the nudge and the corner round. Where the browser
21
+ places it by anchor the nudge rides on the margin, which the flip fallbacks turn with it. */
22
+ .ws-popover { --ws-popover-from: calc(var(--ws-nudge) * -1); }
23
+ .ws-popover--above, .ws-popover[data-side="top"] { --ws-popover-from: var(--ws-nudge); transform-origin: bottom right; }
24
+ @keyframes ws-popover-in { from { opacity: 0; transform: translateY(var(--ws-popover-from)) scale(var(--ws-open-scale)); } }
25
+ @keyframes ws-popover-out { to { opacity: 0; transform: translateY(var(--ws-popover-from)) scale(var(--ws-open-scale)); } }
26
+ @media (prefers-reduced-motion: no-preference) {
27
+ .ws-popover:not([popover]) { animation: ws-popover-in var(--ws-spring-settle-duration) var(--ws-spring-settle) backwards; }
28
+ .ws-popover[data-leaving] { animation: ws-popover-out var(--ws-duration-exit) var(--ws-ease-exit) forwards; pointer-events: none; }
29
+ .ws-popover[popover] { transition: opacity var(--ws-spring-settle-duration) var(--ws-spring-settle), transform var(--ws-spring-settle-duration) var(--ws-spring-settle), margin-block var(--ws-spring-settle-duration) var(--ws-spring-settle), overlay var(--ws-duration-exit) allow-discrete, display var(--ws-duration-exit) allow-discrete; }
30
+ .ws-popover[popover]:not(:popover-open) { opacity: 0; transform: translateY(var(--ws-popover-from)) scale(var(--ws-open-scale)); transition-duration: var(--ws-duration-exit); transition-timing-function: var(--ws-ease-exit); }
31
+ @starting-style { .ws-popover[popover]:popover-open { opacity: 0; transform: translateY(var(--ws-popover-from)) scale(var(--ws-open-scale)); } }
32
+ @supports (position-area: block-end) {
33
+ .ws-popover[popover]:not([data-side]) { --ws-popover-from: 0px; }
34
+ .ws-popover[popover]:not([data-side]):not(:popover-open) { margin-block-start: calc(var(--space-xs) - var(--ws-nudge)); }
35
+ .ws-popover--above[popover]:not([data-side]):not(:popover-open) { margin-block: var(--space-xs) calc(var(--space-xs) - var(--ws-nudge)); }
36
+ @starting-style {
37
+ .ws-popover[popover]:not([data-side]):popover-open { margin-block-start: calc(var(--space-xs) - var(--ws-nudge)); }
38
+ .ws-popover--above[popover]:not([data-side]):popover-open { margin-block: var(--space-xs) calc(var(--space-xs) - var(--ws-nudge)); }
39
+ }
40
+ }
41
+ }