@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,259 @@
1
+ <!-- GENERATED from card-button.contract.json. Do not edit. -->
2
+
3
+ # CardButton
4
+
5
+ A card that responds to a press. The whole surface is the target — a feature and where it leads, a market and its page, a plan and what it costs — so pressing anywhere on it does the thing, and what the thing is decides the element: an `<a>` when it is given an href, a `<button>` when it is not. One component rather than two, because a card that goes to a page and a card that opens something are the same gesture with different destinations, and the element is what tells a browser which.
6
+
7
+ ## Use when
8
+
9
+ - 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
10
+ - 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
11
+ - Pressing it opens something the page owns rather than leaving the page — a dialog, a video, a step in a sign-up
12
+
13
+ ## Do not use
14
+
15
+ - The card holds a control of its own as well → `Card`
16
+ - Nothing happens when it is pressed → `Card`
17
+ - A card containing a button, a link or a field. Every one of them is unreachable inside a button or an anchor, and the rule about it is the one rule in this system that cannot live on any single component
18
+ - An href to somewhere that does not exist. Given one this becomes a real anchor, so the destination has to be a place a reader could bookmark — an action dressed as a destination sends them nowhere and offers to open it in a tab
19
+ - A whole section of the page. A card stands for something else and points at it; a surface wrapping an entire band with an href on it is a page linking to itself
20
+ - Making a card feel lively. The lift under the pointer is what a control looks like, and putting it on something that does nothing teaches a reader that movement means nothing
21
+
22
+ ## Anatomy
23
+
24
+ CardButton renders one element.
25
+
26
+ - `root` — `<button>`, class `dds-cardbutton`. The surface, and the target. An `<a>` when given an href and a `<button>` when not, because a card that goes to a page and a card that opens a dialog are the same gesture and the element is what tells a browser which — one answers Space, the other answers cmd-click.
27
+
28
+ Everything Card's surface does, it does: the four grounds, the corner, `overflow: hidden` so a picture meets that corner, and no inset of its own. What it adds is that the whole of it is one target, and what it gives up is holding a control of its own.
29
+
30
+ It sets its own colour rather than letting it inherit, which the anchor makes necessary: a `<button>` takes the text colour around it and an `<a>` does not — it takes the browser's link blue, and every word in the card goes with it. So each ground names its ink here, exactly as Card does, and CardBody's regions inherit that.
31
+
32
+ The response to a pointer is movement rather than colour, and that is not a stylistic preference — it is the only thing that works on all four grounds at once. There is one hover fill in this package and it is a five-percent black: it darkens a white card, does almost nothing to the coral, and is invisible on the near-black. A movement says the same thing on every ground.
33
+
34
+ It rises rather than grows. A scale is what Product's card does and it was the first thing tried here, but it enlarges the type and the picture along with the surface, so the card is momentarily a different size from its neighbours in a row and the copy inside it is momentarily a different size from the copy beside it. A lift moves the whole card as one object and changes nothing about what is in it.
35
+
36
+ `motion.translate.hover` is a fixed distance rather than a share of the element, which matters for a card more than for most things: cards in a row are rarely the same height, and a proportional lift would raise the tall one further than the short one and break the line they sit on. Nothing reflows either way — a translate is painted, not laid out — so the cards around it do not move.
37
+
38
+ It takes `motion.duration.normal` to get there, which the scale reads oddly until you look at what each step is for: `fast` is the one named for hover, and it is named for the hover of a control that has somewhere to be — a toggle flipping, a button darkening. `normal` names card hover in as many words, because a card is a large object and a large object crossing a short distance in a hundred milliseconds does not read as rising, it reads as flicking. The distance is small enough that the extra hundred is still well inside the time a pointer rests.
39
+
40
+ `easing.standard` rather than `enter`, which is a distinction the scale is explicit about: `enter` is for something arriving on screen and this is already here, moving in place.
41
+
42
+ It lifts and does not give. There is no pressed state here on purpose: a return distance would be a second token, and a card that dipped under the press would be answering a question nobody has asked of this package yet.
43
+
44
+ And a floor in both directions, which being a control rather than a box is what makes necessary. A card is as big as what is in it, and what is in it is usually plenty — but nothing guarantees it, and a card holding one short line is a target smaller than the pad of a finger. `size.target.min` costs nothing to a card that is already bigger and catches the one that is not.
45
+
46
+ It holds one child. The wildcard beside `CardBody` in `allowedChildren` is older than that: it was there for a picture reaching the card's edges while the copy stayed inset, which was a second child until CardMedia folded into the body and became `src`. What the wildcard still buys is content that is not a body at all — a chart, a band of art — and there is still only ever one of it. Two bodies in one card is two padded stacks with a seam down the middle, which is a page composing a section rather than a card holding one. And a pressable card is one target: two of anything inside it asks which of them the press belonged to.
47
+
48
+ `plain` gives up three things the other four keep, and they are one decision rather than three: the fill, the corner that shape needs, and the lift. A filled card rises on hover as one object because it is one object — a ground with a corner, sitting on the page. Take the ground away and what is left to rise is a picture and some loose text, which reads as the words sliding rather than as a card lifting. So the translate is bound per variant on the four that have a fill, and the editorial card answers the pointer through its picture instead, with CardBody's `zoomOnHover`. The focus ring is unconditional and stays: the lift was decoration, and that is not.
49
+
50
+ There is a second rule beside that one, and the two are independent. This one is about the ground; the other is about the motion already present — a card whose body zooms does not lift either, whatever its fill, because two movements answering one hover read as a glitch rather than as emphasis. That rule cannot be bound: its condition is CardBody's prop, one level down, and neither a token binding nor a structural rule can name another component's axis. It is in the impl sheet as a `:has()` on this root, which reads the child without styling it — so an editorial card on `surface` keeps its fill and its corner and still holds still while its picture moves.
51
+
52
+ Apply these classes from the generated `cardButtonParts` constant rather than writing the strings by hand.
53
+
54
+ ## Composition
55
+
56
+ - Can contain: any content
57
+ - Never contains: `Card`, `CardButton`, `Breadcrumb`, `BreadcrumbItem` — in children or in any prop that takes a node
58
+ - Holds at least 1 and at most 1
59
+
60
+ ## Props
61
+
62
+ ### variant — `surface` | `surface-raised` | `accent` | `accent-strong` | `plain` (default `surface`)
63
+
64
+ - `surface` — The default, and right for a pressable card on the page. The same recessed step off the white page that Card takes, so a row mixing pressable and plain cards reads as one row
65
+ - `surface-raised` — The card sits on a color.bg.subtle band rather than on the page, where the recessed fill all but disappears and this one lifts off the band instead
66
+ - `accent` — One card in a set is the promotional one and the page has already earned the colour
67
+ - `accent-strong` — A card carrying more weight than its neighbours. The darkest of the four, and the one that takes white at 20.55:1 — the most legible ground a marketing card has
68
+ - `plain` — An editorial card that goes somewhere — an article, a post, a release note. No fill, no corner and no lift: what marks it out is its picture and the gap to the next one, the way a column of articles is told apart on a page rather than the way a row of tiles is. The same ground Card's own plain variant takes, so a pressable article card and a static one sit in one column without a seam
69
+
70
+ ### href — `string`
71
+
72
+ Use when: The press goes somewhere with a URL of its own. It makes this an anchor rather than a button, which is what gives a reader cmd-click, a visible destination and a copyable link — none of which mean anything for a press that opens a dialog. This is the ordinary case on a marketing page, where most cards point at a page
73
+ Never for: A press the page handles itself. An anchor with an href nothing can navigate to is a promise the browser will try to keep
74
+
75
+ Also accepts everything from `ButtonHTMLAttributes<HTMLButtonElement>`.
76
+
77
+ ## Accessibility
78
+
79
+ Guaranteed by the component. Write none of it by hand: the ids these attributes point at are generated per instance, so an attribute set from outside either says the same thing twice or points at nothing.
80
+
81
+ - Announced as: `button`
82
+ - `Tab` — move focus. One stop, on the card itself, because the card is the target — there is nothing inside it that takes focus, which is what forbidding controls in it buys
83
+ - `Enter` — press it. A button and an anchor both answer Enter, so this reads the same either way
84
+ - `Space` — press it, where it is a button. An anchor does not answer Space, and that difference belongs to the element rather than to this component — a reader who knows the difference is told which by how it was announced
85
+ - What the card is for is readable from its own words. A card announced as a link or a button with nothing in it but a picture has no accessible name, so the title inside it is what names it — which is why the body's title is a heading rather than a styled line.
86
+ - Nothing inside it takes focus. A button, a link or a field within this is unreachable to a keyboard and ambiguous to a pointer, and a card needing both a press and its own control is a Card with the control inside it.
87
+
88
+ ## Rules
89
+
90
+ - **On a phone a section's actions stack and each fills the width, including when there is only one** — 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.
91
+
92
+ 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.
93
+
94
+ 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.
95
+
96
+ 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.
97
+
98
+ 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.
99
+
100
+ 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.
101
+ Guidance only — cannot be checked automatically.
102
+ - **Never nest one interactive element inside another** — 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.
103
+ Guidance only — cannot be checked automatically.
104
+ - **A section that paints a ground sets the ink to go with it** — 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.
105
+
106
+ 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.
107
+
108
+ 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.
109
+ Guidance only — cannot be checked automatically.
110
+ - **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side** — 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.
111
+
112
+ 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.
113
+
114
+ 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.
115
+
116
+ 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.
117
+
118
+ 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.
119
+
120
+ 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.
121
+
122
+ 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.
123
+
124
+ 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.
125
+
126
+ 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.
127
+ Guidance only — cannot be checked automatically.
128
+ - **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone** — Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
129
+
130
+ 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.
131
+
132
+ 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.
133
+
134
+ 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.
135
+
136
+ 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.
137
+
138
+ 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.
139
+
140
+ 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.
141
+
142
+ 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.
143
+
144
+ 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.
145
+ Guidance only — cannot be checked automatically.
146
+ - **Anything a pointer has to hit is at least 24px in both directions** — 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.
147
+
148
+ 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.
149
+
150
+ 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.
151
+
152
+ 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.
153
+ Guidance only — cannot be checked automatically.
154
+
155
+ ## Anti-examples
156
+
157
+ ❌ CardButton for: The card holds a control of its own as well
158
+ A button inside a button, or inside an anchor, is what no-nested-interactive refuses — and a card with its own 'Get started' in it is exactly that. Use a Card and put the control inside it: the card is then a box holding something pressable rather than being it
159
+ → use `Card` instead.
160
+
161
+ ❌ CardButton for: Nothing happens when it is pressed
162
+ This takes focus, sits in the tab order and announces itself as a control. A card that merely wants a hover flourish and does nothing is a trap for anybody moving through the page by keyboard, who arrives somewhere that will not answer them
163
+ → use `Card` instead.
164
+
165
+ ❌ variant=plain + state=hover
166
+ The editorial card does not move under the cursor, and this is the declaration of that rather than an omission. The other four variants lift, which works because each is one object — a ground with a corner, sitting on the page. plain has no ground, so what would rise is a picture and some loose text, and that reads as the words sliding rather than as a card lifting.
167
+
168
+ What answers the pointer instead is the picture, through CardBody's zoomOnHover, and it has to live there because the picture is that component's part. Bound here as a no-op — scale at motion.scale.none — it would have been worse than nothing: a rule of the same specificity as the four lifts, later in the file, ranked by the cascade for no reason. Focus is untouched and stays unconditional: the lift was decoration and the ring is not.
169
+
170
+ This covers plain alone. A filled variant whose body zooms also stops lifting, but that is not an unbound cell — the binding is there and a `:has()` rule in the impl sheet overrides it, which is why it needs no exemption here.
171
+
172
+ ## Example
173
+
174
+ ```tsx
175
+ import { CardButton, CardBody } from '@deriv-com/dds-marketing'
176
+
177
+ <CardButton href="/markets/forex">
178
+ <CardBody title="Forex" description="Trade the world's most liquid market, around the clock." />
179
+ </CardButton>
180
+ ```
181
+
182
+ ## In use
183
+
184
+ ### The element follows the destination
185
+
186
+ href decides what this is. An anchor gives cmd-click, a visible destination and a copyable link; a button answers Space and does what the page says. One gesture, two destinations.
187
+
188
+ ```tsx
189
+ import { CardBody, CardButton } from '@deriv-com/dds-marketing'
190
+
191
+ // With href — an anchor, and a real destination
192
+ <CardButton href="/markets/forex">
193
+ <CardBody title="Forex" description="Trade the world's most liquid market." />
194
+ </CardButton>
195
+
196
+ // Without href — a button the page handles
197
+ <CardButton>
198
+ <CardBody title="Watch the tour" description="Two minutes on how the platform works." />
199
+ </CardButton>
200
+ ```
201
+
202
+ ### The four grounds, all pressable
203
+
204
+ The same grounds Card offers, so a row mixing pressable and plain cards reads as one row. The response to a pointer is movement rather than colour, which is the only thing that works on all four.
205
+
206
+ ```tsx
207
+ import { CardBody, CardButton } from '@deriv-com/dds-marketing'
208
+
209
+ // surface — on the page
210
+ <CardButton variant="surface" href="/markets">
211
+ <CardBody title="Tight spreads" description="Competitive pricing on every market." />
212
+ </CardButton>
213
+
214
+ // surface-raised — on a subtle band
215
+ <CardButton variant="surface-raised" href="/markets/indices">
216
+ <CardBody title="Indices" description="Track the world’s major markets in one place." />
217
+ </CardButton>
218
+
219
+ // accent — the promotional one
220
+ <CardButton variant="accent" href="/signup">
221
+ <CardBody title="Open an account" description="It takes about three minutes." />
222
+ </CardButton>
223
+
224
+ // accent-strong — carrying more weight
225
+ <CardButton variant="accent-strong" href="/pro">
226
+ <CardBody title="Deriv Pro" description="Institutional pricing and dedicated support." />
227
+ </CardButton>
228
+ ```
229
+
230
+ ### A picture that answers the pointer
231
+
232
+ The card clips, so the picture grows inside its frame rather than spilling. The root lifts and the picture lifts with it, so the picture moves about twice as far — one token, compounded.
233
+
234
+ ```tsx
235
+ import { CardBody, CardButton } from '@deriv-com/dds-marketing'
236
+
237
+ // Hover it — the picture pushes into the crop
238
+ <CardButton href="/markets/commodities">
239
+ <CardBody title="Commodities" description="Gold, oil and more, with tight spreads." src="/sample-card-image.svg" alt="" />
240
+ </CardButton>
241
+ ```
242
+
243
+ ### It zooms instead of lifting
244
+
245
+ An editorial card zooms its picture and does not lift, on any ground. CardButton drops its own lift whenever the body it holds zooms — one motion per gesture, whichever variant is under it.
246
+
247
+ ```tsx
248
+ import { CardBody, CardButton } from '@deriv-com/dds-marketing'
249
+
250
+ // plain — no ground to lift; the picture moves
251
+ <CardButton variant="plain" href="/news/banking-hall">
252
+ <CardBody flush zoomOnHover src="/sample-card-image.svg" alt="The entrance to a bank, seen from street level." mediaPosition="above" aspect={1.7777777777777777} eyebrow="14 August 2026" title="A bank can bank your IPO and still refuse your account" />
253
+ </CardButton>
254
+
255
+ // surface — a fill, and still no lift while it zooms
256
+ <CardButton variant="surface" href="/news/banking-hall">
257
+ <CardBody zoomOnHover src="/sample-card-image.svg" alt="The entrance to a bank, seen from street level." mediaPosition="above" aspect={1.7777777777777777} eyebrow="14 August 2026" title="A bank can bank your IPO and still refuse your account" />
258
+ </CardButton>
259
+ ```
@@ -0,0 +1,285 @@
1
+ <!-- GENERATED from checkbox.contract.json. Do not edit. -->
2
+
3
+ # Checkbox
4
+
5
+ Records a single on-or-off choice that is submitted with the form around it rather than applied the moment it is ticked.
6
+
7
+ ## Use when
8
+
9
+ - A choice the user makes now and confirms later — the form's Save or Continue is what applies it
10
+ - Agreeing to something before proceeding — terms, a risk disclosure, a confirmation the user must actively give
11
+ - One of several independent choices, each of which can be on or off without affecting the others
12
+
13
+ ## Do not use
14
+
15
+ - Choosing exactly one option from a short set, where picking one unpicks the others → `SegmentedControl`
16
+ - Performing an action rather than recording a choice → `Button`
17
+ - A setting that takes effect the moment it is ticked. A checkbox is a value the form around it submits, and one that applied immediately would misreport itself — the reader looks for Save, finds nothing waiting, and cannot tell whether the change took. Marketing has no immediate-apply toggle to send them to
18
+ - Destructive or irreversible changes — a checkbox is a value in a form, and a tick is not a confirmation step
19
+ - A choice the user cannot see the label of. The label is required and always rendered: a bare box states nothing about what ticking it agrees to
20
+
21
+ ## Anatomy
22
+
23
+ Checkbox renders 9 elements. A token binding names the part it applies to.
24
+
25
+ - `root` — `<div>`, class `dds-checkbox`. The whole control: the row a pointer aims at, and whatever the field has to report under it. A column rather than the row it used to be — the status message is about the field and not about its words, so it starts where the box starts instead of indenting to the label, which is where a set would put its own. Carries the tone, checked, status and disabled attributes, which is what lets every part below respond to them. Its structural keywords are the contract's own staticCss rather than a part-level one, which is where the root's always belong.
26
+ - `control` — `<div>`, class `dds-checkbox__control`. The row a pointer aims at: the box and the words that name it. Named `control` for the same reason TextInput's box is — it is the part a reader operates, as against the message about it. Where the box sits against those words is the one thing about this part the contract does not decide: it is aligned to the start of the cross axis here, which is right when the label wrapped, and checkbox-impl.css centres it instead when there is a description, which is right when the second line belongs to the first. That rule needs to ask whether a part exists, which a token binding cannot, and it says so in its own header.
27
+ - `box` — `<span>`, class `dds-checkbox__box`. The square the user sees, and the only part that reports the state — its fill, its border and what sits inside it. A span rather than the input itself because the tick has to live inside the box, and an <input> is void: it can hold no child. The positioning context for the field that covers it. Its corner is radius.control.sm where product's is radius.subtle, and the difference is the role rather than the decision: marketing's subtle step is twelve where product's is eight, deliberately, so the rest of its ramp sits a step above. Twelve on a twenty-pixel square is past half its width, which draws the box as a circle — a checkbox shaped like a radio button. Eight is the only step this ramp has below half, and the box is a control, which is what that role names. Retuning subtle instead would have moved breadcrumb, link and tooltip for one box. Its unticked fill is color.bg.surface-raised, where product's box paints color.bg.transparent and lets whatever contains it show through. Both answer the same question — a box has to be told apart from the surface under it — and this package answers it with the white raised ground, because its surface is the grey one a card is recessed into.
28
+ - `field` — `<input>`, class `dds-checkbox__field`. The real control — a native checkbox, covering the box exactly and invisible over it. Invisible rather than absent: this is what submits with the form, what the keyboard reaches, what carries the native indeterminate property, and what :focus-visible and :disabled are answered from. Every state the box and the label draw is read off this element through :has().
29
+ - `indicator` — `<span>`, class `dds-checkbox__indicator`. What the box says: a tick when checked, a dash when indeterminate, nothing when neither. Takes its colour from a binding here rather than from the glyph, so the shape and what colours it stay separate. Decorative to a screen reader — the input's own state already announces it, and hearing both says it twice.
30
+ - `text` — `<div>`, class `dds-checkbox__text`. Stacks the label and whatever is said under it. An element of its own because the root lays the box beside the words in a row, and a description added without it would be a third item in that row rather than a second line under the label. Rendered even with nothing to stack, so the box meets the same box either way and a checkbox does not shift sideways the moment it gains a second line. No gap between the two lines, deliberately: body.md and body.sm both carry a line-height above one, so the half-leading either side of them already separates the label from the description, and a space.gap.xs on top of that read as more room than the space.gap.sm between one control and the next.
31
+ - `label` — `<label>`, class `dds-checkbox__label`. States what ticking the box agrees to. Always rendered — a checkbox whose label is optional is a checkbox that ships bare. Tied to the field by htmlFor, which is what makes the text itself a target: the box on its own is a small square, and the words beside it are most of what a user actually aims at.
32
+
33
+ It can be clipped rather than removed, and the difference is the whole of why the prop is not called `label: false`. A box that summarises a set is the case: the select-all in a table's header sits over a column of boxes and takes its meaning from the column, so drawing "Select all" beside it puts body-sized words in a row of column names — a control shouting where the names are eleven pixels. Clipped, the name is still there for anyone who cannot see the column, which is the half that matters.
34
+ - `description-text` — `<span>`, class `dds-checkbox__description-text`. What ticking the box commits the user to, under the label it belongs to. Quieter than the label and smaller, so a column of checkboxes still scans as a list of choices rather than as a list of paragraphs. Named as the field's description rather than as part of its label, because a screen reader should reach it after the thing it qualifies rather than folded into its name. Rendered only when `description` is set.
35
+ - `message` — `<span>`, class `dds-checkbox__message`. The glyph for the status and what the status means, in the colour of the status. The glyph takes that colour from the text beside it rather than binding one, and is decorative to a screen reader because the words say the same thing — its shape is what separates an error from a warning for a reader who cannot tell those two colours apart. Sits under the whole control rather than inside the words, so it lines up with the box rather than with the words — it reports on the field, and a message indented to the label read as a third line of the label. Stacks under the description rather than replacing it: a description says what ticking the box commits you to and a message says what is wrong with the answer, so they are not two ways of filling one slot. A success status may be silent — the contract requires a message only for an error or a warning. Rendered only when `status` is set.
36
+
37
+ Apply these classes from the generated `checkboxParts` constant rather than writing the strings by hand.
38
+
39
+ ## Composition
40
+
41
+ - Takes no children. Everything it renders comes from props
42
+ - Never contains: `Button`, `TextInput` — in children or in any prop that takes a node
43
+
44
+ ## Props
45
+
46
+ ### tone — `standard` | `accent` (default `standard`)
47
+
48
+ - `standard` — The default, and almost always right — the ticked box fills with the neutral that outranks everything around it, so the choice is legible before any colour is read and it is the fill every other chosen control in this package takes, which is what lets a form of them read as one set of answers
49
+ - `accent` — The checkbox is the brand moment of the view — a single consent the design is deliberately drawing the eye to — and the surrounding design already carries brand red
50
+
51
+ ### checked — `unchecked` | `checked` | `indeterminate` (default `unchecked`)
52
+
53
+ - `unchecked` — The default — the choice has not been made, or has been made against
54
+ - `checked` — The user has made this choice, or it arrives pre-made and they may change it
55
+ - `indeterminate` — A box that summarises others, where some but not all of them are ticked — a Select all above a partly selected list
56
+ Never for: A pending or loading state. Indeterminate means partly chosen, not not-yet-known, and a user who ticks it expects the group to follow
57
+
58
+ ### status — `none` | `error` | `warning` | `success` (default `none`)
59
+
60
+ - `none` — The default — the choice has not been judged, or it passed and there is nothing to say
61
+ - `error` — The box had to be ticked and was not, or what ticking it asks for is not accepted
62
+ - `warning` — The choice is accepted but has a consequence the user should see before submitting
63
+ - `success` — The choice was checked against something and passed, and confirming that is worth the room
64
+ Never for: A box in a set where something above it already asks the question and reports the error. The message answers for the whole set, and a box repeating it states the same failure twice. This prop is for the box that stands alone, which is the case a group cannot cover: a single consent has nothing above it to carry the error. Also never for guidance shown before the user has answered, which is what description is for
65
+
66
+ ### label — `string` **Required.**
67
+
68
+ Use when: Always — it states what ticking the box agrees to, and the box shows nothing on its own. A phrase the user can read as a claim they are agreeing with: "Send me trade confirmations", not "Confirmations". Sentence case, and no full stop — a label is a phrase rather than a sentence, and a stop at the end of one reads as the start of prose. In a set, phrase every box the same way, so a reader compares the answers rather than the grammar
69
+ Never for: The consequence or the rule, which belongs beside the form rather than inside the choice — a label that explains has stopped naming the thing being agreed to, and there is a description for what it was trying to say. Never phrased as an opt-out either: ticking a box means yes, so "Do not send me email" makes a ticked box a double negative and leaves the user working out which way round it is
70
+
71
+ ### showLabel — `boolean` (default `true`)
72
+
73
+ Use when: Drawing the words, which is nearly always. A checkbox on its own is a question, and a question with no words is not one
74
+ Never for: Deciding whether the box has a label. It always has one and it is always announced — this only says whether the label is drawn. Off is clipped, not removed, so a screen reader still reads it
75
+
76
+ ### description — `string`
77
+
78
+ Use when: Ticking the box commits the user to something the label cannot carry without becoming a sentence — what it costs, how often it happens, what it applies to. On a box that summarises others it is where the summary belongs: "Four of six are on" says what an indeterminate tick cannot
79
+ Never for: Guidance about the form as a whole, or the rule behind the choice, which belongs beside the form rather than under one of its controls. A note repeated under every box is describing the set, and putting it on one of them says it is true of that one only
80
+
81
+ ### statusMessage — `string` **Required when status=error, or when status=warning.**
82
+
83
+ Use when: Whenever the status is an error or a warning — the words are what the user acts on, and the colour alone is not available to everyone
84
+ Never for: Restating the label. The message says what happened and what to do, not what the choice was
85
+
86
+ Also accepts everything from `InputHTMLAttributes<HTMLInputElement>`.
87
+
88
+ ## States
89
+
90
+ States you set. Everything else is driven by the browser.
91
+
92
+ - `disabled` — The choice cannot be made from here — a term the user's account has already accepted, or an option their plan does not offer
93
+ Avoid when: The choice is merely unticked, which is what the unchecked state is for
94
+
95
+ ## Accessibility
96
+
97
+ Guaranteed by the component. Write none of it by hand: the ids these attributes point at are generated per instance, so an attribute set from outside either says the same thing twice or points at nothing.
98
+
99
+ - Announced as: `checkbox`
100
+ - `Space` — toggle
101
+ - `Tab` — move focus
102
+ - a programmatically associated label
103
+ - the mixed state carried on the input's native indeterminate property, never as aria-checked="mixed". A native checkbox already announces mixed from that property; a second declaration can desync from it and override it. Not verifiable in a DOM here — indeterminate is a property rather than an attribute, so nothing in the tree records it
104
+ - aria-describedby pointing at the description, so what ticking the box commits the user to is heard after the choice rather than folded into its name
105
+ - aria-invalid on the field while the status is an error, so a reader is told the box is the problem rather than only shown it in red
106
+
107
+ ## Rules
108
+
109
+ - **On a phone a section's actions stack and each fills the width, including when there is only one** — 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.
110
+
111
+ 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.
112
+
113
+ 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.
114
+
115
+ 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.
116
+
117
+ 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.
118
+
119
+ 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.
120
+ Guidance only — cannot be checked automatically.
121
+ - **Never nest one interactive element inside another** — 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.
122
+ Guidance only — cannot be checked automatically.
123
+ - **A section that paints a ground sets the ink to go with it** — 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.
124
+
125
+ 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.
126
+
127
+ 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.
128
+ Guidance only — cannot be checked automatically.
129
+ - **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side** — 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.
130
+
131
+ 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.
132
+
133
+ 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.
134
+
135
+ 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.
136
+
137
+ 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.
138
+
139
+ 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.
140
+
141
+ 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.
142
+
143
+ 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.
144
+
145
+ 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.
146
+ Guidance only — cannot be checked automatically.
147
+ - **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone** — Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
148
+
149
+ 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.
150
+
151
+ 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.
152
+
153
+ 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.
154
+
155
+ 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.
156
+
157
+ 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.
158
+
159
+ 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.
160
+
161
+ 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.
162
+
163
+ 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.
164
+ Guidance only — cannot be checked automatically.
165
+ - **Anything a pointer has to hit is at least 24px in both directions** — 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.
166
+
167
+ 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.
168
+
169
+ 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.
170
+
171
+ 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.
172
+ Guidance only — cannot be checked automatically.
173
+
174
+ ## Anti-examples
175
+
176
+ ❌ Checkbox for: Choosing exactly one option from a short set, where picking one unpicks the others
177
+ Checkboxes are independent by construction — nothing about a row of them says only one may be on, and enforcing it in the consumer's handler leaves the control lying about what it allows. The row is for two to four alternatives shown at once; a longer set of exclusive choices has no control here yet
178
+ → use `SegmentedControl` instead.
179
+
180
+ ❌ Checkbox for: Performing an action rather than recording a choice
181
+ A checkbox describes a value the form will carry; an action that happens on press is a button
182
+ → use `Button` instead.
183
+
184
+ ❌ status=error + statusMessage missing or empty
185
+ An error with no explanation leaves the user stuck
186
+
187
+ ❌ status=warning + statusMessage missing or empty
188
+ A warning with no explanation is a choice the user cannot act on
189
+
190
+ ## Example
191
+
192
+ ```tsx
193
+ import { Checkbox } from '@deriv-com/dds-marketing'
194
+
195
+ <Checkbox label="Send me product updates and market insights" checked="unchecked" />
196
+ ```
197
+
198
+ ```tsx
199
+ import { useState } from 'react'
200
+ import { Checkbox } from '@deriv-com/dds-marketing'
201
+
202
+ // Controlled: Checkbox reports the DOM event, so the value is read off it.
203
+ // Unlike AmountInput and SearchInput, which declare an onChange that hands back the
204
+ // value itself — the two shapes look the same at the call site and are not.
205
+ const [value, setValue] = useState('')
206
+ <Checkbox label="Send me product updates and market insights" checked="unchecked" value={value} onChange={(event) => setValue(event.target.value)} />
207
+ ```
208
+
209
+ ## In use
210
+
211
+ ### States
212
+
213
+ The three values a checkbox can hold. Indeterminate is not a choice the reader picks — it is what a summary box shows when the boxes under it disagree.
214
+
215
+ ```tsx
216
+ import { Checkbox } from '@deriv-com/dds-marketing'
217
+
218
+ // Not chosen
219
+ <Checkbox label="Send me product updates and market insights" checked="unchecked" />
220
+
221
+ // Chosen
222
+ <Checkbox label="Send me product updates and market insights" checked="checked" />
223
+
224
+ // Summarising a partly chosen group
225
+ <Checkbox label="All email preferences" checked="indeterminate" description="Three of the five below are on" />
226
+ ```
227
+
228
+ ### What ticking it commits you to
229
+
230
+ A description carries what the label cannot without becoming a sentence — how often something arrives, or what it applies to.
231
+
232
+ ```tsx
233
+ import { Checkbox } from '@deriv-com/dds-marketing'
234
+
235
+ // The choice, and how often it acts
236
+ <Checkbox label="Send me product updates" description="About one a month, unsubscribe any time" checked="checked" />
237
+
238
+ // Described, and not on offer
239
+ <Checkbox label="Send me updates by SMS" description="Not available in your region" checked="unchecked" disabled />
240
+ ```
241
+
242
+ ### A consent that has to be given
243
+
244
+ The case a lone box owns and a group cannot: there is nothing above it to carry the error, so the box reports its own.
245
+
246
+ ```tsx
247
+ import { Checkbox } from '@deriv-com/dds-marketing'
248
+
249
+ // Submitted without the consent, and told so
250
+ <Checkbox label="I accept the Terms of Use and the Privacy Policy" checked="unchecked" status="error" statusMessage="Accept the terms to create your account" />
251
+
252
+ // Given, with a consequence worth seeing
253
+ <Checkbox label="Share my activity with partner sites" checked="checked" status="warning" statusMessage="Partners may contact you about their own products" />
254
+
255
+ // Checked against something, and it passed
256
+ <Checkbox label="I accept the Terms of Use and the Privacy Policy" checked="checked" status="success" statusMessage="Consent recorded" />
257
+ ```
258
+
259
+ ### Tone
260
+
261
+ Standard suits every form. Accent is for the one box a page is deliberately drawing the eye to, and is worth spending once rather than down a column.
262
+
263
+ ```tsx
264
+ import { Checkbox } from '@deriv-com/dds-marketing'
265
+
266
+ // Standard, the default
267
+ <Checkbox label="Send me product updates and market insights" checked="checked" />
268
+
269
+ // Accent, for a deliberate brand moment
270
+ <Checkbox label="I accept the Terms of Use and the Privacy Policy" checked="checked" tone="accent" />
271
+ ```
272
+
273
+ ### Unavailable
274
+
275
+ A choice that cannot be made from here. Disabled says the control is inert — not that the answer is no, which is what an unticked box says.
276
+
277
+ ```tsx
278
+ import { Checkbox } from '@deriv-com/dds-marketing'
279
+
280
+ // Already given, and not withdrawable here
281
+ <Checkbox label="I accept the Terms of Use and the Privacy Policy" checked="checked" disabled />
282
+
283
+ // Not offered in this region
284
+ <Checkbox label="Send me updates by SMS" checked="unchecked" disabled />
285
+ ```