@deriv-com/dds-marketing 0.1.0 → 1.0.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 +201 -0
- package/.llm/components/accordionitem.md +244 -0
- package/.llm/components/aspectratio.md +220 -0
- package/.llm/components/badge.md +239 -0
- package/.llm/components/bottomsheet.md +412 -0
- package/.llm/components/breadcrumb.md +205 -0
- package/.llm/components/breadcrumbitem.md +186 -0
- package/.llm/components/button.md +295 -0
- package/.llm/components/buttonicon.md +321 -0
- package/.llm/components/card.md +327 -0
- package/.llm/components/cardbody.md +435 -0
- package/.llm/components/cardbutton.md +273 -0
- package/.llm/components/checkbox.md +293 -0
- package/.llm/components/ctabanner.md +186 -0
- package/.llm/components/ctabannerslider.md +204 -0
- package/.llm/components/divider.md +238 -0
- package/.llm/components/dropdownmenu.md +461 -0
- package/.llm/components/faqaccordion.md +217 -0
- package/.llm/components/featurebullets.md +254 -0
- package/.llm/components/featurecards.md +313 -0
- package/.llm/components/featurescroll.md +284 -0
- package/.llm/components/featuresplit.md +249 -0
- package/.llm/components/filterchip.md +322 -0
- package/.llm/components/footer.md +416 -0
- package/.llm/components/footergroup.md +249 -0
- package/.llm/components/grid.md +667 -0
- package/.llm/components/icon.md +202 -0
- package/.llm/components/landinghero.md +254 -0
- package/.llm/components/link.md +362 -0
- package/.llm/components/logocolumns.md +235 -0
- package/.llm/components/logorows.md +212 -0
- package/.llm/components/menuitem.md +226 -0
- package/.llm/components/navbar.md +522 -0
- package/.llm/components/navbaritem.md +246 -0
- package/.llm/components/navbarmenu.md +327 -0
- package/.llm/components/navbarmenugroup.md +192 -0
- package/.llm/components/navbarpanel.md +263 -0
- package/.llm/components/navbarswitcher.md +351 -0
- package/.llm/components/navbarswitcheroption.md +164 -0
- package/.llm/components/option.md +276 -0
- package/.llm/components/pageheader.md +231 -0
- package/.llm/components/pagination.md +298 -0
- package/.llm/components/paginationdots.md +215 -0
- package/.llm/components/producthero.md +248 -0
- package/.llm/components/removablechip.md +255 -0
- package/.llm/components/row.md +389 -0
- package/.llm/components/scroller.md +478 -0
- package/.llm/components/searchinput.md +287 -0
- package/.llm/components/segmentedcontrol.md +366 -0
- package/.llm/components/segmentedcontrolitem.md +280 -0
- package/.llm/components/select.md +517 -0
- package/.llm/components/selectchip.md +375 -0
- package/.llm/components/spinner.md +230 -0
- package/.llm/components/stack.md +342 -0
- package/.llm/components/statusdot.md +213 -0
- package/.llm/components/subdomainnavbar.md +335 -0
- package/.llm/components/tab.md +299 -0
- package/.llm/components/table.md +668 -0
- package/.llm/components/tablebody.md +266 -0
- package/.llm/components/tablecell.md +256 -0
- package/.llm/components/tablehead.md +256 -0
- package/.llm/components/tableheadercell.md +306 -0
- package/.llm/components/tablerow.md +293 -0
- package/.llm/components/tablist.md +218 -0
- package/.llm/components/testimonialrow.md +235 -0
- package/.llm/components/testimonialslider.md +254 -0
- package/.llm/components/textarea.md +370 -0
- package/.llm/components/textinput.md +475 -0
- package/.llm/components/tooltip.md +275 -0
- package/.llm/components/typography.md +253 -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 +53 -0
- package/.llm/digest/buttonicon.md +61 -0
- package/.llm/digest/card.md +51 -0
- package/.llm/digest/cardbody.md +70 -0
- package/.llm/digest/cardbutton.md +50 -0
- package/.llm/digest/checkbox.md +63 -0
- package/.llm/digest/ctabanner.md +44 -0
- package/.llm/digest/ctabannerslider.md +45 -0
- package/.llm/digest/divider.md +52 -0
- package/.llm/digest/dropdownmenu.md +67 -0
- package/.llm/digest/faqaccordion.md +43 -0
- package/.llm/digest/featurebullets.md +52 -0
- package/.llm/digest/featurecards.md +49 -0
- package/.llm/digest/featurescroll.md +52 -0
- package/.llm/digest/featuresplit.md +54 -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/landinghero.md +53 -0
- package/.llm/digest/link.md +59 -0
- package/.llm/digest/logocolumns.md +55 -0
- package/.llm/digest/logorows.md +48 -0
- package/.llm/digest/menuitem.md +46 -0
- package/.llm/digest/navbar.md +75 -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/pageheader.md +49 -0
- package/.llm/digest/pagination.md +60 -0
- package/.llm/digest/paginationdots.md +43 -0
- package/.llm/digest/producthero.md +53 -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 +73 -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/testimonialrow.md +51 -0
- package/.llm/digest/testimonialslider.md +51 -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 +107 -0
- package/.llm/rules.md +146 -0
- package/.llm/tokens.md +385 -0
- package/AGENTS.md +189 -0
- package/LICENSE +21 -0
- package/README.md +78 -10
- package/dist/components/banner-data.d.ts +38 -0
- package/dist/components/banner-data.js +15 -0
- package/dist/components/blocks/block-reveal.css +90 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
- package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
- package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
- package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
- package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
- package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
- package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
- package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
- package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
- package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
- package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
- package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
- package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
- package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
- package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
- package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
- package/dist/components/blocks/page-header/PageHeader.css +79 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
- package/dist/components/blocks/page-header/PageHeader.js +43 -0
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
- package/dist/components/blocks/page-header/page-header-impl.css +176 -0
- package/dist/components/blocks/product-hero/ProductHero.css +86 -0
- package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
- package/dist/components/blocks/product-hero/ProductHero.js +48 -0
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
- package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
- package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
- package/dist/components/blocks/use-reveal.d.ts +46 -0
- package/dist/components/blocks/use-reveal.js +120 -0
- package/dist/components/blocks/use-rotation.d.ts +62 -0
- package/dist/components/blocks/use-rotation.js +176 -0
- 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 +99 -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 +188 -0
- package/dist/components/core/button/Button.d.ts +27 -0
- package/dist/components/core/button/Button.js +57 -0
- package/dist/components/core/button/Button.types.d.ts +35 -0
- package/dist/components/core/button/Button.types.js +9 -0
- package/dist/components/core/button/button-impl.css +71 -0
- package/dist/components/core/button-icon/ButtonIcon.css +151 -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 +74 -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 +34 -0
- package/dist/components/core/card/Card.types.js +7 -0
- package/dist/components/core/card-body/CardBody.css +144 -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 +64 -0
- package/dist/components/core/card-body/CardBody.types.js +16 -0
- package/dist/components/core/card-body/card-body-impl.css +87 -0
- package/dist/components/core/card-button/CardButton.css +82 -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 +25 -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 +156 -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 +147 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +24 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.js +311 -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 +150 -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 +91 -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 +134 -0
- package/dist/components/core/navbar/Navbar.d.ts +52 -0
- package/dist/components/core/navbar/Navbar.js +498 -0
- package/dist/components/core/navbar/Navbar.types.d.ts +68 -0
- package/dist/components/core/navbar/Navbar.types.js +17 -0
- package/dist/components/core/navbar/navbar-impl.css +597 -0
- package/dist/components/core/navbar/navbar-material.css +96 -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 +130 -0
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +6 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +187 -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 +118 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +21 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +91 -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 +163 -0
- package/dist/components/core/pagination/Pagination.d.ts +30 -0
- package/dist/components/core/pagination/Pagination.js +366 -0
- package/dist/components/core/pagination/Pagination.types.d.ts +47 -0
- package/dist/components/core/pagination/Pagination.types.js +12 -0
- package/dist/components/core/pagination/pagination-impl.css +17 -0
- package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
- package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -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 +401 -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 +162 -0
- package/dist/components/core/select-chip/SelectChip.d.ts +20 -0
- package/dist/components/core/select-chip/SelectChip.js +276 -0
- package/dist/components/core/select-chip/SelectChip.types.d.ts +62 -0
- package/dist/components/core/select-chip/SelectChip.types.js +14 -0
- package/dist/components/core/select-chip/select-chip-impl.css +49 -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 +97 -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 +149 -1
- package/dist/components/index.js +145 -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/logo-data.d.ts +24 -0
- package/dist/components/logo-data.js +11 -0
- package/dist/components/scroll-data.d.ts +64 -0
- package/dist/components/scroll-data.js +17 -0
- package/dist/components/testimonial-row-data.d.ts +51 -0
- package/dist/components/testimonial-row-data.js +11 -0
- package/dist/components/testimonial-slider-data.d.ts +26 -0
- package/dist/components/testimonial-slider-data.js +10 -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 +581 -162
- package/package.json +13 -4
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
<!-- GENERATED from spinner.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Spinner
|
|
4
|
+
|
|
5
|
+
A turning ring that says a wait is real and the page has not stalled. A marketing page has very little to wait for — it is copy and pictures, and they arrive with the page — so a spinner here is the exception rather than the furniture: a form that has just been submitted, an embed or a demo still loading, a band of live figures being fetched.
|
|
6
|
+
|
|
7
|
+
That rarity is the brief. In an app a spinner is ordinary and a reader waits because they have an account and a reason to; on a landing page it is shown to someone with no stake in the outcome and nothing keeping them there. So it appears where a wait has already started — after the reader did something, or where a section has visibly held space for something that has not come — and nowhere else.
|
|
8
|
+
|
|
9
|
+
## Use when
|
|
10
|
+
|
|
11
|
+
- The reader has just submitted something — a signup, a contact request — and the page owes them a sign that it is working
|
|
12
|
+
- A section is holding space for content that arrives separately: an embed, a demo, a band of live figures
|
|
13
|
+
- Something the reader asked for is on its way and nobody can say how long it will take
|
|
14
|
+
|
|
15
|
+
## Do not use
|
|
16
|
+
|
|
17
|
+
- The wait is the page's own first load → nothing here does this
|
|
18
|
+
- How much is done is known, or could be → nothing here does this
|
|
19
|
+
- A wait short enough that the ring is a flash. A spinner that appears and goes inside a few hundred milliseconds reads as a glitch in the page rather than as work being done, and the reader is left with the flicker rather than the result
|
|
20
|
+
- More than one in a view. Three rings turning in three cards is a page that looks broken rather than busy — one spinner for the thing being waited on, at the level the reader is looking
|
|
21
|
+
- Decoration. A ring turning in a hero because the section looked static is motion with nothing behind it, and it teaches a reader that a spinner on this site does not mean a wait
|
|
22
|
+
- Standing in for content whose shape is already known. A ring in the middle of a section says nothing about what is coming and holds no room for it, so the layout jumps when it arrives — space the content will fill is better held by the space itself
|
|
23
|
+
|
|
24
|
+
## Anatomy
|
|
25
|
+
|
|
26
|
+
Spinner renders 4 elements. A token binding names the part it applies to.
|
|
27
|
+
|
|
28
|
+
- `root` — `<div>`, class `dds-spinner`. The container, and the thing that carries the accessible name when there is one. `inline-flex` in a column with the items centred: the circle, and the label beneath it when there is a label to draw.
|
|
29
|
+
|
|
30
|
+
A column rather than a row, and there is no orientation to choose. The label is off by default and the cases that show one are standalone — a section or a form waiting — where the words sit under the ring and the pair reads as one centred block. A spinner beside a line of text is the other case, and it is better served by omitting the label entirely and letting the sentence already on the page say what is loading.
|
|
31
|
+
- `circle` — `<svg>`, class `dds-spinner__circle`. The turning ring. Its shapes carry `vector-effect: non-scaling-stroke`, which is what makes the stroke-width tokens mean rendered pixels rather than viewBox units — without it one token would draw a different thickness at every size, right at one of them and wrong at the rest.
|
|
32
|
+
|
|
33
|
+
It takes the colour and the size — a fill role rather than an ink one, because the ring is a drawn shape and not text, and the fg roles are darkened to carry contrast as words; the rotation is in `spinner-impl.css`, because a keyframed loop is not something a contract can hold. It reads `--motion-duration-spinner` and `--motion-easing-spinner` straight from the built stylesheet: the token build emits every semantic role whether a contract binds it or not, so binding them here bought two `transition-*` declarations on an element that never transitions. That file also stops it under `prefers-reduced-motion`, where the ring stands still and the arc alone still marks the component as present.
|
|
34
|
+
- `track` — `<circle>`, class `dds-spinner__track`. The faint full ring the arc travels over. Drawn in the same colour as the arc, so the only thing separating them is its alpha — which is why it is a part rather than an attribute: `stroke-opacity` inherits, so bound on the svg it would fade the arc along with it and leave a ring with nothing moving on it.
|
|
35
|
+
- `label` — `<span>`, class `dds-spinner__label`. What is loading, in words. Rendered whenever a label is given, and hidden visually rather than dropped when `showLabel` is false — `role="status"` is a live region and a live region with no name is one that fires with nothing to say.
|
|
36
|
+
|
|
37
|
+
Absent with no label, rather than present and empty: the span exists to carry the name, and with no name to carry it is a flex item holding a gap open under the ring.
|
|
38
|
+
|
|
39
|
+
Its family is bound rather than inherited. A component that does not bind one takes whatever the page sets, and a marketing page sets a great many things — the ratified stack governs nothing it does not already happen to get. Rendered only when `label` is set.
|
|
40
|
+
|
|
41
|
+
Apply these classes from the generated `spinnerParts` constant rather than writing the strings by hand.
|
|
42
|
+
|
|
43
|
+
## Composition
|
|
44
|
+
|
|
45
|
+
- Takes no children. Everything it renders comes from props
|
|
46
|
+
|
|
47
|
+
## Props
|
|
48
|
+
|
|
49
|
+
### size — `sm` | `md` | `lg` (default `md`)
|
|
50
|
+
|
|
51
|
+
- `sm` — In a line of body copy, or inside a control the reader has just pressed. Sixteen, the size of the words beside it, so it sits on the line rather than in front of it
|
|
52
|
+
- `md` — The default. A form that has been submitted, a card waiting on the figure it is going to show
|
|
53
|
+
- `lg` — A section holding space for something that arrives separately — an embed, a demo, a band of live figures. Sized to be found from where the reader is looking, which is the whole section rather than one control in it
|
|
54
|
+
|
|
55
|
+
### variant — `accent` | `neutral` | `inherit` (default `accent`)
|
|
56
|
+
|
|
57
|
+
- `accent` — The default, and what a page nearly always wants. The wait is the one thing happening, and the brand colour is what says the page is doing it rather than failing to
|
|
58
|
+
- `neutral` — The wait is incidental to what the reader came for — a figure refreshing inside a card that is otherwise readable. Brand colour on a wait nobody is watching spends attention the page needs further down
|
|
59
|
+
- `inherit` — Inside something that has already set a colour: a filled button, a dark band, a coloured panel. `currentColor` reaches the ring and the label together.
|
|
60
|
+
|
|
61
|
+
This is also how a spinner on a dark section or a photograph gets its colour. There is no fixed-light or fixed-dark role in this package, and adding one would be asking a second time a question the section has already answered by setting its text colour
|
|
62
|
+
Never for: Marking one wait as more important than another. Two spinners in a view is the thing to fix; recolouring one of them is not
|
|
63
|
+
|
|
64
|
+
### label — `string` **Required when showLabel=true.**
|
|
65
|
+
|
|
66
|
+
Use when: Naming what is loading, for a spinner that stands on its own — a section, a form, a button whose own words have been replaced by it. Without it the spinner is decorative and says so properly: no role, no name, hidden from a screen reader outright
|
|
67
|
+
Never for: A second voice for something the page has already said. A ring beside a line reading “Sending your details” is not a separate thing loading, and naming it makes a screen reader announce the wait twice. Omitting it is what that case is for — an empty string is not, because an unnamed live region is still a live region and it still fires
|
|
68
|
+
|
|
69
|
+
### showLabel — `boolean` (default `false`)
|
|
70
|
+
|
|
71
|
+
Use when: The words should be drawn as well as announced — beneath the ring, for a section or a form where the reader can see the wait but not what it is for
|
|
72
|
+
|
|
73
|
+
Also accepts everything from `HTMLAttributes<HTMLDivElement>`.
|
|
74
|
+
|
|
75
|
+
## Accessibility
|
|
76
|
+
|
|
77
|
+
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.
|
|
78
|
+
|
|
79
|
+
- Announced as: `status`
|
|
80
|
+
- accessible name from label
|
|
81
|
+
- A spinner with no label carries no role either. Decorative is a real mode here rather than an oversight — aria-hidden, no live region, nothing announced — and it is the right one wherever the copy beside the ring already names the wait.
|
|
82
|
+
|
|
83
|
+
## Rules
|
|
84
|
+
|
|
85
|
+
- **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.
|
|
86
|
+
|
|
87
|
+
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.
|
|
88
|
+
|
|
89
|
+
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.
|
|
90
|
+
|
|
91
|
+
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.
|
|
92
|
+
|
|
93
|
+
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.
|
|
94
|
+
|
|
95
|
+
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.
|
|
96
|
+
Guidance only — cannot be checked automatically.
|
|
97
|
+
- **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.
|
|
98
|
+
Guidance only — cannot be checked automatically.
|
|
99
|
+
- **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.
|
|
100
|
+
|
|
101
|
+
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.
|
|
102
|
+
|
|
103
|
+
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.
|
|
104
|
+
Guidance only — cannot be checked automatically.
|
|
105
|
+
- **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.
|
|
106
|
+
|
|
107
|
+
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.
|
|
108
|
+
|
|
109
|
+
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.
|
|
110
|
+
|
|
111
|
+
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.
|
|
112
|
+
|
|
113
|
+
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.
|
|
114
|
+
|
|
115
|
+
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.
|
|
116
|
+
|
|
117
|
+
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.
|
|
118
|
+
|
|
119
|
+
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.
|
|
120
|
+
|
|
121
|
+
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.
|
|
122
|
+
Guidance only — cannot be checked automatically.
|
|
123
|
+
- **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.
|
|
124
|
+
|
|
125
|
+
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.
|
|
126
|
+
|
|
127
|
+
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.
|
|
128
|
+
|
|
129
|
+
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.
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
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.
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
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.
|
|
138
|
+
|
|
139
|
+
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.
|
|
140
|
+
Guidance only — cannot be checked automatically.
|
|
141
|
+
- **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.
|
|
142
|
+
|
|
143
|
+
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.
|
|
144
|
+
|
|
145
|
+
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.
|
|
146
|
+
|
|
147
|
+
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.
|
|
148
|
+
Guidance only — cannot be checked automatically.
|
|
149
|
+
- **A component is written along the reading axis, not along the page's left and right** — Every measure, inset and placement in this package names an axis rather than a side: inline-size and block-size, padding-inline and padding-block, inset-inline-start and inset-block-end, margin-inline: auto, text-align: start. Written that way a component follows whichever direction the page is read in, and a band whose claim ranges to the leading edge with its subject on the trailing one is the same composition in Arabic as in English, mirrored, with nothing restated. Written as left and right it is the same pixels in both, which is a layout nobody designed for the second language.
|
|
150
|
+
|
|
151
|
+
The enum values follow the same rule and for the same reason. A prop that names where a picture sits takes start and end, never left and right — FeatureSplit, FeatureBullets and FeatureScroll all declare mediaPosition that way, and the flex directions they generate flip on their own because row already means the reading order. A value called left would have to be re-read as right by every author working in a mirrored page, which is a translation this system should be doing rather than asking for.
|
|
152
|
+
|
|
153
|
+
The guidance a contract carries is part of the component, so it follows too. Describing a claim as ranging left is describing one of the two languages, and it was written that way here for a while: three of the opening bands said so in their own intent. A reader in a mirrored page meets that sentence and has to decide whether the component is wrong or the sentence is, and neither answer is one documentation should force.
|
|
154
|
+
|
|
155
|
+
Two things genuinely have no logical form and are not covered by this. A CSS gradient takes a physical direction — there is no to inline-end — so a pattern that must mirror has to be stated twice under a direction query, and one that is periodic and centred, like PageHeader's rule grid, does not need to. A glyph that points the way onward is the other: an arrow is a picture of a direction, and mirroring it belongs to the icon set rather than to the component holding it.
|
|
156
|
+
Guidance only — cannot be checked automatically.
|
|
157
|
+
|
|
158
|
+
## Anti-examples
|
|
159
|
+
|
|
160
|
+
❌ Spinner for: The wait is the page's own first load
|
|
161
|
+
Nothing here does this, and the useful thing is knowing why. A landing page that opens on a spinner has replaced its first impression with a placeholder — the reader has not asked for anything yet, so there is no wait they are party to, only a page that is not ready. That is a build and delivery problem, and a ring turning in the middle of it makes it look deliberate.
|
|
162
|
+
→ nothing in this system does this. Not a gap waiting to be filled — the case belongs outside it.
|
|
163
|
+
|
|
164
|
+
❌ Spinner for: How much is done is known, or could be
|
|
165
|
+
Nothing in this package shows progress yet, and a spinner is not a stand-in for it: a ring turning says only that something is happening, which is the right answer when it is the true one and a worse one than a bar whenever a share of the work can be named.
|
|
166
|
+
→ nothing in this system does this. Not a gap waiting to be filled — the case belongs outside it.
|
|
167
|
+
|
|
168
|
+
❌ showLabel=true + label missing or empty
|
|
169
|
+
A label shown on screen with no text in it is a gap held open under the ring, and a centred block that is no longer centred on anything
|
|
170
|
+
|
|
171
|
+
## Example
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { Spinner } from '@deriv-com/dds-marketing'
|
|
175
|
+
|
|
176
|
+
<Spinner label="Sending your details" showLabel />
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## In use
|
|
180
|
+
|
|
181
|
+
### Three sizes, three places
|
|
182
|
+
|
|
183
|
+
The size follows what the reader is looking at when the wait starts — a line of copy, a form, or a whole section holding space.
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { Spinner } from '@deriv-com/dds-marketing'
|
|
187
|
+
|
|
188
|
+
// sm — in a line of body copy, or in a control just pressed
|
|
189
|
+
<Spinner size="sm" label="Checking that address" />
|
|
190
|
+
|
|
191
|
+
// md — the default: a form that has just been submitted
|
|
192
|
+
<Spinner size="md" label="Sending your details" />
|
|
193
|
+
|
|
194
|
+
// lg — a section holding space for an embed or live figures
|
|
195
|
+
<Spinner size="lg" label="Loading live spreads" />
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Three colours, and the one that borrows
|
|
199
|
+
|
|
200
|
+
Brand says the page is working on what the reader asked for. Neutral is a wait nobody is watching. Inherit takes currentColor, which is how a ring gets its colour on a filled button or a dark band.
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { Spinner } from '@deriv-com/dds-marketing'
|
|
204
|
+
|
|
205
|
+
// accent — the default, and the wait the page owes the reader
|
|
206
|
+
<Spinner variant="accent" label="Sending your details" />
|
|
207
|
+
|
|
208
|
+
// neutral — a figure refreshing in a readable card
|
|
209
|
+
<Spinner variant="neutral" label="Refreshing prices" />
|
|
210
|
+
|
|
211
|
+
// inherit — inside something that has already set a colour
|
|
212
|
+
<Spinner variant="inherit" label="Sending your details" />
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Named, drawn, or neither
|
|
216
|
+
|
|
217
|
+
A standalone spinner has to name itself, and showLabel decides only whether the words are drawn. Omitting the label is the third mode: no role, nothing announced.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { Spinner } from '@deriv-com/dds-marketing'
|
|
221
|
+
|
|
222
|
+
// Named and announced, not drawn — the default
|
|
223
|
+
<Spinner label="Sending your details" />
|
|
224
|
+
|
|
225
|
+
// Drawn as well — the wait is visible, its reason is not
|
|
226
|
+
<Spinner label="Loading live spreads" showLabel size="lg" />
|
|
227
|
+
|
|
228
|
+
// Neither — decorative, beside copy that names the wait
|
|
229
|
+
<Spinner />
|
|
230
|
+
```
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
<!-- GENERATED from stack.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Stack
|
|
4
|
+
|
|
5
|
+
A column, and one measure between its rows. It draws nothing — no ground, no edge, no padding — and owns one decision: how far apart the things stacked in it sit. Everything else about them stays theirs.
|
|
6
|
+
|
|
7
|
+
It exists because the measure is what pages get wrong, and get wrong quietly. A gap typed as a number agreed with the system on the day it was written and never again. A gap written as a margin on the row belongs to the row, and travels with it into the next layout, where it is wrong and where nobody thinks to look — the last row of every group carrying a measure into whatever follows it. The column is the one thing that can see both sides of the space, so the column is what should own it.
|
|
8
|
+
|
|
9
|
+
On a marketing page the rhythm is the argument. A hero, a proof, a price and an ask are read in order and at a pace the spacing sets, and a page whose steps are picked one at a time reads as a list of things that happened to be put on a page. The ramp is what makes that pace a decision rather than an accumulation.
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
- Two or more things are read down the page in order and the space between them is the same the whole way down — an eyebrow, a headline and a line of copy; the points of a feature list; the rows of a plan
|
|
14
|
+
- The spacing is a fact about the group rather than about any member of it. Set here, every row agrees; set on the rows, the group is only as consistent as the last person to add one
|
|
15
|
+
- The measure should tighten on a phone without anyone writing a breakpoint. The top three steps of this ramp already do, so a column set at one of them is narrower below 768px and nothing about the page says so
|
|
16
|
+
|
|
17
|
+
## Do not use
|
|
18
|
+
|
|
19
|
+
- The things sit beside one another rather than one above the next → `Row`
|
|
20
|
+
- The things must line up across as well as down → `Grid`
|
|
21
|
+
- The set has to stay on one line and the reader moves along it → `Scroller`
|
|
22
|
+
- Padding. It sets space between its children and none at all around them, so a stack reached for to inset a section leaves the band that should have carried the padding with none — and the inset now lives on an element that has no ground to sit on
|
|
23
|
+
- A single child. A column of one has nothing to space: the gap is inert, and what is left is an element that renders, costs a node, and explains nothing to the next person to read it
|
|
24
|
+
- Reaching a width. It is as wide as whatever holds it and declares no size of its own. A page's measure is a decision about the page, and a stack used to constrain one is a width hidden inside a spacing decision, in the one place nobody will search for it
|
|
25
|
+
- Putting one thing in a particular place. The gap is a relationship between rows, not a distance from an edge — a measure picked because it lands something where it looks right is a position written in the wrong units, and it is wrong at the next width and on the next screen
|
|
26
|
+
- Separating sections that a ground already separates. A band with a fill of its own has an edge, and an edge is the separation; a large gap on top of it is the page saying the same thing twice and the reader reading a hole
|
|
27
|
+
|
|
28
|
+
## Anatomy
|
|
29
|
+
|
|
30
|
+
Stack renders one element.
|
|
31
|
+
|
|
32
|
+
- `root` — `<div>`, class `dds-stack`. The column, and the whole of what this component is. It paints nothing, holds no corner and takes no padding: an arrangement is not a surface, and one that brought a ground of its own would be a second surface inside whatever it was put in.
|
|
33
|
+
|
|
34
|
+
A flex column rather than a block with margins, because the gap has to be a property of the container for the rows to be interchangeable. Written as margins, the measure lives on the rows, the first or the last carries one nobody wanted, and reordering the group changes the spacing — three faults with one cause. It also means adjacent margins cannot collapse into one another, which is the oldest way for a page's rhythm to come out smaller than the sum of its parts with nothing in the source to show for it.
|
|
35
|
+
|
|
36
|
+
Its inline size is whatever contains it, and it declares none. What it does declare is `min-inline-size: 0`, which looks like nothing and is the difference between a stack that shrinks and one that does not: a flex item refuses to go below its content's intrinsic width, so a column holding a long unbroken string — a URL, an email address, a product name nobody hyphenated — placed inside a row would push its container wider rather than wrapping, and the overflow surfaces somewhere else entirely.
|
|
37
|
+
|
|
38
|
+
The gap is the one token binding here, and the top three steps of this package's ramp are redefined below 768px. That is the whole of this component's responsiveness and it is inherited rather than declared: the column asks for a role, the role is narrower on a phone, and no breakpoint is written here. A page wanting a different pace on a phone changes the token, not the column.
|
|
39
|
+
|
|
40
|
+
Apply these classes from the generated `stackParts` constant rather than writing the strings by hand.
|
|
41
|
+
|
|
42
|
+
## Composition
|
|
43
|
+
|
|
44
|
+
- Can contain: any content
|
|
45
|
+
|
|
46
|
+
## Props
|
|
47
|
+
|
|
48
|
+
### gap — `none` | `xs` | `sm` | `md` | `lg` | `xl` | `2xl` | `3xl` (default `md`)
|
|
49
|
+
|
|
50
|
+
- `none` — No gap at all, for rows meant to read as one object rather than as a list of controls. The only step here that is a decision rather than a measure
|
|
51
|
+
- `xs` — The tightest gap between related elements — an eyebrow and the headline under it, a figure and the caption beneath
|
|
52
|
+
- `sm` — The default step for sibling controls, and what the token names for a form label and the input under it
|
|
53
|
+
- `md` — The default, and what the token names for stacked items: form fields, feature list items, pricing features. Reach for this unless the column has a reason to be tighter or looser
|
|
54
|
+
- `lg` — Between content groups — feature cards, footer columns, one pricing plan and the next
|
|
55
|
+
- `xl` — Between the parts of a card, or between a heading and the block it introduces. Drops one step below 768px, a phone having a third of the width to spend
|
|
56
|
+
- `2xl` — Between one section of a page and the next. Drops one step below 768px, a phone having a third of the width to spend
|
|
57
|
+
- `3xl` — The largest gap, for separating whole movements of a long page. Drops one step below 768px, a phone having a third of the width to spend
|
|
58
|
+
|
|
59
|
+
Use when: Always. The measure between rows is the component's one decision and the reason it exists, so there is no case for leaving it unstated
|
|
60
|
+
Never for: Reaching a distance. The gap is a relationship between two rows rather than a measure from anything — a step picked because it puts something where it looks right is a position written in the wrong units, and it is wrong at the next width
|
|
61
|
+
|
|
62
|
+
### align — `start` | `center` | `end` | `stretch` (default `stretch`)
|
|
63
|
+
|
|
64
|
+
- `start` — Rows keep their own width and sit against the leading edge — a column of links, or a call to action as wide as its own label
|
|
65
|
+
- `center` — Rows keep their own width and are centred — a hero's copy, a closing block, anything read as one object on a ground wider than it
|
|
66
|
+
- `end` — Rows keep their own width and sit against the trailing edge, which on a page is rare and usually means the column is in a panel rather than in the flow
|
|
67
|
+
- `stretch` — The default. Every row takes the column's full width, which is what stacked cards, fields and bands want, and what makes their edges agree down the page
|
|
68
|
+
|
|
69
|
+
Use when: How wide the rows are, and where they sit across the column. The default is the common case and the one that keeps a stacked set looking like a set
|
|
70
|
+
Never for: Centring the words inside a row. This moves the row and not its contents — a paragraph centred by setting the column to `center` is also a paragraph shrunk to the width of its longest line, which is a different thing and rarely the wanted one. Centred text is `text-align` on the text
|
|
71
|
+
|
|
72
|
+
### justify — `start` | `center` | `end` | `between` (default `start`)
|
|
73
|
+
|
|
74
|
+
- `start` — The default. Rows sit at the top, and a column with no height of its own is exactly as tall as they are
|
|
75
|
+
- `center` — Rows sit together in the middle of a column that is taller than they are — a card in a row of cards whose copy is shorter than its neighbours'
|
|
76
|
+
- `end` — Rows sit at the foot of a column taller than they are
|
|
77
|
+
- `between` — The first row at the top, the last at the foot, and whatever room is spare shared between them — the shape a pricing card takes, where the price is at the top and the button has to sit on the same line as every other card's
|
|
78
|
+
|
|
79
|
+
Use when: Where the rows sit down a column that has more height than they need. On a page that is usually a card in a row of cards, stretched to its tallest neighbour
|
|
80
|
+
Never for: Making a column taller. This shares out height the column already has; where the column is sized by its own contents there is no room to share, and every value here draws exactly the same thing — which is the failure this prop has, silent and easy to spend an afternoon on
|
|
81
|
+
|
|
82
|
+
Also accepts everything from `HTMLAttributes<HTMLDivElement>`.
|
|
83
|
+
|
|
84
|
+
## Choosing a variant
|
|
85
|
+
|
|
86
|
+
Placement in, props out. When one of these describes what you are building, take
|
|
87
|
+
its props — do not re-derive them from the variant descriptions above.
|
|
88
|
+
|
|
89
|
+
- **An eyebrow, a headline and a line of copy at the top of a section** — `gap="xs"`
|
|
90
|
+
Three lines that read as one block. The tightest step is what says the headline belongs to the eyebrow rather than following it
|
|
91
|
+
- **The points of a feature list, one under the next** — `gap="md"`
|
|
92
|
+
The default step, and the one the token names for stacked items. Every point agrees without any point being asked
|
|
93
|
+
- **The sections of a long page, stacked** — `gap="2xl"`
|
|
94
|
+
Between one section and the next, and it tightens a step below 768px on its own — a phone having a third of the width to spend, and the same air reading as a hole
|
|
95
|
+
- **A closing block — one line and one call to action, centred on a wide ground** — `gap="lg"` `align="center"`
|
|
96
|
+
The rows keep their own width and sit in the middle, so the button is as wide as its label rather than as wide as the band. Stretched, one action reads as a bar
|
|
97
|
+
|
|
98
|
+
## Accessibility
|
|
99
|
+
|
|
100
|
+
Guaranteed by the component. Write none of it by hand: the ids these attributes point at are generated per instance, so an attribute set from outside either says the same thing twice or points at nothing.
|
|
101
|
+
|
|
102
|
+
- the column announces nothing of its own. It is an arrangement, and an arrangement is not something a reader needs told — what is inside carries the meaning, and each row keeps whatever name or role it would have had anywhere else
|
|
103
|
+
- a run of things of a kind is marked as one somewhere other than here. Spacing is not structure: six cards in a column are announced as six unrelated things however tightly they sit, and the markup around them is what says otherwise
|
|
104
|
+
- the order the rows are written in is the order they are read in. Nothing here reorders anything, and nothing here should be made to — a column whose visual order and DOM order disagree is read in one order and seen in another
|
|
105
|
+
|
|
106
|
+
## Rules
|
|
107
|
+
|
|
108
|
+
- **On a phone a section's actions stack and each fills the width, including when there is only one** — On a phone a page's actions stack, and each one fills the width. Not most of it, and not the width its label happens to need — the whole column.
|
|
109
|
+
|
|
110
|
+
Two side by side is what this replaces. On the narrowest screen each gets half a column minus the gap, which is rarely enough for a real label: the words wrap inside the pills, the two buttons come out different heights, and the pair reads as a broken row rather than as a choice. Stacked, each has the whole width and neither has to shorten its words to fit.
|
|
111
|
+
|
|
112
|
+
A single action fills too, and that is the part worth saying, because it is the one that looks unnecessary. A lone button has the room to sit at its natural width and still should not: a full-width control is the phone's convention for the thing the screen is asking you to do, and a pill hugging its label reads as one option among others that are not there. It also makes the target predictable — the whole width, wherever the thumb lands — which a centred pill does not.
|
|
113
|
+
|
|
114
|
+
Filling is the row's job rather than the button's. A button has no width of its own and is not given one; the row it sits in becomes a column and stretches its children, so nothing about the control changes and the same button is full width here and its own size on a desktop.
|
|
115
|
+
|
|
116
|
+
This is the phone's breakpoint, size.breakpoint.md, and not the wider one that decides whether a heading is centred. Those are different questions and they break at different widths: a heading stops being centred when the measure is the screen, while a button stops being full width much sooner than that — stretched across a tablet it is a long way from its own label, and a label centred in a metre of pill is harder to hit than one in a pill the size of the words.
|
|
117
|
+
|
|
118
|
+
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
119
|
+
Guidance only — cannot be checked automatically.
|
|
120
|
+
- **Never nest one interactive element inside another** — Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link, Input and Switch simultaneously.
|
|
121
|
+
Guidance only — cannot be checked automatically.
|
|
122
|
+
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
123
|
+
|
|
124
|
+
color.bg.brand carries a second limit that is not about forgetting. Its ink measures 3.39:1, which clears the 3:1 a heading needs and misses the 4.5:1 running copy needs. A coral band may carry a headline and a call to action; a paragraph on one is text the reader has to work through at a ratio the waiver on that role does not cover — the waiver says so itself. A section with copy in it takes color.bg.brand-strong, which is near-black and carries white at full contrast.
|
|
125
|
+
|
|
126
|
+
color.bg.strong is not a section ground. It is the inverted fill for an action that has to outrank what surrounds it, and the components that paint it — Button and ButtonIcon in their inverse form — already set both halves in one rule, which is the pattern a hand-painted section has to copy.
|
|
127
|
+
Guidance only — cannot be checked automatically.
|
|
128
|
+
- **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side** — A section's spacing is named by the relationship it expresses, not chosen by size. Every gap in a section has a role token, and reaching for a step off the generic scale because it happens to be the right number is how two sections written by two people stop lining up: the numbers agree today and drift the first time one of them is tuned.
|
|
129
|
+
|
|
130
|
+
The heading group is three steps, not one gap. An eyebrow sits nearer its title than the title sits to its description, and the actions sit further from the description than either — space.heading.eyebrow-title, space.heading.title-description, space.heading.description-actions, in that order. A single `gap` on the group cannot say this; it sets all three the same and the block reads as evenly spaced lines rather than as a mark, a name and a paragraph. The eyebrow has to identify itself for this to work, because a group that opens with a title must not give its description the eyebrow's tighter step.
|
|
131
|
+
|
|
132
|
+
The step between a title and its description follows the size of the title, which is why there are two of it. What a reader sees is not the gap but the gap plus the leading above it, and leading scales with the type: under a display title the leading is most of the space, under a card's title it is half as deep. One value for both makes a card look loose at the size that made a section look right. So space.heading.title-description is the display step and space.heading.title-description-compact is the step at a card's size, and the choice is made by how big the title is rather than by what kind of block it sits in.
|
|
133
|
+
|
|
134
|
+
Every one of those steps is smaller than the gap below the group, and that ordering is what holds the group together as one thing. space.heading.content is the step between a heading group and the content it introduces, and it is the widest measure inside a section: the one gap the eye reads as a change of subject rather than as a continuation.
|
|
135
|
+
|
|
136
|
+
That step is the same whether the content is under the heading or beside it. A split is the same relationship turned on its side — a heading group and the content it introduces — so the space between the two halves is space.heading.content, not a gutter. When the split collapses to one column on a phone the gap becomes vertical again, which is where it started, and nothing has to change for that to be right.
|
|
137
|
+
|
|
138
|
+
space.grid.gutter is between two things of the same kind. Two cards in a row are the same kind; the two halves of a split are not, which is why the gutter is the wrong measure there even when the number would have looked acceptable. The gutter runs on both axes, so a grid reads as an even field rather than as rows with a seam down them.
|
|
139
|
+
|
|
140
|
+
space.inset.card is the card's, not the page's. A row of cards padded differently is a row of different cards, and the fill is the only edge they have. A page composing a row does not get to choose it.
|
|
141
|
+
|
|
142
|
+
Column count is not a breakpoint decision. A row holds as many columns as fit before a column would be narrower than size.grid.column-min, and drops one when they would not. Written as a fixed count that collapses at a breakpoint, a four-up row keeps four columns at every width above the phone and sets its copy two or three words to a line through the whole of the tablet range — and on a narrow desktop, which no breakpoint sits on at all. The threshold is a property of the row rather than of a card: a card fills whatever cell it is given.
|
|
143
|
+
|
|
144
|
+
What this does not cover is the space above and below a section, which is space.section.default and space.section.compact, and the page's own side margin, which is space.inset.page. Those are the section's outside; everything here is its inside.
|
|
145
|
+
Guidance only — cannot be checked automatically.
|
|
146
|
+
- **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone** — Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
|
|
147
|
+
|
|
148
|
+
Content stacked under the title — a row of cards, an accordion, a set of steps — takes a centred title. The heading group and the block below it share one axis, so a centred title is symmetric with the thing it names, and the eye drops from the middle of the words to the middle of the set. A title starting at the left over a centred or full-width block reads as belonging to the first column rather than to all of them.
|
|
149
|
+
|
|
150
|
+
Content beside the title — a split, a picture in the other half, anything laid out in columns — takes a title that starts where its content starts. The two share a left edge, and that edge is what says they are one thing read across rather than two stacked. Centring the title there breaks the only alignment the reader has to hold the halves together, and it drifts further from its content the wider the page gets.
|
|
151
|
+
|
|
152
|
+
The heading group is what carries this, not the heading alone. An eyebrow, a title and a description are read as one block and align together; aligning the title without them leaves a centred heading over start-aligned copy, which reads as a mistake rather than as a choice.
|
|
153
|
+
|
|
154
|
+
Centred means all of it, not just the words. A badge, a row of actions, a picture — these are flex children, and a flex child is placed by align-items rather than by text-align, so a block that only sets the text leaves everything that is not text at the start. A hero is the case that shows it: its title and copy centred while its badge and its buttons did not.
|
|
155
|
+
|
|
156
|
+
A capped block centres itself as well as its words. A heading group takes size.heading-group.max, and a cap that is not centred leaves the measure at the start of the column with the words centred inside it — composed, and a long way left of the middle it appears to be in.
|
|
157
|
+
|
|
158
|
+
Both arrangements go to the start on a phone. A centred block reverts below the breakpoint, and the reason is the measure: on a phone the measure is the screen, so a centred title wraps to three or four ragged lines and the eye loses the left edge it was tracking — the same symmetry that reads as composure on a desktop is what makes it hard to scan on a phone. Centring there has to be asked for twice, and a section title is not one of the things that asks: it is centred because there is room for it, and on a phone there is not. Going back to the start means all of it too, and a capped block is the one that hides a leftover: its words go to the start while its measure stays in the middle of the column, which reads as a title still centred over a badge and buttons that are not — the box in the middle and the line inside it at the edge.
|
|
159
|
+
|
|
160
|
+
A hero is a section like any other: its badge, title, copy and actions are one stacked block, so it is centred on a desktop and starts on a phone with everything else.
|
|
161
|
+
|
|
162
|
+
What this is not about is a page whose body is a form or a document. A title over a sign-up form or a guide is not introducing a set of content — it is the first line of the thing itself, and it keeps the alignment the body has, which for running text is the start. The distinction is whether the block below is content the title names or content the title is part of.
|
|
163
|
+
Guidance only — cannot be checked automatically.
|
|
164
|
+
- **Anything a pointer has to hit is at least 24px in both directions** — A control sized by its contents is as big as its contents, and a glyph is chosen for how it reads rather than for how easily it is hit. An icon-only button with no padding is a 16px target — smaller than the pad of a finger, and smaller than the tremor of a hand using a mouse.
|
|
165
|
+
|
|
166
|
+
WCAG 2.2 asks for 24 by 24 CSS pixels at AA. The exceptions are narrower than they look: inline targets inside a sentence are exempt, and so is a small target with 24px of clear space around it — but a clear button sits against the field it empties, and a field is itself a target, so the spacing exemption does not apply to the case that keeps arising.
|
|
167
|
+
|
|
168
|
+
The target and the mark are separate decisions, and conflating them is what produces both faults. Growing the glyph to 24px makes it shout; leaving the button at 16px makes it hard to hit. So the glyph keeps the size that reads correctly beside its text, and the box around it declares a minimum of its own — which is what size.target.min is for.
|
|
169
|
+
|
|
170
|
+
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
171
|
+
Guidance only — cannot be checked automatically.
|
|
172
|
+
- **A component is written along the reading axis, not along the page's left and right** — Every measure, inset and placement in this package names an axis rather than a side: inline-size and block-size, padding-inline and padding-block, inset-inline-start and inset-block-end, margin-inline: auto, text-align: start. Written that way a component follows whichever direction the page is read in, and a band whose claim ranges to the leading edge with its subject on the trailing one is the same composition in Arabic as in English, mirrored, with nothing restated. Written as left and right it is the same pixels in both, which is a layout nobody designed for the second language.
|
|
173
|
+
|
|
174
|
+
The enum values follow the same rule and for the same reason. A prop that names where a picture sits takes start and end, never left and right — FeatureSplit, FeatureBullets and FeatureScroll all declare mediaPosition that way, and the flex directions they generate flip on their own because row already means the reading order. A value called left would have to be re-read as right by every author working in a mirrored page, which is a translation this system should be doing rather than asking for.
|
|
175
|
+
|
|
176
|
+
The guidance a contract carries is part of the component, so it follows too. Describing a claim as ranging left is describing one of the two languages, and it was written that way here for a while: three of the opening bands said so in their own intent. A reader in a mirrored page meets that sentence and has to decide whether the component is wrong or the sentence is, and neither answer is one documentation should force.
|
|
177
|
+
|
|
178
|
+
Two things genuinely have no logical form and are not covered by this. A CSS gradient takes a physical direction — there is no to inline-end — so a pattern that must mirror has to be stated twice under a direction query, and one that is periodic and centred, like PageHeader's rule grid, does not need to. A glyph that points the way onward is the other: an arrow is a picture of a direction, and mirroring it belongs to the icon set rather than to the component holding it.
|
|
179
|
+
Guidance only — cannot be checked automatically.
|
|
180
|
+
|
|
181
|
+
## Anti-examples
|
|
182
|
+
|
|
183
|
+
❌ Stack for: The things sit beside one another rather than one above the next
|
|
184
|
+
A line and a column are different questions, and the props that answer them differ — a row wraps, and aligns to a baseline, neither of which means anything down a column
|
|
185
|
+
→ use `Row` instead.
|
|
186
|
+
|
|
187
|
+
❌ Stack for: The things must line up across as well as down
|
|
188
|
+
A column gives every row the full width and no row any relation to the one beside it, there being none. A set of cards that must agree in both directions is tracks, and a stack that looks like a grid at one width stops being one at the next
|
|
189
|
+
→ use `Grid` instead.
|
|
190
|
+
|
|
191
|
+
❌ Stack for: The set has to stay on one line and the reader moves along it
|
|
192
|
+
That is the third answer to a row that has run out of room, and it carries the snapping and the tab stop that make the rail reachable. A column never has the problem
|
|
193
|
+
→ use `Scroller` instead.
|
|
194
|
+
|
|
195
|
+
## Example
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
199
|
+
|
|
200
|
+
<Stack gap="xs">
|
|
201
|
+
<Typography variant="eyebrow">Why Deriv</Typography>
|
|
202
|
+
<Typography variant="h2" as="h2">Trade the markets you already follow</Typography>
|
|
203
|
+
<Typography variant="body-lg">Over 200 instruments, one account, and no minimum to begin.</Typography>
|
|
204
|
+
</Stack>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## In use
|
|
208
|
+
|
|
209
|
+
### What it is for
|
|
210
|
+
|
|
211
|
+
Things read down the page with one measure between them. On a page the rhythm is the argument, and the column is what sets its pace.
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
215
|
+
|
|
216
|
+
// An eyebrow, a headline, a line
|
|
217
|
+
<Stack gap="xs">
|
|
218
|
+
<Typography variant="eyebrow">Why Deriv</Typography>
|
|
219
|
+
<Typography variant="h2" as="h2">Trade the markets you already follow</Typography>
|
|
220
|
+
<Typography variant="body-lg">Over 200 instruments, one account, and no minimum to begin.</Typography>
|
|
221
|
+
</Stack>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Every step between rows
|
|
225
|
+
|
|
226
|
+
The same two lines at each step. Nothing about the words changes — the measure decides whether the second reads as part of the first, beside it, or long after it.
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
import { Stack, Typography } from '@deriv-com/dds-marketing'
|
|
230
|
+
|
|
231
|
+
// none — rows carry their own
|
|
232
|
+
<Stack gap="none">
|
|
233
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
234
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
235
|
+
</Stack>
|
|
236
|
+
|
|
237
|
+
// xs — two lines that read as one
|
|
238
|
+
<Stack gap="xs">
|
|
239
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
240
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
241
|
+
</Stack>
|
|
242
|
+
|
|
243
|
+
// sm — a label and the field under it
|
|
244
|
+
<Stack gap="sm">
|
|
245
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
246
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
247
|
+
</Stack>
|
|
248
|
+
|
|
249
|
+
// md — the default — stacked peers
|
|
250
|
+
<Stack gap="md">
|
|
251
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
252
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
253
|
+
</Stack>
|
|
254
|
+
|
|
255
|
+
// lg — content groups
|
|
256
|
+
<Stack gap="lg">
|
|
257
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
258
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
259
|
+
</Stack>
|
|
260
|
+
|
|
261
|
+
// xl — parts of a card — tightens on a phone
|
|
262
|
+
<Stack gap="xl">
|
|
263
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
264
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
265
|
+
</Stack>
|
|
266
|
+
|
|
267
|
+
// 2xl — one section to the next — tightens
|
|
268
|
+
<Stack gap="2xl">
|
|
269
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
270
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
271
|
+
</Stack>
|
|
272
|
+
|
|
273
|
+
// 3xl — whole movements — tightens
|
|
274
|
+
<Stack gap="3xl">
|
|
275
|
+
<Typography variant="h4" as="h3">Regulated in six jurisdictions</Typography>
|
|
276
|
+
<Typography variant="body-md">Client funds are held in segregated accounts.</Typography>
|
|
277
|
+
</Stack>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### How wide the rows are
|
|
281
|
+
|
|
282
|
+
The default stretches every row to the column's width. The other three let each row be as wide as its own contents — the shape a hero's copy or a closing block takes.
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
import { Button, Stack, Typography } from '@deriv-com/dds-marketing'
|
|
286
|
+
|
|
287
|
+
// stretch — the default — every row the full width
|
|
288
|
+
<Stack gap="sm" align="stretch">
|
|
289
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
290
|
+
<Button variant="primary">Get started</Button>
|
|
291
|
+
</Stack>
|
|
292
|
+
|
|
293
|
+
// start — each row its own width, leading
|
|
294
|
+
<Stack gap="sm" align="start">
|
|
295
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
296
|
+
<Button variant="primary">Get started</Button>
|
|
297
|
+
</Stack>
|
|
298
|
+
|
|
299
|
+
// center — each row its own width, centred
|
|
300
|
+
<Stack gap="sm" align="center">
|
|
301
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
302
|
+
<Button variant="primary">Get started</Button>
|
|
303
|
+
</Stack>
|
|
304
|
+
|
|
305
|
+
// end — each row its own width, trailing
|
|
306
|
+
<Stack gap="sm" align="end">
|
|
307
|
+
<Typography variant="body-md">Open an account in minutes.</Typography>
|
|
308
|
+
<Button variant="primary">Get started</Button>
|
|
309
|
+
</Stack>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Where the rows sit
|
|
313
|
+
|
|
314
|
+
Only bites where something has given the column a height — a card stretched to its tallest neighbour. Nothing here has, so all four draw identically.
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
import { Button, Stack, Typography } from '@deriv-com/dds-marketing'
|
|
318
|
+
|
|
319
|
+
// start — rows at the top
|
|
320
|
+
<Stack gap="sm" justify="start">
|
|
321
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
322
|
+
<Button variant="secondary">Choose plan</Button>
|
|
323
|
+
</Stack>
|
|
324
|
+
|
|
325
|
+
// center — rows in the middle
|
|
326
|
+
<Stack gap="sm" justify="center">
|
|
327
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
328
|
+
<Button variant="secondary">Choose plan</Button>
|
|
329
|
+
</Stack>
|
|
330
|
+
|
|
331
|
+
// end — rows at the foot
|
|
332
|
+
<Stack gap="sm" justify="end">
|
|
333
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
334
|
+
<Button variant="secondary">Choose plan</Button>
|
|
335
|
+
</Stack>
|
|
336
|
+
|
|
337
|
+
// between — first at top, last at foot
|
|
338
|
+
<Stack gap="sm" justify="between">
|
|
339
|
+
<Typography variant="h4" as="h3">Standard</Typography>
|
|
340
|
+
<Button variant="secondary">Choose plan</Button>
|
|
341
|
+
</Stack>
|
|
342
|
+
```
|