@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,52 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import './Navbar.css';
|
|
3
|
+
import './navbar-impl.css';
|
|
4
|
+
import './navbar-material.css';
|
|
5
|
+
import { type NavbarProps } from './Navbar.types.js';
|
|
6
|
+
export type { NavbarProps };
|
|
7
|
+
/**
|
|
8
|
+
* Whether the bar is gathered, given what it was and how far the page has moved.
|
|
9
|
+
*
|
|
10
|
+
* Lifted out of the listener and exported because it is the one part of the scroll behaviour that
|
|
11
|
+
* can be checked without a browser: jsdom has no scrolling, no layout and no pointer, so the hook
|
|
12
|
+
* around this can only be run, not observed. The rule it encodes — that the two thresholds differ,
|
|
13
|
+
* and which way round — is exactly the part that was wrong before and would be wrong again quietly.
|
|
14
|
+
*/
|
|
15
|
+
export declare function gathered(was: boolean, offset: number): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* A slot's contents as one flat list, with every fragment opened.
|
|
18
|
+
*
|
|
19
|
+
* A page hands a pair of actions over as `<>…</>` and a list of switchers the same way, and
|
|
20
|
+
* `Children.map` does not look inside a fragment — so a fragment reached anything that matched on
|
|
21
|
+
* type, NavbarPanel's switcher-to-row swap included, as one opaque element. Opened here, once,
|
|
22
|
+
* each control is a child of its own wherever the slot is drawn.
|
|
23
|
+
*
|
|
24
|
+
* Every element comes out with a key unique across the whole list. `Children.toArray` keys each
|
|
25
|
+
* level from `.0` again, so the children of two fragments side by side would share keys and React
|
|
26
|
+
* could hand one control's state — an open switcher, say — to another. Each key is prefixed with
|
|
27
|
+
* the path of fragments it came through, the way React keys nested arrays itself.
|
|
28
|
+
*/
|
|
29
|
+
export declare function flattened(node: ReactNode, path?: string): ReactNode[];
|
|
30
|
+
/**
|
|
31
|
+
* The bar across the top of a marketing page: the mark, the places the site has,
|
|
32
|
+
* and the things a reader reaches for rather than navigates to.
|
|
33
|
+
*
|
|
34
|
+
* It holds no destinations of its own — what goes in it is what the page
|
|
35
|
+
* composes. What this owns is the bar, and running out of room is the whole of
|
|
36
|
+
* its behaviour: below the width its three regions fit in, the destinations and
|
|
37
|
+
* the utilities stop being drawn and the trigger takes their place.
|
|
38
|
+
*
|
|
39
|
+
* Which section is open is the bar's, not each menu's. A menu cannot see its
|
|
40
|
+
* neighbours, so left to themselves two of them open at once and two surfaces
|
|
41
|
+
* overlap in front of the page. Injected the way TabList injects `selected`, and
|
|
42
|
+
* for the same reason.
|
|
43
|
+
*
|
|
44
|
+
* The rail paints nothing and the row inside it is the container a reader sees.
|
|
45
|
+
* That split is why there is no line under the bar: what separates it from the
|
|
46
|
+
* page is a surface of its own with air around it.
|
|
47
|
+
*
|
|
48
|
+
* No `role="banner"`. A `<header>` outside a sectioning element already is that
|
|
49
|
+
* landmark, and writing it as well says so a second time in a way that goes stale
|
|
50
|
+
* if the element is ever nested.
|
|
51
|
+
*/
|
|
52
|
+
export declare function Navbar({ tone, label, menuLabel, closeLabel, brand, utilities, compactAction, preferences, showThemeToggle, theme, onThemeChange, themeToggleLabel, menuOpen, onMenuOpenChange, children, ...rest }: NavbarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useLayoutEffect, Children, Fragment, cloneElement, isValidElement, useCallback, useEffect, useRef, useState, } from 'react';
|
|
4
|
+
import { BarsRegularIcon, MoonRegularIcon, SunBrightRegularIcon, XmarkRegularIcon, } from '@deriv-com/quill-icons-web';
|
|
5
|
+
import './Navbar.css';
|
|
6
|
+
import './navbar-impl.css';
|
|
7
|
+
import './navbar-material.css';
|
|
8
|
+
import { Button } from '../button/Button.js';
|
|
9
|
+
import { buttonDefaults } from '../button/Button.types.js';
|
|
10
|
+
import { ButtonIcon } from '../button-icon/ButtonIcon.js';
|
|
11
|
+
import { milliseconds } from '../../css-time.js';
|
|
12
|
+
import { DropdownMenu } from '../dropdown-menu/DropdownMenu.js';
|
|
13
|
+
import { Icon } from '../icon/Icon.js';
|
|
14
|
+
import { NavbarItem } from '../navbar-item/NavbarItem.js';
|
|
15
|
+
import { NavbarMenu } from '../navbar-menu/NavbarMenu.js';
|
|
16
|
+
import { NavbarPanel } from '../navbar-panel/NavbarPanel.js';
|
|
17
|
+
import { NavbarSwitcher } from '../navbar-switcher/NavbarSwitcher.js';
|
|
18
|
+
import { navbarDefaults, navbarParts } from './Navbar.types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Both handlers, the menu's own first.
|
|
21
|
+
*
|
|
22
|
+
* `cloneElement` replaces rather than merges, so a menu already reporting its own
|
|
23
|
+
* state would silently stop — and that is the handler a page is most likely to
|
|
24
|
+
* have written, since it is how they learn which section was opened.
|
|
25
|
+
*/
|
|
26
|
+
function chain(theirs, ours) {
|
|
27
|
+
if (theirs === undefined)
|
|
28
|
+
return ours;
|
|
29
|
+
return (open) => {
|
|
30
|
+
theirs(open);
|
|
31
|
+
ours(open);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether anything beneath the bar has been scrolled.
|
|
36
|
+
*
|
|
37
|
+
* The window is the usual answer and not the only one: a bar inside a box with
|
|
38
|
+
* its own `overflow` — a preview stage, a split layout, an embedded view —
|
|
39
|
+
* travels with that box, and the window beneath it never moves at all. So the
|
|
40
|
+
* question is asked of every ancestor rather than of one guessed node.
|
|
41
|
+
*
|
|
42
|
+
* Listened for in the capture phase on the document, because a scroll event
|
|
43
|
+
* does not bubble: a listener on the window hears the window and nothing else,
|
|
44
|
+
* which is precisely the case that was already broken.
|
|
45
|
+
*
|
|
46
|
+
* Absent outside a browser rather than fatal. The bar renders at rest on a
|
|
47
|
+
* server and in jsdom, which is where the generated behaviour test runs it, and
|
|
48
|
+
* at rest is the correct first frame either way.
|
|
49
|
+
*/
|
|
50
|
+
/** How far the page travels before the bar gathers, and how far back before it lets go. */
|
|
51
|
+
const CONDENSE_AT = 32;
|
|
52
|
+
const RESTORE_AT = 0;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the bar is gathered, given what it was and how far the page has moved.
|
|
55
|
+
*
|
|
56
|
+
* Lifted out of the listener and exported because it is the one part of the scroll behaviour that
|
|
57
|
+
* can be checked without a browser: jsdom has no scrolling, no layout and no pointer, so the hook
|
|
58
|
+
* around this can only be run, not observed. The rule it encodes — that the two thresholds differ,
|
|
59
|
+
* and which way round — is exactly the part that was wrong before and would be wrong again quietly.
|
|
60
|
+
*/
|
|
61
|
+
export function gathered(was, offset) {
|
|
62
|
+
return was ? offset > RESTORE_AT : offset > CONDENSE_AT;
|
|
63
|
+
}
|
|
64
|
+
function useScrolled(root) {
|
|
65
|
+
const [scrolled, setScrolled] = useState(false);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (typeof window === 'undefined')
|
|
68
|
+
return;
|
|
69
|
+
const read = () => {
|
|
70
|
+
let offset = window.scrollY;
|
|
71
|
+
for (let node = root.current?.parentElement ?? null; node !== null; node = node.parentElement) {
|
|
72
|
+
offset = Math.max(offset, node.scrollTop);
|
|
73
|
+
}
|
|
74
|
+
/*
|
|
75
|
+
Two thresholds, not one. A single boundary at nought meant one pixel of
|
|
76
|
+
travel rearranged the whole bar — and a trackpad resting against the top
|
|
77
|
+
of a page, or a rubber-band easing back, crosses that boundary repeatedly
|
|
78
|
+
in both directions: the bar flickered between its two arrangements while
|
|
79
|
+
the reader was not scrolling at all.
|
|
80
|
+
|
|
81
|
+
Gathering needs a deliberate scroll; returning needs the top of the page.
|
|
82
|
+
The gap between the two is what makes the state sticky in the ordinary
|
|
83
|
+
sense of the word — once it changes, small movements cannot change it
|
|
84
|
+
back.
|
|
85
|
+
*/
|
|
86
|
+
setScrolled((was) => gathered(was, offset));
|
|
87
|
+
};
|
|
88
|
+
// Once before listening. A reader arriving at an anchor deep in the page, or
|
|
89
|
+
// returning to one the browser has restored the scroll position of, is
|
|
90
|
+
// already past the top and never fires a scroll event to say so.
|
|
91
|
+
read();
|
|
92
|
+
// Passive: this only reads, and saying so lets the browser scroll without
|
|
93
|
+
// waiting to find out whether the handler means to cancel it.
|
|
94
|
+
document.addEventListener('scroll', read, { capture: true, passive: true });
|
|
95
|
+
return () => document.removeEventListener('scroll', read, { capture: true });
|
|
96
|
+
}, [root]);
|
|
97
|
+
return scrolled;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A box that comes and goes, by collapsing in place rather than leaving.
|
|
101
|
+
*
|
|
102
|
+
* The bar holds two copies of the mark and two of the actions — one pair at the row's ends, one
|
|
103
|
+
* pair inside the pill — and exactly one of each is showing. What makes the change between them
|
|
104
|
+
* smooth is not how the copies are hidden but that they are hidden *in the flow*: a box whose width
|
|
105
|
+
* travels to nothing takes the row with it, so the pill grows into the space as it is given up and
|
|
106
|
+
* the destinations slide along on their own. Nothing has to be measured afterwards and moved back.
|
|
107
|
+
*
|
|
108
|
+
* Everything this replaces was a workaround for having prevented that. Taking the copies out of the
|
|
109
|
+
* flow stopped the row reflowing, so the pill's growth had to be faked by drawing its shape in, and
|
|
110
|
+
* the words inside it had to be caught mid-jump and played backwards. Three mechanisms, each with
|
|
111
|
+
* its own bugs, standing in for the one the layout does by itself.
|
|
112
|
+
*
|
|
113
|
+
* The width has to be measured because CSS cannot travel between a length and `auto`, and the
|
|
114
|
+
* steady states are `0` and whatever the contents come to. The layout effect runs after React has
|
|
115
|
+
* written the change and before the browser paints it, so the element is already at its new size:
|
|
116
|
+
* expanding, that is the size to arrive at; collapsing, the size to leave from is the one held from
|
|
117
|
+
* last time.
|
|
118
|
+
*
|
|
119
|
+
* The gap goes with it. A flex container puts its gap either side of every item including one that
|
|
120
|
+
* is nought wide, so a collapsed copy would leave the space it used to occupy — the pill would sit
|
|
121
|
+
* a gap wider than its contents at rest. The margin against that gap travels to minus it, on the
|
|
122
|
+
* side the gap is on, which is the end the box is at.
|
|
123
|
+
*
|
|
124
|
+
* `overflow: hidden` only while it runs. Permanently, it would clip a focus ring on the button
|
|
125
|
+
* inside; for the four hundred milliseconds the box is narrower than what it holds, it is the
|
|
126
|
+
* difference between contents that are revealed and contents that spill.
|
|
127
|
+
*/
|
|
128
|
+
function useCollapse(element, collapsed, gapSide) {
|
|
129
|
+
const width = useRef(null);
|
|
130
|
+
const inset = useRef(null);
|
|
131
|
+
const settled = useRef(false);
|
|
132
|
+
const latest = useRef(null);
|
|
133
|
+
useLayoutEffect(() => {
|
|
134
|
+
const node = element.current;
|
|
135
|
+
if (node === null)
|
|
136
|
+
return;
|
|
137
|
+
const measured = node.getBoundingClientRect().width;
|
|
138
|
+
const previous = width.current;
|
|
139
|
+
const held = inset.current;
|
|
140
|
+
if (!collapsed) {
|
|
141
|
+
width.current = measured;
|
|
142
|
+
// Read while it is showing: collapsed, the stylesheet has already taken it to nothing, and a
|
|
143
|
+
// keyframe built from that would travel from nothing to nothing.
|
|
144
|
+
const shown = getComputedStyle(node);
|
|
145
|
+
inset.current = `${shown.paddingInlineStart} ${shown.paddingInlineEnd}`;
|
|
146
|
+
}
|
|
147
|
+
/*
|
|
148
|
+
The first pass is the page arriving, not the bar changing. Without this the copies that are
|
|
149
|
+
showing on load would travel in from nothing, which is an entrance nobody asked for and a
|
|
150
|
+
flash on every render.
|
|
151
|
+
*/
|
|
152
|
+
const first = !settled.current;
|
|
153
|
+
settled.current = true;
|
|
154
|
+
if (first)
|
|
155
|
+
return;
|
|
156
|
+
/*
|
|
157
|
+
And a width to leave from is only needed when leaving. Expanding, the size to arrive at is the
|
|
158
|
+
one just measured — the element is already at it, because CSS has stopped collapsing it and
|
|
159
|
+
the browser has not painted yet.
|
|
160
|
+
|
|
161
|
+
That distinction is the whole of a glitch that showed once per page. The pill's pair is
|
|
162
|
+
collapsed when the bar first renders, so nothing measured it, so the guard that waits for a
|
|
163
|
+
previous width caught them on the first gather and they appeared in one frame while the row's
|
|
164
|
+
pair collapsed smoothly beside them. Only once, and only ever on the way out.
|
|
165
|
+
*/
|
|
166
|
+
if (collapsed && previous === null)
|
|
167
|
+
return;
|
|
168
|
+
/*
|
|
169
|
+
Absent outside a browser that draws: jsdom implements neither, and the generated tests render
|
|
170
|
+
this component. Asking for the feature rather than for an environment.
|
|
171
|
+
*/
|
|
172
|
+
if (typeof window === 'undefined')
|
|
173
|
+
return;
|
|
174
|
+
if (typeof window.matchMedia !== 'function')
|
|
175
|
+
return;
|
|
176
|
+
if (typeof node.animate !== 'function')
|
|
177
|
+
return;
|
|
178
|
+
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches)
|
|
179
|
+
return;
|
|
180
|
+
const style = getComputedStyle(node);
|
|
181
|
+
const duration = milliseconds(style.getPropertyValue('--motion-duration-shift')) ?? 400;
|
|
182
|
+
const easing = style.getPropertyValue('--motion-easing-shift').trim() || 'ease';
|
|
183
|
+
const gap = style.getPropertyValue('--space-gap-md').trim() || '0';
|
|
184
|
+
const margin = gapSide === 'start' ? 'marginInlineStart' : 'marginInlineEnd';
|
|
185
|
+
/*
|
|
186
|
+
The inset travels with the width, because `box-sizing: border-box` will not take a box below
|
|
187
|
+
its own padding: a mark collapsed to nothing still held the twelve pixels it insets itself by,
|
|
188
|
+
and left them standing at the pill's leading edge.
|
|
189
|
+
*/
|
|
190
|
+
const padding = (collapsed ? held : inset.current) ?? '0';
|
|
191
|
+
const open = {
|
|
192
|
+
inlineSize: `${collapsed ? (previous ?? measured) : measured}px`,
|
|
193
|
+
[margin]: '0',
|
|
194
|
+
opacity: 1,
|
|
195
|
+
paddingInline: padding,
|
|
196
|
+
};
|
|
197
|
+
const shut = { inlineSize: '0', [margin]: `calc(${gap} * -1)`, opacity: 0, paddingInline: '0' };
|
|
198
|
+
node.style.overflow = 'hidden';
|
|
199
|
+
/*
|
|
200
|
+
`fill: backwards` is what stops the flicker, and it is one frame long.
|
|
201
|
+
|
|
202
|
+
The effect below runs before the browser paints, but an animation does not take hold until the
|
|
203
|
+
frame after it is started — so for exactly one frame the element is drawn at whatever the
|
|
204
|
+
stylesheet says, which is the state it is travelling *to*. Expanding, that is a mark at full
|
|
205
|
+
width appearing for a frame and then starting again from nothing. Backwards fill applies the
|
|
206
|
+
first keyframe from the moment the animation exists rather than from the moment it starts.
|
|
207
|
+
*/
|
|
208
|
+
const running = node.animate(collapsed ? [open, shut] : [shut, open], {
|
|
209
|
+
duration,
|
|
210
|
+
easing,
|
|
211
|
+
fill: 'backwards',
|
|
212
|
+
});
|
|
213
|
+
/*
|
|
214
|
+
Put the overflow back whether it finished or was cut short — a second scroll cancels the first
|
|
215
|
+
animation, which rejects `finished`, and a box left clipped would clip the focus ring on the
|
|
216
|
+
button inside it for the rest of the session.
|
|
217
|
+
|
|
218
|
+
Only if this is still the animation in force, though. Scrolling up and down quickly starts a
|
|
219
|
+
second before the first has resolved, and the first one's cleanup would otherwise unclip a box
|
|
220
|
+
that the second is still narrowing — which is the content spilling out of it and back in, once
|
|
221
|
+
per change of mind.
|
|
222
|
+
*/
|
|
223
|
+
latest.current = running;
|
|
224
|
+
const restore = () => {
|
|
225
|
+
if (latest.current !== running)
|
|
226
|
+
return;
|
|
227
|
+
node.style.overflow = '';
|
|
228
|
+
};
|
|
229
|
+
running.finished.then(restore).catch(restore);
|
|
230
|
+
}, [element, collapsed, gapSide]);
|
|
231
|
+
}
|
|
232
|
+
/** The two of this package's own components a page is likely to put in a switcher slot. */
|
|
233
|
+
const TONED = [DropdownMenu, ButtonIcon, NavbarSwitcher];
|
|
234
|
+
/**
|
|
235
|
+
* The tone, pressed on a switcher or a secondary action the page passed in.
|
|
236
|
+
*
|
|
237
|
+
* A slot is the page's and this component does not dress what goes in one — that rule is why the
|
|
238
|
+
* mark is the page's to make legible. This is the exception, and it earns it: what the tone has to
|
|
239
|
+
* answer is the ground *this* component painted, and it changes on scroll, which no page can see
|
|
240
|
+
* without writing a second scroll listener against the bar it is already inside.
|
|
241
|
+
*
|
|
242
|
+
* A secondary Button is told too, and only a secondary one. Its `inverse` tone is a fill for a dark
|
|
243
|
+
* ground, and a page that set it for the hero left it white-on-white once the bar gathered into its
|
|
244
|
+
* pill. A primary is coral on either ground and carries its own, so it is left as it was handed.
|
|
245
|
+
*
|
|
246
|
+
* And every Button in the bar's action slots is drawn at `md`, whatever the page passed: the bar's
|
|
247
|
+
* items stand at size.control.md, and a button a step taller than the row it sits in pushes the
|
|
248
|
+
* bar taller with it. The collapsed panel's foot is not the bar, so it keeps the page's size.
|
|
249
|
+
*
|
|
250
|
+
* Matched by type rather than hoped for. Anything else the slot is handed goes through untouched,
|
|
251
|
+
* because pressing the prop on a component that does not declare it would put an unknown attribute
|
|
252
|
+
* on a DOM node, which React says out loud and a reader then has to go and disprove.
|
|
253
|
+
*
|
|
254
|
+
* Each of several, not only a lone one. The slot is for "a language picker, a theme toggle", and
|
|
255
|
+
* handed both as a list the second used to go through undressed — dark ink on a dark hero.
|
|
256
|
+
*/
|
|
257
|
+
function toned(children, dressing) {
|
|
258
|
+
// An empty slot stays empty rather than becoming `[]`, which every "is there anything here"
|
|
259
|
+
// check downstream — NavbarPanel's among them, and the bar's own — would read as something to
|
|
260
|
+
// draw a box for. `false` from a `{signedIn && <Button/>}` flattens to nothing, so it is empty too.
|
|
261
|
+
return children.length === 0 ? undefined : children.map((child) => dressed(child, dressing));
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* A slot's contents as one flat list, with every fragment opened.
|
|
265
|
+
*
|
|
266
|
+
* A page hands a pair of actions over as `<>…</>` and a list of switchers the same way, and
|
|
267
|
+
* `Children.map` does not look inside a fragment — so a fragment reached anything that matched on
|
|
268
|
+
* type, NavbarPanel's switcher-to-row swap included, as one opaque element. Opened here, once,
|
|
269
|
+
* each control is a child of its own wherever the slot is drawn.
|
|
270
|
+
*
|
|
271
|
+
* Every element comes out with a key unique across the whole list. `Children.toArray` keys each
|
|
272
|
+
* level from `.0` again, so the children of two fragments side by side would share keys and React
|
|
273
|
+
* could hand one control's state — an open switcher, say — to another. Each key is prefixed with
|
|
274
|
+
* the path of fragments it came through, the way React keys nested arrays itself.
|
|
275
|
+
*/
|
|
276
|
+
export function flattened(node, path = '') {
|
|
277
|
+
return Children.toArray(node).flatMap((child) => {
|
|
278
|
+
if (!isValidElement(child))
|
|
279
|
+
return [child];
|
|
280
|
+
const key = `${path}${String(child.key)}`;
|
|
281
|
+
if (child.type === Fragment)
|
|
282
|
+
return flattened(child.props.children, `${key}/`);
|
|
283
|
+
return [path === '' ? child : cloneElement(child, { key })];
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* The bar's actions are a pair, and a page that hands it more is told.
|
|
288
|
+
*
|
|
289
|
+
* At most two Buttons: one primary, and one secondary beside it — the conversion and the way back
|
|
290
|
+
* in. A lone Button is the primary. A third, or a second of either rank, is the bar asking the
|
|
291
|
+
* reader to choose between things it should have ranked; the `navbar-actions-are-a-pair` rule has
|
|
292
|
+
* the reasoning. Nothing checks a page's JSX yet, so this is where it is caught.
|
|
293
|
+
*
|
|
294
|
+
* Said, not refused. The bar still draws what it was handed — a page mid-build that lost its
|
|
295
|
+
* buttons would be worse than one with a third — and says so once for each shape of mistake, the
|
|
296
|
+
* way product's charts warn about a crowded palette.
|
|
297
|
+
*/
|
|
298
|
+
const warned = new Set();
|
|
299
|
+
function warnIfActionsAreNotAPair(utilities) {
|
|
300
|
+
const variants = utilities
|
|
301
|
+
.filter((child) => isValidElement(child) && child.type === Button)
|
|
302
|
+
.map((button) => button.props.variant ?? buttonDefaults.variant);
|
|
303
|
+
const problem = variants.length > 2
|
|
304
|
+
? `was handed ${variants.length} Buttons`
|
|
305
|
+
: variants.length === 1 && variants[0] !== 'primary'
|
|
306
|
+
? `was handed a single ${variants[0]} Button`
|
|
307
|
+
: variants.length === 2 && !(variants.includes('primary') && variants.includes('secondary'))
|
|
308
|
+
? `was handed two Buttons that are ${variants.join(' and ')}`
|
|
309
|
+
: undefined;
|
|
310
|
+
if (problem === undefined || warned.has(problem))
|
|
311
|
+
return;
|
|
312
|
+
warned.add(problem);
|
|
313
|
+
// eslint-disable-next-line no-console
|
|
314
|
+
console.warn(`Navbar ${problem} in utilities. The bar holds at most two: one primary, and one secondary ` +
|
|
315
|
+
'beside it — a lone Button is the primary. A third action belongs somewhere on the page, ' +
|
|
316
|
+
'not in the bar. See the navbar-actions-are-a-pair rule.');
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* One control, dressed for where it stands.
|
|
320
|
+
*
|
|
321
|
+
* Only what the dressing sets is written. `openOnHover` in particular is a page's to decide in a
|
|
322
|
+
* slot the bar has no view on, and cloning `{ openOnHover: undefined }` would reset it rather than
|
|
323
|
+
* leave it — an explicit `undefined` is an override to `cloneElement`, not an absence.
|
|
324
|
+
*
|
|
325
|
+
* A Button takes the bar's tone whatever its variant. On a secondary the tone is the fill; on the
|
|
326
|
+
* others it is only the focus ring, which has to follow the ground as much as any fill does — a
|
|
327
|
+
* primary keeping `inverse` from the hero would draw a white ring on the white pill.
|
|
328
|
+
*/
|
|
329
|
+
function dressed(node, { tone, openOnHover, size }) {
|
|
330
|
+
if (!isValidElement(node))
|
|
331
|
+
return node;
|
|
332
|
+
if (node.type === Button) {
|
|
333
|
+
return cloneElement(node, { tone, ...(size === undefined ? {} : { size }) });
|
|
334
|
+
}
|
|
335
|
+
if (!TONED.includes(node.type))
|
|
336
|
+
return node;
|
|
337
|
+
const hover = node.type === DropdownMenu && openOnHover !== undefined ? { openOnHover } : {};
|
|
338
|
+
return cloneElement(node, { tone, ...hover });
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* The bar across the top of a marketing page: the mark, the places the site has,
|
|
342
|
+
* and the things a reader reaches for rather than navigates to.
|
|
343
|
+
*
|
|
344
|
+
* It holds no destinations of its own — what goes in it is what the page
|
|
345
|
+
* composes. What this owns is the bar, and running out of room is the whole of
|
|
346
|
+
* its behaviour: below the width its three regions fit in, the destinations and
|
|
347
|
+
* the utilities stop being drawn and the trigger takes their place.
|
|
348
|
+
*
|
|
349
|
+
* Which section is open is the bar's, not each menu's. A menu cannot see its
|
|
350
|
+
* neighbours, so left to themselves two of them open at once and two surfaces
|
|
351
|
+
* overlap in front of the page. Injected the way TabList injects `selected`, and
|
|
352
|
+
* for the same reason.
|
|
353
|
+
*
|
|
354
|
+
* The rail paints nothing and the row inside it is the container a reader sees.
|
|
355
|
+
* That split is why there is no line under the bar: what separates it from the
|
|
356
|
+
* page is a surface of its own with air around it.
|
|
357
|
+
*
|
|
358
|
+
* No `role="banner"`. A `<header>` outside a sectioning element already is that
|
|
359
|
+
* landmark, and writing it as well says so a second time in a way that goes stale
|
|
360
|
+
* if the element is ever nested.
|
|
361
|
+
*/
|
|
362
|
+
export function Navbar({ tone = navbarDefaults.tone, label, menuLabel, closeLabel, brand, utilities, compactAction, preferences, showThemeToggle = navbarDefaults.showThemeToggle, theme, onThemeChange, themeToggleLabel, menuOpen, onMenuOpenChange, children, ...rest }) {
|
|
363
|
+
/*
|
|
364
|
+
The theme toggle, drawn by the bar and placed after whatever the page put in preferences.
|
|
365
|
+
|
|
366
|
+
A ButtonIcon rather than a switcher: two themes are a toggle, not a choice among many, so a
|
|
367
|
+
menu listing both is a step nobody needs. `plain` so it is one of the pill's own items, and
|
|
368
|
+
`md` because that square is size.control.md — the height every item, menu and switcher in the
|
|
369
|
+
pill stands at, and the size the bar's buttons are. The glyph is the theme a press moves to; the name stays the theme it turns on
|
|
370
|
+
and aria-pressed carries the state, so a screen reader hears one name whichever way it is.
|
|
371
|
+
|
|
372
|
+
Joined to preferences as a list rather than drawn in a box of its own, so it takes the same
|
|
373
|
+
tone on the hero and in the pill, and the collapsed panel draws it at its foot beside the
|
|
374
|
+
rest — both come for free from how that slot is already handled.
|
|
375
|
+
*/
|
|
376
|
+
/*
|
|
377
|
+
Drawn only once it can be named. The pairing is enforced by the types, which a consumer
|
|
378
|
+
writing JavaScript never sees — and a glyph-only toggle with no label is a button a screen
|
|
379
|
+
reader announces with nothing after it. Absent is the honest failure; unnamed is not.
|
|
380
|
+
*/
|
|
381
|
+
const themeToggle = showThemeToggle && theme !== undefined && themeToggleLabel !== undefined && themeToggleLabel !== '' ? (_jsx(ButtonIcon, { variant: "plain", size: "md", label: themeToggleLabel, "aria-pressed": theme === 'dark', icon: theme === 'dark' ? _jsx(SunBrightRegularIcon, {}) : _jsx(MoonRegularIcon, {}), onClick: () => onThemeChange?.(theme === 'dark' ? 'light' : 'dark') }, "dds-navbar-theme-toggle")) : null;
|
|
382
|
+
/*
|
|
383
|
+
Each slot opened into one flat list, once per render — the warning, the bar and the panel all
|
|
384
|
+
read these rather than each walking the fragments again.
|
|
385
|
+
*/
|
|
386
|
+
const preferenceList = themeToggle === null ? flattened(preferences) : [...flattened(preferences), themeToggle];
|
|
387
|
+
const utilityList = flattened(utilities);
|
|
388
|
+
const compactList = flattened(compactAction);
|
|
389
|
+
const rootRef = useRef(null);
|
|
390
|
+
const condensed = useScrolled(rootRef);
|
|
391
|
+
const gathered = condensed ? 'true' : undefined;
|
|
392
|
+
/*
|
|
393
|
+
The tone the bar is actually wearing, which is not always the one it was given.
|
|
394
|
+
|
|
395
|
+
`inverse` describes a ground: it is set because the first section of the page painted itself
|
|
396
|
+
dark and the bar is standing on it. Scrolling takes the bar off that section, so it gathers
|
|
397
|
+
into the same white pill a light bar does — and everything on it has to agree, at once.
|
|
398
|
+
|
|
399
|
+
Derived here rather than in the stylesheet, which is where it was and where it could only ever
|
|
400
|
+
be half a fix. A rule can repaint this component's own parts; it cannot reach the `tone` a
|
|
401
|
+
destination was handed, because that is a prop. So the bar went white while the items on it
|
|
402
|
+
went on tinting their hovers for a dark ground — a hover nobody could see, which is exactly
|
|
403
|
+
what a light-ground hover looks like on light ground.
|
|
404
|
+
|
|
405
|
+
One value, read by the attribute the stylesheet matches and by every child that is told a tone.
|
|
406
|
+
*/
|
|
407
|
+
const worn = condensed ? 'default' : tone;
|
|
408
|
+
/*
|
|
409
|
+
Each slot dressed once, for the ground it stands on. The utilities are drawn in two places —
|
|
410
|
+
inside the pill once it gathers, and at the trailing end before — and both show the same
|
|
411
|
+
element, so they share one dressing rather than keeping two in step by hand.
|
|
412
|
+
*/
|
|
413
|
+
const barSwitchers = toned(preferenceList, { tone: worn, openOnHover: true });
|
|
414
|
+
warnIfActionsAreNotAPair(utilityList);
|
|
415
|
+
const barUtilities = toned(utilityList, { tone: worn, size: 'md' });
|
|
416
|
+
const barCompact = toned(compactList, { tone: worn, size: 'md' });
|
|
417
|
+
const triggerRef = useRef(null);
|
|
418
|
+
/*
|
|
419
|
+
The pill's pair, which is the half of this that JavaScript has to do.
|
|
420
|
+
|
|
421
|
+
The row's pair is a share of the row, so it collapses by taking that share to nothing — a number,
|
|
422
|
+
which CSS can transition, so the stylesheet owns it. These two are sized by what they hold, and
|
|
423
|
+
a width cannot travel between a length and `auto`, so their measure has to be taken. Each
|
|
424
|
+
collapses against the gap on the side it is at: the mark at a leading edge, the actions at a
|
|
425
|
+
trailing one.
|
|
426
|
+
*/
|
|
427
|
+
const pillBrandRef = useRef(null);
|
|
428
|
+
const pillActionsRef = useRef(null);
|
|
429
|
+
useCollapse(pillBrandRef, !condensed, 'end');
|
|
430
|
+
useCollapse(pillActionsRef, !condensed, 'start');
|
|
431
|
+
/*
|
|
432
|
+
Controlled when told, its own answer otherwise. A private copy alongside a
|
|
433
|
+
passed one would be two answers to a question with one truth, and would show
|
|
434
|
+
the stale one for a frame the first time a page set it from anywhere else.
|
|
435
|
+
*/
|
|
436
|
+
const [held, setHeld] = useState(false);
|
|
437
|
+
const controlled = menuOpen !== undefined;
|
|
438
|
+
const open = controlled ? menuOpen : held;
|
|
439
|
+
const setOpen = useCallback((next) => {
|
|
440
|
+
if (!controlled)
|
|
441
|
+
setHeld(next);
|
|
442
|
+
onMenuOpenChange?.(next);
|
|
443
|
+
}, [controlled, onMenuOpenChange]);
|
|
444
|
+
const close = useCallback(() => setOpen(false), [setOpen]);
|
|
445
|
+
// Which section is showing, by position in the row. Positions rather than
|
|
446
|
+
// labels: two sections can share a name in a way nothing here should have an
|
|
447
|
+
// opinion about, and an index is stable for as long as the row is.
|
|
448
|
+
const [section, setSection] = useState(null);
|
|
449
|
+
/*
|
|
450
|
+
Which section was open before this render, so a menu can be told whether it is arriving or
|
|
451
|
+
taking another's place. Written in an effect rather than during render, so what it holds is the
|
|
452
|
+
value the last committed render was drawn with — which is exactly the question being asked.
|
|
453
|
+
*/
|
|
454
|
+
const previous = useRef(null);
|
|
455
|
+
useEffect(() => {
|
|
456
|
+
previous.current = section;
|
|
457
|
+
}, [section]);
|
|
458
|
+
const items = Children.toArray(children);
|
|
459
|
+
const governed = items.map((child, index) => {
|
|
460
|
+
if (!isValidElement(child) || child.type !== NavbarMenu) {
|
|
461
|
+
// A destination takes the tone as well. It is not governed — nothing about it
|
|
462
|
+
// opens — so it is cloned for this alone rather than passed through untouched.
|
|
463
|
+
return isValidElement(child) && child.type === NavbarItem
|
|
464
|
+
? cloneElement(child, { tone: worn })
|
|
465
|
+
: child;
|
|
466
|
+
}
|
|
467
|
+
return cloneElement(child, {
|
|
468
|
+
/*
|
|
469
|
+
The tone travels with the open state, and for the same reason: a row
|
|
470
|
+
where one trigger is inverse and its neighbours are not is a row whose
|
|
471
|
+
hovers half disappear. The bar is the only thing that knows what it is
|
|
472
|
+
standing on, so it tells them rather than asking the page to tell each.
|
|
473
|
+
*/
|
|
474
|
+
tone: worn,
|
|
475
|
+
open: section === index,
|
|
476
|
+
replacing: section === index && previous.current !== null && previous.current !== index,
|
|
477
|
+
onOpenChange: chain(child.props.onOpenChange, (next) => {
|
|
478
|
+
setSection(next ? index : null);
|
|
479
|
+
}),
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
return (_jsxs("header", { ...rest, ref: rootRef, className: navbarParts.root, "data-tone": worn, "data-condensed": gathered, "data-dds-pinned-surface": open ? 'open' : undefined, children: [_jsxs("div", { className: navbarParts.inner, "data-condensed": gathered, children: [_jsx("div", { className: navbarParts.ground, "data-condensed": gathered }), brand !== undefined && brand !== null && (_jsx("div", { className: navbarParts.brand, "data-condensed": gathered, children: brand })), _jsxs("div", { className: navbarParts.cluster, "data-condensed": gathered, children: [brand !== undefined && brand !== null && (_jsx("div", { ref: pillBrandRef, className: navbarParts.brand, children: brand })), _jsx("nav", { className: navbarParts.nav, "aria-label": label, children: governed }), barSwitchers !== undefined && (_jsx("div", { className: navbarParts.preferences, children: barSwitchers })), barUtilities !== undefined && (_jsx("div", { ref: pillActionsRef, className: navbarParts.utilities, children: barUtilities }))] }), barUtilities !== undefined && (_jsx("div", { className: navbarParts.utilities, "data-condensed": gathered, children: barUtilities })), barCompact !== undefined && (_jsx("div", { className: navbarParts['compact-action'], children: barCompact })), _jsx("button", { ref: triggerRef, type: "button", className: navbarParts.trigger, "aria-label": menuLabel, "aria-expanded": open, onClick: () => setOpen(!open), children: _jsx(Icon, { size: "md", children: open ? _jsx(XmarkRegularIcon, {}) : _jsx(BarsRegularIcon, {}) }) })] }), open && (_jsx("div", { className: navbarParts['panel-host'], children: _jsx(NavbarPanel, { label: label, closeLabel: closeLabel, onClose: close, brand: brand,
|
|
483
|
+
/*
|
|
484
|
+
Both, because the pill they were drawn in is not drawn at this width and
|
|
485
|
+
the foot is where everything that was in the bar has gone. What a reader
|
|
486
|
+
sets comes first: the actions are the last thing the panel offers, and a
|
|
487
|
+
switcher underneath them would be a preference hidden below a conversion.
|
|
488
|
+
*/
|
|
489
|
+
/*
|
|
490
|
+
At the panel's tone, not the bar's. The panel is paper whatever the bar is standing
|
|
491
|
+
on, and this is the same element drawn in the pill — told `inverse` there and wrong
|
|
492
|
+
here, where a hover tinted for a dark ground lands on white and disappears.
|
|
493
|
+
|
|
494
|
+
And not told to open on hover: in a panel a switcher is a row read down with a
|
|
495
|
+
finger, and the panel is the thing that turns it into one.
|
|
496
|
+
*/
|
|
497
|
+
preferences: toned(preferenceList, { tone: 'default', openOnHover: false }), footer: toned(utilityList, { tone: 'default' }), openerRef: triggerRef, children: children }) }))] }));
|
|
498
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface NavbarOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `default` — The page begins on a light ground, which is most marketing pages. The bar paints in ink and the pill is paper
|
|
5
|
+
* `inverse` — The first section of the page paints its own dark ground and the bar stands on it — a dark hero, a photograph, a brand-coloured takeover. The bar's ink runs light, and the pill and the collapsed bar take the dark see-through material — a near-opaque black base, a white tint and a blur — so a light photograph behind cannot wash them out
|
|
6
|
+
*/
|
|
7
|
+
tone?: 'default' | 'inverse';
|
|
8
|
+
/** Always — it names the navigation landmark, and a page with an unnamed one tells a screen-reader user there is navigation here without saying which navigation. Name the set rather than the act: 'Main', not 'Main navigation' — the role already supplies the word, and a name carrying it is announced as 'main navigation navigation' */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Always — the trigger is an icon-only button and this is the only name it has, at the width where it is the only way through the site. Name what it reveals rather than its state: 'Menu', not 'Open menu', because aria-expanded already says which way it is and a name that also said so would contradict itself every other press */
|
|
11
|
+
menuLabel: string;
|
|
12
|
+
/** Always — it names the panel's close button, which is the only visible way out of a surface covering the whole page. 'Close' is enough; the panel it closes is the only thing open */
|
|
13
|
+
closeLabel: string;
|
|
14
|
+
/** Effectively always on a real site — the mark, and usually an anchor to the home page wrapped around it. It is drawn twice: in the bar, and again in the panel's header, where it is the only thing left saying whose site this is */
|
|
15
|
+
brand?: ReactNode;
|
|
16
|
+
/** The bar's trailing end has the site's actions in it: one Button, which is primary, or two — one primary and one secondary, the conversion beside the way back in. A switcher is a DropdownMenu with the current choice on its trigger, which is what DropdownMenu's own guidance describes and why it is accepted here alongside the two controls. They are drawn in the row at wide widths and across the foot of the panel once it collapses. The bar dresses what it is handed: every Button here is drawn at md and takes the tone of the ground the bar is on at that scroll position — inverse on the hero, default once the pill gathers — and a ButtonIcon or a DropdownMenu takes the tone too. That reaches the controls handed in directly, or in a fragment; a control inside a component of the page's own is past it, so a wrapper takes tone and size as props and passes them down */
|
|
17
|
+
utilities?: ReactNode;
|
|
18
|
+
/** The one thing a reader should still be able to do once the bar has collapsed and everything else has gone into the panel — a sign-up, usually. Drawn beside the control that opens the panel, and only at the widths where that control is drawn. Dressed like utilities: a Button here is drawn at md and takes the bar's tone */
|
|
19
|
+
compactAction?: ReactNode;
|
|
20
|
+
/** A switcher that belongs with the destinations rather than with the conversion — a language picker, a theme toggle. It is drawn inside the pill, beside the sections, at every scroll position. A NavbarSwitcher is the one built for it: in the pill it is a trigger and a menu, and in the collapsed panel the same element becomes a row that opens a page of its own with a way back, because a dropdown inside a surface already covering the screen is a surface inside a surface */
|
|
21
|
+
preferences?: ReactNode;
|
|
22
|
+
/** The page is holding whether the panel is open, because something else depends on it — a route change that should close it, a surface of its own that must not open at the same time. Passing it makes the bar controlled: it shows what it is told and reports presses through onMenuOpenChange.
|
|
23
|
+
|
|
24
|
+
Leave it off and the bar holds its own answer, which is the ordinary case: a narrow-width navigation panel is opened and closed by the reader and by nothing else */
|
|
25
|
+
menuOpen?: boolean;
|
|
26
|
+
/** Whenever menuOpen is — together they are how a page holds the panel. It is called with the state being moved to, by the trigger, by the close button and by Escape, so a page listening to it hears every way the panel can change */
|
|
27
|
+
onMenuOpenChange?: (open: boolean) => void;
|
|
28
|
+
/** Allowed: NavbarItem, NavbarMenu */
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}
|
|
31
|
+
export type NavbarProps = NavbarOwnProps & Omit<HTMLAttributes<HTMLElement>, 'className' | 'tone' | 'label' | 'menuLabel' | 'closeLabel' | 'brand' | 'utilities' | 'compactAction' | 'preferences' | 'showThemeToggle' | 'theme' | 'onThemeChange' | 'themeToggleLabel' | 'menuOpen' | 'onMenuOpenChange'> & ({
|
|
32
|
+
showThemeToggle?: boolean;
|
|
33
|
+
theme: 'light' | 'dark';
|
|
34
|
+
} | {
|
|
35
|
+
showThemeToggle?: false;
|
|
36
|
+
theme?: 'light' | 'dark';
|
|
37
|
+
}) & ({
|
|
38
|
+
showThemeToggle?: boolean;
|
|
39
|
+
onThemeChange: (theme: 'light' | 'dark') => void;
|
|
40
|
+
} | {
|
|
41
|
+
showThemeToggle?: false;
|
|
42
|
+
onThemeChange?: (theme: 'light' | 'dark') => void;
|
|
43
|
+
}) & ({
|
|
44
|
+
showThemeToggle?: boolean;
|
|
45
|
+
themeToggleLabel: string;
|
|
46
|
+
} | {
|
|
47
|
+
showThemeToggle?: false;
|
|
48
|
+
themeToggleLabel?: string;
|
|
49
|
+
});
|
|
50
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
51
|
+
export declare const navbarParts: {
|
|
52
|
+
readonly root: "dds-navbar";
|
|
53
|
+
readonly inner: "dds-navbar__inner";
|
|
54
|
+
readonly ground: "dds-navbar__ground";
|
|
55
|
+
readonly brand: "dds-navbar__brand";
|
|
56
|
+
readonly nav: "dds-navbar__nav";
|
|
57
|
+
readonly preferences: "dds-navbar__preferences";
|
|
58
|
+
readonly utilities: "dds-navbar__utilities";
|
|
59
|
+
readonly 'compact-action': "dds-navbar__compact-action";
|
|
60
|
+
readonly trigger: "dds-navbar__trigger";
|
|
61
|
+
readonly 'panel-host': "dds-navbar__panel-host";
|
|
62
|
+
readonly cluster: "dds-navbar__cluster";
|
|
63
|
+
};
|
|
64
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
65
|
+
export declare const navbarDefaults: {
|
|
66
|
+
readonly tone: "default";
|
|
67
|
+
readonly showThemeToggle: false;
|
|
68
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// GENERATED from navbar.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const navbarParts = {
|
|
4
|
+
root: 'dds-navbar',
|
|
5
|
+
inner: 'dds-navbar__inner',
|
|
6
|
+
ground: 'dds-navbar__ground',
|
|
7
|
+
brand: 'dds-navbar__brand',
|
|
8
|
+
nav: 'dds-navbar__nav',
|
|
9
|
+
preferences: 'dds-navbar__preferences',
|
|
10
|
+
utilities: 'dds-navbar__utilities',
|
|
11
|
+
'compact-action': 'dds-navbar__compact-action',
|
|
12
|
+
trigger: 'dds-navbar__trigger',
|
|
13
|
+
'panel-host': 'dds-navbar__panel-host',
|
|
14
|
+
cluster: 'dds-navbar__cluster',
|
|
15
|
+
};
|
|
16
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
17
|
+
export const navbarDefaults = { tone: 'default', showThemeToggle: false };
|