@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.
- package/.llm/components/accordion.md +193 -0
- package/.llm/components/accordionitem.md +236 -0
- package/.llm/components/aspectratio.md +212 -0
- package/.llm/components/badge.md +231 -0
- package/.llm/components/bottomsheet.md +404 -0
- package/.llm/components/breadcrumb.md +197 -0
- package/.llm/components/breadcrumbitem.md +178 -0
- package/.llm/components/button.md +271 -0
- package/.llm/components/buttonicon.md +313 -0
- package/.llm/components/card.md +313 -0
- package/.llm/components/cardbody.md +409 -0
- package/.llm/components/cardbutton.md +259 -0
- package/.llm/components/checkbox.md +285 -0
- package/.llm/components/divider.md +230 -0
- package/.llm/components/dropdownmenu.md +453 -0
- package/.llm/components/filterchip.md +314 -0
- package/.llm/components/footer.md +408 -0
- package/.llm/components/footergroup.md +241 -0
- package/.llm/components/grid.md +659 -0
- package/.llm/components/icon.md +194 -0
- package/.llm/components/link.md +354 -0
- package/.llm/components/menuitem.md +218 -0
- package/.llm/components/navbar.md +458 -0
- package/.llm/components/navbaritem.md +238 -0
- package/.llm/components/navbarmenu.md +319 -0
- package/.llm/components/navbarmenugroup.md +184 -0
- package/.llm/components/navbarpanel.md +255 -0
- package/.llm/components/navbarswitcher.md +343 -0
- package/.llm/components/navbarswitcheroption.md +156 -0
- package/.llm/components/option.md +268 -0
- package/.llm/components/pagination.md +361 -0
- package/.llm/components/removablechip.md +247 -0
- package/.llm/components/row.md +381 -0
- package/.llm/components/scroller.md +470 -0
- package/.llm/components/searchinput.md +279 -0
- package/.llm/components/segmentedcontrol.md +358 -0
- package/.llm/components/segmentedcontrolitem.md +272 -0
- package/.llm/components/select.md +509 -0
- package/.llm/components/selectchip.md +334 -0
- package/.llm/components/spinner.md +222 -0
- package/.llm/components/stack.md +334 -0
- package/.llm/components/statusdot.md +205 -0
- package/.llm/components/subdomainnavbar.md +327 -0
- package/.llm/components/tab.md +291 -0
- package/.llm/components/table.md +660 -0
- package/.llm/components/tablebody.md +258 -0
- package/.llm/components/tablecell.md +248 -0
- package/.llm/components/tablehead.md +248 -0
- package/.llm/components/tableheadercell.md +298 -0
- package/.llm/components/tablerow.md +285 -0
- package/.llm/components/tablist.md +210 -0
- package/.llm/components/textarea.md +362 -0
- package/.llm/components/textinput.md +467 -0
- package/.llm/components/tooltip.md +267 -0
- package/.llm/components/typography.md +245 -0
- package/.llm/digest/accordion.md +43 -0
- package/.llm/digest/accordionitem.md +47 -0
- package/.llm/digest/aspectratio.md +47 -0
- package/.llm/digest/badge.md +45 -0
- package/.llm/digest/bottomsheet.md +69 -0
- package/.llm/digest/breadcrumb.md +38 -0
- package/.llm/digest/breadcrumbitem.md +43 -0
- package/.llm/digest/button.md +48 -0
- package/.llm/digest/buttonicon.md +61 -0
- package/.llm/digest/card.md +50 -0
- package/.llm/digest/cardbody.md +68 -0
- package/.llm/digest/cardbutton.md +49 -0
- package/.llm/digest/checkbox.md +63 -0
- package/.llm/digest/divider.md +52 -0
- package/.llm/digest/dropdownmenu.md +67 -0
- package/.llm/digest/filterchip.md +68 -0
- package/.llm/digest/footer.md +57 -0
- package/.llm/digest/footergroup.md +42 -0
- package/.llm/digest/grid.md +62 -0
- package/.llm/digest/icon.md +45 -0
- package/.llm/digest/link.md +59 -0
- package/.llm/digest/menuitem.md +46 -0
- package/.llm/digest/navbar.md +60 -0
- package/.llm/digest/navbaritem.md +54 -0
- package/.llm/digest/navbarmenu.md +54 -0
- package/.llm/digest/navbarmenugroup.md +40 -0
- package/.llm/digest/navbarpanel.md +53 -0
- package/.llm/digest/navbarswitcher.md +51 -0
- package/.llm/digest/navbarswitcheroption.md +37 -0
- package/.llm/digest/option.md +54 -0
- package/.llm/digest/pagination.md +71 -0
- package/.llm/digest/removablechip.md +51 -0
- package/.llm/digest/row.md +60 -0
- package/.llm/digest/scroller.md +59 -0
- package/.llm/digest/searchinput.md +56 -0
- package/.llm/digest/segmentedcontrol.md +59 -0
- package/.llm/digest/segmentedcontrolitem.md +59 -0
- package/.llm/digest/select.md +92 -0
- package/.llm/digest/selectchip.md +68 -0
- package/.llm/digest/spinner.md +52 -0
- package/.llm/digest/stack.md +56 -0
- package/.llm/digest/statusdot.md +46 -0
- package/.llm/digest/subdomainnavbar.md +54 -0
- package/.llm/digest/tab.md +60 -0
- package/.llm/digest/table.md +71 -0
- package/.llm/digest/tablebody.md +49 -0
- package/.llm/digest/tablecell.md +55 -0
- package/.llm/digest/tablehead.md +50 -0
- package/.llm/digest/tableheadercell.md +65 -0
- package/.llm/digest/tablerow.md +56 -0
- package/.llm/digest/tablist.md +46 -0
- package/.llm/digest/textarea.md +78 -0
- package/.llm/digest/textinput.md +95 -0
- package/.llm/digest/tooltip.md +58 -0
- package/.llm/digest/typography.md +59 -0
- package/.llm/index.md +86 -0
- package/.llm/rules.md +122 -0
- package/.llm/tokens.md +341 -0
- package/AGENTS.md +164 -0
- package/LICENSE +21 -0
- package/README.md +63 -15
- package/dist/components/core/accordion/Accordion.css +10 -0
- package/dist/components/core/accordion/Accordion.d.ts +20 -0
- package/dist/components/core/accordion/Accordion.js +69 -0
- package/dist/components/core/accordion/Accordion.types.d.ts +20 -0
- package/dist/components/core/accordion/Accordion.types.js +7 -0
- package/dist/components/core/accordion-item/AccordionItem.css +98 -0
- package/dist/components/core/accordion-item/AccordionItem.d.ts +44 -0
- package/dist/components/core/accordion-item/AccordionItem.js +63 -0
- package/dist/components/core/accordion-item/AccordionItem.types.d.ts +32 -0
- package/dist/components/core/accordion-item/AccordionItem.types.js +13 -0
- package/dist/components/core/accordion-item/accordion-item-impl.css +107 -0
- package/dist/components/core/badge/Badge.css +37 -0
- package/dist/components/core/badge/Badge.d.ts +37 -0
- package/dist/components/core/badge/Badge.js +40 -0
- package/dist/components/core/badge/Badge.types.d.ts +24 -0
- package/dist/components/core/badge/Badge.types.js +8 -0
- package/dist/components/core/badge/badge-impl.css +32 -0
- package/dist/components/core/bottom-sheet/BottomSheet.css +178 -0
- package/dist/components/core/bottom-sheet/BottomSheet.d.ts +22 -0
- package/dist/components/core/bottom-sheet/BottomSheet.js +359 -0
- package/dist/components/core/bottom-sheet/BottomSheet.types.d.ts +67 -0
- package/dist/components/core/bottom-sheet/BottomSheet.types.js +18 -0
- package/dist/components/core/bottom-sheet/bottom-sheet-impl.css +57 -0
- package/dist/components/core/breadcrumb/Breadcrumb.css +19 -0
- package/dist/components/core/breadcrumb/Breadcrumb.d.ts +16 -0
- package/dist/components/core/breadcrumb/Breadcrumb.js +22 -0
- package/dist/components/core/breadcrumb/Breadcrumb.types.d.ts +18 -0
- package/dist/components/core/breadcrumb/Breadcrumb.types.js +9 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.css +34 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.d.ts +12 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.js +15 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.d.ts +22 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.js +9 -0
- package/dist/components/core/button/Button.css +141 -0
- package/dist/components/core/button/Button.d.ts +25 -0
- package/dist/components/core/button/Button.js +28 -0
- package/dist/components/core/button/Button.types.d.ts +40 -0
- package/dist/components/core/button/Button.types.js +9 -0
- package/dist/components/core/button/button-impl.css +46 -0
- package/dist/components/core/button-icon/ButtonIcon.css +135 -0
- package/dist/components/core/button-icon/ButtonIcon.d.ts +34 -0
- package/dist/components/core/button-icon/ButtonIcon.js +117 -0
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +41 -0
- package/dist/components/core/button-icon/ButtonIcon.types.js +8 -0
- package/dist/components/core/card/Card.css +65 -0
- package/dist/components/core/card/Card.d.ts +24 -0
- package/dist/components/core/card/Card.js +26 -0
- package/dist/components/core/card/Card.types.d.ts +33 -0
- package/dist/components/core/card/Card.types.js +7 -0
- package/dist/components/core/card-body/CardBody.css +139 -0
- package/dist/components/core/card-body/CardBody.d.ts +62 -0
- package/dist/components/core/card-body/CardBody.js +97 -0
- package/dist/components/core/card-body/CardBody.types.d.ts +61 -0
- package/dist/components/core/card-body/CardBody.types.js +15 -0
- package/dist/components/core/card-body/card-body-impl.css +87 -0
- package/dist/components/core/card-button/CardButton.css +73 -0
- package/dist/components/core/card-button/CardButton.d.ts +27 -0
- package/dist/components/core/card-button/CardButton.js +37 -0
- package/dist/components/core/card-button/CardButton.types.d.ts +24 -0
- package/dist/components/core/card-button/CardButton.types.js +7 -0
- package/dist/components/core/card-button/card-button-impl.css +39 -0
- package/dist/components/core/checkbox/Checkbox.css +149 -0
- package/dist/components/core/checkbox/Checkbox.d.ts +21 -0
- package/dist/components/core/checkbox/Checkbox.js +97 -0
- package/dist/components/core/checkbox/Checkbox.types.d.ts +46 -0
- package/dist/components/core/checkbox/Checkbox.types.js +15 -0
- package/dist/components/core/checkbox/checkbox-impl.css +90 -0
- package/dist/components/core/divider/Divider.css +41 -0
- package/dist/components/core/divider/Divider.d.ts +46 -0
- package/dist/components/core/divider/Divider.js +51 -0
- package/dist/components/core/divider/Divider.types.d.ts +25 -0
- package/dist/components/core/divider/Divider.types.js +9 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.css +146 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +22 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.js +309 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.types.d.ts +62 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.types.js +12 -0
- package/dist/components/core/dropdown-menu/dropdown-menu-impl.css +70 -0
- package/dist/components/core/filter-chip/FilterChip.css +149 -0
- package/dist/components/core/filter-chip/FilterChip.d.ts +23 -0
- package/dist/components/core/filter-chip/FilterChip.js +37 -0
- package/dist/components/core/filter-chip/FilterChip.types.d.ts +53 -0
- package/dist/components/core/filter-chip/FilterChip.types.js +12 -0
- package/dist/components/core/footer/Footer.css +104 -0
- package/dist/components/core/footer/Footer.d.ts +43 -0
- package/dist/components/core/footer/Footer.js +53 -0
- package/dist/components/core/footer/Footer.types.d.ts +47 -0
- package/dist/components/core/footer/Footer.types.js +18 -0
- package/dist/components/core/footer/footer-impl.css +218 -0
- package/dist/components/core/footer-group/FooterGroup.css +90 -0
- package/dist/components/core/footer-group/FooterGroup.d.ts +32 -0
- package/dist/components/core/footer-group/FooterGroup.js +64 -0
- package/dist/components/core/footer-group/FooterGroup.types.d.ts +25 -0
- package/dist/components/core/footer-group/FooterGroup.types.js +12 -0
- package/dist/components/core/footer-group/footer-group-impl.css +78 -0
- package/dist/components/core/icon/Icon.css +40 -0
- package/dist/components/core/icon/Icon.d.ts +23 -0
- package/dist/components/core/icon/Icon.js +79 -0
- package/dist/components/core/icon/Icon.types.d.ts +24 -0
- package/dist/components/core/icon/Icon.types.js +7 -0
- package/dist/components/core/link/Link.css +89 -0
- package/dist/components/core/link/Link.d.ts +37 -0
- package/dist/components/core/link/Link.js +141 -0
- package/dist/components/core/link/Link.types.d.ts +41 -0
- package/dist/components/core/link/Link.types.js +9 -0
- package/dist/components/core/link/link-impl.css +168 -0
- package/dist/components/core/menu-item/MenuItem.css +70 -0
- package/dist/components/core/menu-item/MenuItem.d.ts +11 -0
- package/dist/components/core/menu-item/MenuItem.js +26 -0
- package/dist/components/core/menu-item/MenuItem.types.d.ts +28 -0
- package/dist/components/core/menu-item/MenuItem.types.js +9 -0
- package/dist/components/core/navbar/Navbar.css +135 -0
- package/dist/components/core/navbar/Navbar.d.ts +36 -0
- package/dist/components/core/navbar/Navbar.js +371 -0
- package/dist/components/core/navbar/Navbar.types.d.ts +49 -0
- package/dist/components/core/navbar/Navbar.types.js +17 -0
- package/dist/components/core/navbar/navbar-impl.css +590 -0
- package/dist/components/core/navbar-item/NavbarItem.css +75 -0
- package/dist/components/core/navbar-item/NavbarItem.d.ts +22 -0
- package/dist/components/core/navbar-item/NavbarItem.js +40 -0
- package/dist/components/core/navbar-item/NavbarItem.types.d.ts +34 -0
- package/dist/components/core/navbar-item/NavbarItem.types.js +10 -0
- package/dist/components/core/navbar-menu/NavbarMenu.css +128 -0
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +5 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +186 -0
- package/dist/components/core/navbar-menu/NavbarMenu.types.d.ts +45 -0
- package/dist/components/core/navbar-menu/NavbarMenu.types.js +12 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +186 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.css +26 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.d.ts +17 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.js +22 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.d.ts +14 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.js +7 -0
- package/dist/components/core/navbar-panel/NavbarPanel.css +87 -0
- package/dist/components/core/navbar-panel/NavbarPanel.d.ts +34 -0
- package/dist/components/core/navbar-panel/NavbarPanel.js +46 -0
- package/dist/components/core/navbar-panel/NavbarPanel.types.d.ts +29 -0
- package/dist/components/core/navbar-panel/NavbarPanel.types.js +12 -0
- package/dist/components/core/navbar-panel/navbar-panel-impl.css +104 -0
- package/dist/components/core/navbar-panel/use-navbar-panel.d.ts +26 -0
- package/dist/components/core/navbar-panel/use-navbar-panel.js +135 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.css +117 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +20 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +90 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.types.d.ts +46 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.types.js +13 -0
- package/dist/components/core/navbar-switcher/navbar-switcher-impl.css +179 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.css +39 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.d.ts +16 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.js +19 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.d.ts +18 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.js +7 -0
- package/dist/components/core/option/Option.css +133 -0
- package/dist/components/core/option/Option.d.ts +25 -0
- package/dist/components/core/option/Option.js +31 -0
- package/dist/components/core/option/Option.types.d.ts +44 -0
- package/dist/components/core/option/Option.types.js +14 -0
- package/dist/components/core/pagination/Pagination.css +237 -0
- package/dist/components/core/pagination/Pagination.d.ts +30 -0
- package/dist/components/core/pagination/Pagination.js +406 -0
- package/dist/components/core/pagination/Pagination.types.d.ts +59 -0
- package/dist/components/core/pagination/Pagination.types.js +14 -0
- package/dist/components/core/pagination/pagination-impl.css +17 -0
- package/dist/components/core/removable-chip/RemovableChip.css +125 -0
- package/dist/components/core/removable-chip/RemovableChip.d.ts +25 -0
- package/dist/components/core/removable-chip/RemovableChip.js +36 -0
- package/dist/components/core/removable-chip/RemovableChip.types.d.ts +38 -0
- package/dist/components/core/removable-chip/RemovableChip.types.js +13 -0
- package/dist/components/core/search-input/SearchInput.css +205 -0
- package/dist/components/core/search-input/SearchInput.d.ts +5 -0
- package/dist/components/core/search-input/SearchInput.js +81 -0
- package/dist/components/core/search-input/SearchInput.types.d.ts +43 -0
- package/dist/components/core/search-input/SearchInput.types.js +13 -0
- package/dist/components/core/search-input/search-input-impl.css +20 -0
- package/dist/components/core/segmented-control/SegmentedControl.css +57 -0
- package/dist/components/core/segmented-control/SegmentedControl.d.ts +37 -0
- package/dist/components/core/segmented-control/SegmentedControl.js +269 -0
- package/dist/components/core/segmented-control/SegmentedControl.types.d.ts +38 -0
- package/dist/components/core/segmented-control/SegmentedControl.types.js +8 -0
- package/dist/components/core/segmented-control/segmented-control-impl.css +57 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +151 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.d.ts +50 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.js +101 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.types.d.ts +37 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.types.js +10 -0
- package/dist/components/core/segmented-control-item/segmented-control-item-impl.css +69 -0
- package/dist/components/core/select/Select.css +400 -0
- package/dist/components/core/select/Select.d.ts +29 -0
- package/dist/components/core/select/Select.js +524 -0
- package/dist/components/core/select/Select.types.d.ts +96 -0
- package/dist/components/core/select/Select.types.js +26 -0
- package/dist/components/core/select/select-impl.css +114 -0
- package/dist/components/core/select-chip/SelectChip.css +155 -0
- package/dist/components/core/select-chip/SelectChip.d.ts +20 -0
- package/dist/components/core/select-chip/SelectChip.js +273 -0
- package/dist/components/core/select-chip/SelectChip.types.d.ts +56 -0
- package/dist/components/core/select-chip/SelectChip.types.js +14 -0
- package/dist/components/core/select-chip/select-chip-impl.css +38 -0
- package/dist/components/core/spinner/Spinner.css +76 -0
- package/dist/components/core/spinner/Spinner.d.ts +5 -0
- package/dist/components/core/spinner/Spinner.js +29 -0
- package/dist/components/core/spinner/Spinner.types.d.ts +37 -0
- package/dist/components/core/spinner/Spinner.types.js +10 -0
- package/dist/components/core/spinner/spinner-impl.css +27 -0
- package/dist/components/core/status-dot/StatusDot.css +43 -0
- package/dist/components/core/status-dot/StatusDot.d.ts +35 -0
- package/dist/components/core/status-dot/StatusDot.js +46 -0
- package/dist/components/core/status-dot/StatusDot.types.d.ts +29 -0
- package/dist/components/core/status-dot/StatusDot.types.js +7 -0
- package/dist/components/core/status-dot/status-dot-impl.css +42 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +89 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.d.ts +21 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.js +127 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.d.ts +43 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.js +13 -0
- package/dist/components/core/subdomain-navbar/subdomain-navbar-impl.css +147 -0
- package/dist/components/core/tab/Tab.css +113 -0
- package/dist/components/core/tab/Tab.d.ts +36 -0
- package/dist/components/core/tab/Tab.js +53 -0
- package/dist/components/core/tab/Tab.types.d.ts +42 -0
- package/dist/components/core/tab/Tab.types.js +13 -0
- package/dist/components/core/tab/tab-impl.css +49 -0
- package/dist/components/core/tab-list/TabList.css +40 -0
- package/dist/components/core/tab-list/TabList.d.ts +26 -0
- package/dist/components/core/tab-list/TabList.js +124 -0
- package/dist/components/core/tab-list/TabList.types.d.ts +20 -0
- package/dist/components/core/tab-list/TabList.types.js +7 -0
- package/dist/components/core/tab-list/tab-list-impl.css +56 -0
- package/dist/components/core/table/Table.css +40 -0
- package/dist/components/core/table/Table.d.ts +19 -0
- package/dist/components/core/table/Table.js +55 -0
- package/dist/components/core/table/Table.types.d.ts +59 -0
- package/dist/components/core/table/Table.types.js +9 -0
- package/dist/components/core/table/table-impl.css +75 -0
- package/dist/components/core/table/use-table-sort.d.ts +43 -0
- package/dist/components/core/table/use-table-sort.js +51 -0
- package/dist/components/core/table-body/TableBody.css +6 -0
- package/dist/components/core/table-body/TableBody.d.ts +12 -0
- package/dist/components/core/table-body/TableBody.js +26 -0
- package/dist/components/core/table-body/TableBody.types.d.ts +36 -0
- package/dist/components/core/table-body/TableBody.types.js +7 -0
- package/dist/components/core/table-cell/TableCell.css +76 -0
- package/dist/components/core/table-cell/TableCell.d.ts +21 -0
- package/dist/components/core/table-cell/TableCell.js +31 -0
- package/dist/components/core/table-cell/TableCell.types.d.ts +43 -0
- package/dist/components/core/table-cell/TableCell.types.js +7 -0
- package/dist/components/core/table-head/TableHead.css +6 -0
- package/dist/components/core/table-head/TableHead.d.ts +22 -0
- package/dist/components/core/table-head/TableHead.js +52 -0
- package/dist/components/core/table-head/TableHead.types.d.ts +39 -0
- package/dist/components/core/table-head/TableHead.types.js +7 -0
- package/dist/components/core/table-head/table-head-impl.css +51 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.css +126 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.d.ts +21 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.js +34 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.types.d.ts +56 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.types.js +9 -0
- package/dist/components/core/table-header-cell/table-header-cell-impl.css +74 -0
- package/dist/components/core/table-row/TableRow.css +18 -0
- package/dist/components/core/table-row/TableRow.d.ts +17 -0
- package/dist/components/core/table-row/TableRow.js +32 -0
- package/dist/components/core/table-row/TableRow.types.d.ts +45 -0
- package/dist/components/core/table-row/TableRow.types.js +7 -0
- package/dist/components/core/table-row/table-row-impl.css +31 -0
- package/dist/components/core/text-area/TextArea.css +325 -0
- package/dist/components/core/text-area/TextArea.d.ts +13 -0
- package/dist/components/core/text-area/TextArea.js +133 -0
- package/dist/components/core/text-area/TextArea.types.d.ts +67 -0
- package/dist/components/core/text-area/TextArea.types.js +19 -0
- package/dist/components/core/text-area/text-area-impl.css +36 -0
- package/dist/components/core/text-input/TextInput.css +400 -0
- package/dist/components/core/text-input/TextInput.d.ts +5 -0
- package/dist/components/core/text-input/TextInput.js +130 -0
- package/dist/components/core/text-input/TextInput.types.d.ts +96 -0
- package/dist/components/core/text-input/TextInput.types.js +24 -0
- package/dist/components/core/text-input/text-input-impl.css +36 -0
- package/dist/components/core/tooltip/Tooltip.css +101 -0
- package/dist/components/core/tooltip/Tooltip.d.ts +51 -0
- package/dist/components/core/tooltip/Tooltip.js +87 -0
- package/dist/components/core/tooltip/Tooltip.types.d.ts +38 -0
- package/dist/components/core/tooltip/Tooltip.types.js +9 -0
- package/dist/components/core/tooltip/TooltipAnchor.d.ts +52 -0
- package/dist/components/core/tooltip/TooltipAnchor.js +69 -0
- package/dist/components/core/tooltip/tooltip-anchor.css +145 -0
- package/dist/components/core/tooltip/tooltip-impl.css +54 -0
- package/dist/components/core/tooltip/use-tooltip.d.ts +111 -0
- package/dist/components/core/tooltip/use-tooltip.js +189 -0
- package/dist/components/core/typography/Typography.css +96 -0
- package/dist/components/core/typography/Typography.d.ts +297 -0
- package/dist/components/core/typography/Typography.js +28 -0
- package/dist/components/core/typography/Typography.types.d.ts +40 -0
- package/dist/components/core/typography/Typography.types.js +7 -0
- package/dist/components/css-time.d.ts +20 -0
- package/dist/components/css-time.js +30 -0
- package/dist/components/given.d.ts +7 -0
- package/dist/components/given.js +9 -0
- package/dist/components/hover-open.d.ts +34 -0
- package/dist/components/hover-open.js +90 -0
- package/dist/components/index.d.ts +114 -1
- package/dist/components/index.js +115 -2
- package/dist/components/layout/aspect-ratio/AspectRatio.css +29 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.d.ts +24 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.js +26 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.types.d.ts +22 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.types.js +7 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio-impl.css +44 -0
- package/dist/components/layout/grid/Grid.css +76 -0
- package/dist/components/layout/grid/Grid.d.ts +31 -0
- package/dist/components/layout/grid/Grid.js +33 -0
- package/dist/components/layout/grid/Grid.types.d.ts +48 -0
- package/dist/components/layout/grid/Grid.types.js +7 -0
- package/dist/components/layout/grid/grid-impl.css +62 -0
- package/dist/components/layout/row/Row.css +85 -0
- package/dist/components/layout/row/Row.d.ts +32 -0
- package/dist/components/layout/row/Row.js +34 -0
- package/dist/components/layout/row/Row.types.d.ts +45 -0
- package/dist/components/layout/row/Row.types.js +7 -0
- package/dist/components/layout/scroller/Scroller.css +59 -0
- package/dist/components/layout/scroller/Scroller.d.ts +34 -0
- package/dist/components/layout/scroller/Scroller.js +36 -0
- package/dist/components/layout/scroller/Scroller.types.d.ts +38 -0
- package/dist/components/layout/scroller/Scroller.types.js +7 -0
- package/dist/components/layout/scroller/scroller-impl.css +45 -0
- package/dist/components/layout/stack/Stack.css +73 -0
- package/dist/components/layout/stack/Stack.d.ts +28 -0
- package/dist/components/layout/stack/Stack.js +30 -0
- package/dist/components/layout/stack/Stack.types.d.ts +41 -0
- package/dist/components/layout/stack/Stack.types.js +7 -0
- package/dist/components/visually-hidden.d.ts +22 -0
- package/dist/components/visually-hidden.js +31 -0
- package/dist/fonts/LICENSE-inter.txt +93 -0
- package/dist/fonts/LICENSE-red-hat-mono.txt +93 -0
- package/dist/fonts/fonts.css +111 -0
- package/dist/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts/red-hat-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/red-hat-mono-latin-wght-normal.woff2 +0 -0
- package/dist/marketing.css +289 -241
- package/package.json +18 -4
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
<!-- GENERATED from stack.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Stack
|
|
4
|
+
|
|
5
|
+
A column, and one measure between its rows. It draws nothing — no ground, no edge, no padding — and owns one decision: how far apart the things stacked in it sit. Everything else about them stays theirs.
|
|
6
|
+
|
|
7
|
+
It exists because the measure is what pages get wrong, and get wrong quietly. A gap typed as a number agreed with the system on the day it was written and never again. A gap written as a margin on the row belongs to the row, and travels with it into the next layout, where it is wrong and where nobody thinks to look — the last row of every group carrying a measure into whatever follows it. The column is the one thing that can see both sides of the space, so the column is what should own it.
|
|
8
|
+
|
|
9
|
+
On a marketing page the rhythm is the argument. A hero, a proof, a price and an ask are read in order and at a pace the spacing sets, and a page whose steps are picked one at a time reads as a list of things that happened to be put on a page. The ramp is what makes that pace a decision rather than an accumulation.
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
- Two or more things are read down the page in order and the space between them is the same the whole way down — an eyebrow, a headline and a line of copy; the points of a feature list; the rows of a plan
|
|
14
|
+
- The spacing is a fact about the group rather than about any member of it. Set here, every row agrees; set on the rows, the group is only as consistent as the last person to add one
|
|
15
|
+
- The measure should tighten on a phone without anyone writing a breakpoint. The top three steps of this ramp already do, so a column set at one of them is narrower below 768px and nothing about the page says so
|
|
16
|
+
|
|
17
|
+
## Do not use
|
|
18
|
+
|
|
19
|
+
- The things sit beside one another rather than one above the next → `Row`
|
|
20
|
+
- The things must line up across as well as down → `Grid`
|
|
21
|
+
- The set has to stay on one line and the reader moves along it → `Scroller`
|
|
22
|
+
- Padding. It sets space between its children and none at all around them, so a stack reached for to inset a section leaves the band that should have carried the padding with none — and the inset now lives on an element that has no ground to sit on
|
|
23
|
+
- A single child. A column of one has nothing to space: the gap is inert, and what is left is an element that renders, costs a node, and explains nothing to the next person to read it
|
|
24
|
+
- Reaching a width. It is as wide as whatever holds it and declares no size of its own. A page's measure is a decision about the page, and a stack used to constrain one is a width hidden inside a spacing decision, in the one place nobody will search for it
|
|
25
|
+
- Putting one thing in a particular place. The gap is a relationship between rows, not a distance from an edge — a measure picked because it lands something where it looks right is a position written in the wrong units, and it is wrong at the next width and on the next screen
|
|
26
|
+
- Separating sections that a ground already separates. A band with a fill of its own has an edge, and an edge is the separation; a large gap on top of it is the page saying the same thing twice and the reader reading a hole
|
|
27
|
+
|
|
28
|
+
## Anatomy
|
|
29
|
+
|
|
30
|
+
Stack renders one element.
|
|
31
|
+
|
|
32
|
+
- `root` — `<div>`, class `dds-stack`. The column, and the whole of what this component is. It paints nothing, holds no corner and takes no padding: an arrangement is not a surface, and one that brought a ground of its own would be a second surface inside whatever it was put in.
|
|
33
|
+
|
|
34
|
+
A flex column rather than a block with margins, because the gap has to be a property of the container for the rows to be interchangeable. Written as margins, the measure lives on the rows, the first or the last carries one nobody wanted, and reordering the group changes the spacing — three faults with one cause. It also means adjacent margins cannot collapse into one another, which is the oldest way for a page's rhythm to come out smaller than the sum of its parts with nothing in the source to show for it.
|
|
35
|
+
|
|
36
|
+
Its inline size is whatever contains it, and it declares none. What it does declare is `min-inline-size: 0`, which looks like nothing and is the difference between a stack that shrinks and one that does not: a flex item refuses to go below its content's intrinsic width, so a column holding a long unbroken string — a URL, an email address, a product name nobody hyphenated — placed inside a row would push its container wider rather than wrapping, and the overflow surfaces somewhere else entirely.
|
|
37
|
+
|
|
38
|
+
The gap is the one token binding here, and the top three steps of this package's ramp are redefined below 768px. That is the whole of this component's responsiveness and it is inherited rather than declared: the column asks for a role, the role is narrower on a phone, and no breakpoint is written here. A page wanting a different pace on a phone changes the token, not the column.
|
|
39
|
+
|
|
40
|
+
Apply these classes from the generated `stackParts` constant rather than writing the strings by hand.
|
|
41
|
+
|
|
42
|
+
## Composition
|
|
43
|
+
|
|
44
|
+
- Can contain: any content
|
|
45
|
+
|
|
46
|
+
## Props
|
|
47
|
+
|
|
48
|
+
### gap — `none` | `xs` | `sm` | `md` | `lg` | `xl` | `2xl` | `3xl` (default `md`)
|
|
49
|
+
|
|
50
|
+
- `none` — No gap at all, for rows meant to read as one object rather than as a list of controls. The only step here that is a decision rather than a measure
|
|
51
|
+
- `xs` — The tightest gap between related elements — an eyebrow and the headline under it, a figure and the caption beneath
|
|
52
|
+
- `sm` — The default step for sibling controls, and what the token names for a form label and the input under it
|
|
53
|
+
- `md` — The default, and what the token names for stacked items: form fields, feature list items, pricing features. Reach for this unless the column has a reason to be tighter or looser
|
|
54
|
+
- `lg` — Between content groups — feature cards, footer columns, one pricing plan and the next
|
|
55
|
+
- `xl` — Between the parts of a card, or between a heading and the block it introduces. Drops one step below 768px, a phone having a third of the width to spend
|
|
56
|
+
- `2xl` — Between one section of a page and the next. Drops one step below 768px, a phone having a third of the width to spend
|
|
57
|
+
- `3xl` — The largest gap, for separating whole movements of a long page. Drops one step below 768px, a phone having a third of the width to spend
|
|
58
|
+
|
|
59
|
+
Use when: Always. The measure between rows is the component's one decision and the reason it exists, so there is no case for leaving it unstated
|
|
60
|
+
Never for: Reaching a distance. The gap is a relationship between two rows rather than a measure from anything — a step picked because it puts something where it looks right is a position written in the wrong units, and it is wrong at the next width
|
|
61
|
+
|
|
62
|
+
### align — `start` | `center` | `end` | `stretch` (default `stretch`)
|
|
63
|
+
|
|
64
|
+
- `start` — Rows keep their own width and sit against the leading edge — a column of links, or a call to action as wide as its own label
|
|
65
|
+
- `center` — Rows keep their own width and are centred — a hero's copy, a closing block, anything read as one object on a ground wider than it
|
|
66
|
+
- `end` — Rows keep their own width and sit against the trailing edge, which on a page is rare and usually means the column is in a panel rather than in the flow
|
|
67
|
+
- `stretch` — The default. Every row takes the column's full width, which is what stacked cards, fields and bands want, and what makes their edges agree down the page
|
|
68
|
+
|
|
69
|
+
Use when: How wide the rows are, and where they sit across the column. The default is the common case and the one that keeps a stacked set looking like a set
|
|
70
|
+
Never for: Centring the words inside a row. This moves the row and not its contents — a paragraph centred by setting the column to `center` is also a paragraph shrunk to the width of its longest line, which is a different thing and rarely the wanted one. Centred text is `text-align` on the text
|
|
71
|
+
|
|
72
|
+
### justify — `start` | `center` | `end` | `between` (default `start`)
|
|
73
|
+
|
|
74
|
+
- `start` — The default. Rows sit at the top, and a column with no height of its own is exactly as tall as they are
|
|
75
|
+
- `center` — Rows sit together in the middle of a column that is taller than they are — a card in a row of cards whose copy is shorter than its neighbours'
|
|
76
|
+
- `end` — Rows sit at the foot of a column taller than they are
|
|
77
|
+
- `between` — The first row at the top, the last at the foot, and whatever room is spare shared between them — the shape a pricing card takes, where the price is at the top and the button has to sit on the same line as every other card's
|
|
78
|
+
|
|
79
|
+
Use when: Where the rows sit down a column that has more height than they need. On a page that is usually a card in a row of cards, stretched to its tallest neighbour
|
|
80
|
+
Never for: Making a column taller. This shares out height the column already has; where the column is sized by its own contents there is no room to share, and every value here draws exactly the same thing — which is the failure this prop has, silent and easy to spend an afternoon on
|
|
81
|
+
|
|
82
|
+
Also accepts everything from `HTMLAttributes<HTMLDivElement>`.
|
|
83
|
+
|
|
84
|
+
## Choosing a variant
|
|
85
|
+
|
|
86
|
+
Placement in, props out. When one of these describes what you are building, take
|
|
87
|
+
its props — do not re-derive them from the variant descriptions above.
|
|
88
|
+
|
|
89
|
+
- **An eyebrow, a headline and a line of copy at the top of a section** — `gap="xs"`
|
|
90
|
+
Three lines that read as one block. The tightest step is what says the headline belongs to the eyebrow rather than following it
|
|
91
|
+
- **The points of a feature list, one under the next** — `gap="md"`
|
|
92
|
+
The default step, and the one the token names for stacked items. Every point agrees without any point being asked
|
|
93
|
+
- **The sections of a long page, stacked** — `gap="2xl"`
|
|
94
|
+
Between one section and the next, and it tightens a step below 768px on its own — a phone having a third of the width to spend, and the same air reading as a hole
|
|
95
|
+
- **A closing block — one line and one call to action, centred on a wide ground** — `gap="lg"` `align="center"`
|
|
96
|
+
The rows keep their own width and sit in the middle, so the button is as wide as its label rather than as wide as the band. Stretched, one action reads as a bar
|
|
97
|
+
|
|
98
|
+
## Accessibility
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
- the column announces nothing of its own. It is an arrangement, and an arrangement is not something a reader needs told — what is inside carries the meaning, and each row keeps whatever name or role it would have had anywhere else
|
|
103
|
+
- a run of things of a kind is marked as one somewhere other than here. Spacing is not structure: six cards in a column are announced as six unrelated things however tightly they sit, and the markup around them is what says otherwise
|
|
104
|
+
- the order the rows are written in is the order they are read in. Nothing here reorders anything, and nothing here should be made to — a column whose visual order and DOM order disagree is read in one order and seen in another
|
|
105
|
+
|
|
106
|
+
## Rules
|
|
107
|
+
|
|
108
|
+
- **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.
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
|
|
112
|
+
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.
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
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.
|
|
119
|
+
Guidance only — cannot be checked automatically.
|
|
120
|
+
- **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.
|
|
121
|
+
Guidance only — cannot be checked automatically.
|
|
122
|
+
- **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.
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
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.
|
|
127
|
+
Guidance only — cannot be checked automatically.
|
|
128
|
+
- **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.
|
|
129
|
+
|
|
130
|
+
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.
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
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.
|
|
137
|
+
|
|
138
|
+
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.
|
|
139
|
+
|
|
140
|
+
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.
|
|
141
|
+
|
|
142
|
+
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.
|
|
143
|
+
|
|
144
|
+
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.
|
|
145
|
+
Guidance only — cannot be checked automatically.
|
|
146
|
+
- **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.
|
|
147
|
+
|
|
148
|
+
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.
|
|
149
|
+
|
|
150
|
+
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.
|
|
151
|
+
|
|
152
|
+
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.
|
|
153
|
+
|
|
154
|
+
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.
|
|
155
|
+
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
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.
|
|
159
|
+
|
|
160
|
+
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.
|
|
161
|
+
|
|
162
|
+
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.
|
|
163
|
+
Guidance only — cannot be checked automatically.
|
|
164
|
+
- **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.
|
|
165
|
+
|
|
166
|
+
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.
|
|
167
|
+
|
|
168
|
+
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.
|
|
169
|
+
|
|
170
|
+
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.
|
|
171
|
+
Guidance only — cannot be checked automatically.
|
|
172
|
+
|
|
173
|
+
## Anti-examples
|
|
174
|
+
|
|
175
|
+
❌ Stack for: The things sit beside one another rather than one above the next
|
|
176
|
+
A line and a column are different questions, and the props that answer them differ — a row wraps, and aligns to a baseline, neither of which means anything down a column
|
|
177
|
+
→ use `Row` instead.
|
|
178
|
+
|
|
179
|
+
❌ Stack for: The things must line up across as well as down
|
|
180
|
+
A column gives every row the full width and no row any relation to the one beside it, there being none. A set of cards that must agree in both directions is tracks, and a stack that looks like a grid at one width stops being one at the next
|
|
181
|
+
→ use `Grid` instead.
|
|
182
|
+
|
|
183
|
+
❌ Stack for: The set has to stay on one line and the reader moves along it
|
|
184
|
+
That is the third answer to a row that has run out of room, and it carries the snapping and the tab stop that make the rail reachable. A column never has the problem
|
|
185
|
+
→ use `Scroller` instead.
|
|
186
|
+
|
|
187
|
+
## Example
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
191
|
+
|
|
192
|
+
<Stack gap="xs">
|
|
193
|
+
<Typography variant="eyebrow">Why Deriv</Typography>
|
|
194
|
+
<Typography variant="h2" as="h2">Trade the markets you already follow</Typography>
|
|
195
|
+
<Typography variant="body-lg">Over 200 instruments, one account, and no minimum to begin.</Typography>
|
|
196
|
+
</Stack>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## In use
|
|
200
|
+
|
|
201
|
+
### What it is for
|
|
202
|
+
|
|
203
|
+
Things read down the page with one measure between them. On a page the rhythm is the argument, and the column is what sets its pace.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
207
|
+
|
|
208
|
+
// An eyebrow, a headline, a line
|
|
209
|
+
<Stack gap="xs">
|
|
210
|
+
<Typography variant="eyebrow">Why Deriv</Typography>
|
|
211
|
+
<Typography variant="h2" as="h2">Trade the markets you already follow</Typography>
|
|
212
|
+
<Typography variant="body-lg">Over 200 instruments, one account, and no minimum to begin.</Typography>
|
|
213
|
+
</Stack>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Every step between rows
|
|
217
|
+
|
|
218
|
+
The same two lines at each step. Nothing about the words changes — the measure decides whether the second reads as part of the first, beside it, or long after it.
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
222
|
+
|
|
223
|
+
// none — rows carry their own
|
|
224
|
+
<Stack gap="none">
|
|
225
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
226
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
227
|
+
</Stack>
|
|
228
|
+
|
|
229
|
+
// xs — two lines that read as one
|
|
230
|
+
<Stack gap="xs">
|
|
231
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
232
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
233
|
+
</Stack>
|
|
234
|
+
|
|
235
|
+
// sm — a label and the field under it
|
|
236
|
+
<Stack gap="sm">
|
|
237
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
238
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
239
|
+
</Stack>
|
|
240
|
+
|
|
241
|
+
// md — the default — stacked peers
|
|
242
|
+
<Stack gap="md">
|
|
243
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
244
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
245
|
+
</Stack>
|
|
246
|
+
|
|
247
|
+
// lg — content groups
|
|
248
|
+
<Stack gap="lg">
|
|
249
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
250
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
251
|
+
</Stack>
|
|
252
|
+
|
|
253
|
+
// xl — parts of a card — tightens on a phone
|
|
254
|
+
<Stack gap="xl">
|
|
255
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
256
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
257
|
+
</Stack>
|
|
258
|
+
|
|
259
|
+
// 2xl — one section to the next — tightens
|
|
260
|
+
<Stack gap="2xl">
|
|
261
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
262
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
263
|
+
</Stack>
|
|
264
|
+
|
|
265
|
+
// 3xl — whole movements — tightens
|
|
266
|
+
<Stack gap="3xl">
|
|
267
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
268
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
269
|
+
</Stack>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### How wide the rows are
|
|
273
|
+
|
|
274
|
+
The default stretches every row to the column's width. The other three let each row be as wide as its own contents — the shape a hero's copy or a closing block takes.
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { Button, Stack, Typography } from '@deriv-com/dds-marketing'
|
|
278
|
+
|
|
279
|
+
// stretch — the default — every row the full width
|
|
280
|
+
<Stack gap="sm" align="stretch">
|
|
281
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
282
|
+
<Button variant="primary">Get started</Button>
|
|
283
|
+
</Stack>
|
|
284
|
+
|
|
285
|
+
// start — each row its own width, leading
|
|
286
|
+
<Stack gap="sm" align="start">
|
|
287
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
288
|
+
<Button variant="primary">Get started</Button>
|
|
289
|
+
</Stack>
|
|
290
|
+
|
|
291
|
+
// center — each row its own width, centred
|
|
292
|
+
<Stack gap="sm" align="center">
|
|
293
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
294
|
+
<Button variant="primary">Get started</Button>
|
|
295
|
+
</Stack>
|
|
296
|
+
|
|
297
|
+
// end — each row its own width, trailing
|
|
298
|
+
<Stack gap="sm" align="end">
|
|
299
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
300
|
+
<Button variant="primary">Get started</Button>
|
|
301
|
+
</Stack>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Where the rows sit
|
|
305
|
+
|
|
306
|
+
Only bites where something has given the column a height — a card stretched to its tallest neighbour. Nothing here has, so all four draw identically.
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
import { Button, Stack, Typography } from '@deriv-com/dds-marketing'
|
|
310
|
+
|
|
311
|
+
// start — rows at the top
|
|
312
|
+
<Stack gap="sm" justify="start">
|
|
313
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
314
|
+
<Button variant="secondary">Choose plan</Button>
|
|
315
|
+
</Stack>
|
|
316
|
+
|
|
317
|
+
// center — rows in the middle
|
|
318
|
+
<Stack gap="sm" justify="center">
|
|
319
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
320
|
+
<Button variant="secondary">Choose plan</Button>
|
|
321
|
+
</Stack>
|
|
322
|
+
|
|
323
|
+
// end — rows at the foot
|
|
324
|
+
<Stack gap="sm" justify="end">
|
|
325
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
326
|
+
<Button variant="secondary">Choose plan</Button>
|
|
327
|
+
</Stack>
|
|
328
|
+
|
|
329
|
+
// between — first at top, last at foot
|
|
330
|
+
<Stack gap="sm" justify="between">
|
|
331
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
332
|
+
<Button variant="secondary">Choose plan</Button>
|
|
333
|
+
</Stack>
|
|
334
|
+
```
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<!-- GENERATED from status-dot.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# StatusDot
|
|
4
|
+
|
|
5
|
+
A small coloured circle that marks one thing in a list of otherwise equal things — either because it is worth noticing, or because it is in a state the others are not. The accent one draws attention and says nothing about a condition; the four beside it each name one. It never carries the meaning on its own: the words next to it do, because a colour is not readable to everyone who has to read it.
|
|
6
|
+
|
|
7
|
+
## Use when
|
|
8
|
+
|
|
9
|
+
- Marking something the page is pointing at — a plan that is new, a feature worth finding in a list of them. That is the accent one, and on a marketing page it is most of them
|
|
10
|
+
- Showing presence or availability alongside a name
|
|
11
|
+
- Indicating system health or severity in a compact space, where a word for each would cost more room than the difference is worth
|
|
12
|
+
|
|
13
|
+
## Do not use
|
|
14
|
+
|
|
15
|
+
- The status needs a text label inside a colored pill → `Badge`
|
|
16
|
+
- Conveying status without an adjacent text label — color alone is not accessible
|
|
17
|
+
- A bullet, or a mark that means nothing at all — use plain CSS or a list element. The accent variant is not the exception it looks like: it says the page is pointing at this one rather than the others, which is a meaning. A dot on every row in a list means nothing by saying it everywhere
|
|
18
|
+
- Carrying the meaning in tooltip alone — a description that has to be pointed at is absent on touch and to anyone reading the page rather than exploring it. The adjacent text label is what says what the state is; the tooltip only says more about it
|
|
19
|
+
|
|
20
|
+
## Anatomy
|
|
21
|
+
|
|
22
|
+
StatusDot renders one element.
|
|
23
|
+
|
|
24
|
+
- `root` — `<span>`, class `dds-statusdot`. The colored circle. Carries the variant and optional pulse animation, and the description when it has one.
|
|
25
|
+
|
|
26
|
+
Apply these classes from the generated `statusDotParts` constant rather than writing the strings by hand.
|
|
27
|
+
|
|
28
|
+
## Composition
|
|
29
|
+
|
|
30
|
+
- Takes no children. Everything it renders comes from props
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
### variant — `accent` | `success` | `warning` | `error` | `info` (default `accent`)
|
|
35
|
+
|
|
36
|
+
- `accent` — A mark in the brand colour, for something worth noticing that is not a state — a feature that is new, an item the page is pointing at. It is the default because most dots on a marketing page are drawing attention rather than reporting a condition, which is the opposite of the balance an application view has.
|
|
37
|
+
- `success` — Available, online, healthy, or passing
|
|
38
|
+
- `warning` — Away, degraded, or approaching a limit
|
|
39
|
+
- `error` — Busy, offline, failed, or critical
|
|
40
|
+
- `info` — In progress, syncing, or informational
|
|
41
|
+
Never for: And never as a neutral or unknown state. This variant says the brand is pointing at something; it does not say a condition is unknown, and there is no longer a dot that does — the four that remain each name a condition, and a mark that reports nothing at all is text or a Badge rather than a dot.
|
|
42
|
+
|
|
43
|
+
### pulse — `boolean` (default `false`)
|
|
44
|
+
|
|
45
|
+
Use when: The status is live or actively changing — draws attention to an ongoing state
|
|
46
|
+
|
|
47
|
+
### label — `string` **Required when tooltip is set.**
|
|
48
|
+
|
|
49
|
+
Use when: The rare dot that stands alone. Ordinarily leave this out: the contract asks for a visible text label beside every dot, and that text is what says what the state is — so a dot naming itself as well is heard twice, "Status, Online". Set it where the words beside the dot do not name the state, and the contract insists on it wherever tooltip is set
|
|
50
|
+
Never for: Repeating the words already beside it, which is what makes a screen reader say the state twice. Nor for the explanation, which is tooltip. There is deliberately no default: a generic name would satisfy this without anybody choosing it, and it did — every unconfigured dot announced the word "Status" beside text that already said the state
|
|
51
|
+
|
|
52
|
+
### tooltip — `string`
|
|
53
|
+
|
|
54
|
+
Use when: The state has a meaning the colour and the adjacent label together still do not explain — why a service is degraded, what "away" counts as. A few words, revealed on hover and on keyboard focus
|
|
55
|
+
Never for: A sentence the reader must have, or anything longer than a phrase. Setting this puts the dot in the tab order, because a description no keyboard can reach is one this system does not ship — so a tooltip on every dot in a list of twenty is twenty new tab stops, and worth spending only where the explanation is
|
|
56
|
+
|
|
57
|
+
Also accepts everything from `HTMLAttributes<HTMLSpanElement>`.
|
|
58
|
+
|
|
59
|
+
## Accessibility
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
- `Tab` — Reaches the dot, but only while it carries a tooltip — a dot with nothing to describe is not a stop
|
|
64
|
+
- `Escape` — Dismisses the tooltip, and does not reveal it again until focus leaves and returns
|
|
65
|
+
- no role and no name of its own, unless label is set. The colour is the mark and the words beside it are the meaning, which the contract requires anyway — so the dot is hidden from a screen reader rather than repeating them. It carried role="status" and a name defaulting to "Status", which made every dot a live region announcing a word that says nothing.
|
|
66
|
+
- an accessible name from label wherever label is set, since that is the case where the dot is carrying the state itself
|
|
67
|
+
- aria-describedby pointing at the tooltip that explains the state, set whether the chip is revealed or not
|
|
68
|
+
- focusable while it carries a tooltip, so the description is not one only a pointer can reach — and named, because a stop with no name is announced as nothing
|
|
69
|
+
|
|
70
|
+
## Rules
|
|
71
|
+
|
|
72
|
+
- **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.
|
|
73
|
+
|
|
74
|
+
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.
|
|
75
|
+
|
|
76
|
+
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.
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
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.
|
|
81
|
+
|
|
82
|
+
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.
|
|
83
|
+
Guidance only — cannot be checked automatically.
|
|
84
|
+
- **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.
|
|
85
|
+
Guidance only — cannot be checked automatically.
|
|
86
|
+
- **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.
|
|
87
|
+
|
|
88
|
+
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.
|
|
89
|
+
|
|
90
|
+
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.
|
|
91
|
+
Guidance only — cannot be checked automatically.
|
|
92
|
+
- **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.
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
96
|
+
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.
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
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.
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
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.
|
|
107
|
+
|
|
108
|
+
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.
|
|
109
|
+
Guidance only — cannot be checked automatically.
|
|
110
|
+
- **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.
|
|
111
|
+
|
|
112
|
+
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.
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
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.
|
|
119
|
+
|
|
120
|
+
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.
|
|
121
|
+
|
|
122
|
+
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.
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
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.
|
|
127
|
+
Guidance only — cannot be checked automatically.
|
|
128
|
+
- **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.
|
|
129
|
+
|
|
130
|
+
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.
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
Guidance only — cannot be checked automatically.
|
|
136
|
+
|
|
137
|
+
## Anti-examples
|
|
138
|
+
|
|
139
|
+
❌ StatusDot for: The status needs a text label inside a colored pill
|
|
140
|
+
A badge carries its own label — a dot relies on surrounding text
|
|
141
|
+
→ use `Badge` instead.
|
|
142
|
+
|
|
143
|
+
❌ tooltip is set + label missing or empty
|
|
144
|
+
A tooltip puts the dot in the tab order, so that it can be reached by something other than a pointer. A focusable thing with no accessible name is announced as nothing at all — the reader arrives somewhere and is told only that they have arrived.
|
|
145
|
+
|
|
146
|
+
## Example
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { StatusDot } from '@deriv-com/dds-marketing'
|
|
150
|
+
|
|
151
|
+
<StatusDot variant="success" />
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## In use
|
|
155
|
+
|
|
156
|
+
### What the colour says
|
|
157
|
+
|
|
158
|
+
One mark for attention and four for a condition. The dot never carries the meaning alone — the words beside it do, which is why it is hidden from a screen reader unless nothing else says it.
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { StatusDot } from '@deriv-com/dds-marketing'
|
|
162
|
+
|
|
163
|
+
// Accent — the brand pointing at something
|
|
164
|
+
<StatusDot />
|
|
165
|
+
|
|
166
|
+
// Success — available, healthy, connected
|
|
167
|
+
<StatusDot variant="success" />
|
|
168
|
+
|
|
169
|
+
// Warning — degraded, and still working
|
|
170
|
+
<StatusDot variant="warning" />
|
|
171
|
+
|
|
172
|
+
// Error — down, or failing
|
|
173
|
+
<StatusDot variant="error" />
|
|
174
|
+
|
|
175
|
+
// Info — a state worth marking, not judging
|
|
176
|
+
<StatusDot variant="info" />
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Beating, for something live
|
|
180
|
+
|
|
181
|
+
A pulse says the state is being watched right now — a stream that is connected, a check that is running. On a dot that will not change it is motion for its own sake.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { StatusDot } from '@deriv-com/dds-marketing'
|
|
185
|
+
|
|
186
|
+
// Still — the ordinary case
|
|
187
|
+
<StatusDot variant="success" />
|
|
188
|
+
|
|
189
|
+
// Pulsing — a live connection
|
|
190
|
+
<StatusDot variant="success" pulse />
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### When the dot has to name itself
|
|
194
|
+
|
|
195
|
+
Ordinarily it does not: the text beside it is the meaning, and a dot repeating it is heard twice. Two cases need a name — one standing alone, and any dot with a tooltip.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { StatusDot } from '@deriv-com/dds-marketing'
|
|
199
|
+
|
|
200
|
+
// Named, because a tooltip makes it a tab stop
|
|
201
|
+
<StatusDot variant="warning" label="Degraded" tooltip="Order routing is slower than usual" />
|
|
202
|
+
|
|
203
|
+
// Named, standing where no words say the state
|
|
204
|
+
<StatusDot variant="error" label="Disconnected" />
|
|
205
|
+
```
|