@deriv-com/dds-marketing 0.1.0 → 0.2.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 (460) hide show
  1. package/.llm/components/accordion.md +193 -0
  2. package/.llm/components/accordionitem.md +236 -0
  3. package/.llm/components/aspectratio.md +212 -0
  4. package/.llm/components/badge.md +231 -0
  5. package/.llm/components/bottomsheet.md +404 -0
  6. package/.llm/components/breadcrumb.md +197 -0
  7. package/.llm/components/breadcrumbitem.md +178 -0
  8. package/.llm/components/button.md +271 -0
  9. package/.llm/components/buttonicon.md +313 -0
  10. package/.llm/components/card.md +313 -0
  11. package/.llm/components/cardbody.md +409 -0
  12. package/.llm/components/cardbutton.md +259 -0
  13. package/.llm/components/checkbox.md +285 -0
  14. package/.llm/components/divider.md +230 -0
  15. package/.llm/components/dropdownmenu.md +453 -0
  16. package/.llm/components/filterchip.md +314 -0
  17. package/.llm/components/footer.md +408 -0
  18. package/.llm/components/footergroup.md +241 -0
  19. package/.llm/components/grid.md +659 -0
  20. package/.llm/components/icon.md +194 -0
  21. package/.llm/components/link.md +354 -0
  22. package/.llm/components/menuitem.md +218 -0
  23. package/.llm/components/navbar.md +458 -0
  24. package/.llm/components/navbaritem.md +238 -0
  25. package/.llm/components/navbarmenu.md +319 -0
  26. package/.llm/components/navbarmenugroup.md +184 -0
  27. package/.llm/components/navbarpanel.md +255 -0
  28. package/.llm/components/navbarswitcher.md +343 -0
  29. package/.llm/components/navbarswitcheroption.md +156 -0
  30. package/.llm/components/option.md +268 -0
  31. package/.llm/components/pagination.md +361 -0
  32. package/.llm/components/removablechip.md +247 -0
  33. package/.llm/components/row.md +381 -0
  34. package/.llm/components/scroller.md +470 -0
  35. package/.llm/components/searchinput.md +279 -0
  36. package/.llm/components/segmentedcontrol.md +358 -0
  37. package/.llm/components/segmentedcontrolitem.md +272 -0
  38. package/.llm/components/select.md +509 -0
  39. package/.llm/components/selectchip.md +334 -0
  40. package/.llm/components/spinner.md +222 -0
  41. package/.llm/components/stack.md +334 -0
  42. package/.llm/components/statusdot.md +205 -0
  43. package/.llm/components/subdomainnavbar.md +327 -0
  44. package/.llm/components/tab.md +291 -0
  45. package/.llm/components/table.md +660 -0
  46. package/.llm/components/tablebody.md +258 -0
  47. package/.llm/components/tablecell.md +248 -0
  48. package/.llm/components/tablehead.md +248 -0
  49. package/.llm/components/tableheadercell.md +298 -0
  50. package/.llm/components/tablerow.md +285 -0
  51. package/.llm/components/tablist.md +210 -0
  52. package/.llm/components/textarea.md +362 -0
  53. package/.llm/components/textinput.md +467 -0
  54. package/.llm/components/tooltip.md +267 -0
  55. package/.llm/components/typography.md +245 -0
  56. package/.llm/digest/accordion.md +43 -0
  57. package/.llm/digest/accordionitem.md +47 -0
  58. package/.llm/digest/aspectratio.md +47 -0
  59. package/.llm/digest/badge.md +45 -0
  60. package/.llm/digest/bottomsheet.md +69 -0
  61. package/.llm/digest/breadcrumb.md +38 -0
  62. package/.llm/digest/breadcrumbitem.md +43 -0
  63. package/.llm/digest/button.md +48 -0
  64. package/.llm/digest/buttonicon.md +61 -0
  65. package/.llm/digest/card.md +50 -0
  66. package/.llm/digest/cardbody.md +68 -0
  67. package/.llm/digest/cardbutton.md +49 -0
  68. package/.llm/digest/checkbox.md +63 -0
  69. package/.llm/digest/divider.md +52 -0
  70. package/.llm/digest/dropdownmenu.md +67 -0
  71. package/.llm/digest/filterchip.md +68 -0
  72. package/.llm/digest/footer.md +57 -0
  73. package/.llm/digest/footergroup.md +42 -0
  74. package/.llm/digest/grid.md +62 -0
  75. package/.llm/digest/icon.md +45 -0
  76. package/.llm/digest/link.md +59 -0
  77. package/.llm/digest/menuitem.md +46 -0
  78. package/.llm/digest/navbar.md +60 -0
  79. package/.llm/digest/navbaritem.md +54 -0
  80. package/.llm/digest/navbarmenu.md +54 -0
  81. package/.llm/digest/navbarmenugroup.md +40 -0
  82. package/.llm/digest/navbarpanel.md +53 -0
  83. package/.llm/digest/navbarswitcher.md +51 -0
  84. package/.llm/digest/navbarswitcheroption.md +37 -0
  85. package/.llm/digest/option.md +54 -0
  86. package/.llm/digest/pagination.md +71 -0
  87. package/.llm/digest/removablechip.md +51 -0
  88. package/.llm/digest/row.md +60 -0
  89. package/.llm/digest/scroller.md +59 -0
  90. package/.llm/digest/searchinput.md +56 -0
  91. package/.llm/digest/segmentedcontrol.md +59 -0
  92. package/.llm/digest/segmentedcontrolitem.md +59 -0
  93. package/.llm/digest/select.md +92 -0
  94. package/.llm/digest/selectchip.md +68 -0
  95. package/.llm/digest/spinner.md +52 -0
  96. package/.llm/digest/stack.md +56 -0
  97. package/.llm/digest/statusdot.md +46 -0
  98. package/.llm/digest/subdomainnavbar.md +54 -0
  99. package/.llm/digest/tab.md +60 -0
  100. package/.llm/digest/table.md +71 -0
  101. package/.llm/digest/tablebody.md +49 -0
  102. package/.llm/digest/tablecell.md +55 -0
  103. package/.llm/digest/tablehead.md +50 -0
  104. package/.llm/digest/tableheadercell.md +65 -0
  105. package/.llm/digest/tablerow.md +56 -0
  106. package/.llm/digest/tablist.md +46 -0
  107. package/.llm/digest/textarea.md +78 -0
  108. package/.llm/digest/textinput.md +95 -0
  109. package/.llm/digest/tooltip.md +58 -0
  110. package/.llm/digest/typography.md +59 -0
  111. package/.llm/index.md +86 -0
  112. package/.llm/rules.md +122 -0
  113. package/.llm/tokens.md +341 -0
  114. package/AGENTS.md +164 -0
  115. package/LICENSE +21 -0
  116. package/README.md +63 -15
  117. package/dist/components/core/accordion/Accordion.css +10 -0
  118. package/dist/components/core/accordion/Accordion.d.ts +20 -0
  119. package/dist/components/core/accordion/Accordion.js +69 -0
  120. package/dist/components/core/accordion/Accordion.types.d.ts +20 -0
  121. package/dist/components/core/accordion/Accordion.types.js +7 -0
  122. package/dist/components/core/accordion-item/AccordionItem.css +98 -0
  123. package/dist/components/core/accordion-item/AccordionItem.d.ts +44 -0
  124. package/dist/components/core/accordion-item/AccordionItem.js +63 -0
  125. package/dist/components/core/accordion-item/AccordionItem.types.d.ts +32 -0
  126. package/dist/components/core/accordion-item/AccordionItem.types.js +13 -0
  127. package/dist/components/core/accordion-item/accordion-item-impl.css +107 -0
  128. package/dist/components/core/badge/Badge.css +37 -0
  129. package/dist/components/core/badge/Badge.d.ts +37 -0
  130. package/dist/components/core/badge/Badge.js +40 -0
  131. package/dist/components/core/badge/Badge.types.d.ts +24 -0
  132. package/dist/components/core/badge/Badge.types.js +8 -0
  133. package/dist/components/core/badge/badge-impl.css +32 -0
  134. package/dist/components/core/bottom-sheet/BottomSheet.css +178 -0
  135. package/dist/components/core/bottom-sheet/BottomSheet.d.ts +22 -0
  136. package/dist/components/core/bottom-sheet/BottomSheet.js +359 -0
  137. package/dist/components/core/bottom-sheet/BottomSheet.types.d.ts +67 -0
  138. package/dist/components/core/bottom-sheet/BottomSheet.types.js +18 -0
  139. package/dist/components/core/bottom-sheet/bottom-sheet-impl.css +57 -0
  140. package/dist/components/core/breadcrumb/Breadcrumb.css +19 -0
  141. package/dist/components/core/breadcrumb/Breadcrumb.d.ts +16 -0
  142. package/dist/components/core/breadcrumb/Breadcrumb.js +22 -0
  143. package/dist/components/core/breadcrumb/Breadcrumb.types.d.ts +18 -0
  144. package/dist/components/core/breadcrumb/Breadcrumb.types.js +9 -0
  145. package/dist/components/core/breadcrumb-item/BreadcrumbItem.css +34 -0
  146. package/dist/components/core/breadcrumb-item/BreadcrumbItem.d.ts +12 -0
  147. package/dist/components/core/breadcrumb-item/BreadcrumbItem.js +15 -0
  148. package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.d.ts +22 -0
  149. package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.js +9 -0
  150. package/dist/components/core/button/Button.css +141 -0
  151. package/dist/components/core/button/Button.d.ts +25 -0
  152. package/dist/components/core/button/Button.js +28 -0
  153. package/dist/components/core/button/Button.types.d.ts +40 -0
  154. package/dist/components/core/button/Button.types.js +9 -0
  155. package/dist/components/core/button/button-impl.css +46 -0
  156. package/dist/components/core/button-icon/ButtonIcon.css +135 -0
  157. package/dist/components/core/button-icon/ButtonIcon.d.ts +34 -0
  158. package/dist/components/core/button-icon/ButtonIcon.js +117 -0
  159. package/dist/components/core/button-icon/ButtonIcon.types.d.ts +41 -0
  160. package/dist/components/core/button-icon/ButtonIcon.types.js +8 -0
  161. package/dist/components/core/card/Card.css +65 -0
  162. package/dist/components/core/card/Card.d.ts +24 -0
  163. package/dist/components/core/card/Card.js +26 -0
  164. package/dist/components/core/card/Card.types.d.ts +33 -0
  165. package/dist/components/core/card/Card.types.js +7 -0
  166. package/dist/components/core/card-body/CardBody.css +139 -0
  167. package/dist/components/core/card-body/CardBody.d.ts +62 -0
  168. package/dist/components/core/card-body/CardBody.js +97 -0
  169. package/dist/components/core/card-body/CardBody.types.d.ts +61 -0
  170. package/dist/components/core/card-body/CardBody.types.js +15 -0
  171. package/dist/components/core/card-body/card-body-impl.css +87 -0
  172. package/dist/components/core/card-button/CardButton.css +73 -0
  173. package/dist/components/core/card-button/CardButton.d.ts +27 -0
  174. package/dist/components/core/card-button/CardButton.js +37 -0
  175. package/dist/components/core/card-button/CardButton.types.d.ts +24 -0
  176. package/dist/components/core/card-button/CardButton.types.js +7 -0
  177. package/dist/components/core/card-button/card-button-impl.css +39 -0
  178. package/dist/components/core/checkbox/Checkbox.css +149 -0
  179. package/dist/components/core/checkbox/Checkbox.d.ts +21 -0
  180. package/dist/components/core/checkbox/Checkbox.js +97 -0
  181. package/dist/components/core/checkbox/Checkbox.types.d.ts +46 -0
  182. package/dist/components/core/checkbox/Checkbox.types.js +15 -0
  183. package/dist/components/core/checkbox/checkbox-impl.css +90 -0
  184. package/dist/components/core/divider/Divider.css +41 -0
  185. package/dist/components/core/divider/Divider.d.ts +46 -0
  186. package/dist/components/core/divider/Divider.js +51 -0
  187. package/dist/components/core/divider/Divider.types.d.ts +25 -0
  188. package/dist/components/core/divider/Divider.types.js +9 -0
  189. package/dist/components/core/dropdown-menu/DropdownMenu.css +146 -0
  190. package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +22 -0
  191. package/dist/components/core/dropdown-menu/DropdownMenu.js +309 -0
  192. package/dist/components/core/dropdown-menu/DropdownMenu.types.d.ts +62 -0
  193. package/dist/components/core/dropdown-menu/DropdownMenu.types.js +12 -0
  194. package/dist/components/core/dropdown-menu/dropdown-menu-impl.css +70 -0
  195. package/dist/components/core/filter-chip/FilterChip.css +149 -0
  196. package/dist/components/core/filter-chip/FilterChip.d.ts +23 -0
  197. package/dist/components/core/filter-chip/FilterChip.js +37 -0
  198. package/dist/components/core/filter-chip/FilterChip.types.d.ts +53 -0
  199. package/dist/components/core/filter-chip/FilterChip.types.js +12 -0
  200. package/dist/components/core/footer/Footer.css +104 -0
  201. package/dist/components/core/footer/Footer.d.ts +43 -0
  202. package/dist/components/core/footer/Footer.js +53 -0
  203. package/dist/components/core/footer/Footer.types.d.ts +47 -0
  204. package/dist/components/core/footer/Footer.types.js +18 -0
  205. package/dist/components/core/footer/footer-impl.css +218 -0
  206. package/dist/components/core/footer-group/FooterGroup.css +90 -0
  207. package/dist/components/core/footer-group/FooterGroup.d.ts +32 -0
  208. package/dist/components/core/footer-group/FooterGroup.js +64 -0
  209. package/dist/components/core/footer-group/FooterGroup.types.d.ts +25 -0
  210. package/dist/components/core/footer-group/FooterGroup.types.js +12 -0
  211. package/dist/components/core/footer-group/footer-group-impl.css +78 -0
  212. package/dist/components/core/icon/Icon.css +40 -0
  213. package/dist/components/core/icon/Icon.d.ts +23 -0
  214. package/dist/components/core/icon/Icon.js +79 -0
  215. package/dist/components/core/icon/Icon.types.d.ts +24 -0
  216. package/dist/components/core/icon/Icon.types.js +7 -0
  217. package/dist/components/core/link/Link.css +89 -0
  218. package/dist/components/core/link/Link.d.ts +37 -0
  219. package/dist/components/core/link/Link.js +141 -0
  220. package/dist/components/core/link/Link.types.d.ts +41 -0
  221. package/dist/components/core/link/Link.types.js +9 -0
  222. package/dist/components/core/link/link-impl.css +168 -0
  223. package/dist/components/core/menu-item/MenuItem.css +70 -0
  224. package/dist/components/core/menu-item/MenuItem.d.ts +11 -0
  225. package/dist/components/core/menu-item/MenuItem.js +26 -0
  226. package/dist/components/core/menu-item/MenuItem.types.d.ts +28 -0
  227. package/dist/components/core/menu-item/MenuItem.types.js +9 -0
  228. package/dist/components/core/navbar/Navbar.css +135 -0
  229. package/dist/components/core/navbar/Navbar.d.ts +36 -0
  230. package/dist/components/core/navbar/Navbar.js +371 -0
  231. package/dist/components/core/navbar/Navbar.types.d.ts +49 -0
  232. package/dist/components/core/navbar/Navbar.types.js +17 -0
  233. package/dist/components/core/navbar/navbar-impl.css +590 -0
  234. package/dist/components/core/navbar-item/NavbarItem.css +75 -0
  235. package/dist/components/core/navbar-item/NavbarItem.d.ts +22 -0
  236. package/dist/components/core/navbar-item/NavbarItem.js +40 -0
  237. package/dist/components/core/navbar-item/NavbarItem.types.d.ts +34 -0
  238. package/dist/components/core/navbar-item/NavbarItem.types.js +10 -0
  239. package/dist/components/core/navbar-menu/NavbarMenu.css +128 -0
  240. package/dist/components/core/navbar-menu/NavbarMenu.d.ts +5 -0
  241. package/dist/components/core/navbar-menu/NavbarMenu.js +186 -0
  242. package/dist/components/core/navbar-menu/NavbarMenu.types.d.ts +45 -0
  243. package/dist/components/core/navbar-menu/NavbarMenu.types.js +12 -0
  244. package/dist/components/core/navbar-menu/navbar-menu-impl.css +186 -0
  245. package/dist/components/core/navbar-menu-group/NavbarMenuGroup.css +26 -0
  246. package/dist/components/core/navbar-menu-group/NavbarMenuGroup.d.ts +17 -0
  247. package/dist/components/core/navbar-menu-group/NavbarMenuGroup.js +22 -0
  248. package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.d.ts +14 -0
  249. package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.js +7 -0
  250. package/dist/components/core/navbar-panel/NavbarPanel.css +87 -0
  251. package/dist/components/core/navbar-panel/NavbarPanel.d.ts +34 -0
  252. package/dist/components/core/navbar-panel/NavbarPanel.js +46 -0
  253. package/dist/components/core/navbar-panel/NavbarPanel.types.d.ts +29 -0
  254. package/dist/components/core/navbar-panel/NavbarPanel.types.js +12 -0
  255. package/dist/components/core/navbar-panel/navbar-panel-impl.css +104 -0
  256. package/dist/components/core/navbar-panel/use-navbar-panel.d.ts +26 -0
  257. package/dist/components/core/navbar-panel/use-navbar-panel.js +135 -0
  258. package/dist/components/core/navbar-switcher/NavbarSwitcher.css +117 -0
  259. package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +20 -0
  260. package/dist/components/core/navbar-switcher/NavbarSwitcher.js +90 -0
  261. package/dist/components/core/navbar-switcher/NavbarSwitcher.types.d.ts +46 -0
  262. package/dist/components/core/navbar-switcher/NavbarSwitcher.types.js +13 -0
  263. package/dist/components/core/navbar-switcher/navbar-switcher-impl.css +179 -0
  264. package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.css +39 -0
  265. package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.d.ts +16 -0
  266. package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.js +19 -0
  267. package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.d.ts +18 -0
  268. package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.js +7 -0
  269. package/dist/components/core/option/Option.css +133 -0
  270. package/dist/components/core/option/Option.d.ts +25 -0
  271. package/dist/components/core/option/Option.js +31 -0
  272. package/dist/components/core/option/Option.types.d.ts +44 -0
  273. package/dist/components/core/option/Option.types.js +14 -0
  274. package/dist/components/core/pagination/Pagination.css +237 -0
  275. package/dist/components/core/pagination/Pagination.d.ts +30 -0
  276. package/dist/components/core/pagination/Pagination.js +406 -0
  277. package/dist/components/core/pagination/Pagination.types.d.ts +59 -0
  278. package/dist/components/core/pagination/Pagination.types.js +14 -0
  279. package/dist/components/core/pagination/pagination-impl.css +17 -0
  280. package/dist/components/core/removable-chip/RemovableChip.css +125 -0
  281. package/dist/components/core/removable-chip/RemovableChip.d.ts +25 -0
  282. package/dist/components/core/removable-chip/RemovableChip.js +36 -0
  283. package/dist/components/core/removable-chip/RemovableChip.types.d.ts +38 -0
  284. package/dist/components/core/removable-chip/RemovableChip.types.js +13 -0
  285. package/dist/components/core/search-input/SearchInput.css +205 -0
  286. package/dist/components/core/search-input/SearchInput.d.ts +5 -0
  287. package/dist/components/core/search-input/SearchInput.js +81 -0
  288. package/dist/components/core/search-input/SearchInput.types.d.ts +43 -0
  289. package/dist/components/core/search-input/SearchInput.types.js +13 -0
  290. package/dist/components/core/search-input/search-input-impl.css +20 -0
  291. package/dist/components/core/segmented-control/SegmentedControl.css +57 -0
  292. package/dist/components/core/segmented-control/SegmentedControl.d.ts +37 -0
  293. package/dist/components/core/segmented-control/SegmentedControl.js +269 -0
  294. package/dist/components/core/segmented-control/SegmentedControl.types.d.ts +38 -0
  295. package/dist/components/core/segmented-control/SegmentedControl.types.js +8 -0
  296. package/dist/components/core/segmented-control/segmented-control-impl.css +57 -0
  297. package/dist/components/core/segmented-control-item/SegmentedControlItem.css +151 -0
  298. package/dist/components/core/segmented-control-item/SegmentedControlItem.d.ts +50 -0
  299. package/dist/components/core/segmented-control-item/SegmentedControlItem.js +101 -0
  300. package/dist/components/core/segmented-control-item/SegmentedControlItem.types.d.ts +37 -0
  301. package/dist/components/core/segmented-control-item/SegmentedControlItem.types.js +10 -0
  302. package/dist/components/core/segmented-control-item/segmented-control-item-impl.css +69 -0
  303. package/dist/components/core/select/Select.css +400 -0
  304. package/dist/components/core/select/Select.d.ts +29 -0
  305. package/dist/components/core/select/Select.js +524 -0
  306. package/dist/components/core/select/Select.types.d.ts +96 -0
  307. package/dist/components/core/select/Select.types.js +26 -0
  308. package/dist/components/core/select/select-impl.css +114 -0
  309. package/dist/components/core/select-chip/SelectChip.css +155 -0
  310. package/dist/components/core/select-chip/SelectChip.d.ts +20 -0
  311. package/dist/components/core/select-chip/SelectChip.js +273 -0
  312. package/dist/components/core/select-chip/SelectChip.types.d.ts +56 -0
  313. package/dist/components/core/select-chip/SelectChip.types.js +14 -0
  314. package/dist/components/core/select-chip/select-chip-impl.css +38 -0
  315. package/dist/components/core/spinner/Spinner.css +76 -0
  316. package/dist/components/core/spinner/Spinner.d.ts +5 -0
  317. package/dist/components/core/spinner/Spinner.js +29 -0
  318. package/dist/components/core/spinner/Spinner.types.d.ts +37 -0
  319. package/dist/components/core/spinner/Spinner.types.js +10 -0
  320. package/dist/components/core/spinner/spinner-impl.css +27 -0
  321. package/dist/components/core/status-dot/StatusDot.css +43 -0
  322. package/dist/components/core/status-dot/StatusDot.d.ts +35 -0
  323. package/dist/components/core/status-dot/StatusDot.js +46 -0
  324. package/dist/components/core/status-dot/StatusDot.types.d.ts +29 -0
  325. package/dist/components/core/status-dot/StatusDot.types.js +7 -0
  326. package/dist/components/core/status-dot/status-dot-impl.css +42 -0
  327. package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +89 -0
  328. package/dist/components/core/subdomain-navbar/SubdomainNavbar.d.ts +21 -0
  329. package/dist/components/core/subdomain-navbar/SubdomainNavbar.js +127 -0
  330. package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.d.ts +43 -0
  331. package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.js +13 -0
  332. package/dist/components/core/subdomain-navbar/subdomain-navbar-impl.css +147 -0
  333. package/dist/components/core/tab/Tab.css +113 -0
  334. package/dist/components/core/tab/Tab.d.ts +36 -0
  335. package/dist/components/core/tab/Tab.js +53 -0
  336. package/dist/components/core/tab/Tab.types.d.ts +42 -0
  337. package/dist/components/core/tab/Tab.types.js +13 -0
  338. package/dist/components/core/tab/tab-impl.css +49 -0
  339. package/dist/components/core/tab-list/TabList.css +40 -0
  340. package/dist/components/core/tab-list/TabList.d.ts +26 -0
  341. package/dist/components/core/tab-list/TabList.js +124 -0
  342. package/dist/components/core/tab-list/TabList.types.d.ts +20 -0
  343. package/dist/components/core/tab-list/TabList.types.js +7 -0
  344. package/dist/components/core/tab-list/tab-list-impl.css +56 -0
  345. package/dist/components/core/table/Table.css +40 -0
  346. package/dist/components/core/table/Table.d.ts +19 -0
  347. package/dist/components/core/table/Table.js +55 -0
  348. package/dist/components/core/table/Table.types.d.ts +59 -0
  349. package/dist/components/core/table/Table.types.js +9 -0
  350. package/dist/components/core/table/table-impl.css +75 -0
  351. package/dist/components/core/table/use-table-sort.d.ts +43 -0
  352. package/dist/components/core/table/use-table-sort.js +51 -0
  353. package/dist/components/core/table-body/TableBody.css +6 -0
  354. package/dist/components/core/table-body/TableBody.d.ts +12 -0
  355. package/dist/components/core/table-body/TableBody.js +26 -0
  356. package/dist/components/core/table-body/TableBody.types.d.ts +36 -0
  357. package/dist/components/core/table-body/TableBody.types.js +7 -0
  358. package/dist/components/core/table-cell/TableCell.css +76 -0
  359. package/dist/components/core/table-cell/TableCell.d.ts +21 -0
  360. package/dist/components/core/table-cell/TableCell.js +31 -0
  361. package/dist/components/core/table-cell/TableCell.types.d.ts +43 -0
  362. package/dist/components/core/table-cell/TableCell.types.js +7 -0
  363. package/dist/components/core/table-head/TableHead.css +6 -0
  364. package/dist/components/core/table-head/TableHead.d.ts +22 -0
  365. package/dist/components/core/table-head/TableHead.js +52 -0
  366. package/dist/components/core/table-head/TableHead.types.d.ts +39 -0
  367. package/dist/components/core/table-head/TableHead.types.js +7 -0
  368. package/dist/components/core/table-head/table-head-impl.css +51 -0
  369. package/dist/components/core/table-header-cell/TableHeaderCell.css +126 -0
  370. package/dist/components/core/table-header-cell/TableHeaderCell.d.ts +21 -0
  371. package/dist/components/core/table-header-cell/TableHeaderCell.js +34 -0
  372. package/dist/components/core/table-header-cell/TableHeaderCell.types.d.ts +56 -0
  373. package/dist/components/core/table-header-cell/TableHeaderCell.types.js +9 -0
  374. package/dist/components/core/table-header-cell/table-header-cell-impl.css +74 -0
  375. package/dist/components/core/table-row/TableRow.css +18 -0
  376. package/dist/components/core/table-row/TableRow.d.ts +17 -0
  377. package/dist/components/core/table-row/TableRow.js +32 -0
  378. package/dist/components/core/table-row/TableRow.types.d.ts +45 -0
  379. package/dist/components/core/table-row/TableRow.types.js +7 -0
  380. package/dist/components/core/table-row/table-row-impl.css +31 -0
  381. package/dist/components/core/text-area/TextArea.css +325 -0
  382. package/dist/components/core/text-area/TextArea.d.ts +13 -0
  383. package/dist/components/core/text-area/TextArea.js +133 -0
  384. package/dist/components/core/text-area/TextArea.types.d.ts +67 -0
  385. package/dist/components/core/text-area/TextArea.types.js +19 -0
  386. package/dist/components/core/text-area/text-area-impl.css +36 -0
  387. package/dist/components/core/text-input/TextInput.css +400 -0
  388. package/dist/components/core/text-input/TextInput.d.ts +5 -0
  389. package/dist/components/core/text-input/TextInput.js +130 -0
  390. package/dist/components/core/text-input/TextInput.types.d.ts +96 -0
  391. package/dist/components/core/text-input/TextInput.types.js +24 -0
  392. package/dist/components/core/text-input/text-input-impl.css +36 -0
  393. package/dist/components/core/tooltip/Tooltip.css +101 -0
  394. package/dist/components/core/tooltip/Tooltip.d.ts +51 -0
  395. package/dist/components/core/tooltip/Tooltip.js +87 -0
  396. package/dist/components/core/tooltip/Tooltip.types.d.ts +38 -0
  397. package/dist/components/core/tooltip/Tooltip.types.js +9 -0
  398. package/dist/components/core/tooltip/TooltipAnchor.d.ts +52 -0
  399. package/dist/components/core/tooltip/TooltipAnchor.js +69 -0
  400. package/dist/components/core/tooltip/tooltip-anchor.css +145 -0
  401. package/dist/components/core/tooltip/tooltip-impl.css +54 -0
  402. package/dist/components/core/tooltip/use-tooltip.d.ts +111 -0
  403. package/dist/components/core/tooltip/use-tooltip.js +189 -0
  404. package/dist/components/core/typography/Typography.css +96 -0
  405. package/dist/components/core/typography/Typography.d.ts +297 -0
  406. package/dist/components/core/typography/Typography.js +28 -0
  407. package/dist/components/core/typography/Typography.types.d.ts +40 -0
  408. package/dist/components/core/typography/Typography.types.js +7 -0
  409. package/dist/components/css-time.d.ts +20 -0
  410. package/dist/components/css-time.js +30 -0
  411. package/dist/components/given.d.ts +7 -0
  412. package/dist/components/given.js +9 -0
  413. package/dist/components/hover-open.d.ts +34 -0
  414. package/dist/components/hover-open.js +90 -0
  415. package/dist/components/index.d.ts +114 -1
  416. package/dist/components/index.js +115 -2
  417. package/dist/components/layout/aspect-ratio/AspectRatio.css +29 -0
  418. package/dist/components/layout/aspect-ratio/AspectRatio.d.ts +24 -0
  419. package/dist/components/layout/aspect-ratio/AspectRatio.js +26 -0
  420. package/dist/components/layout/aspect-ratio/AspectRatio.types.d.ts +22 -0
  421. package/dist/components/layout/aspect-ratio/AspectRatio.types.js +7 -0
  422. package/dist/components/layout/aspect-ratio/aspect-ratio-impl.css +44 -0
  423. package/dist/components/layout/grid/Grid.css +76 -0
  424. package/dist/components/layout/grid/Grid.d.ts +31 -0
  425. package/dist/components/layout/grid/Grid.js +33 -0
  426. package/dist/components/layout/grid/Grid.types.d.ts +48 -0
  427. package/dist/components/layout/grid/Grid.types.js +7 -0
  428. package/dist/components/layout/grid/grid-impl.css +62 -0
  429. package/dist/components/layout/row/Row.css +85 -0
  430. package/dist/components/layout/row/Row.d.ts +32 -0
  431. package/dist/components/layout/row/Row.js +34 -0
  432. package/dist/components/layout/row/Row.types.d.ts +45 -0
  433. package/dist/components/layout/row/Row.types.js +7 -0
  434. package/dist/components/layout/scroller/Scroller.css +59 -0
  435. package/dist/components/layout/scroller/Scroller.d.ts +34 -0
  436. package/dist/components/layout/scroller/Scroller.js +36 -0
  437. package/dist/components/layout/scroller/Scroller.types.d.ts +38 -0
  438. package/dist/components/layout/scroller/Scroller.types.js +7 -0
  439. package/dist/components/layout/scroller/scroller-impl.css +45 -0
  440. package/dist/components/layout/stack/Stack.css +73 -0
  441. package/dist/components/layout/stack/Stack.d.ts +28 -0
  442. package/dist/components/layout/stack/Stack.js +30 -0
  443. package/dist/components/layout/stack/Stack.types.d.ts +41 -0
  444. package/dist/components/layout/stack/Stack.types.js +7 -0
  445. package/dist/components/visually-hidden.d.ts +22 -0
  446. package/dist/components/visually-hidden.js +31 -0
  447. package/dist/fonts/LICENSE-inter.txt +93 -0
  448. package/dist/fonts/LICENSE-red-hat-mono.txt +93 -0
  449. package/dist/fonts/fonts.css +111 -0
  450. package/dist/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
  451. package/dist/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
  452. package/dist/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
  453. package/dist/fonts/inter-greek-wght-normal.woff2 +0 -0
  454. package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
  455. package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
  456. package/dist/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
  457. package/dist/fonts/red-hat-mono-latin-ext-wght-normal.woff2 +0 -0
  458. package/dist/fonts/red-hat-mono-latin-wght-normal.woff2 +0 -0
  459. package/dist/marketing.css +289 -241
  460. package/package.json +18 -4
