@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,248 @@
|
|
|
1
|
+
<!-- GENERATED from table-head.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# TableHead
|
|
4
|
+
|
|
5
|
+
The column names, above the data, and the filter row where there is one. It exists as a component rather than a wrapper because a screen reader announces a column's header before every value under it — which is the whole of how a reader knows what a number means without looking it up — and that only happens if the header is marked up as one rather than styled to look like one.
|
|
6
|
+
|
|
7
|
+
A second row is allowed and a third is not. The second is the filter row: one control per column, sitting under the name of the column it narrows, which is the whole reason it is in here rather than in a toolbar above the table — a toolbar has to say which column each control acts on, and a row under the names has already said it. It gives up the inset above it, so the controls sit under the names rather than a gap of two insets away — the head is one thing, and each of its rows carrying its own air made it read as two. It is cells rather than header cells, because a control is not the name of a column and a screen reader announcing it as one would read a search box out before every value beneath it.
|
|
8
|
+
|
|
9
|
+
Beyond two there is nothing a head is doing that a reader can still follow. Column names, and at most one row of controls over them.
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
- Naming the columns, which almost every table should. A column of numbers with nothing at the top is a column a reader has to infer
|
|
14
|
+
|
|
15
|
+
## Do not use
|
|
16
|
+
|
|
17
|
+
- The row is data rather than a name for data → `TableBody`
|
|
18
|
+
- A second row of data dressed as a subheading. Everything here names columns, and a reader is told so on every cell beneath
|
|
19
|
+
- Skipping. A table with no header is a grid of values a reader has to work out from the data itself, which is guesswork on the first row and wrong on the rest
|
|
20
|
+
|
|
21
|
+
## Anatomy
|
|
22
|
+
|
|
23
|
+
TableHead renders one element.
|
|
24
|
+
|
|
25
|
+
- `root` — `<thead>`, class `dds-tablehead`. The header section. It carries no rules of its own — the line under a header is the header row's, drawn by TableRow the same way the rules between data rows are — so this element is structure and nothing else. It takes the table's size so the header row is drawn at the same rhythm as the rows under it.
|
|
26
|
+
|
|
27
|
+
It paints no band. A tinted header was here first and was the wrong answer for this design: the names are told apart from the data by their ink and by the rule under them, and a second fill behind them makes the header the loudest thing in a table whose whole point is the values. Declared as transparent rather than left unsaid, so the table's own surface is what shows through rather than whatever a page happens to sit it on.
|
|
28
|
+
|
|
29
|
+
Apply these classes from the generated `tableHeadParts` constant rather than writing the strings by hand.
|
|
30
|
+
|
|
31
|
+
## Composition
|
|
32
|
+
|
|
33
|
+
- Can contain: `TableRow`
|
|
34
|
+
- Never contains: `Table`, `TableHead`, `TableBody`, `TableCell` — in children or in any prop that takes a node
|
|
35
|
+
- Holds at least 1 and at most 2
|
|
36
|
+
|
|
37
|
+
## Props
|
|
38
|
+
|
|
39
|
+
### headerCase — `upper` | `title` (default `upper`)
|
|
40
|
+
|
|
41
|
+
- `upper` — The house setting: column names in capitals, at the role that suits them. A header is read once where the data under it is read many times, and capitals are what stop it competing
|
|
42
|
+
- `title` — Names drawn as they were written, at twelve pixels. Right where the names are long, are proper nouns whose own capitals would be flattened, or are in a script with no case at all
|
|
43
|
+
|
|
44
|
+
### dividers — `rows` | `grid` | `none` (default `rows`)
|
|
45
|
+
|
|
46
|
+
- `rows` — The default. A line between rows and none between columns. The head draws neither: the rule under it is the first data row’s top edge, and there are no columns to separate
|
|
47
|
+
- `grid` — Lines both ways, for a table read as a matrix rather than as a list of records. The head takes the vertical half of it — a column read top to bottom starts at its name, and a grid whose rules begin below the header leaves the names floating over the columns they belong to
|
|
48
|
+
- `none` — No lines at all, which for the head is what it already draws
|
|
49
|
+
Never for: Giving the head a rule of its own under the names. That line already exists as the first data row’s top edge, and a second drawn here would double it at exactly the weight a hairline is chosen to avoid
|
|
50
|
+
|
|
51
|
+
### overflow — `wrap` | `truncate` (default `wrap`)
|
|
52
|
+
|
|
53
|
+
- `wrap` — The default. Text too long for its column wraps and the row grows taller, so nothing is hidden — right whenever the value is the point and a reader has to read all of it
|
|
54
|
+
- `truncate` — Rows must stay one line high — a dense table a reader scans down, where a row that grew would break the rhythm they are scanning by. The value is clipped with an ellipsis and the whole of it is still reachable, so this trades seeing for scanning rather than losing anything
|
|
55
|
+
Never for: Making a column narrow enough to be worth truncating. Clipping is what a column does when it has run out of room, not a way to give it less — a table of ellipses has hidden its data behind a hover on every cell
|
|
56
|
+
|
|
57
|
+
### size — `sm` | `md` | `lg` (default `md`)
|
|
58
|
+
|
|
59
|
+
- `sm` — Compact. Dense data a reader scans rather than reads — a ledger, a positions table, anything where fitting more rows on screen is worth more than air around each one
|
|
60
|
+
- `md` — Balanced, and the default: rows a reader moves through at reading pace, with enough room that the eye does not slip between them
|
|
61
|
+
- `lg` — Spacious. Few rows, each carrying something substantial — a plan comparison, a summary of three accounts. Reach for it when the table is the page rather than a part of it
|
|
62
|
+
Never for: Making the text bigger or smaller. It changes how tall a row is and nothing else — the type stays one size down the whole table, because a reader comparing values across three tables at three densities is comparing the values rather than the tables. A table too wide for its column scrolls, and a smaller size only makes the same problem harder to read
|
|
63
|
+
|
|
64
|
+
Also accepts everything from `HTMLAttributes<HTMLTableSectionElement>`.
|
|
65
|
+
|
|
66
|
+
## Accessibility
|
|
67
|
+
|
|
68
|
+
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.
|
|
69
|
+
|
|
70
|
+
- a control in the head sits in a cell and not in a header cell. A filter row marked up as headers gives every column a second name, and a screen reader reads that name out before every value beneath it — so a column of amounts is announced as "Filter by balance" three times over
|
|
71
|
+
|
|
72
|
+
## Rules
|
|
73
|
+
|
|
74
|
+
- **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.
|
|
75
|
+
|
|
76
|
+
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.
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
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.
|
|
81
|
+
|
|
82
|
+
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.
|
|
83
|
+
|
|
84
|
+
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.
|
|
85
|
+
Guidance only — cannot be checked automatically.
|
|
86
|
+
- **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.
|
|
87
|
+
Guidance only — cannot be checked automatically.
|
|
88
|
+
- **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.
|
|
89
|
+
|
|
90
|
+
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.
|
|
91
|
+
|
|
92
|
+
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.
|
|
93
|
+
Guidance only — cannot be checked automatically.
|
|
94
|
+
- **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.
|
|
95
|
+
|
|
96
|
+
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.
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
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.
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
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.
|
|
107
|
+
|
|
108
|
+
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.
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
Guidance only — cannot be checked automatically.
|
|
112
|
+
- **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.
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
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.
|
|
119
|
+
|
|
120
|
+
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.
|
|
121
|
+
|
|
122
|
+
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.
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
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.
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
Guidance only — cannot be checked automatically.
|
|
130
|
+
- **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.
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
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.
|
|
137
|
+
Guidance only — cannot be checked automatically.
|
|
138
|
+
|
|
139
|
+
## Anti-examples
|
|
140
|
+
|
|
141
|
+
❌ TableHead for: The row is data rather than a name for data
|
|
142
|
+
What goes here is announced as the header of everything below it, so a data row placed here is read out before every other row as though it were their name
|
|
143
|
+
→ use `TableBody` instead.
|
|
144
|
+
|
|
145
|
+
## Example
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { TableHead, TableRow, TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
149
|
+
|
|
150
|
+
<TableHead>
|
|
151
|
+
<TableRow>
|
|
152
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
153
|
+
<TableHeaderCell>Email</TableHeaderCell>
|
|
154
|
+
<TableHeaderCell>Role</TableHeaderCell>
|
|
155
|
+
</TableRow>
|
|
156
|
+
</TableHead>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## In use
|
|
160
|
+
|
|
161
|
+
Most rows below hold the same set, written once here:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { TableHeaderCell, TableRow } from '@deriv-com/dds-marketing'
|
|
165
|
+
|
|
166
|
+
const tablerows = (
|
|
167
|
+
<>
|
|
168
|
+
<TableRow>
|
|
169
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
170
|
+
<TableHeaderCell>Email</TableHeaderCell>
|
|
171
|
+
<TableHeaderCell>Role</TableHeaderCell>
|
|
172
|
+
</TableRow>
|
|
173
|
+
</>
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### What it holds
|
|
178
|
+
|
|
179
|
+
A header is announced before every value under it, which is how a reader knows what a number means without looking it up.
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { TableHead } from '@deriv-com/dds-marketing'
|
|
183
|
+
|
|
184
|
+
// Three columns
|
|
185
|
+
<TableHead>{tablerows}</TableHead>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Row density
|
|
189
|
+
|
|
190
|
+
Taken from the table and handed to every row, so a table's air is one decision made once rather than a measure repeated per cell.
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { TableHead } from '@deriv-com/dds-marketing'
|
|
194
|
+
|
|
195
|
+
// sm
|
|
196
|
+
<TableHead size="sm">{tablerows}</TableHead>
|
|
197
|
+
|
|
198
|
+
// md
|
|
199
|
+
<TableHead size="md">{tablerows}</TableHead>
|
|
200
|
+
|
|
201
|
+
// lg
|
|
202
|
+
<TableHead size="lg">{tablerows}</TableHead>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### When a value is too long
|
|
206
|
+
|
|
207
|
+
Handed down so every cell in the section agrees. Wrapping grows the row; truncating keeps it one line high.
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
import { TableHead } from '@deriv-com/dds-marketing'
|
|
211
|
+
|
|
212
|
+
// wrap
|
|
213
|
+
<TableHead overflow="wrap">{tablerows}</TableHead>
|
|
214
|
+
|
|
215
|
+
// truncate
|
|
216
|
+
<TableHead overflow="truncate">{tablerows}</TableHead>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### The case of the names it holds
|
|
220
|
+
|
|
221
|
+
Set here and drawn by the cells, so one head's names agree with each other.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
import { TableHead } from '@deriv-com/dds-marketing'
|
|
225
|
+
|
|
226
|
+
// upper — capitals
|
|
227
|
+
<TableHead headerCase="upper">{tablerows}</TableHead>
|
|
228
|
+
|
|
229
|
+
// title — as written
|
|
230
|
+
<TableHead headerCase="title">{tablerows}</TableHead>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### The rules it draws
|
|
234
|
+
|
|
235
|
+
The head takes the vertical half of a grid and never the horizontal one: the line under the names is the first data row’s top edge.
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import { TableHead } from '@deriv-com/dds-marketing'
|
|
239
|
+
|
|
240
|
+
// rows — no rule between the names
|
|
241
|
+
<TableHead dividers="rows">{tablerows}</TableHead>
|
|
242
|
+
|
|
243
|
+
// grid — a column starts at its name
|
|
244
|
+
<TableHead dividers="grid">{tablerows}</TableHead>
|
|
245
|
+
|
|
246
|
+
// none — what the head already draws
|
|
247
|
+
<TableHead dividers="none">{tablerows}</TableHead>
|
|
248
|
+
```
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
<!-- GENERATED from table-header-cell.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# TableHeaderCell
|
|
4
|
+
|
|
5
|
+
The name of a column, announced before every value under it. That is the whole of why it is a component rather than a styled cell: a screen reader reads the header before each cell in the column, which is how a reader knows what a number means without looking it up — and it only happens if the header is a header in the markup.
|
|
6
|
+
|
|
7
|
+
Where the column can be sorted, the header holds the control that sorts it. A button rather than a click handler on the cell, because sorting is an action: it has to be reachable by keyboard, announced as pressable, and able to say which way the column is currently ordered.
|
|
8
|
+
|
|
9
|
+
## Use when
|
|
10
|
+
|
|
11
|
+
- Naming a column, which every column should have
|
|
12
|
+
- A column a reader can order, where `sortable` draws the control and `sortDirection` says which way it is ordered now
|
|
13
|
+
|
|
14
|
+
## Do not use
|
|
15
|
+
|
|
16
|
+
- The cell holds a value rather than the name of a column → `TableCell`
|
|
17
|
+
- A column that cannot actually be sorted. `sortable` draws a control, and a control that reports to nobody is the clearest promise a table can break — the reader presses it twice before deciding the page is broken
|
|
18
|
+
- Holding which column is sorted. `sortDirection` draws the answer for this one column; which column the table is ordered by outlives the render and belongs to the page, through useTableSort or its own state
|
|
19
|
+
- A row of names inside the data. Everything marked up this way is announced as naming what follows it, so a header in the middle of a table re-names every row beneath
|
|
20
|
+
|
|
21
|
+
## Anatomy
|
|
22
|
+
|
|
23
|
+
TableHeaderCell renders 3 elements. A token binding names the part it applies to.
|
|
24
|
+
|
|
25
|
+
- `root` — `<th>`, class `dds-tableheadercell`. The column's name. It shares the cell's padding and alignment so a header sits directly over the values it names — a header ranged to the start above a column of numbers ranged to the end is two edges where a reader expects one.
|
|
26
|
+
|
|
27
|
+
Its case is the table's decision, and the two settings are typographic pairings rather than one role with a transform on it. In capitals it takes font.overline — eleven pixels, medium, with that role's wide tracking, which is the role's own stated purpose: "uppercase category labels, e.g. stat labels, section tags, table column headers". Drawn as written it takes font.label.sm — twelve pixels, medium, ordinary tracking. Caps set at body spacing is the setting caps are least legible in, the letterforms being all one height, so the tracking travels with the case rather than being left behind by it.
|
|
28
|
+
|
|
29
|
+
Capitals are the default because a header is read once where the values under it are read many times: a run of caps is a different texture from the data rather than a louder version of it, which is what a larger or heavier header would have been. As written is the setting for names that are long, for proper nouns whose own capitals capitals flatten, and for a script that has no case at all — where capitals are either unreadable or meaningless.
|
|
30
|
+
|
|
31
|
+
The capitals are drawn and never typed. `text-transform` leaves the accessible name as written, so a screen reader says "Market" where a header typed MARKET into a sidecar would be spelled out letter by letter — and the sidecar would then hold a value no consumer could change the case of.
|
|
32
|
+
|
|
33
|
+
The capitals reach the column's name and stop there. A header cell is a slot, and a page may put a control or a mark in one — a word inside it came out in capitals with the column names, shouting in a row of quiet names. A component placed in a header keeps its own case, its typography being its own.
|
|
34
|
+
|
|
35
|
+
It aligns to the bottom of its row rather than the top, unlike a data cell. Headers are short and the data beneath starts at the row's top edge, so ranging the name to the bottom is what puts it closest to what it names when a header row wraps to two lines.
|
|
36
|
+
|
|
37
|
+
It draws no rule of its own. The line under a header is the first data row's top edge — TableRow draws its rule above itself, so the separator between the names and the data is already there, and a second edge here would be two lines collapsing into one thicker one.
|
|
38
|
+
|
|
39
|
+
It draws the rule above itself. A `<tr>` border is painted only while a table collapses its borders, and this table separates them so it can hold a corner — so the line between two rows is a run of cell edges rather than one row edge, and `border-spacing: 0` on the table is what keeps them touching.
|
|
40
|
+
|
|
41
|
+
It always truncates, and takes no say in it. A header is one or two words naming a column, and a header that wrapped would push the whole row taller to fit a name — where the data under it is what the height should be answering to. A column whose name does not fit is a column named too long rather than one needing more room.
|
|
42
|
+
- `trigger` — `<button>`, class `dds-tableheadercell__trigger`. The control that orders the column, drawn only where there is one. A real button rather than a handler on the cell: sorting is an action, so it has to be reachable by Tab, answer Enter and Space, and take a focus ring — none of which a `<th>` does.
|
|
43
|
+
|
|
44
|
+
It fills the cell and takes its alignment, so the whole header reads as one target rather than a word with a hit area around it. Its own colour and font are the header's, inherited rather than restated — a button that set them would be a second place for the header's type to be decided.
|
|
45
|
+
|
|
46
|
+
The cell keeps `aria-sort`, not this button. The sort state is a fact about the column, and the column is the cell; announcing it on the control would say the button is ascending rather than the data.
|
|
47
|
+
|
|
48
|
+
It takes no fill of its own when the pointer is over it. A wash across the whole header is the same gesture a row uses to say a press would land there, and at the top of the table it reads as a selected column rather than as feedback — a block of grey behind a name that is not a value. The mark answers instead, which is the smaller thing that moved.
|
|
49
|
+
|
|
50
|
+
Its case is inherited by declaration rather than by luck, the way its font and its colour already are. `text-transform` is an inherited property, but a `<button>` is a form control and a browser's own stylesheet resets those — so a sortable column drew its name as written while the plain column beside it drew the same word in capitals. Two cases in one row of names, which is the one thing a row of names cannot have. The `font: inherit` above does not cover it: the shorthand carries the family, the size, the weight and the line height, and the case is none of those.
|
|
51
|
+
|
|
52
|
+
It translates the cell's alignment into its own, because the two are not the same property. The cell ranges its text with `text-align`, which moves nothing inside a flex container — so a sortable column ignored the alignment it was given: a header over a column of amounts sat at the start of a full-width button while every number under it ranged to the end, and the non-sortable column beside it lined up correctly. Two edges where a reader expects one, which is the fault the alignment exists to prevent, reintroduced by the control that makes the column sortable. Rendered only when `sortable` is set.
|
|
53
|
+
- `indicator` — `<span>`, class `dds-tableheadercell__indicator`. Which way the column is ordered, as a mark beside its name. Always drawn where the column is sortable — including when it is not the sorted column — because a mark that appeared only on the active header would leave a reader guessing which of the others could be pressed at all. Unsorted it takes the muted ink; sorted it takes the default one, so the active column reads first. A colour rather than a transparency: an opacity would fade the mark against whatever it happens to sit on, where an ink is the same decision the header's own text is already making.
|
|
54
|
+
|
|
55
|
+
It is not the announcement. `aria-sort` on the cell is, and this is the sighted half of the same fact — which is why a column's direction is never carried by the mark alone.
|
|
56
|
+
|
|
57
|
+
It is also what answers the pointer. Hovering anywhere on the header takes this from the muted ink to the default one, and nothing else changes — the whole cell stays the target, so the hit area is unchanged and only the feedback moved. That cannot be a binding here: a binding names a part and a state, and this is one part's state drawn on another. It sits in the impl sheet for the reason the row's pointer gate does.
|
|
58
|
+
|
|
59
|
+
A hovered unsorted mark and a sorted one both take the default ink, and they are still told apart, because the glyph is not the same: unsorted is the two-headed arrow, sorted is a single chevron pointing the way the column runs. The ink says the header is live, the glyph says what it did.
|
|
60
|
+
|
|
61
|
+
A flex box rather than a plain span, which is a centring fix and not a layout choice. Holding the glyph inline put it on `vertical-align: middle`, which is the midpoint of the x-height rather than of the line — a few pixels low, and low enough that the mark hung under a name with no descenders to explain it. As a flex box the span is as tall as the glyph and the header's own centring does the rest.
|
|
62
|
+
|
|
63
|
+
The glyph is drawn at xs, which is the smallest step this package has. Product draws the same mark a step below that, at a size its Icon reserves for "a subtle inline indicator that sits inside a line of text — a caret, a sort arrow, a status dot", and it reached that size by way of a bug: at xs the mark stood half again the height of the name beside it, so the column read as an arrow with a label rather than as a name with a mark. This package's icon ramp does not go there. Its steps run larger throughout, which is the same position its type ramp takes and deliberate rather than drift — but it means the mark is sixteen pixels against a twelve-pixel name, which is the ratio product's own argument objects to. The mark is the quietest thing this package can draw here, and it is still not as quiet as the one product settled on. Rendered only when `sortable` is set.
|
|
64
|
+
|
|
65
|
+
Apply these classes from the generated `tableHeaderCellParts` constant rather than writing the strings by hand.
|
|
66
|
+
|
|
67
|
+
## Composition
|
|
68
|
+
|
|
69
|
+
- Can contain: any content
|
|
70
|
+
- Never contains: `Table`, `TableHead`, `TableBody`, `TableRow`, `TableCell`, `TableHeaderCell`, `Button`, `Link` — in children or in any prop that takes a node
|
|
71
|
+
|
|
72
|
+
## Props
|
|
73
|
+
|
|
74
|
+
### size — `sm` | `md` | `lg` (default `md`)
|
|
75
|
+
|
|
76
|
+
- `sm` — Compact. Dense data a reader scans rather than reads — a ledger, a positions table, anything where fitting more rows on screen is worth more than air around each one
|
|
77
|
+
- `md` — Balanced, and the default: rows a reader moves through at reading pace, with enough room that the eye does not slip between them
|
|
78
|
+
- `lg` — Spacious. Few rows, each carrying something substantial — a plan comparison, a summary of three accounts. Reach for it when the table is the page rather than a part of it
|
|
79
|
+
Never for: Making the text bigger or smaller. It changes how tall a row is and nothing else — the type stays one size down the whole table, because a reader comparing values across three tables at three densities is comparing the values rather than the tables. A table too wide for its column scrolls, and a smaller size only makes the same problem harder to read
|
|
80
|
+
|
|
81
|
+
### align — `start` | `center` | `end` (default `start`)
|
|
82
|
+
|
|
83
|
+
- `start` — Words. Names, descriptions, statuses — anything read left to right starts where the reading does, and a column of them shares one edge the eye can run down
|
|
84
|
+
- `center` — Rare, and worth arguing for: a single glyph or a very short state where neither edge means anything. A centred column of words has two ragged edges instead of one
|
|
85
|
+
- `end` — Numbers that line up under each other — amounts, counts, percentages. The decimal point is what a reader compares down a column, and ranging to the end is what puts it in one place
|
|
86
|
+
Never for: Making a table look balanced. Alignment says what kind of thing a column holds; using it to even out a layout tells the reader the numbers are words
|
|
87
|
+
|
|
88
|
+
### sortDirection — `none` | `ascending` | `descending` (default `none`)
|
|
89
|
+
|
|
90
|
+
- `none` — The column can be sorted and the table is not currently ordered by it. The mark is drawn quietly, which is what tells a reader the column is available rather than active
|
|
91
|
+
- `ascending` — The table is ordered by this column, smallest first — A to Z, earliest date, lowest amount
|
|
92
|
+
- `descending` — The table is ordered by this column, largest first. The commoner opening state for money and dates, where the newest or the biggest is what a reader came for
|
|
93
|
+
Never for: Two columns at once. A table is ordered by one column, so a second header claiming a direction tells the reader the data is sorted two ways and leaves them unable to trust either
|
|
94
|
+
|
|
95
|
+
### dividers — `rows` | `grid` | `none` (default `rows`)
|
|
96
|
+
|
|
97
|
+
- `rows` — The default. A line between rows and none between columns, which is what stops the eye slipping from one row's start to another's end — the mistake a wide table invites and the one a reader never notices making
|
|
98
|
+
- `grid` — Lines both ways, for a table read as a matrix rather than as a list of records: a rate card, a comparison where the reader traces a column as often as a row. It is more lines than most tables need, so it should be asked for
|
|
99
|
+
- `none` — No lines at all. Right for two or three rows, where the rules are more structure than data, and for a table whose columns are already separated by their alignment
|
|
100
|
+
Never for: Marking a group. A missing line is not a heading — a table that wants sections wants a header row inside the body, or two tables. Nor `grid` as decoration on a long table: every vertical line is another thing between a reader and the value they came for
|
|
101
|
+
|
|
102
|
+
### headerCase — `upper` | `title` (default `upper`)
|
|
103
|
+
|
|
104
|
+
- `upper` — The house setting. Column names in capitals at font.overline — eleven pixels with wide tracking — which reads as a different texture from the values rather than a louder version of them. A header is read once where the data under it is read many times, and capitals are what stop it competing
|
|
105
|
+
- `title` — Names drawn as they were written, at font.label.sm — twelve pixels, medium, ordinary tracking. Right where the names are long, are proper nouns whose own capitals capitals would flatten, or are in a script that has no case at all, and right wherever a product has decided its tables read as sentences rather than as labels
|
|
106
|
+
|
|
107
|
+
### sortable — `boolean` (default `false`)
|
|
108
|
+
|
|
109
|
+
Use when: The reader can order the table by this column. It draws the control and the mark; what pressing it does is the page's, reported through `onSort`
|
|
110
|
+
Never for: A column that only looks orderable. There is no state where the control is drawn and inert — a header that could be pressed to no effect is worse than one that was never offered
|
|
111
|
+
|
|
112
|
+
### onSort — `callback` **Required when sortable=true.**
|
|
113
|
+
|
|
114
|
+
Use when: Told the header was pressed. It hands back nothing: the page rendered this header and knows which column it is, and what the next direction should be is the page's rule rather than this component's — `useTableSort` is where that rule lives if you want one written
|
|
115
|
+
Never for: Sorting the data. This reports the press; the order of the rows is decided by whatever holds them, and a table that re-ordered its own children would be holding state it cannot own
|
|
116
|
+
|
|
117
|
+
Also accepts everything from `ThHTMLAttributes<HTMLTableCellElement>`.
|
|
118
|
+
|
|
119
|
+
## Accessibility
|
|
120
|
+
|
|
121
|
+
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.
|
|
122
|
+
|
|
123
|
+
- Announced as: `columnheader`
|
|
124
|
+
- `Tab` — reaches the sort control where the column has one. A header that cannot be sorted is not a tab stop — it is a name
|
|
125
|
+
- `Enter` — sorts the column
|
|
126
|
+
- `Space` — sorts the column, which is what makes it a button rather than a link
|
|
127
|
+
- the sort state is announced with aria-sort on the header cell, not on the control inside it. The direction is a fact about the column, and a reader moving through the table is told it as they enter the column rather than only if they reach the button
|
|
128
|
+
- the direction is never carried by the mark alone. The indicator is drawn and never announced, so aria-sort is what tells a reader which way the data runs
|
|
129
|
+
- a sortable header is a real button — reachable by Tab, answering Enter and Space, and carrying a visible focus ring. A cell with a click handler is none of those
|
|
130
|
+
- the header names its column in words. It is announced before every value beneath it, so a header drawn as a glyph alone leaves the whole column unnamed
|
|
131
|
+
|
|
132
|
+
## Rules
|
|
133
|
+
|
|
134
|
+
- **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.
|
|
135
|
+
|
|
136
|
+
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.
|
|
137
|
+
|
|
138
|
+
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.
|
|
139
|
+
|
|
140
|
+
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.
|
|
141
|
+
|
|
142
|
+
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.
|
|
143
|
+
|
|
144
|
+
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.
|
|
145
|
+
Guidance only — cannot be checked automatically.
|
|
146
|
+
- **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.
|
|
147
|
+
Guidance only — cannot be checked automatically.
|
|
148
|
+
- **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.
|
|
149
|
+
|
|
150
|
+
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.
|
|
151
|
+
|
|
152
|
+
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.
|
|
153
|
+
Guidance only — cannot be checked automatically.
|
|
154
|
+
- **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.
|
|
155
|
+
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
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.
|
|
159
|
+
|
|
160
|
+
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.
|
|
161
|
+
|
|
162
|
+
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.
|
|
163
|
+
|
|
164
|
+
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.
|
|
165
|
+
|
|
166
|
+
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.
|
|
167
|
+
|
|
168
|
+
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.
|
|
169
|
+
|
|
170
|
+
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.
|
|
171
|
+
Guidance only — cannot be checked automatically.
|
|
172
|
+
- **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.
|
|
173
|
+
|
|
174
|
+
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.
|
|
175
|
+
|
|
176
|
+
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.
|
|
177
|
+
|
|
178
|
+
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.
|
|
179
|
+
|
|
180
|
+
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.
|
|
181
|
+
|
|
182
|
+
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.
|
|
183
|
+
|
|
184
|
+
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.
|
|
185
|
+
|
|
186
|
+
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.
|
|
187
|
+
|
|
188
|
+
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.
|
|
189
|
+
Guidance only — cannot be checked automatically.
|
|
190
|
+
- **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.
|
|
191
|
+
|
|
192
|
+
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.
|
|
193
|
+
|
|
194
|
+
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.
|
|
195
|
+
|
|
196
|
+
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.
|
|
197
|
+
Guidance only — cannot be checked automatically.
|
|
198
|
+
|
|
199
|
+
## Anti-examples
|
|
200
|
+
|
|
201
|
+
❌ TableHeaderCell for: The cell holds a value rather than the name of a column
|
|
202
|
+
A header is announced before every cell beneath it, so a value placed here is read out as the name of its own column and of every value under it
|
|
203
|
+
→ use `TableCell` instead.
|
|
204
|
+
|
|
205
|
+
❌ sortable=true + onSort missing or empty
|
|
206
|
+
A control the reader can press that reports to nobody. `sortable` draws the button and `onSort` is what answers it, and the pair with the second missing is a column that looks orderable and is not — pressed once, pressed again, and then read as a page that is broken rather than one that meant it
|
|
207
|
+
|
|
208
|
+
## Example
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
212
|
+
|
|
213
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## In use
|
|
217
|
+
|
|
218
|
+
### Naming a column
|
|
219
|
+
|
|
220
|
+
Announced before every value beneath it. It shares the cell's alignment so a header sits directly over the values it names rather than across from them.
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
224
|
+
|
|
225
|
+
// A name
|
|
226
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
227
|
+
|
|
228
|
+
// center — a short state, rarely
|
|
229
|
+
<TableHeaderCell align="center">Status</TableHeaderCell>
|
|
230
|
+
|
|
231
|
+
// Over a numeric column
|
|
232
|
+
<TableHeaderCell align="end">Balance</TableHeaderCell>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Ordering the column
|
|
236
|
+
|
|
237
|
+
A real button, because sorting is an action: reachable by Tab, answering Enter and Space, and carrying a focus ring. A cell with a click handler is none of those.
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
241
|
+
|
|
242
|
+
// Sortable, not currently sorted
|
|
243
|
+
<TableHeaderCell onSort={() => { /* your handler */ }} sortable sortDirection="none">Name</TableHeaderCell>
|
|
244
|
+
|
|
245
|
+
// Ascending
|
|
246
|
+
<TableHeaderCell onSort={() => { /* your handler */ }} sortable sortDirection="ascending">Name</TableHeaderCell>
|
|
247
|
+
|
|
248
|
+
// Descending
|
|
249
|
+
<TableHeaderCell onSort={() => { /* your handler */ }} sortable sortDirection="descending">Name</TableHeaderCell>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Row density
|
|
253
|
+
|
|
254
|
+
Set in the strong cut of the body face: a header is read once and the data many times, so it needs telling apart rather than making prominent.
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
258
|
+
|
|
259
|
+
// sm
|
|
260
|
+
<TableHeaderCell size="sm">Name</TableHeaderCell>
|
|
261
|
+
|
|
262
|
+
// md
|
|
263
|
+
<TableHeaderCell size="md">Name</TableHeaderCell>
|
|
264
|
+
|
|
265
|
+
// lg
|
|
266
|
+
<TableHeaderCell size="lg">Name</TableHeaderCell>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Dividers
|
|
270
|
+
|
|
271
|
+
A header draws no line above itself — the rule under it is the first data row's top edge — but it takes the vertical rules where the table is a matrix.
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
275
|
+
|
|
276
|
+
// rows
|
|
277
|
+
<TableHeaderCell dividers="rows">Name</TableHeaderCell>
|
|
278
|
+
|
|
279
|
+
// grid
|
|
280
|
+
<TableHeaderCell dividers="grid">Name</TableHeaderCell>
|
|
281
|
+
|
|
282
|
+
// none
|
|
283
|
+
<TableHeaderCell dividers="none">Name</TableHeaderCell>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### How the name is cased
|
|
287
|
+
|
|
288
|
+
Capitals at eleven pixels with wide tracking, or the name as written at twelve. The capitals are drawn rather than typed, so the accessible name keeps the case it was authored in.
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
import { TableHeaderCell } from '@deriv-com/dds-marketing'
|
|
292
|
+
|
|
293
|
+
// upper — capitals
|
|
294
|
+
<TableHeaderCell headerCase="upper">Name</TableHeaderCell>
|
|
295
|
+
|
|
296
|
+
// title — as written
|
|
297
|
+
<TableHeaderCell headerCase="title">Name</TableHeaderCell>
|
|
298
|
+
```
|