@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,130 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId, useRef, useState } from 'react';
|
|
4
|
+
import { CircleCheckSolidIcon, CircleExclamationSolidIcon, CircleInfoRegularIcon, CircleXmarkSolidIcon, TriangleExclamationSolidIcon, } from '@deriv-com/quill-icons-web';
|
|
5
|
+
import './TextInput.css';
|
|
6
|
+
import './text-input-impl.css';
|
|
7
|
+
import { Icon } from '../icon/Icon.js';
|
|
8
|
+
import { TooltipAnchor } from '../tooltip/TooltipAnchor.js';
|
|
9
|
+
import { given } from '../../given.js';
|
|
10
|
+
import { textInputDefaults, textInputGlyphStep, textInputParts } from './TextInput.types.js';
|
|
11
|
+
/**
|
|
12
|
+
* What each reported status looks like.
|
|
13
|
+
*
|
|
14
|
+
* Circle for error, triangle for warning: the two colours are close enough that a
|
|
15
|
+
* red-green deficiency can converge them, so the shape is what separates the pair at a
|
|
16
|
+
* glance and neither should be varied to match the other.
|
|
17
|
+
*
|
|
18
|
+
* No entry for `pending`. Product turns a Spinner there and marketing has none to turn —
|
|
19
|
+
* see the note at `reporting` below for what that costs.
|
|
20
|
+
*/
|
|
21
|
+
const statusGlyph = {
|
|
22
|
+
error: _jsx(CircleExclamationSolidIcon, {}),
|
|
23
|
+
warning: _jsx(TriangleExclamationSolidIcon, {}),
|
|
24
|
+
success: _jsx(CircleCheckSolidIcon, {}),
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The step a mark inside the field takes, against the value's own type rather than the
|
|
28
|
+
* page's. `textInputGlyphStep` is the contract's, for the ornaments a consumer supplies;
|
|
29
|
+
* this is for the two marks the component draws itself, which track the text beside them.
|
|
30
|
+
*/
|
|
31
|
+
const fieldGlyphStep = { sm: 'xs', md: 'xs', lg: 'sm' };
|
|
32
|
+
export function TextInput({ size = textInputDefaults.size, status = textInputDefaults.status, type = textInputDefaults.type, label, labelTooltip, placeholder, helperText, statusMessage, leadingIcon, prefix, suffix, trailingIcon, clearable = textInputDefaults.clearable, clearLabel, required = textInputDefaults.required, requiredMark = textInputDefaults.requiredMark, optional = textInputDefaults.optional, ...rest }) {
|
|
33
|
+
/**
|
|
34
|
+
* One id for the field, and one for whichever line is describing it.
|
|
35
|
+
*
|
|
36
|
+
* `useId` rather than a prop, because a marketing page renders the same form in a hero
|
|
37
|
+
* and again in the footer, and two fields sharing a `for` means clicking the second
|
|
38
|
+
* label focuses the first.
|
|
39
|
+
*/
|
|
40
|
+
const base = useId();
|
|
41
|
+
const fieldId = `${base}-field`;
|
|
42
|
+
/**
|
|
43
|
+
* Whether there is anything to clear.
|
|
44
|
+
*
|
|
45
|
+
* Observed rather than owned. A consumer controlling the field passes `value`, so that is
|
|
46
|
+
* read directly; one that does not keeps the value in the DOM, so the element is watched
|
|
47
|
+
* for its own input events. Either way this component never sets it — a clear button that
|
|
48
|
+
* appears on an empty field is a button that does nothing.
|
|
49
|
+
*
|
|
50
|
+
* The ref is on the box rather than the input, because in React 19 `ref` is an ordinary
|
|
51
|
+
* prop and `rest` would overwrite one placed on the input the moment a consumer passed
|
|
52
|
+
* their own.
|
|
53
|
+
*/
|
|
54
|
+
const controlRef = useRef(null);
|
|
55
|
+
const [typed, setTyped] = useState(false);
|
|
56
|
+
const controlled = 'value' in rest;
|
|
57
|
+
const held = controlled ? String(rest.value ?? '') : '';
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (controlled)
|
|
60
|
+
return undefined;
|
|
61
|
+
const field = controlRef.current?.querySelector('input');
|
|
62
|
+
if (field === null || field === undefined)
|
|
63
|
+
return undefined;
|
|
64
|
+
const sync = () => setTyped(field.value !== '');
|
|
65
|
+
sync();
|
|
66
|
+
field.addEventListener('input', sync);
|
|
67
|
+
return () => field.removeEventListener('input', sync);
|
|
68
|
+
}, [controlled]);
|
|
69
|
+
const hasValue = controlled ? held !== '' : typed;
|
|
70
|
+
/**
|
|
71
|
+
* Whether the value is the reader's to change.
|
|
72
|
+
*
|
|
73
|
+
* Read out of `rest` rather than declared as props, because both arrive through
|
|
74
|
+
* InputHTMLAttributes and belong to the element — declaring them here would give the
|
|
75
|
+
* field two sources for one attribute.
|
|
76
|
+
*
|
|
77
|
+
* The clear button goes when this is false, which the contract states as the `clear`
|
|
78
|
+
* part's `absentWhen`. Dimming it was not enough: the button sits inside the control, so
|
|
79
|
+
* the disabled state's opacity made it look unavailable while it stayed a live button
|
|
80
|
+
* that emptied the field.
|
|
81
|
+
*/
|
|
82
|
+
const editable = rest.disabled !== true && rest.readOnly !== true;
|
|
83
|
+
/**
|
|
84
|
+
* The message replaces the helper rather than joining it.
|
|
85
|
+
*
|
|
86
|
+
* Both at once is two lines of small text under a field the reader is trying to fix, and
|
|
87
|
+
* the one that matters is the one they did not expect. So only one is ever rendered, and
|
|
88
|
+
* `aria-describedby` points at whichever it is.
|
|
89
|
+
*
|
|
90
|
+
* Gated on the status rather than on the message existing: a form library may hold a
|
|
91
|
+
* message for a field that is not currently reporting anything, and rendering it then
|
|
92
|
+
* shows a verdict to people reading the form while nothing is announced to people
|
|
93
|
+
* hearing it.
|
|
94
|
+
*
|
|
95
|
+
* `pending` is the one status with nothing of its own to show. Product turns a Spinner
|
|
96
|
+
* beside the message, or in the field when there is no message to sit beside; marketing
|
|
97
|
+
* has no Spinner, so a pending check reaches the eye only through the words in its
|
|
98
|
+
* message, and reaches a screen reader through `aria-busy` either way. A pending status
|
|
99
|
+
* with no message is currently invisible — the gap closes when marketing has a Spinner.
|
|
100
|
+
*/
|
|
101
|
+
const reporting = status !== 'none';
|
|
102
|
+
const showsMessage = reporting && given(statusMessage);
|
|
103
|
+
const showsHelper = given(helperText) && !reporting;
|
|
104
|
+
const described = showsMessage ? 'message' : showsHelper ? 'helper' : undefined;
|
|
105
|
+
const mark = status === 'error' || status === 'warning' || status === 'success';
|
|
106
|
+
return (_jsxs("div", { className: textInputParts.root, "data-size": size, "data-status": status, children: [_jsxs("div", { className: textInputParts['label-row'], children: [_jsxs("label", { className: textInputParts.label, htmlFor: fieldId, children: [label, required ? (_jsx("span", { className: textInputParts['required-mark'], "aria-hidden": "true", children: requiredMark === 'asterisk' ? '*' : 'required' })) : null, optional ? _jsx("span", { className: textInputParts['optional-mark'], children: "optional" }) : null] }), given(labelTooltip) ? (_jsx(TooltipAnchor, { content: labelTooltip, placement: "top", children: _jsx("button", { type: "button", className: textInputParts['label-tooltip'], "aria-label": `About ${label}`, children: _jsx(Icon, { size: fieldGlyphStep[size], children: _jsx(CircleInfoRegularIcon, {}) }) }) })) : null] }), _jsxs("div", { ref: controlRef, className: textInputParts.control,
|
|
107
|
+
// The inset belongs to the box, so an affix sits inside it — which leaves a strip
|
|
108
|
+
// of the box that is not the input, and clicking it would do nothing where a
|
|
109
|
+
// native input's own padding puts the caret in. Only when the box itself was hit:
|
|
110
|
+
// anything inside it has its own business.
|
|
111
|
+
onMouseDown: (event) => {
|
|
112
|
+
if (event.target === event.currentTarget) {
|
|
113
|
+
event.currentTarget.querySelector('input')?.focus();
|
|
114
|
+
}
|
|
115
|
+
}, children: [leadingIcon === undefined || leadingIcon === null ? null : (_jsx("span", { className: textInputParts['leading-icon'], children: _jsx(Icon, { size: textInputGlyphStep[size], children: leadingIcon }) })), given(prefix) ? _jsx("span", { className: textInputParts.prefix, children: prefix }) : null, _jsx("input", { ...rest, id: fieldId, className: textInputParts.field, type: type, placeholder: placeholder, "aria-invalid": status === 'error' || undefined, "aria-required": required || undefined, "aria-busy": status === 'pending' || undefined, "aria-describedby": described === undefined ? undefined : `${base}-${described}` }), given(suffix) ? _jsx("span", { className: textInputParts.suffix, children: suffix }) : null, clearable && hasValue && editable ? (_jsx("button", { type: "button", className: textInputParts.clear, "aria-label": clearLabel,
|
|
116
|
+
// Emptying a field is a change to its value, so it is reported the way every
|
|
117
|
+
// other change is — through onChange, which arrives from api.extends. The
|
|
118
|
+
// component owns no value and cannot clear one: it sets the element's value
|
|
119
|
+
// through the prototype's own setter and dispatches the event React listens
|
|
120
|
+
// for, which is what makes a controlled consumer see it as their own change.
|
|
121
|
+
onClick: (event) => {
|
|
122
|
+
const field = event.currentTarget.parentElement?.querySelector('input');
|
|
123
|
+
if (field === null || field === undefined)
|
|
124
|
+
return;
|
|
125
|
+
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
|
|
126
|
+
setter?.call(field, '');
|
|
127
|
+
field.dispatchEvent(new Event('input', { bubbles: true }));
|
|
128
|
+
field.focus();
|
|
129
|
+
}, children: _jsx(Icon, { size: fieldGlyphStep[size], children: _jsx(CircleXmarkSolidIcon, {}) }) })) : null, trailingIcon === undefined || trailingIcon === null ? null : (_jsx("span", { className: textInputParts['trailing-icon'], children: _jsx(Icon, { size: textInputGlyphStep[size], children: trailingIcon }) }))] }), showsMessage ? (_jsxs("span", { id: `${base}-message`, className: textInputParts.message, children: [mark ? (_jsx("span", { className: textInputParts['message-icon'], children: _jsx(Icon, { size: "xs", children: statusGlyph[status] }) })) : null, statusMessage] })) : null, showsHelper ? (_jsx("span", { id: `${base}-helper`, className: textInputParts.helper, children: helperText })) : null] }));
|
|
130
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TextInputOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `sm` — A field in a dense desktop arrangement — a filter row above a list, a field beside body copy rather than heading a section. Not on a phone, where thirty-two is below what a finger reliably hits
|
|
5
|
+
* `md` — The default, and nearly every form on a page — an inline signup, a contact form in a section
|
|
6
|
+
* `lg` — A hero's single field, or a conversion band where the form is the reason the section exists and has to be found from a distance
|
|
7
|
+
*/
|
|
8
|
+
size?: 'sm' | 'md' | 'lg';
|
|
9
|
+
/**
|
|
10
|
+
* `text` — A name, a company, anything with no keypad or validation of its own
|
|
11
|
+
* `email` — An address. It brings the right keypad on a phone — the @ without a modifier — which is the difference between a typo and a lost signup
|
|
12
|
+
* `tel` — A phone number, for the numeric keypad. It does no validation and should not pretend to: numbers differ by country and a field that rejects a valid one is worse than a field that accepts anything
|
|
13
|
+
* `url` — A website, on a form that asks for one
|
|
14
|
+
*/
|
|
15
|
+
type?: 'text' | 'email' | 'tel' | 'url';
|
|
16
|
+
/** Always — it names the field, it is drawn, and clicking it focuses the input. One or two words: 'Email', 'Full name', 'Work email' */
|
|
17
|
+
label: string;
|
|
18
|
+
/** A field needs a sentence the label has no room for — why the address is being asked for, what happens to it */
|
|
19
|
+
labelTooltip?: string;
|
|
20
|
+
/** Showing the shape of the value where the shape is not obvious — 'name@example.com' on an email field. It is an example, and it is allowed to be skipped */
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
/** Saying what happens to the value — what the page will send, how often, what it will not do with the address. On a marketing form this is frequently what decides whether the reader types a real one */
|
|
23
|
+
helperText?: string;
|
|
24
|
+
/** A mark that says what the field takes at a glance — an envelope on an address, a globe on a site */
|
|
25
|
+
leadingIcon?: ReactNode;
|
|
26
|
+
/** A fixed part of the value the reader should not have to type — a currency mark, https:// */
|
|
27
|
+
prefix?: string;
|
|
28
|
+
/** A fixed tail — a unit, a domain every address on this form shares */
|
|
29
|
+
suffix?: string;
|
|
30
|
+
/** A mark at the far edge that comments on the value rather than introducing it */
|
|
31
|
+
trailingIcon?: ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* `numeric` — Digits and nothing else — a postcode, a reference number
|
|
34
|
+
* `decimal` — A number that may carry a separator — an amount
|
|
35
|
+
*/
|
|
36
|
+
inputMode?: 'numeric' | 'decimal';
|
|
37
|
+
/**
|
|
38
|
+
* `text` — The default. The word 'required' says what it means in the reader's own language and needs no key
|
|
39
|
+
* `asterisk` — A dense form where the word would repeat down the column, and a legend explains the mark once
|
|
40
|
+
*/
|
|
41
|
+
requiredMark?: 'text' | 'asterisk';
|
|
42
|
+
}
|
|
43
|
+
export type TextInputProps = TextInputOwnProps & Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size' | 'status' | 'type' | 'label' | 'labelTooltip' | 'placeholder' | 'helperText' | 'leadingIcon' | 'prefix' | 'suffix' | 'trailingIcon' | 'clearable' | 'clearLabel' | 'inputMode' | 'statusMessage' | 'required' | 'requiredMark' | 'optional'> & ({
|
|
44
|
+
status?: 'none' | 'error' | 'warning' | 'success' | 'pending';
|
|
45
|
+
statusMessage: string;
|
|
46
|
+
} | {
|
|
47
|
+
status?: Exclude<'none' | 'error' | 'warning' | 'success' | 'pending', 'error' | 'warning'>;
|
|
48
|
+
statusMessage?: string;
|
|
49
|
+
}) & ({
|
|
50
|
+
required?: boolean;
|
|
51
|
+
optional?: false;
|
|
52
|
+
} | {
|
|
53
|
+
required?: false;
|
|
54
|
+
optional?: boolean;
|
|
55
|
+
}) & ({
|
|
56
|
+
clearable?: boolean;
|
|
57
|
+
clearLabel: string;
|
|
58
|
+
} | {
|
|
59
|
+
clearable?: false;
|
|
60
|
+
clearLabel?: string;
|
|
61
|
+
});
|
|
62
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
63
|
+
export declare const textInputParts: {
|
|
64
|
+
readonly root: "dds-textinput";
|
|
65
|
+
readonly 'label-row': "dds-textinput__label-row";
|
|
66
|
+
readonly label: "dds-textinput__label";
|
|
67
|
+
readonly 'required-mark': "dds-textinput__required-mark";
|
|
68
|
+
readonly 'optional-mark': "dds-textinput__optional-mark";
|
|
69
|
+
readonly 'label-tooltip': "dds-textinput__label-tooltip";
|
|
70
|
+
readonly control: "dds-textinput__control";
|
|
71
|
+
readonly 'leading-icon': "dds-textinput__leading-icon";
|
|
72
|
+
readonly prefix: "dds-textinput__prefix";
|
|
73
|
+
readonly field: "dds-textinput__field";
|
|
74
|
+
readonly suffix: "dds-textinput__suffix";
|
|
75
|
+
readonly clear: "dds-textinput__clear";
|
|
76
|
+
readonly 'trailing-icon': "dds-textinput__trailing-icon";
|
|
77
|
+
readonly helper: "dds-textinput__helper";
|
|
78
|
+
readonly message: "dds-textinput__message";
|
|
79
|
+
readonly 'message-icon': "dds-textinput__message-icon";
|
|
80
|
+
};
|
|
81
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
82
|
+
export declare const textInputDefaults: {
|
|
83
|
+
readonly size: "md";
|
|
84
|
+
readonly status: "none";
|
|
85
|
+
readonly type: "text";
|
|
86
|
+
readonly clearable: false;
|
|
87
|
+
readonly required: false;
|
|
88
|
+
readonly requiredMark: "text";
|
|
89
|
+
readonly optional: false;
|
|
90
|
+
};
|
|
91
|
+
/** The step this component draws a glyph slot at. Generated — do not retype. */
|
|
92
|
+
export declare const textInputGlyphStep: {
|
|
93
|
+
readonly sm: "xs";
|
|
94
|
+
readonly md: "sm";
|
|
95
|
+
readonly lg: "sm";
|
|
96
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// GENERATED from text-input.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const textInputParts = {
|
|
4
|
+
root: 'dds-textinput',
|
|
5
|
+
'label-row': 'dds-textinput__label-row',
|
|
6
|
+
label: 'dds-textinput__label',
|
|
7
|
+
'required-mark': 'dds-textinput__required-mark',
|
|
8
|
+
'optional-mark': 'dds-textinput__optional-mark',
|
|
9
|
+
'label-tooltip': 'dds-textinput__label-tooltip',
|
|
10
|
+
control: 'dds-textinput__control',
|
|
11
|
+
'leading-icon': 'dds-textinput__leading-icon',
|
|
12
|
+
prefix: 'dds-textinput__prefix',
|
|
13
|
+
field: 'dds-textinput__field',
|
|
14
|
+
suffix: 'dds-textinput__suffix',
|
|
15
|
+
clear: 'dds-textinput__clear',
|
|
16
|
+
'trailing-icon': 'dds-textinput__trailing-icon',
|
|
17
|
+
helper: 'dds-textinput__helper',
|
|
18
|
+
message: 'dds-textinput__message',
|
|
19
|
+
'message-icon': 'dds-textinput__message-icon',
|
|
20
|
+
};
|
|
21
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
22
|
+
export const textInputDefaults = { size: 'md', status: 'none', type: 'text', clearable: false, required: false, requiredMark: 'text', optional: false };
|
|
23
|
+
/** The step this component draws a glyph slot at. Generated — do not retype. */
|
|
24
|
+
export const textInputGlyphStep = { sm: 'xs', md: 'sm', lg: 'sm' };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* `:where([data-dds-context="marketing"])` confines these rules without contributing
|
|
5
|
+
* specificity, so the one override below still ties or beats exactly what it did before.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* The status glyph's box is one line of the message tall.
|
|
10
|
+
*
|
|
11
|
+
* The contract binds the font size and the line height on this part, which is what makes it
|
|
12
|
+
* one line — but a line's height is those two multiplied, and a binding carries one token,
|
|
13
|
+
* not an expression over two. So the multiplication happens here, over the same variables the
|
|
14
|
+
* contract bound: no measure is declared, and retuning either token moves this with it.
|
|
15
|
+
*
|
|
16
|
+
* Why a height at all, when the part could simply hold the glyph: aligned to the start of the
|
|
17
|
+
* block axis, a glyph is as tall as itself — 16px against a 21px line — so its middle sits
|
|
18
|
+
* above the first line's and the words beside it read as pushed down. A box one line tall with
|
|
19
|
+
* the glyph centred in it puts the two middles on each other.
|
|
20
|
+
*
|
|
21
|
+
* Centred geometrically rather than on the inline baseline. `vertical-align: middle` is the
|
|
22
|
+
* usual recipe and it is not the same thing: it puts a glyph's middle on the baseline plus half
|
|
23
|
+
* an x-height, which lands a pixel or so below the middle of a line of capitals and leaves the
|
|
24
|
+
* glyph hanging under the baseline where the type has its descender.
|
|
25
|
+
*
|
|
26
|
+
* One rule rather than one per size, because the message is font.body.sm at every step — it is
|
|
27
|
+
* the small print under a field whatever size it is, and the field's own sizes do not reach it. The day
|
|
28
|
+
* that stops being true this needs a second rule, and naming the role rather than a measure is
|
|
29
|
+
* what will make that obvious.
|
|
30
|
+
*
|
|
31
|
+
* The same problem InlineAlert solved first, and the same answer; the argument in full is in
|
|
32
|
+
* inline-alert-impl.css.
|
|
33
|
+
*/
|
|
34
|
+
:where([data-dds-context="marketing"]) .dds-textinput__message-icon {
|
|
35
|
+
block-size: calc(var(--font-body-sm-size) * var(--font-body-sm-line-height));
|
|
36
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* GENERATED from tooltip.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-tooltip {
|
|
4
|
+
transition-property: opacity, scale;
|
|
5
|
+
align-items: center;
|
|
6
|
+
display: flex;
|
|
7
|
+
pointer-events: none;
|
|
8
|
+
width: max-content;
|
|
9
|
+
font-family: var(--font-body-sm-family);
|
|
10
|
+
font-size: var(--font-body-sm-size);
|
|
11
|
+
font-weight: var(--font-body-sm-weight);
|
|
12
|
+
line-height: var(--font-body-sm-line-height);
|
|
13
|
+
transition-duration: var(--motion-duration-fast);
|
|
14
|
+
transition-timing-function: var(--motion-easing-enter);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:where([data-dds-context="marketing"]) .dds-tooltip .dds-tooltip__caret {
|
|
18
|
+
box-sizing: content-box;
|
|
19
|
+
color: var(--color-bg-strong);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
:where([data-dds-context="marketing"]) .dds-tooltip .dds-tooltip__body {
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
overflow-wrap: break-word;
|
|
25
|
+
text-wrap: balance;
|
|
26
|
+
background-color: var(--color-bg-strong);
|
|
27
|
+
border-radius: var(--radius-subtle);
|
|
28
|
+
box-shadow: var(--elevation-surface-floating);
|
|
29
|
+
color: var(--color-fg-on-strong);
|
|
30
|
+
max-inline-size: var(--size-tooltip-max);
|
|
31
|
+
padding-block: var(--space-inset-sm);
|
|
32
|
+
padding-inline: var(--space-inset-md);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="bottom"] {
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
transform-origin: top;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="left"] {
|
|
41
|
+
flex-direction: row-reverse;
|
|
42
|
+
transform-origin: right;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="right"] {
|
|
46
|
+
flex-direction: row;
|
|
47
|
+
transform-origin: left;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="top"] {
|
|
51
|
+
flex-direction: column-reverse;
|
|
52
|
+
transform-origin: bottom;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-alignment="center"] .dds-tooltip__caret {
|
|
56
|
+
align-self: center;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-alignment="end"] .dds-tooltip__caret {
|
|
60
|
+
align-self: flex-end;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-alignment="start"] .dds-tooltip__caret {
|
|
64
|
+
align-self: flex-start;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-hidden="true"] {
|
|
68
|
+
opacity: var(--opacity-hidden);
|
|
69
|
+
scale: var(--motion-scale-enter);
|
|
70
|
+
transition-duration: var(--motion-duration-instant);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="bottom"] .dds-tooltip__caret {
|
|
74
|
+
height: var(--space-gap-xs);
|
|
75
|
+
padding-inline: var(--space-inset-sm);
|
|
76
|
+
width: var(--space-gap-sm);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="left"] .dds-tooltip__caret {
|
|
80
|
+
height: var(--space-gap-sm);
|
|
81
|
+
padding-block: var(--space-inset-sm);
|
|
82
|
+
width: var(--space-gap-xs);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="right"] .dds-tooltip__caret {
|
|
86
|
+
height: var(--space-gap-sm);
|
|
87
|
+
padding-block: var(--space-inset-sm);
|
|
88
|
+
width: var(--space-gap-xs);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:where([data-dds-context="marketing"]) .dds-tooltip[data-placement="top"] .dds-tooltip__caret {
|
|
92
|
+
height: var(--space-gap-xs);
|
|
93
|
+
padding-inline: var(--space-inset-sm);
|
|
94
|
+
width: var(--space-gap-sm);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@media (prefers-reduced-motion: reduce) {
|
|
98
|
+
:where([data-dds-context="marketing"]) .dds-tooltip,
|
|
99
|
+
:where([data-dds-context="marketing"]) .dds-tooltip * { transition: none; }
|
|
100
|
+
}
|
|
101
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import './Tooltip.css';
|
|
2
|
+
import './tooltip-impl.css';
|
|
3
|
+
import { type TooltipProps } from './Tooltip.types.js';
|
|
4
|
+
export type { TooltipProps };
|
|
5
|
+
/**
|
|
6
|
+
* The chip only. When it appears, and where, is the anchor's decision — this
|
|
7
|
+
* component has neither a timer nor a position of its own. Both ship beside it, as
|
|
8
|
+
* `useTooltip` and `TooltipAnchor`, so that a consumer with a trigger this cannot
|
|
9
|
+
* wrap still has the parts to assemble one.
|
|
10
|
+
*
|
|
11
|
+
* `placement` names where the tooltip sits relative to its anchor — `top` is above
|
|
12
|
+
* it — and the caret is drawn on the opposite edge so it points back at what it
|
|
13
|
+
* describes. Naming the placement rather than the caret's own edge is what lets the
|
|
14
|
+
* wrapper pass one value straight through to two readers: the stylesheet that moves
|
|
15
|
+
* the chip, and this file that picks which triangle to draw. Neither has to remember
|
|
16
|
+
* to invert it. Nothing here moves the tooltip, so a `placement` that disagrees with
|
|
17
|
+
* where the chip actually sits is still the consumer's mistake to avoid.
|
|
18
|
+
*
|
|
19
|
+
* `role="tooltip"` carries no behaviour of its own; it is what makes the
|
|
20
|
+
* `aria-describedby` on the anchor announce as a description rather than as a
|
|
21
|
+
* second, unrelated run of text. Which is why the contract's second `a11y`
|
|
22
|
+
* requirement has no executable `check`: the association lives on the anchor,
|
|
23
|
+
* and nothing in this component's own DOM can prove it was made.
|
|
24
|
+
*
|
|
25
|
+
* `id` is not a declared prop — it arrives through `HTMLAttributes`, and the
|
|
26
|
+
* anchor needs it to point here at all. That is the reason this contract has an
|
|
27
|
+
* `api.extends` where Card deliberately does not.
|
|
28
|
+
*
|
|
29
|
+
* `showCaret` decides whether the caret is rendered at all, rather than rendered and
|
|
30
|
+
* hidden. That is a contract decision and not this file's: the anatomy declares the
|
|
31
|
+
* part `presentWhen: "showCaret"`, which is how a conditional part is described here
|
|
32
|
+
* and how the generated stylesheet and behaviour test both come to know about it.
|
|
33
|
+
* The alternative it replaced — one `placement` value meaning "nowhere", drawing a
|
|
34
|
+
* caret and then hiding it with `display: none` — spent a whole axis of the variant
|
|
35
|
+
* matrix on a chip that had no position to point from.
|
|
36
|
+
*
|
|
37
|
+
* DOM order is fixed: caret first, always. `flex-direction` carries the side —
|
|
38
|
+
* `column` and `column-reverse`, `row` and `row-reverse` — so which end of the
|
|
39
|
+
* chip the caret sits at is decided by the stylesheet from the contract, and this
|
|
40
|
+
* file never branches on placement.
|
|
41
|
+
*
|
|
42
|
+
* `hidden` shadows the native attribute of the same name and does not mean what it
|
|
43
|
+
* means: native `hidden` is `display: none`, and a tooltip that leaves the layout
|
|
44
|
+
* has nothing to fade from and no box to fade in. This one is a bound opacity, so
|
|
45
|
+
* the chip stays where it is, stays measurable, and stays pointed at by the anchor's
|
|
46
|
+
* `aria-describedby` — the description is still announced with the control it
|
|
47
|
+
* explains, which is the whole reason that association exists. Shadowing a native
|
|
48
|
+
* attribute is Input's precedent, where `size` means the control's scale rather than
|
|
49
|
+
* a character count.
|
|
50
|
+
*/
|
|
51
|
+
export declare function Tooltip({ placement, alignment, showCaret, hidden, children, ...rest }: TooltipProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import './Tooltip.css';
|
|
3
|
+
import './tooltip-impl.css';
|
|
4
|
+
import { tooltipDefaults, tooltipParts } from './Tooltip.types.js';
|
|
5
|
+
/**
|
|
6
|
+
* The caret, once per side the tooltip can sit on.
|
|
7
|
+
*
|
|
8
|
+
* Keyed by `placement`, which names where the tooltip is — so each entry holds the
|
|
9
|
+
* triangle that points back the other way, at the anchor. `top` means the tooltip
|
|
10
|
+
* is above its anchor, so `top` draws a triangle pointing down. Reading this table
|
|
11
|
+
* as "the direction the caret points" gets every entry backwards, which is the one
|
|
12
|
+
* mistake this shape invites.
|
|
13
|
+
*
|
|
14
|
+
* Four paths rather than one path rotated four ways, because rotation is not
|
|
15
|
+
* something a contract can express: `structure` carries CSS keywords, and every
|
|
16
|
+
* form of `rotate` needs an angle. Drawing each direction moves that decision
|
|
17
|
+
* into geometry, where it costs nothing — the shape of a triangle is not a design
|
|
18
|
+
* decision that a designer would ever want to vary by brand or mode.
|
|
19
|
+
*
|
|
20
|
+
* Shape is all that is left here. How big the caret is, and how far it sits from
|
|
21
|
+
* the chip's rounded corner, are both design decisions and both live in the
|
|
22
|
+
* contract — `width`/`height` per side, and `padding-inline`/`padding-block` for
|
|
23
|
+
* the inset that keeps the caret clear of the chip's rounded corner. This file
|
|
24
|
+
* carried the size for one pass, as an `em` ratio on the SVG itself, and that put
|
|
25
|
+
* a decision where no contract, no generated doc and no Figma push could see it.
|
|
26
|
+
*
|
|
27
|
+
* So there is no width or height attribute below. The stylesheet supplies both,
|
|
28
|
+
* and each direction carries only its own viewBox — the aspect the triangle is
|
|
29
|
+
* drawn at, which has to agree with the bound box or the shape would be scaled to
|
|
30
|
+
* fit and stop being the shape that was drawn.
|
|
31
|
+
*/
|
|
32
|
+
const CARET = {
|
|
33
|
+
top: { viewBox: '0 0 8 4', d: 'M0 0 L4 4 L8 0 Z' },
|
|
34
|
+
right: { viewBox: '0 0 4 8', d: 'M4 0 L0 4 L4 8 Z' },
|
|
35
|
+
bottom: { viewBox: '0 0 8 4', d: 'M0 4 L4 0 L8 4 Z' },
|
|
36
|
+
left: { viewBox: '0 0 4 8', d: 'M0 0 L4 4 L0 8 Z' },
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The chip only. When it appears, and where, is the anchor's decision — this
|
|
40
|
+
* component has neither a timer nor a position of its own. Both ship beside it, as
|
|
41
|
+
* `useTooltip` and `TooltipAnchor`, so that a consumer with a trigger this cannot
|
|
42
|
+
* wrap still has the parts to assemble one.
|
|
43
|
+
*
|
|
44
|
+
* `placement` names where the tooltip sits relative to its anchor — `top` is above
|
|
45
|
+
* it — and the caret is drawn on the opposite edge so it points back at what it
|
|
46
|
+
* describes. Naming the placement rather than the caret's own edge is what lets the
|
|
47
|
+
* wrapper pass one value straight through to two readers: the stylesheet that moves
|
|
48
|
+
* the chip, and this file that picks which triangle to draw. Neither has to remember
|
|
49
|
+
* to invert it. Nothing here moves the tooltip, so a `placement` that disagrees with
|
|
50
|
+
* where the chip actually sits is still the consumer's mistake to avoid.
|
|
51
|
+
*
|
|
52
|
+
* `role="tooltip"` carries no behaviour of its own; it is what makes the
|
|
53
|
+
* `aria-describedby` on the anchor announce as a description rather than as a
|
|
54
|
+
* second, unrelated run of text. Which is why the contract's second `a11y`
|
|
55
|
+
* requirement has no executable `check`: the association lives on the anchor,
|
|
56
|
+
* and nothing in this component's own DOM can prove it was made.
|
|
57
|
+
*
|
|
58
|
+
* `id` is not a declared prop — it arrives through `HTMLAttributes`, and the
|
|
59
|
+
* anchor needs it to point here at all. That is the reason this contract has an
|
|
60
|
+
* `api.extends` where Card deliberately does not.
|
|
61
|
+
*
|
|
62
|
+
* `showCaret` decides whether the caret is rendered at all, rather than rendered and
|
|
63
|
+
* hidden. That is a contract decision and not this file's: the anatomy declares the
|
|
64
|
+
* part `presentWhen: "showCaret"`, which is how a conditional part is described here
|
|
65
|
+
* and how the generated stylesheet and behaviour test both come to know about it.
|
|
66
|
+
* The alternative it replaced — one `placement` value meaning "nowhere", drawing a
|
|
67
|
+
* caret and then hiding it with `display: none` — spent a whole axis of the variant
|
|
68
|
+
* matrix on a chip that had no position to point from.
|
|
69
|
+
*
|
|
70
|
+
* DOM order is fixed: caret first, always. `flex-direction` carries the side —
|
|
71
|
+
* `column` and `column-reverse`, `row` and `row-reverse` — so which end of the
|
|
72
|
+
* chip the caret sits at is decided by the stylesheet from the contract, and this
|
|
73
|
+
* file never branches on placement.
|
|
74
|
+
*
|
|
75
|
+
* `hidden` shadows the native attribute of the same name and does not mean what it
|
|
76
|
+
* means: native `hidden` is `display: none`, and a tooltip that leaves the layout
|
|
77
|
+
* has nothing to fade from and no box to fade in. This one is a bound opacity, so
|
|
78
|
+
* the chip stays where it is, stays measurable, and stays pointed at by the anchor's
|
|
79
|
+
* `aria-describedby` — the description is still announced with the control it
|
|
80
|
+
* explains, which is the whole reason that association exists. Shadowing a native
|
|
81
|
+
* attribute is Input's precedent, where `size` means the control's scale rather than
|
|
82
|
+
* a character count.
|
|
83
|
+
*/
|
|
84
|
+
export function Tooltip({ placement = tooltipDefaults.placement, alignment = tooltipDefaults.alignment, showCaret = tooltipDefaults.showCaret, hidden = tooltipDefaults.hidden, children, ...rest }) {
|
|
85
|
+
const caret = CARET[placement];
|
|
86
|
+
return (_jsxs("div", { className: tooltipParts.root, role: "tooltip", "data-placement": placement, "data-alignment": alignment, "data-hidden": hidden, ...rest, children: [showCaret && (_jsx("svg", { className: tooltipParts.caret, viewBox: caret.viewBox, "aria-hidden": "true", children: _jsx("path", { d: caret.d, fill: "currentColor" }) })), _jsx("div", { className: tooltipParts.body, children: children })] }));
|
|
87
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TooltipOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `top` — The tooltip sits above its anchor, so the caret drops from the bottom edge to meet it
|
|
5
|
+
* `right` — The tooltip sits on the trailing side of its anchor — the right in English, the left in Arabic — so the caret reaches back across to meet it. The name is physical and the behaviour is logical: the chip's own direction mirrors this, caret and all
|
|
6
|
+
* `bottom` — The tooltip sits below its anchor, so the caret rises from the top edge to meet it
|
|
7
|
+
* `left` — The tooltip sits on the leading side of its anchor — the left in English, the right in Arabic — so the caret reaches across to meet it. The name is physical and the behaviour is logical: the chip's own direction mirrors this, caret and all
|
|
8
|
+
*/
|
|
9
|
+
placement?: 'top' | 'right' | 'bottom' | 'left';
|
|
10
|
+
/**
|
|
11
|
+
* `center` — The chip is centred on its anchor and the caret's point lands on the middle of it. Use this unless the chip is much wider than the thing it points at
|
|
12
|
+
* `start` — The chip's leading edge lines up with the anchor's own, so a chip wider than its anchor grows away from it rather than back across the layout. For an anchor at the start of a row
|
|
13
|
+
* `end` — The mirror of start: the chip's trailing edge lines up with the anchor's, for an anchor at the end of a row
|
|
14
|
+
*/
|
|
15
|
+
alignment?: 'center' | 'start' | 'end';
|
|
16
|
+
/** Whatever reveals the tooltip has not revealed it yet, or has dismissed it. Defaults to false, which means visible — so something has to drive this, or the chip is simply on. Keeping it mounted and hidden rather than unmounting it is what lets it fade in, and what keeps the anchor's aria-describedby pointing at something real.
|
|
17
|
+
|
|
18
|
+
Flipping it is the whole animation. The chip fades from opacity.hidden and scales up from motion.scale.enter over motion.duration.fast on motion.easing.enter, growing out of the edge nearest its anchor rather than its own middle. The dismissal is not animated at all — transition-duration is motion.duration.instant while hidden, because by then the pointer has already gone somewhere else. Do not write a transition of your own: the stylesheet declares transition-property from what this axis changes, and a second declaration would both override that list and escape the prefers-reduced-motion guard generated with it. */
|
|
19
|
+
hidden?: boolean;
|
|
20
|
+
/** Drawn by default. Leave it on whenever something holds the chip against its anchor — the point is what ties a floating description to the control it belongs to */
|
|
21
|
+
showCaret?: boolean;
|
|
22
|
+
/** Allowed: text */
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
export type TooltipProps = TooltipOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'placement' | 'alignment' | 'hidden' | 'showCaret'>;
|
|
26
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
27
|
+
export declare const tooltipParts: {
|
|
28
|
+
readonly root: "dds-tooltip";
|
|
29
|
+
readonly caret: "dds-tooltip__caret";
|
|
30
|
+
readonly body: "dds-tooltip__body";
|
|
31
|
+
};
|
|
32
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
33
|
+
export declare const tooltipDefaults: {
|
|
34
|
+
readonly placement: "top";
|
|
35
|
+
readonly alignment: "center";
|
|
36
|
+
readonly hidden: false;
|
|
37
|
+
readonly showCaret: true;
|
|
38
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// GENERATED from tooltip.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const tooltipParts = {
|
|
4
|
+
root: 'dds-tooltip',
|
|
5
|
+
caret: 'dds-tooltip__caret',
|
|
6
|
+
body: 'dds-tooltip__body',
|
|
7
|
+
};
|
|
8
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
9
|
+
export const tooltipDefaults = { placement: 'top', alignment: 'center', hidden: false, showCaret: true };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import './tooltip-anchor.css';
|
|
2
|
+
import { type HTMLAttributes, type ReactElement, type ReactNode } from 'react';
|
|
3
|
+
import { type TooltipProps } from './Tooltip.types.js';
|
|
4
|
+
import { type UseTooltipOptions } from './use-tooltip.js';
|
|
5
|
+
export interface TooltipAnchorProps extends UseTooltipOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The trigger: one element, which the description is attached to and the pointer and
|
|
8
|
+
* focus handlers are added to. It has to be something focus can rest on — a button
|
|
9
|
+
* or a link, not a span — or the description is one no keyboard ever reaches.
|
|
10
|
+
*
|
|
11
|
+
* Typed as a single element rather than ReactNode because this clones it. Text, a
|
|
12
|
+
* fragment or a list has nothing to clone and nowhere to put an aria-describedby, so
|
|
13
|
+
* the constraint is better carried by the type than discovered at runtime.
|
|
14
|
+
*
|
|
15
|
+
* A component works as well as a plain element, provided it forwards the props it is
|
|
16
|
+
* handed — which is what a contract's `api.extends` promises, and why Button can be a
|
|
17
|
+
* trigger. One that declares none swallows them silently: the type still fits, and the
|
|
18
|
+
* description reaches nothing.
|
|
19
|
+
*/
|
|
20
|
+
children: ReactElement<HTMLAttributes<HTMLElement>>;
|
|
21
|
+
/** The description. Short — the contract's own guidance is that this is a label, not a panel. */
|
|
22
|
+
content: ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Which side of the anchor the chip sits on, passed straight through to the chip so
|
|
25
|
+
* one value places the box and draws the caret pointing back the other way.
|
|
26
|
+
*/
|
|
27
|
+
placement?: TooltipProps['placement'];
|
|
28
|
+
/** Where along that side, which is the axis the placement did not use. */
|
|
29
|
+
alignment?: TooltipProps['alignment'];
|
|
30
|
+
/** Passed through to the chip, which renders the caret or leaves it out. */
|
|
31
|
+
showCaret?: TooltipProps['showCaret'];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A trigger and its tooltip, placed against each other.
|
|
35
|
+
*
|
|
36
|
+
* `Tooltip` is the chip and nothing else, and `useTooltip` is when it arrives. This is
|
|
37
|
+
* the third thing neither of them does: where it lands. It is a wrapper rather than
|
|
38
|
+
* anything cleverer because the placement is pure CSS — one positioning context around
|
|
39
|
+
* both boxes, and `placement` read by a stylesheet — so there is nothing to measure,
|
|
40
|
+
* nothing to watch for resizes, and no layout pass to be one frame behind.
|
|
41
|
+
*
|
|
42
|
+
* What that buys is that the caret now lands on the point it names. What it does not
|
|
43
|
+
* buy is flipping: a chip whose named side has no room overflows rather than moving to
|
|
44
|
+
* the side that does, because knowing there is no room means measuring the viewport.
|
|
45
|
+
* The contract says as much in its own guidance, and this module does not retract it.
|
|
46
|
+
*
|
|
47
|
+
* Reach past this to `useTooltip` when the trigger is not something this can wrap —
|
|
48
|
+
* one already inside another component, or one that is not an element at all. That is
|
|
49
|
+
* the whole of what an external anchor needs: the hook's `anchorProps` go on whatever
|
|
50
|
+
* the trigger turns out to be, and `tooltipProps` on a chip rendered wherever suits.
|
|
51
|
+
*/
|
|
52
|
+
export declare function TooltipAnchor({ children, content, placement, alignment, showCaret, ...options }: TooltipAnchorProps): import("react").JSX.Element;
|