@@ -0,0 +1,95 @@
1
+ <!-- GENERATED from textinput.contract.json. Do not edit. -->
2
+
3
+ # TextInput
4
+
5
+ One line of text a visitor types before they are a customer. …
6
+
7
+ `import { TextInput } from '@deriv-com/dds-marketing'`
8
+
9
+ ## Reach for it when
10
+
11
+ - A page asks for an email — a newsletter, a waitlist, a download behind an address
12
+ - A short form stands between the reader and something they want: a demo booking, a contact request, a callback
13
+ - A value is genuinely one line and the reader can type it without looking anything up
14
+
15
+ ## Something else, when
16
+
17
+ - The value is more than a line — a message, a description, an enquiry → **nothing in this system does this**
18
+ - The reader is choosing from a set rather than typing → **nothing in this system does this**
19
+ - The field is a query against something on the page → **nothing in this system does this**
20
+
21
+ ## Never
22
+
23
+ - Asking for more than the page has earned. Every extra field is a reason to leave, and a marketing form is judged on how little it asks — a name and an email convert where a name, an email, a company, a role and a phone number do not
24
+ - Sensitive data. A landing page has no account, no session and usually no reason to be trusted with anything more than an address. Card numbers, identity documents and passwords belong behind a sign-in, on a page built to hold them
25
+ - A label the reader cannot see. The placeholder is not a label — it disappears the moment they type, taking with it the only thing telling them what the field was for, and it is the first thing lost when someone comes back to check what they filled in
26
+ - Layout. A disabled field holding a value the reader cannot change is not a way to present information — that is copy, and it reads better as copy
27
+
28
+ ## Props
29
+
30
+ - **size** `enum` · default "md"
31
+ - `sm` — A field in a dense desktop arrangement — a filter row above a list, a field beside body copy rather than heading a section. Not on a phone, where thirty-two is below what a finger reliably hits
32
+ - `md` — The default, and nearly every form on a page — an inline signup, a contact form in a section
33
+ - `lg` — A hero's single field, or a conversion band where the form is the reason the section exists and has to be found from a distance
34
+ - **status** `enum` · default "none"
35
+ - `none` — Nothing has been checked yet, which is the field for nearly all of its life — including before it has been filled in. Empty is not an error
36
+ - `error` — Validation has failed and the reader has to change the value before the form will go anywhere
37
+ - `warning` — The value is usable but worth a second look — a work address on a form that expected a personal one. The reader may keep it
38
+ - `success` — A check has run and passed, and saying so is worth a line — an address confirmed as deliverable before the reader commits to it
39
+ - `pending` — A check is in flight. The value is still the reader's to change while it runs
40
+ - never: Decoration, or a permanent state. A status is the result of checking a value, so a field that always looks like a warning is telling the reader nothing
41
+ - **type** `enum` · default "text"
42
+ - `text` — A name, a company, anything with no keypad or validation of its own
43
+ - `email` — An address. It brings the right keypad on a phone — the @ without a modifier — which is the difference between a typo and a lost signup
44
+ - `tel` — A phone number, for the numeric keypad. It does no validation and should not pretend to: numbers differ by country and a field that rejects a valid one is worse than a field that accepts anything
45
+ - `url` — A website, on a form that asks for one
46
+ - never: Standing in for validation. The type chooses a keypad and a browser hint; what makes an address real is checked after the reader has submitted, and said in the message
47
+ - **label** `string` · required — Always — it names the field, it is drawn, and clicking it focuses the input. One or two words: 'Email', 'Full name', 'Work email'
48
+ - never: A sentence, or an instruction. What the field will do with the value is the helper's job, and a label long enough to wrap stops being something the eye can pair with a box
49
+ - **labelTooltip** `string` · optional — A field needs a sentence the label has no room for — why the address is being asked for, what happens to it
50
+ - never: Anything the reader must read to fill the field in. A tooltip is opened on purpose, so what is behind it is what a reader chose to want; the format and the consequence belong in helperText, which is simply there
51
+ - **placeholder** `string` · optional — Showing the shape of the value where the shape is not obvious — 'name@example.com' on an email field. It is an example, and it is allowed to be skipped
52
+ - never: The label. It disappears on the first keystroke, it is gone when the reader comes back to check, and it is announced as nothing once the field has text in it
53
+ - **helperText** `string` · optional — Saying what happens to the value — what the page will send, how often, what it will not do with the address. On a marketing form this is frequently what decides whether the reader types a real one
54
+ - never: Repeating the label in a longer form. A field labelled 'Email' with a helper reading 'Enter your email' has spent a line saying nothing
55
+ - **leadingIcon** `node` · optional — A mark that says what the field takes at a glance — an envelope on an address, a globe on a site
56
+ - never: The label. A glyph names nothing on its own, and a field identified only by a picture is a guess
57
+ - **prefix** `string` · optional — A fixed part of the value the reader should not have to type — a currency mark, https://
58
+ - never: Part of the value you expect back. It is furniture: it is never submitted and the reader cannot edit it
59
+ - **suffix** `string` · optional — A fixed tail — a unit, a domain every address on this form shares
60
+ - never: A unit the reader might need to change. If it is a choice it is a control, not a label stuck to the end of the box
61
+ - **trailingIcon** `node` · optional — A mark at the far edge that comments on the value rather than introducing it
62
+ - never: Anything pressable. It is an ornament, not a control — a button in here has no name and no keyboard route
63
+ - **clearable** `boolean` · default false — A field the reader is likely to retype rather than edit — a search term, a long address typed on a phone
64
+ - never: A short field on a desktop form. Select-all and type is already one gesture, and the button costs a target inside the box for every field that has one
65
+ - **clearLabel** `string` · required — Required whenever clearable is set. It is the button's only name — the glyph says nothing to a screen reader
66
+ - never: Describing the field. 'Clear email address' names the action; 'Email address' names the thing it acts on and is read as a second field
67
+ - **inputMode** `enum` · optional
68
+ - `numeric` — Digits and nothing else — a postcode, a reference number
69
+ - `decimal` — A number that may carry a separator — an amount
70
+ - never: Validation, or type. It chooses the keypad a phone raises and constrains nothing at all
71
+ - **statusMessage** `string` · required — Saying what to change, when the status is an error. It replaces the helper while it is showing
72
+ - never: Announcing that something is wrong without saying what. The field is already red — a message reading 'Invalid' has added a colour and no information
73
+ - **required** `boolean` · default false — The form cannot be sent without this one, and the reader is better off knowing before they reach the button. It draws the mark and sets aria-required
74
+ - never: Validation. It says a field must be filled; whether what was filled in is any good is the status's job, after they submit
75
+ - **requiredMark** `enum` · default "text"
76
+ - `text` — The default. The word 'required' says what it means in the reader's own language and needs no key
77
+ - `asterisk` — A dense form where the word would repeat down the column, and a legend explains the mark once
78
+ - never: Carrying the requirement on its own. The mark is decorative either way — aria-required on the field is what says it to a screen reader
79
+ - **optional** `boolean` · default false — Most of the form is required and one field is not. Marking the exception is what tells the reader anything
80
+ - never: Every field on a form where nothing is required. Marking all of them says the same as marking none, and costs a word on each
81
+
82
+ ## The type refuses
83
+
84
+ - status="error" with statusMessage=null — A field turned red with nothing saying why is a reader stuck at a form with no way forward — and on a marketing page, a reader who leaves
85
+ - status="warning" with statusMessage=null — A warning with nothing saying what to look at is a field the reader cannot act on
86
+ - required=true with optional=true — A field is one or the other, and marking it both says nothing
87
+ - clearable=true with clearLabel=null — A button whose only content is a glyph is announced as nothing without a name
88
+
89
+ ## Inside it
90
+
91
+ - Renders 16 parts: root, label-row, label, required-mark, optional-mark, label-tooltip, control, leading-icon, prefix, field, suffix, clear, trailing-icon, helper, message, message-icon.
92
+
93
+ ---
94
+
95
+ The reasoning behind each of these, the parts this renders, its states and snippets that compile: `.llm/components/textinput.md`.
@@ -0,0 +1,58 @@
1
+ <!-- GENERATED from tooltip.contract.json. Do not edit. -->
2
+
3
+ # Tooltip
4
+
5
+ A brief description of the element it is anchored to, shown on demand
6
+
7
+ `import { Tooltip } from '@deriv-com/dds-marketing'`
8
+
9
+ ## Reach for it when
10
+
11
+ - Naming a control whose icon or abbreviation cannot say what it does
12
+ - Showing the full text of a value the layout has truncated
13
+
14
+ ## Something else, when
15
+
16
+ - The guidance is needed before the reader acts, rather than after they point at something → **nothing in this system does this**
17
+ - The message must persist, be dismissed, or contain something to press → **nothing in this system does this**
18
+
19
+ ## Never
20
+
21
+ - Information the user must have to finish the task — a tooltip is invisible to anyone who never points at it, and absent entirely on touch
22
+ - Anything interactive — a tooltip cannot be focused, so a control inside it cannot be reached
23
+ - More than a sentence — this is a label, not a panel
24
+ - A tooltip that finds its own way out of the viewport's edge. The caret sits at one of twelve fixed points — three along each of the four edges — and the consumer names which one. …
25
+ - A Tooltip rendered on its own. `hidden` defaults to false, so a chip with nothing driving it is visible the moment it mounts, sitting in the layout rather than over it and pointing at nothing — and the aria-describedby that makes it a description belongs to the anchor, which a chip on its own does not have. …
26
+ - Anything but text inside the chip. Composition allows `text` alone and names Button, Input and Card as forbidden: a control in there cannot be reached, and a Card in there is a panel wearing a label's clothes
27
+ - Reporting that something failed. There is no danger ground here, on the same reasoning Badge gives for having none: those roles report what happened to a reader who did something, and a landing page's reader has not done anything yet. …
28
+
29
+ ## Props
30
+
31
+ - **placement** `enum` · default "top"
32
+ - `top` — The tooltip sits above its anchor, so the caret drops from the bottom edge to meet it
33
+ - `right` — The tooltip sits on the trailing side of its anchor — the right in English, the left in Arabic — so the caret reaches back across to meet it. …
34
+ - `bottom` — The tooltip sits below its anchor, so the caret rises from the top edge to meet it
35
+ - `left` — The tooltip sits on the leading side of its anchor — the left in English, the right in Arabic — so the caret reaches across to meet it. …
36
+ - **alignment** `enum` · default "center"
37
+ - `center` — The chip is centred on its anchor and the caret's point lands on the middle of it. Use this unless the chip is much wider than the thing it points at
38
+ - `start` — The chip's leading edge lines up with the anchor's own, so a chip wider than its anchor grows away from it rather than back across the layout. For an anchor at the start of a row
39
+ - `end` — The mirror of start: the chip's trailing edge lines up with the anchor's, for an anchor at the end of a row
40
+ - never: Moving a caret that is not there. With showCaret false nothing about the chip itself changes — though whatever places the chip still reads this to decide which of its edges meets the anchor's
41
+ - **hidden** `boolean` · default false — Whatever reveals the tooltip has not revealed it yet, or has dismissed it. Defaults to false, which means visible — so something has to drive this, or the chip is simply on. …
42
+ - never: Hiding a description the user still needs. A tooltip nobody can reveal is a sentence nobody reads — if it must always be legible it is helperText, not a tooltip
43
+ - **showCaret** `boolean` · default true — Drawn by default. Leave it on whenever something holds the chip against its anchor — the point is what ties a floating description to the control it belongs to
44
+ - never: A chip that whatever positions it does not hold against the anchor's edge, or an anchor unmistakable without one. A caret aimed at nothing is worse than no caret. With it off `alignment` is not dead — it still decides which of the chip's edges meets the anchor's; there is simply no point left for it to move
45
+
46
+ ## Inside it
47
+
48
+ - Takes only text.
49
+ - 5 components are refused inside it; the list and the reasons are in the long document.
50
+ - Renders 3 parts: root, caret, body.
51
+
52
+ ## Needs mounting
53
+
54
+ Does not work from the import alone: useTooltip, useTooltipDefaults, TooltipAnchor. See `.llm/components/tooltip.md` for what to mount and where.
55
+
56
+ ---
57
+
58
+ The reasoning behind each of these, the parts this renders, its states and snippets that compile: `.llm/components/tooltip.md`.
@@ -0,0 +1,59 @@
1
+ <!-- GENERATED from typography.contract.json. Do not edit. -->
2
+
3
+ # Typography
4
+
5
+ Copy, set in one of the page's type roles. …
6
+
7
+ `import { Typography } from '@deriv-com/dds-marketing'`
8
+
9
+ ## Reach for it when
10
+
11
+ - A heading, a paragraph, or a caption on a marketing page — anything the page writes rather than a component draws
12
+ - A heading whose level and whose size disagree, which is most of them past the first section
13
+ - An eyebrow above a headline, where the capitals are a setting rather than something typed
14
+
15
+ ## Something else, when
16
+
17
+ - The text is inside a component that already sets its own type → **nothing in this system does this**
18
+ - The words are a control's name rather than copy → **nothing in this system does this**
19
+ - The page needs the text coloured, spaced or aligned → **nothing in this system does this**
20
+
21
+ ## Never
22
+
23
+ - Choosing an element by picking a size. `as` is the document and `variant` is the scale — a page with six h1 elements is still wrong however it was set
24
+ - Carrying a token this does not offer. label and field-label belong to controls, and a paragraph set at a button's weight is a paragraph pretending to be one
25
+
26
+ ## Props
27
+
28
+ - **variant** `enum` · default "body-md"
29
+ - `h1` — The line a landing page is built around, and there is one of them
30
+ - `h2` — A headline opening a major section of a long page
31
+ - `h3` — A section heading under an h1 and h2
32
+ - `h4` — A subsection heading, the first step below the extrabold the larger headings carry
33
+ - `h5` — A label over a group of cards, a list, or a short block of copy
34
+ - `subtitle` — A secondary title under a heading — a pricing plan's name, a sub-feature group
35
+ - `body-lg` — An introductory paragraph under a headline, a hero description, a section intro
36
+ - `body-md` — The default, and most of the copy on a page — feature descriptions, article text
37
+ - `body-sm` — De-emphasised copy: legal lines, disclaimers, help text
38
+ - `eyebrow` — A category label above a headline — a section tag, a plan badge. Drawn in capitals by this component, so write it in the case it should be read in
39
+ - `figure` — A number that is the point of its block — a count, a total, a span of time — with a label under it
40
+ - never: Picking an element. A variant is a size, and the element is `as`
41
+ - **as** `enum` · default "p"
42
+ - `p` — The default, and any block of prose
43
+ - `span` — Text inside a sentence, or inside something that is already a block
44
+ - `h1` — The page's one document-level heading
45
+ - `h2` — A section heading
46
+ - `h3` — A heading under an h2
47
+ - `h4` — A heading under an h3
48
+ - `h5` — A heading under an h4
49
+ - `h6` — The deepest heading level
50
+ - never: Anything interactive. A link is Link and a control is Button — an element that responds to a click needs a name, a focus ring and a keyboard route, none of which this has
51
+
52
+ ## Inside it
53
+
54
+ - Takes only text.
55
+ - 8 components are refused inside it; the list and the reasons are in the long document.
56
+
57
+ ---
58
+
59
+ The reasoning behind each of these, the parts this renders, its states and snippets that compile: `.llm/components/typography.md`.
package/.llm/index.md ADDED
@@ -0,0 +1,86 @@
1
+ <!-- GENERATED from components/**/*.contract.json. Do not edit. -->
2
+
3
+ # dds components
4
+
5
+ The full guidance for every component, for when the one-line list in AGENTS.md is not
6
+ enough to choose. Load `.llm/components/<name>.md` only for the components you actually
7
+ need — loading all of them dilutes the relevant one.
8
+
9
+ Paths here are from the package root, so they resolve whether this file is read in place
10
+ or its content handed over on its own.
11
+
12
+
13
+ ## Core
14
+
15
+ Domain-neutral building blocks.
16
+
17
+ ### Primitives
18
+
19
+ | Component | Use when | Not for |
20
+ |---|---|---|
21
+ | AccordionItem | One row inside an Accordion — every row of a set is one of these · A single disclosure with no set around it: one topic whose detail is worth offering and not worth showing. The row is whole on its own, and it keeps its own open state when nothing is injecting one | The heading goes somewhere rather than opening something → `CardButton` |
22
+ | Badge | One of a set is the one the page wants read first — the plan most people choose, the market most people start with · Something is new or has changed, and saying so is worth a word rather than a sentence · A number the page is promoting is worth marking as a saving rather than left in the copy — a percentage off, a period free | What it says is a state the reader's account is in → nothing here · The words are the point rather than the mark → `CardBody` |
23
+ | Breadcrumb | The page sits inside a section hierarchy, and the levels above it are places the visitor can navigate to — a product page inside a markets section, a blog post inside a category · A visitor who arrived by search, social link or campaign URL needs to learn where they landed and how the site is organised around them | The visitor is moving through the stages of a sign-up or onboarding flow rather than standing in a hierarchy → nothing here · There is exactly one place to go back to, and it is the previous page rather than a parent section → nothing here |
24
+ | BreadcrumbItem | Rendering one level of a Breadcrumb — every level in a trail is one of these · The level needs a short name the visitor recognises as a place: the section name, not a sentence about it | The destination is somewhere the visitor goes to act rather than a level they climb back to → nothing here |
25
+ | Button | The call to action on a marketing page — the one step you want a visitor to take next · Moving a visitor along a funnel: hero to signup, pricing to checkout, feature page to demo booking · A destination prominent enough that it has to read as a control rather than as words in a sentence | The action happens on the current page — submitting a form, toggling a setting, opening a dialog, removing something → nothing here · The words belong inside a sentence or a paragraph of body copy → nothing here · The control is a glyph alone, with no words → `ButtonIcon` |
26
+ | ButtonIcon | One press with no room for words — a promotional bar's dismiss, a hero's play control, a carousel step, a footer's social links. Whether it navigates or acts in place is decided by href alone, so the same component covers both · A row of glyph-alone destinations where words would only repeat — social accounts in a footer, app stores in a download band, a region switch in a header · A control the page owns rather than a destination — dismissing a promotional bar, playing a hero video, advancing a carousel, opening a mobile nav. Leave href off and it is a button, which answers Space and fires what the page says · The glyph is one a visitor reads without being taught — a play triangle, a dismiss cross, a chevron, a social mark in its monochrome cut. A marketing page gets no onboarding and usually no second visit to learn in · Room is genuinely short and the words would be the same words several times over. One of these on its own beside prose is usually a Button that lost its label | The control has words, or needs them to be understood → `Button` · The whole surface is the target — a card standing for a feature, a market or a plan → `CardButton` · The mark is an ornament rather than a control → `Icon` · The mark reports a state the visitor sets and reads back — sound on or off, a light and dark switch → nothing here |
27
+ | Card | Content that is read as one thing — a feature and the sentence explaining it, a plan and what it costs, a step and what it asks for · A picture that reaches the card's edges, with or without copy inset beneath it — a screenshot, a photograph, a band of art. The corner clips it, and the card adds no inset that would leave it floating in a margin · A row or a column of such groups, where the fill is what separates one from the next · A measure a landing page should not be choosing for itself: the corner a card takes and the ground it sits on · An editorial card — an article, a post, a story — where the picture and the headline do the separating and a fill would be a second, weaker edge. That is `plain`, which paints no ground and keeps the corner | The whole surface is the thing the reader presses → `CardButton` |
28
+ | CardBody | Words, a picture, or both inside a Card — a feature and the sentence explaining it, a screenshot under the copy that describes it · A photograph, render or screenshot that should reach the card's edges while the copy above it stays inset · A picture that should absorb whatever height the copy leaves, so a row of cards ends flush no matter how much each one says · A mark above the words — the glyph a feature card leads with, sized and inset with the copy rather than reaching the card's edges · Copy that sits over the picture rather than beside it — a photograph as the card's ground, with a title and a sentence washed over it · A line above the title filing the card under something — the date an article ran, how long it takes to read, the category it belongs to. It is set in capitals at the eyebrow step, which is what tells it apart from the copy without it needing a colour of its own | The whole card is one picture, with no words at all → `Card` |
29
+ | CardButton | The whole card is the target rather than a link buried in it — a grid of features each leading to its own page, a set of markets, a row of plans · Pressing it goes somewhere with a URL of its own. Pass href and the browser's own navigation works: cmd-click opens a tab, the status bar shows the destination, the link can be copied and it can be crawled · Pressing it opens something the page owns rather than leaving the page — a dialog, a video, a step in a sign-up | The card holds a control of its own as well → `Card` · Nothing happens when it is pressed → `Card` |
30
+ | Checkbox | A choice the user makes now and confirms later — the form's Save or Continue is what applies it · Agreeing to something before proceeding — terms, a risk disclosure, a confirmation the user must actively give · One of several independent choices, each of which can be on or off without affecting the others | Choosing exactly one option from a short set, where picking one unpicks the others → `SegmentedControl` · Performing an action rather than recording a choice → `Button` |
31
+ | Divider | Two groups inside one container that nothing else is separating — a footer's link columns, the tiers inside a pricing card, a card's summary above its detail. Where a heading or a surface of its own already tells the groups apart, that is doing this component's job better than it can · A row of items holding one that belongs to a different set from its neighbours — the vertical case. A legal line beside a copyright notice, a language picker at the end of a nav. It takes its height from the row rather than declaring one, so it is as tall as whatever it stands between · A word between two rules, where that word is the entire content of the divide: OR between two ways of signing up, and little else. The rules either side are what make it read as a fork rather than as a heading | The groups have names → `Typography` · The space between the groups already separates them → nothing here · The line wanted is the edge of a surface → `Card` · The line wanted is the rail under a tab strip → `TabList` |
32
+ | DropdownMenu | A set of destinations too long for the navigation bar and too short to be a page of its own — languages, regions, the parts of a long index · The set is short enough to read at a glance, where a visitor is choosing rather than searching | The set reports a choice the visitor should find marked when they return → nothing here · The destinations belong in the page's navigation → nothing here · It is one destination rather than one of a set → nothing here · The set is long enough that a visitor would rather type than read → nothing here |
33
+ | FooterGroup | A set of a footer's destinations belong under one word — Markets, Support, Legal · The footer has enough links that a reader scanning it needs sets rather than a list | The destinations are the ones a visitor most likely wants → `Navbar` · The group is a named set inside a navigation panel → `NavbarMenuGroup` · There is one link rather than a set → `Link` |
34
+ | Icon | A glyph stands beside words to speed recognition — a mark on a feature card, a chevron on a row, a separator in a trail · A page is composing something a component offers a slot for, and the slot takes a mark rather than a component that draws one | The mark identifies a company or a product — a payment method, an app store, a social network → `Logo` *(not built yet)* · The artwork is a scene rather than a symbol → `Illustration` *(not built yet)* |
35
+ | Link | A term inside running copy has a page of its own — a market named in a paragraph, a fee mentioned in a sentence, a product referred to in passing · The page must offer a destination without pushing it: terms, a full fee schedule, a regulatory notice. A pill would give it the weight of the thing the page is actually asking for · A second destination beside the call to action, where a second pill would be two things asking to be pressed and a reader would have to choose between them before reading either | The destination is the step the page was built to produce → `Button` · Pressing it does something on this page rather than going somewhere → nothing here · The whole card or panel is the target rather than some words in it → `CardButton` |
36
+ | MenuItem | A row in a menu of destinations — a language, a region, a page number an index skipped · A set short enough to read at a glance, where a reader is choosing rather than searching | The row reports a choice the reader should find marked when they return → nothing here · The destination belongs in the page's navigation → nothing here · It is one action rather than one of a set → nothing here |
37
+ | NavbarItem | A section of the site, in a Navbar — the ordinary case and what this is for · A destination that leaves the site, which it marks as a change of context rather than leaving the reader to find out · The same destination inside the panel a narrow bar collapses into: a page writes its navigation once, and what changes with the width is how it is drawn | The destination opens a panel of further destinations rather than going somewhere → `NavbarMenu` · The destination is a phrase inside a sentence, or a call to action beneath a paragraph → `Link` · The item is one of a set of alternatives rather than a place → `Tab` |
38
+ | NavbarMenuGroup | A section's panel holds more destinations than a reader takes in at once, and they fall into sets — markets, tools, payments · Two lists in a panel would be told apart by nothing if the words above them were taken away | The panel holds few enough destinations that naming sets would be naming one thing each → `NavbarItem` · The set is a section of the site rather than a set within one → `NavbarMenu` |
39
+ | Option | An answer inside a control that opens a list — a SelectChip today. One of these per option in the set | Pressing it should do something rather than record an answer → `MenuItem` · The row is one of a few and all of them fit on the page → `FilterChip` |
40
+ | SearchInput | A help centre, a knowledge base, or documentation — more pages than a menu can carry · A blog or resource index a reader arrives at knowing roughly what they want · A directory the page already holds and can filter as the reader types — markets, offices, partners | The field is part of a form the reader will submit → nothing here · The set is small enough to show at once → nothing here · The reader is choosing from known options rather than describing what they want → nothing here |
41
+ | SegmentedControlItem | One option in a SegmentedControl — the thing a reader presses to change which of a few mutually exclusive values is in force · A choice worth showing beside its alternatives rather than hiding in a list, so the reader compares and picks in one glance | The option names a slice of the page the reader moves to rather than a value they set → `Tab` · The choice is on or off rather than one of several → `Button` · The option leads somewhere → `Link` |
42
+ | Select | A form asks for one answer out of a set the visitor recognises — a country, a language, the reason they are getting in touch · An index or a table is worth narrowing, and the choice reshapes the page rather than being submitted — the sort on a list of articles, the market a pricing table shows · The set is long enough that showing it in full would crowd the page, which is what separates this from a row of chips or a segmented control | The set is a handful and worth comparing side by side → `SegmentedControl` · The choices are destinations rather than answers → `DropdownMenu` · The reader can pick more than one → nothing here · The answer is not on the list, and typing one should stand → nothing here |
43
+ | Spinner | The reader has just submitted something — a signup, a contact request — and the page owes them a sign that it is working · A section is holding space for content that arrives separately: an embed, a demo, a band of live figures · Something the reader asked for is on its way and nobody can say how long it will take | The wait is the page's own first load → nothing here · How much is done is known, or could be → nothing here |
44
+ | StatusDot | Marking something the page is pointing at — a plan that is new, a feature worth finding in a list of them. That is the accent one, and on a marketing page it is most of them · Showing presence or availability alongside a name · Indicating system health or severity in a compact space, where a word for each would cost more room than the difference is worth | The status needs a text label inside a colored pill → `Badge` |
45
+ | Tab | One of a small set of comparable versions of the same offer — a billing period, a platform, a market class · The strip is the page's own comparison control and the alternatives are already written on the page | Pressing it should take the reader to another page → `Button` · The item is one of a list of separate topics rather than a version of one → `AccordionItem` |
46
+ | Table | Data with a uniform structure, where the same fields exist on every row and a reader compares one row against another down a column · Values that line up — amounts, dates, counts. A column is what makes them comparable, and comparison is the only reason to pay for a table's weight · Rows that carry more than words: a badge against a name, a link at the end. The cell is a slot, so what a row holds is the page's decision | The records do not share a shape, or each is a thing in itself rather than a row to compare → `Card` · There is one field per record → nothing here |
47
+ | TableBody | The data itself — every row that a reader compares against the others | The row names the columns rather than filling them → `TableHead` |
48
+ | TableCell | A value in a data row — a name, an amount, a date, a state · A cell holding a component rather than words: a Badge against a name, a Link at the end of the row · Numbers a reader compares down the column, where `numeric` ranges them to the end and sets the digits in tabular figures | The cell names the column rather than filling it → `TableHeaderCell` |
49
+ | TableHead | Naming the columns, which almost every table should. A column of numbers with nothing at the top is a column a reader has to infer | The row is data rather than a name for data → `TableBody` |
50
+ | TableHeaderCell | Naming a column, which every column should have · A column a reader can order, where `sortable` draws the control and `sortDirection` says which way it is ordered now | The cell holds a value rather than the name of a column → `TableCell` |
51
+ | TableRow | A record, with one cell per column · A row a reader can pick, where `selected` draws the state the page is holding | The whole row is a target that navigates → `CardButton` |
52
+ | TextArea | A contact form asks what the reader actually wants — the message, the enquiry, the question · An application or partner form asks someone to describe what they do in their own words · Feedback, where the value of the answer is precisely the part no set of options would have caught | The value is one line — a name, an address, a company → nothing here · The reader is choosing from a set rather than composing → nothing here · The page is presenting text rather than collecting it → nothing here |
53
+ | TextInput | A page asks for an email — a newsletter, a waitlist, a download behind an address · A short form stands between the reader and something they want: a demo booking, a contact request, a callback · A value is genuinely one line and the reader can type it without looking anything up | The value is more than a line — a message, a description, an enquiry → nothing here · The reader is choosing from a set rather than typing → nothing here · The field is a query against something on the page → nothing here |
54
+ | Tooltip | Naming a control whose icon or abbreviation cannot say what it does · Showing the full text of a value the layout has truncated | The guidance is needed before the reader acts, rather than after they point at something → nothing here · The message must persist, be dismissed, or contain something to press → nothing here |
55
+ | Typography | A heading, a paragraph, or a caption on a marketing page — anything the page writes rather than a component draws · A heading whose level and whose size disagree, which is most of them past the first section · An eyebrow above a headline, where the capitals are a setting rather than something typed | The text is inside a component that already sets its own type → nothing here · The words are a control's name rather than copy → nothing here · The page needs the text coloured, spaced or aligned → nothing here |
56
+
57
+ ### Patterns
58
+
59
+ | Component | Use when | Not for |
60
+ |---|---|---|
61
+ | Accordion | Questions a reader asks near a decision — what it costs, whether their money is safe, how long a withdrawal takes. Most go unread, which is the point: the ones that matter are found by scanning the headings · The long version of something the page has already said shortly — specifications, trading hours, the full terms. The heading is the topic and the panel is the detail nobody needs until they need it · A run of rows at one depth in the page's outline, sitting under a section heading of their own | There is one thing to disclose rather than a set → `AccordionItem` · The reader is meant to read all of it → `Card` |
62
+ | BottomSheet | A task needs the screen's full width and the reader's undivided attention — a set of filters, a confirmation, an option picker · The choice is the whole of what the reader is doing, and the page behind it is context rather than something to work in | The message is a passing notification the reader does not have to answer → nothing here · The viewport is wide enough for a centred modal → nothing here · The reader is choosing one answer from a set, inside a form → nothing here · A short description of the control the pointer is on → `Tooltip` |
63
+ | FilterChip | An index is long enough to be worth cutting down and its categories are few enough to show in full — a blog filtered by topic, a help centre filtered by product, a market list filtered by asset class · The choice is small enough that a form control would be more machinery than it deserves — turning one topic on is not a question worth a checkbox and a label · What is chosen has to stay visible while the reader reads what it did, so the narrowing and the list it produced can be read together | The token stands for a narrowing already applied, which the reader drops rather than turns off → `RemovableChip` · The thing named cannot be acted on and is there to be read — a tag on an article, a status on a card → `Badge` · The chips are really the navigation of the page, and pressing one changes what the page is → `Tab` · Pressing it goes somewhere — a category page with its own address → `Link` |
64
+ | Footer | A marketing page needs its closing band — the mark, the site's other destinations, the regulatory text and the copyright line · The same footer has to hold its content to the page's measure and gutter without the page restating either · The regulatory or legal wording has to sit in a consistent place across every page of the site | The content closes a card or a panel rather than the page → `Card` · The navigation is the page's primary one, at the top → `Navbar` · What is needed is a horizontal rule between two blocks of content → `Divider` |
65
+ | Navbar | A marketing page needs its top-level navigation — the mark, the sections of the site, and whatever sits at the far end · The same bar has to persist while the page scrolls, so a reader deep in a long page can still leave it · The navigation has to work at a phone's width without the page writing a second version of it | The items are versions of one thing rather than places the site has → `TabList` · What is wanted is one section's panel rather than the bar it hangs from → `NavbarMenu` · The navigation runs down the side of an application rather than across the top of a page → nothing here |
66
+ | NavbarMenu | A section of the site has enough inside it that naming the section is not enough — Trading holding markets, platforms and tools, rather than one page called Trading · The destinations under a section are worth grouping, and the groups are worth heading · The section has something the site wants shown alongside its links: a promotion, a feature, a piece of art | The destination is a single place → `NavbarItem` · What opens is a single column of choices rather than a section of the site → `DropdownMenu` |
67
+ | NavbarPanel | Navbar is collapsing and its destinations have to go somewhere. This is where, and the bar puts them here without being asked · The same navigation has to be read down a phone rather than across a page | The surface is a sheet rising from the foot of the page rather than the site's navigation → `BottomSheet` · What is wanted is a list that opens beside the control that opened it → `DropdownMenu` |
68
+ | NavbarSwitcher | A bar needs a language or region switcher, which is the case this was drawn for · A set of choices changes how the page is drawn or worded rather than taking a reader anywhere · The set is long enough that a phone should give it the whole panel rather than a dropdown inside one | The control opens a set of commands rather than a set of choices → `DropdownMenu` · The control flips between two states → `ButtonIcon` · The items are places the site has → `NavbarMenu` |
69
+ | NavbarSwitcherOption | A NavbarSwitcher needs its choices · One of a set of options is in force and a reader should be able to see which | The row goes somewhere → `NavbarItem` · The row is a command in a dropdown → `MenuItem` |
70
+ | Pagination | An index or archive has been split across pages and the reader needs to move through it — a blog listing, a news archive, a resource library. It belongs below the results, because the decision to move on is one the reader makes after reading what is here · The reader needs to reach a particular page rather than step towards it — page fourteen of forty, in one press. That is the pages variant, and the only one offering a target with a number on it. Where the row has no room for that number, the break standing in for it opens a menu of the pages it hides, so a page the row cannot show is two presses away rather than a walk · The pages have addresses a search engine should follow. Numbered targets drawn as links are how an index gets crawled past its first page, which on a marketing site is usually the reason the index exists · How much is left matters as much as where the reader stands. A total passed to the count variant turns the readout from a position into a measure, which is what tells someone whether to keep reading or search instead · The reader is walking a short visual sequence and what they want to know is where they are in it rather than what that position is called — a carousel of cards, a testimonial slider, a walkthrough. That is the dots variant, and it holds while the set stays under about ten: a dot carries no number, so past a handful the reader is counting marks too small and too many to count | The reader is moving between views of one page rather than through one long set → `TabList` · More results are appended to the view as the reader reaches the end, rather than one page replacing another → `Button` · The reader is hunting for one row among thousands rather than walking the set → `SearchInput` |
71
+ | RemovableChip | An index shows the narrowings currently applied above its results, and each has to come off on its own without clearing the rest · The reader has assembled something across a page — markets on a comparison, topics on a subscription form — and needs to see and unpick what is in it · What was chosen is worth showing as a token rather than as a sentence, because the reader will act on individual pieces of it | The token is turned on and off rather than added and taken away → `FilterChip` · The thing named cannot be taken away and is there to be read — a category on a card, a status on a plan → `Badge` · The token is really a link to the thing it names → `Link` |
72
+ | SegmentedControl | Two to four alternatives that exclude one another, where the whole set is worth showing at once and the reader decides by weighing them side by side rather than recalling which exist · What the reader picks becomes a value something next to it consumes — a period against which prices are quoted, a unit, a plan — which puts the control beside whatever it alters rather than at the head of the page · The alternatives are short enough to read across in a glance. A row is scanned, not worked through | The choice swaps a whole slice of the page rather than setting a value → `TabList` · The alternatives are separate topics rather than values of one question → `Accordion` · There are more than about four, or the labels need more than a word or two → `SelectChip` · The choice is on or off → `Button` · The reader may pick several of the options at once, or none → `FilterChip` |
73
+ | SelectChip | A row narrows an index by one value out of a set, and has to keep showing which value that is · The set is short enough to scan rather than search — a region, a language, a sort order · The row has no space for a form field: nothing above the control, nothing beneath it, only the answer | Pressing an item does something rather than answering something → `DropdownMenu` · The chip answers on its own, or the set is short enough for every answer to sit in the row as a chip of its own → `FilterChip` · Each answer is a page with its own address → `Link` |
74
+ | SubdomainNavbar | A subdomain needs its top-level navigation — the mark, the places that subdomain has, and whatever sits at the far end · The bar should sit still. Nothing about it changes as the page scrolls, which is what a reader working in a page rather than reading down one wants of the chrome above it · The destinations belong at the far end with what a reader reaches for, rather than centred over the page: the mark holds one edge, everything a reader does holds the other, and the middle is left empty on purpose | The page is the marketing site itself → `Navbar` · The items are versions of one thing rather than places the subdomain has → `TabList` |
75
+ | TabList | Two or three versions of one offer differ in a way a reader wants to compare — monthly against yearly, one platform against another · The page has already written every version, and showing them at once would be repetition rather than information · The reader's choice changes what they see and nothing else — no route, no account, nothing the page has to remember | The sections are separate topics rather than versions of one thing → `Accordion` · Every version is worth reading → `Card` · The tabs would go to other pages → nothing here |
76
+
77
+ ## Layout
78
+
79
+ Arrange other components and decide no appearance of their own.
80
+ | Component | Use when | Not for |
81
+ |---|---|---|
82
+ | AspectRatio | A picture whose proportions have to match the ones beside it — a row of cards, a grid of markets, a set of logos. One shape asked for once is what keeps a row from settling on whichever image is tallest · Room that must be reserved before the thing filling it arrives — art loaded late, an embed, anything fetched. The box is the right height from the first paint, so the page under it never moves · An embed that brings its own proportion and no height — a video, a map, a third-party frame. The ratio is the only way to give it one without guessing a pixel measure that is wrong at some width | The picture is the media region of a card → `CardBody` · The thing inside has a size of its own and should keep it → nothing here · The shape changes with the viewport → nothing here |
83
+ | Grid | Several things of the same kind are read across and down, and a cell has to line up with the cell above it — a field of stat cards, a set of tiles, a gallery · The count is more than a line holds and the page cannot say what width it will be read at. The floor decides when a column drops, so the page never names a breakpoint · The cells must finish level regardless of how much is in each. A grid row is as tall as its tallest cell and hands that height to the rest, which a wrapped line does not | The things sit on one line and there is no second row to agree with → `Row` · The things are read one above the next → `Stack` · The set must stay on one line and the reader moves along it → `Scroller` · The cells are the fields of one record, repeated down the page → `Table` |
84
+ | Row | Two or more things are read across rather than down, and the space between them is the same all the way along — a glyph and its label, a title and the action beside it, a set of controls · The spacing is a fact about the group rather than about any member of it. Set here, every item agrees; set on the items, the group is only as consistent as the last person to add one · The items are of different heights and something has to decide how they meet — centred on the line, level at the top, or sitting on one another's baseline. That decision belongs to the line rather than to any item on it | The things are read one above the next → `Stack` · The things must line up down the page as well as across it → `Grid` · The set is longer than the line and has to stay on one line → `Scroller` · The things across are the fields of one record, and the record repeats down the page → `Table` |
85
+ | Scroller | A set is longer than the space and its order is worth keeping — steps in a sequence, results already ranked, a timeline, a run of chips a reader is scanning rather than comparing · The things are of a kind and of a size, so a line of them reads as a line rather than as a row of unrelated objects that happen to be beside one another · Seeing part of the next item is what tells the reader there is more. A rail cut off mid-item is the affordance, and it is the one thing a wrapped line and a grid cannot offer | Everything fits, or should be made to fit → `Row` · The set may break onto a second line and nothing is lost by it → `Row` · The items should line up in columns as well → `Grid` · The region scrolls down rather than across → nothing here |
86
+ | Stack | Two or more things are read down the page in order and the space between them is the same the whole way down — an eyebrow, a headline and a line of copy; the points of a feature list; the rows of a plan · The spacing is a fact about the group rather than about any member of it. Set here, every row agrees; set on the rows, the group is only as consistent as the last person to add one · The measure should tighten on a phone without anyone writing a breakpoint. The top three steps of this ramp already do, so a column set at one of them is narrower below 768px and nothing about the page says so | The things sit beside one another rather than one above the next → `Row` · The things must line up across as well as down → `Grid` · The set has to stay on one line and the reader moves along it → `Scroller` |
package/.llm/rules.md ADDED
@@ -0,0 +1,122 @@
1
+ <!-- GENERATED from rules/*.rule.json. Do not edit. -->
2
+
3
+ # Rules
4
+
5
+ Constraints that span more than one component. Rules about a single component
6
+ also appear in that component's own document.
7
+
8
+ ## Always
9
+
10
+ ### On a phone a section's actions stack and each fills the width, including when there is only one
11
+
12
+ On a phone a page's actions stack, and each one fills the width. Not most of it, and not the width its label happens to need — the whole column.
13
+
14
+ Two side by side is what this replaces. On the narrowest screen each gets half a column minus the gap, which is rarely enough for a real label: the words wrap inside the pills, the two buttons come out different heights, and the pair reads as a broken row rather than as a choice. Stacked, each has the whole width and neither has to shorten its words to fit.
15
+
16
+ A single action fills too, and that is the part worth saying, because it is the one that looks unnecessary. A lone button has the room to sit at its natural width and still should not: a full-width control is the phone's convention for the thing the screen is asking you to do, and a pill hugging its label reads as one option among others that are not there. It also makes the target predictable — the whole width, wherever the thumb lands — which a centred pill does not.
17
+
18
+ Filling is the row's job rather than the button's. A button has no width of its own and is not given one; the row it sits in becomes a column and stretches its children, so nothing about the control changes and the same button is full width here and its own size on a desktop.
19
+
20
+ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that decides whether a heading is centred. Those are different questions and they break at different widths: a heading stops being centred when the measure is the screen, while a button stops being full width much sooner than that — stretched across a tablet it is a long way from its own label, and a label centred in a metre of pill is harder to hit than one in a pill the size of the words.
21
+
22
+ What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
23
+
24
+ Guidance only — cannot be checked automatically.
25
+
26
+ ### Never nest one interactive element inside another
27
+
28
+ Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link, Input and Switch simultaneously.
29
+
30
+ Guidance only — cannot be checked automatically.
31
+
32
+ ### A section that paints a ground sets the ink to go with it
33
+
34
+ A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
35
+
36
+ color.bg.brand carries a second limit that is not about forgetting. Its ink measures 3.39:1, which clears the 3:1 a heading needs and misses the 4.5:1 running copy needs. A coral band may carry a headline and a call to action; a paragraph on one is text the reader has to work through at a ratio the waiver on that role does not cover — the waiver says so itself. A section with copy in it takes color.bg.brand-strong, which is near-black and carries white at full contrast.
37
+
38
+ color.bg.strong is not a section ground. It is the inverted fill for an action that has to outrank what surrounds it, and the components that paint it — Button and ButtonIcon in their inverse form — already set both halves in one rule, which is the pattern a hand-painted section has to copy.
39
+
40
+ Guidance only — cannot be checked automatically.
41
+
42
+ ### Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side
43
+
44
+ A section's spacing is named by the relationship it expresses, not chosen by size. Every gap in a section has a role token, and reaching for a step off the generic scale because it happens to be the right number is how two sections written by two people stop lining up: the numbers agree today and drift the first time one of them is tuned.
45
+
46
+ The heading group is three steps, not one gap. An eyebrow sits nearer its title than the title sits to its description, and the actions sit further from the description than either — space.heading.eyebrow-title, space.heading.title-description, space.heading.description-actions, in that order. A single `gap` on the group cannot say this; it sets all three the same and the block reads as evenly spaced lines rather than as a mark, a name and a paragraph. The eyebrow has to identify itself for this to work, because a group that opens with a title must not give its description the eyebrow's tighter step.
47
+
48
+ The step between a title and its description follows the size of the title, which is why there are two of it. What a reader sees is not the gap but the gap plus the leading above it, and leading scales with the type: under a display title the leading is most of the space, under a card's title it is half as deep. One value for both makes a card look loose at the size that made a section look right. So space.heading.title-description is the display step and space.heading.title-description-compact is the step at a card's size, and the choice is made by how big the title is rather than by what kind of block it sits in.
49
+
50
+ Every one of those steps is smaller than the gap below the group, and that ordering is what holds the group together as one thing. space.heading.content is the step between a heading group and the content it introduces, and it is the widest measure inside a section: the one gap the eye reads as a change of subject rather than as a continuation.
51
+
52
+ That step is the same whether the content is under the heading or beside it. A split is the same relationship turned on its side — a heading group and the content it introduces — so the space between the two halves is space.heading.content, not a gutter. When the split collapses to one column on a phone the gap becomes vertical again, which is where it started, and nothing has to change for that to be right.
53
+
54
+ space.grid.gutter is between two things of the same kind. Two cards in a row are the same kind; the two halves of a split are not, which is why the gutter is the wrong measure there even when the number would have looked acceptable. The gutter runs on both axes, so a grid reads as an even field rather than as rows with a seam down them.
55
+
56
+ space.inset.card is the card's, not the page's. A row of cards padded differently is a row of different cards, and the fill is the only edge they have. A page composing a row does not get to choose it.
57
+
58
+ Column count is not a breakpoint decision. A row holds as many columns as fit before a column would be narrower than size.grid.column-min, and drops one when they would not. Written as a fixed count that collapses at a breakpoint, a four-up row keeps four columns at every width above the phone and sets its copy two or three words to a line through the whole of the tablet range — and on a narrow desktop, which no breakpoint sits on at all. The threshold is a property of the row rather than of a card: a card fills whatever cell it is given.
59
+
60
+ What this does not cover is the space above and below a section, which is space.section.default and space.section.compact, and the page's own side margin, which is space.inset.page. Those are the section's outside; everything here is its inside.
61
+
62
+ Guidance only — cannot be checked automatically.
63
+
64
+ ### A section's title is centred over stacked content, starts beside content in columns, and starts on a phone
65
+
66
+ Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
67
+
68
+ Content stacked under the title — a row of cards, an accordion, a set of steps — takes a centred title. The heading group and the block below it share one axis, so a centred title is symmetric with the thing it names, and the eye drops from the middle of the words to the middle of the set. A title starting at the left over a centred or full-width block reads as belonging to the first column rather than to all of them.
69
+
70
+ Content beside the title — a split, a picture in the other half, anything laid out in columns — takes a title that starts where its content starts. The two share a left edge, and that edge is what says they are one thing read across rather than two stacked. Centring the title there breaks the only alignment the reader has to hold the halves together, and it drifts further from its content the wider the page gets.
71
+
72
+ The heading group is what carries this, not the heading alone. An eyebrow, a title and a description are read as one block and align together; aligning the title without them leaves a centred heading over start-aligned copy, which reads as a mistake rather than as a choice.
73
+
74
+ Centred means all of it, not just the words. A badge, a row of actions, a picture — these are flex children, and a flex child is placed by align-items rather than by text-align, so a block that only sets the text leaves everything that is not text at the start. A hero is the case that shows it: its title and copy centred while its badge and its buttons did not.
75
+
76
+ A capped block centres itself as well as its words. A heading group takes size.heading-group.max, and a cap that is not centred leaves the measure at the start of the column with the words centred inside it — composed, and a long way left of the middle it appears to be in.
77
+
78
+ Both arrangements go to the start on a phone. A centred block reverts below the breakpoint, and the reason is the measure: on a phone the measure is the screen, so a centred title wraps to three or four ragged lines and the eye loses the left edge it was tracking — the same symmetry that reads as composure on a desktop is what makes it hard to scan on a phone. Centring there has to be asked for twice, and a section title is not one of the things that asks: it is centred because there is room for it, and on a phone there is not. Going back to the start means all of it too, and a capped block is the one that hides a leftover: its words go to the start while its measure stays in the middle of the column, which reads as a title still centred over a badge and buttons that are not — the box in the middle and the line inside it at the edge.
79
+
80
+ A hero is a section like any other: its badge, title, copy and actions are one stacked block, so it is centred on a desktop and starts on a phone with everything else.
81
+
82
+ What this is not about is a page whose body is a form or a document. A title over a sign-up form or a guide is not introducing a set of content — it is the first line of the thing itself, and it keeps the alignment the body has, which for running text is the start. The distinction is whether the block below is content the title names or content the title is part of.
83
+
84
+ Guidance only — cannot be checked automatically.
85
+
86
+ ### Anything a pointer has to hit is at least 24px in both directions
87
+
88
+ A control sized by its contents is as big as its contents, and a glyph is chosen for how it reads rather than for how easily it is hit. An icon-only button with no padding is a 16px target — smaller than the pad of a finger, and smaller than the tremor of a hand using a mouse.
89
+
90
+ WCAG 2.2 asks for 24 by 24 CSS pixels at AA. The exceptions are narrower than they look: inline targets inside a sentence are exempt, and so is a small target with 24px of clear space around it — but a clear button sits against the field it empties, and a field is itself a target, so the spacing exemption does not apply to the case that keeps arising.
91
+
92
+ The target and the mark are separate decisions, and conflating them is what produces both faults. Growing the glyph to 24px makes it shout; leaving the button at 16px makes it hard to hit. So the glyph keeps the size that reads correctly beside its text, and the box around it declares a minimum of its own — which is what size.target.min is for.
93
+
94
+ Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
95
+
96
+ Guidance only — cannot be checked automatically.
97
+
98
+ ## Component rules
99
+
100
+ ### Destructive actions require a confirmation step (`Button`) *(applies to something not built yet)*
101
+
102
+ An irreversible action taken by mis-click has no recovery path. The confirmation must name what will be lost, not merely ask whether the user is sure.
103
+
104
+ Guidance only — cannot be checked automatically.
105
+
106
+ ### Solid weight means selected (`Icon`) *(applies to something not built yet)*
107
+
108
+ Solid is not an alternative style, it is what a selected icon looks like. A tab or a navigation item renders regular at rest and swaps to solid when it becomes the current one, so the weight change is what carries the selection. The swap changes weight only — the same glyph at the same size, so the shape stays recognisable and just fills in. Marketing has fewer selected states than Product does, which is the reason to hold the meaning rather than to relax it: a solid glyph used decoratively here teaches a reader that solid means nothing, and they carry that into the product.
109
+
110
+ Guidance only — cannot be checked automatically.
111
+
112
+ ### Match the glyph weight to the icon size (`Icon`) *(applies to something not built yet)*
113
+
114
+ Quill ships every system glyph three times — light, regular and solid — as separate components chosen at the import site. Icon has no weight prop and cannot have one, so nothing in this system can observe the choice, let alone enforce it. Size is what should decide it: a glyph carries its stroke weight through any scale, so a regular-weight glyph drawn for 24px renders its strokes at over three times that width when placed at display size, and reads as heavy rather than confident. At rest, use regular from sm through lg, and light at xl, 2xl and display — selection is the one thing that overrides this, and it only ever moves regular to solid.
115
+
116
+ Guidance only — cannot be checked automatically.
117
+
118
+ ### At most one primary button per view (`Button`)
119
+
120
+ Two primary actions compete for attention; the user cannot tell which one the system wants them to take.
121
+
122
+ Machine-checkable — `dds lint` will enforce this once built.