@deriv-com/dds-marketing 1.0.1 → 1.1.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/awards.md +209 -0
- package/.llm/components/background.md +420 -0
- package/.llm/components/bottomsheet.md +5 -0
- package/.llm/components/comparisoncards.md +257 -0
- package/.llm/components/comparisontable.md +231 -0
- package/.llm/components/ctabanner.md +22 -0
- package/.llm/components/ctabannerslider.md +36 -2
- package/.llm/components/datatable.md +273 -0
- package/.llm/components/downloadbanner.md +283 -0
- package/.llm/components/featurecards.md +41 -3
- package/.llm/components/featurecardscarousel.md +311 -0
- package/.llm/components/featuresplit.md +5 -0
- package/.llm/components/featurestack.md +227 -0
- package/.llm/components/illustrationcard.md +236 -0
- package/.llm/components/illustrationscene.md +229 -0
- package/.llm/components/imagebanner.md +278 -0
- package/.llm/components/landinghero.md +24 -0
- package/.llm/components/navbar.md +1 -1
- package/.llm/components/navbaritem.md +4 -0
- package/.llm/components/pageheader.md +22 -0
- package/.llm/components/paginationdots.md +6 -1
- package/.llm/components/producthero.md +35 -11
- package/.llm/components/resourcebanner.md +247 -0
- package/.llm/components/scenescroll.md +222 -0
- package/.llm/components/select.md +17 -0
- package/.llm/components/stats.md +219 -0
- package/.llm/components/steps.md +286 -0
- package/.llm/components/stickycards.md +251 -0
- package/.llm/components/tableheadercell.md +19 -0
- package/.llm/components/teamgrid.md +243 -0
- package/.llm/components/testimonialrow.md +5 -0
- package/.llm/components/testimonialslider.md +14 -1
- package/.llm/components/textarea.md +13 -0
- package/.llm/components/textinput.md +13 -0
- package/.llm/components/textscroll.md +187 -0
- package/.llm/components/tiers.md +227 -0
- package/.llm/digest/awards.md +45 -0
- package/.llm/digest/background.md +53 -0
- package/.llm/digest/bottomsheet.md +2 -0
- package/.llm/digest/comparisoncards.md +51 -0
- package/.llm/digest/comparisontable.md +53 -0
- package/.llm/digest/ctabanner.md +4 -0
- package/.llm/digest/ctabannerslider.md +7 -0
- package/.llm/digest/datatable.md +65 -0
- package/.llm/digest/downloadbanner.md +65 -0
- package/.llm/digest/featurecards.md +1 -1
- package/.llm/digest/featurecardscarousel.md +54 -0
- package/.llm/digest/featuresplit.md +1 -0
- package/.llm/digest/featurestack.md +48 -0
- package/.llm/digest/illustrationcard.md +46 -0
- package/.llm/digest/illustrationscene.md +50 -0
- package/.llm/digest/imagebanner.md +64 -0
- package/.llm/digest/landinghero.md +7 -0
- package/.llm/digest/navbaritem.md +1 -0
- package/.llm/digest/pageheader.md +4 -0
- package/.llm/digest/paginationdots.md +3 -1
- package/.llm/digest/producthero.md +4 -2
- package/.llm/digest/resourcebanner.md +53 -0
- package/.llm/digest/scenescroll.md +49 -0
- package/.llm/digest/select.md +5 -0
- package/.llm/digest/stats.md +46 -0
- package/.llm/digest/steps.md +55 -0
- package/.llm/digest/stickycards.md +52 -0
- package/.llm/digest/tableheadercell.md +4 -0
- package/.llm/digest/teamgrid.md +53 -0
- package/.llm/digest/testimonialrow.md +2 -0
- package/.llm/digest/testimonialslider.md +4 -0
- package/.llm/digest/textarea.md +4 -0
- package/.llm/digest/textinput.md +4 -0
- package/.llm/digest/textscroll.md +43 -0
- package/.llm/digest/tiers.md +50 -0
- package/.llm/index.md +25 -2
- package/.llm/tokens.md +37 -1
- package/AGENTS.md +20 -1
- package/dist/components/awards-data.d.ts +24 -0
- package/dist/components/awards-data.js +11 -0
- package/dist/components/block-image-data.d.ts +24 -0
- package/dist/components/block-image-data.js +9 -0
- package/dist/components/blocks/awards/Awards.css +134 -0
- package/dist/components/blocks/awards/Awards.d.ts +24 -0
- package/dist/components/blocks/awards/Awards.js +114 -0
- package/dist/components/blocks/awards/Awards.types.d.ts +31 -0
- package/dist/components/blocks/awards/Awards.types.js +16 -0
- package/dist/components/blocks/awards/awards-impl.css +222 -0
- package/dist/components/blocks/cards-of.d.ts +16 -0
- package/dist/components/blocks/cards-of.js +23 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.css +195 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.d.ts +24 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.js +75 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.types.d.ts +49 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.types.js +26 -0
- package/dist/components/blocks/comparison-cards/comparison-cards-impl.css +262 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.css +111 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.d.ts +25 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.js +100 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.types.d.ts +36 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.types.js +15 -0
- package/dist/components/blocks/comparison-table/comparison-table-impl.css +143 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +1 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +1 -1
- package/dist/components/blocks/cta-banner/CtaBanner.js +3 -2
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +6 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +1 -1
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +8 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +1 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +1 -1
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +10 -5
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +12 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +1 -1
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +8 -0
- package/dist/components/blocks/data-table/DataTable.css +170 -0
- package/dist/components/blocks/data-table/DataTable.d.ts +29 -0
- package/dist/components/blocks/data-table/DataTable.js +84 -0
- package/dist/components/blocks/data-table/DataTable.types.d.ts +69 -0
- package/dist/components/blocks/data-table/DataTable.types.js +19 -0
- package/dist/components/blocks/data-table/data-table-impl.css +155 -0
- package/dist/components/blocks/download-banner/DownloadBanner.css +228 -0
- package/dist/components/blocks/download-banner/DownloadBanner.d.ts +28 -0
- package/dist/components/blocks/download-banner/DownloadBanner.js +75 -0
- package/dist/components/blocks/download-banner/DownloadBanner.types.d.ts +56 -0
- package/dist/components/blocks/download-banner/DownloadBanner.types.js +23 -0
- package/dist/components/blocks/download-banner/download-banner-impl.css +216 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +1 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +3 -7
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +1 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +14 -1
- package/dist/components/blocks/feature-cards/FeatureCards.css +1 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +2 -1
- package/dist/components/blocks/feature-cards/FeatureCards.js +4 -21
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +10 -9
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.css +115 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.d.ts +30 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.js +160 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.d.ts +52 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.js +17 -0
- package/dist/components/blocks/feature-cards-carousel/feature-cards-carousel-impl.css +207 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +1 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +1 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +14 -1
- package/dist/components/blocks/feature-stack/FeatureStack.css +86 -0
- package/dist/components/blocks/feature-stack/FeatureStack.d.ts +19 -0
- package/dist/components/blocks/feature-stack/FeatureStack.js +27 -0
- package/dist/components/blocks/feature-stack/FeatureStack.types.d.ts +34 -0
- package/dist/components/blocks/feature-stack/FeatureStack.types.js +14 -0
- package/dist/components/blocks/feature-stack/feature-stack-impl.css +87 -0
- package/dist/components/blocks/image-banner/ImageBanner.css +133 -0
- package/dist/components/blocks/image-banner/ImageBanner.d.ts +32 -0
- package/dist/components/blocks/image-banner/ImageBanner.js +41 -0
- package/dist/components/blocks/image-banner/ImageBanner.types.d.ts +54 -0
- package/dist/components/blocks/image-banner/ImageBanner.types.js +14 -0
- package/dist/components/blocks/image-banner/image-banner-impl.css +281 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +1 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +1 -1
- package/dist/components/blocks/landing-hero/LandingHero.js +4 -3
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +7 -3
- package/dist/components/blocks/logo-columns/LogoColumns.css +1 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +1 -0
- package/dist/components/blocks/page-header/PageHeader.css +1 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +1 -1
- package/dist/components/blocks/page-header/PageHeader.js +3 -2
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +6 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +1 -1
- package/dist/components/blocks/page-header/page-header-impl.css +10 -0
- package/dist/components/blocks/product-hero/ProductHero.css +8 -3
- package/dist/components/blocks/product-hero/ProductHero.d.ts +1 -1
- package/dist/components/blocks/product-hero/ProductHero.js +5 -2
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +5 -1
- package/dist/components/blocks/product-hero/ProductHero.types.js +1 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +43 -12
- package/dist/components/blocks/resource-banner/ResourceBanner.css +106 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.d.ts +32 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.js +51 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.types.d.ts +44 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.types.js +14 -0
- package/dist/components/blocks/resource-banner/resource-banner-impl.css +69 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.css +93 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.d.ts +36 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.js +54 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.types.d.ts +32 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.types.js +15 -0
- package/dist/components/blocks/scene-scroll/scene-scroll-impl.css +275 -0
- package/dist/components/blocks/stats/Stats.css +139 -0
- package/dist/components/blocks/stats/Stats.d.ts +24 -0
- package/dist/components/blocks/stats/Stats.js +120 -0
- package/dist/components/blocks/stats/Stats.types.d.ts +36 -0
- package/dist/components/blocks/stats/Stats.types.js +19 -0
- package/dist/components/blocks/stats/stats-count.d.ts +34 -0
- package/dist/components/blocks/stats/stats-count.js +61 -0
- package/dist/components/blocks/stats/stats-impl.css +284 -0
- package/dist/components/blocks/stats/use-wheel.d.ts +37 -0
- package/dist/components/blocks/stats/use-wheel.js +126 -0
- package/dist/components/blocks/steps/Steps.css +202 -0
- package/dist/components/blocks/steps/Steps.d.ts +32 -0
- package/dist/components/blocks/steps/Steps.js +65 -0
- package/dist/components/blocks/steps/Steps.types.d.ts +48 -0
- package/dist/components/blocks/steps/Steps.types.js +21 -0
- package/dist/components/blocks/steps/steps-impl.css +216 -0
- package/dist/components/blocks/steps/use-turn.d.ts +33 -0
- package/dist/components/blocks/steps/use-turn.js +75 -0
- package/dist/components/blocks/sticky-cards/StickyCards.css +154 -0
- package/dist/components/blocks/sticky-cards/StickyCards.d.ts +35 -0
- package/dist/components/blocks/sticky-cards/StickyCards.js +153 -0
- package/dist/components/blocks/sticky-cards/StickyCards.types.d.ts +43 -0
- package/dist/components/blocks/sticky-cards/StickyCards.types.js +18 -0
- package/dist/components/blocks/sticky-cards/sticky-cards-impl.css +393 -0
- package/dist/components/blocks/team-grid/TeamGrid.css +159 -0
- package/dist/components/blocks/team-grid/TeamGrid.d.ts +28 -0
- package/dist/components/blocks/team-grid/TeamGrid.js +74 -0
- package/dist/components/blocks/team-grid/TeamGrid.types.d.ts +51 -0
- package/dist/components/blocks/team-grid/TeamGrid.types.js +20 -0
- package/dist/components/blocks/team-grid/team-grid-impl.css +129 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +1 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +1 -1
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +4 -3
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +3 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +1 -1
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +8 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +1 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +1 -1
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +2 -2
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +8 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +1 -1
- package/dist/components/blocks/text-scroll/TextScroll.css +53 -0
- package/dist/components/blocks/text-scroll/TextScroll.d.ts +5 -0
- package/dist/components/blocks/text-scroll/TextScroll.js +71 -0
- package/dist/components/blocks/text-scroll/TextScroll.types.d.ts +22 -0
- package/dist/components/blocks/text-scroll/TextScroll.types.js +10 -0
- package/dist/components/blocks/text-scroll/text-scroll-impl.css +115 -0
- package/dist/components/blocks/tiers/Tiers.css +233 -0
- package/dist/components/blocks/tiers/Tiers.d.ts +32 -0
- package/dist/components/blocks/tiers/Tiers.js +68 -0
- package/dist/components/blocks/tiers/Tiers.types.d.ts +45 -0
- package/dist/components/blocks/tiers/Tiers.types.js +25 -0
- package/dist/components/blocks/tiers/tiers-impl.css +185 -0
- package/dist/components/blocks/use-rotation.d.ts +12 -2
- package/dist/components/blocks/use-rotation.js +6 -28
- package/dist/components/comparison-cards-data.d.ts +59 -0
- package/dist/components/comparison-cards-data.js +12 -0
- package/dist/components/comparison-table-data.d.ts +39 -0
- package/dist/components/comparison-table-data.js +11 -0
- package/dist/components/core/accordion-item/AccordionItem.css +1 -5
- package/dist/components/core/background/Background.css +92 -0
- package/dist/components/core/background/Background.d.ts +27 -0
- package/dist/components/core/background/Background.js +45 -0
- package/dist/components/core/background/Background.types.d.ts +39 -0
- package/dist/components/core/background/Background.types.js +11 -0
- package/dist/components/core/background/background-impl.css +760 -0
- package/dist/components/core/background/halftone.d.ts +134 -0
- package/dist/components/core/background/halftone.js +722 -0
- package/dist/components/core/background/patterns.d.ts +66 -0
- package/dist/components/core/background/patterns.js +244 -0
- package/dist/components/core/background/shader.d.ts +44 -0
- package/dist/components/core/background/shader.js +307 -0
- package/dist/components/core/background/use-halftone.d.ts +15 -0
- package/dist/components/core/background/use-halftone.js +27 -0
- package/dist/components/core/background/use-offscreen.d.ts +10 -0
- package/dist/components/core/background/use-offscreen.js +30 -0
- package/dist/components/core/background/use-shader.d.ts +11 -0
- package/dist/components/core/background/use-shader.js +25 -0
- package/dist/components/core/background/use-spotlight.d.ts +14 -0
- package/dist/components/core/background/use-spotlight.js +73 -0
- package/dist/components/core/bottom-sheet/BottomSheet.js +2 -2
- package/dist/components/core/bottom-sheet/BottomSheet.types.d.ts +3 -1
- package/dist/components/core/breadcrumb/Breadcrumb.d.ts +1 -0
- package/dist/components/core/breadcrumb/Breadcrumb.js +1 -0
- package/dist/components/core/breadcrumb/breadcrumb-impl.css +11 -0
- package/dist/components/core/button/button-impl.css +14 -1
- package/dist/components/core/illustration-card/IllustrationCard.css +40 -0
- package/dist/components/core/illustration-card/IllustrationCard.d.ts +22 -0
- package/dist/components/core/illustration-card/IllustrationCard.js +82 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.d.ts +23 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.js +8 -0
- package/dist/components/core/illustration-card/illustration-card-impl.css +47 -0
- package/dist/components/core/illustration-scene/IllustrationScene.css +41 -0
- package/dist/components/core/illustration-scene/IllustrationScene.d.ts +14 -0
- package/dist/components/core/illustration-scene/IllustrationScene.js +16 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +32 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.js +8 -0
- package/dist/components/core/illustration-scene/illustration-scene-impl.css +46 -0
- package/dist/components/core/link/Link.js +7 -3
- package/dist/components/core/link/link-impl.css +29 -2
- package/dist/components/core/navbar/Navbar.css +2 -2
- package/dist/components/core/navbar/Navbar.types.d.ts +1 -1
- package/dist/components/core/navbar-item/NavbarItem.d.ts +2 -1
- package/dist/components/core/navbar-item/NavbarItem.js +3 -10
- package/dist/components/core/navbar-item/NavbarItem.types.d.ts +4 -1
- package/dist/components/core/navbar-item/NavbarItem.types.js +1 -1
- package/dist/components/core/navbar-item/navbar-item-impl.css +10 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +9 -0
- package/dist/components/core/navbar-switcher/navbar-switcher-impl.css +19 -0
- package/dist/components/core/pagination/Pagination.js +1 -1
- package/dist/components/core/pagination/pagination-impl.css +9 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +1 -1
- package/dist/components/core/pagination-dots/PaginationDots.js +3 -3
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +3 -1
- package/dist/components/core/segmented-control/SegmentedControl.css +4 -3
- package/dist/components/core/segmented-control/SegmentedControl.js +17 -3
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +2 -1
- package/dist/components/core/select/Select.js +3 -3
- package/dist/components/core/select/Select.types.d.ts +11 -1
- package/dist/components/core/select/Select.types.js +1 -1
- package/dist/components/core/tab-list/TabList.js +9 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.d.ts +1 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.js +5 -2
- package/dist/components/core/table-header-cell/TableHeaderCell.types.d.ts +7 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.types.js +1 -1
- package/dist/components/core/text-area/TextArea.d.ts +1 -1
- package/dist/components/core/text-area/TextArea.js +2 -2
- package/dist/components/core/text-area/TextArea.types.d.ts +9 -1
- package/dist/components/core/text-area/TextArea.types.js +1 -1
- package/dist/components/core/text-input/TextInput.d.ts +1 -1
- package/dist/components/core/text-input/TextInput.js +2 -2
- package/dist/components/core/text-input/TextInput.types.d.ts +9 -1
- package/dist/components/core/text-input/TextInput.types.js +1 -1
- package/dist/components/data-table-data.d.ts +33 -0
- package/dist/components/data-table-data.js +12 -0
- package/dist/components/download-banner-data.d.ts +52 -0
- package/dist/components/download-banner-data.js +11 -0
- package/dist/components/index.d.ts +51 -0
- package/dist/components/index.js +38 -0
- package/dist/components/resource-banner-data.d.ts +34 -0
- package/dist/components/resource-banner-data.js +13 -0
- package/dist/components/scene-scroll-data.d.ts +24 -0
- package/dist/components/scene-scroll-data.js +9 -0
- package/dist/components/stats-data.d.ts +28 -0
- package/dist/components/stats-data.js +11 -0
- package/dist/components/steps-data.d.ts +38 -0
- package/dist/components/steps-data.js +13 -0
- package/dist/components/sticky-cards-data.d.ts +43 -0
- package/dist/components/sticky-cards-data.js +12 -0
- package/dist/components/team-grid-data.d.ts +38 -0
- package/dist/components/team-grid-data.js +11 -0
- package/dist/components/tiers-data.d.ts +47 -0
- package/dist/components/tiers-data.js +13 -0
- package/dist/marketing.css +101 -28
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { SceneScrollScene } from '../../scene-scroll-data.js';
|
|
3
|
+
export interface SceneScrollOwnProps {
|
|
4
|
+
/**
|
|
5
|
+
* `h2` — The default: the section sits under the page's own h1, and the scenes' titles are drawn at font.h2
|
|
6
|
+
* `h1` — The section opens a campaign page and the first scene's title is the page's heading — the reference design's hero use. Drawn at font.h1, the opening band's size
|
|
7
|
+
*/
|
|
8
|
+
headingLevel?: 'h2' | 'h1';
|
|
9
|
+
/** Always. The scene the section opens on: a title in a few words, a line under it where the title needs one, and the photograph filling the band behind them. Its title names the section, so it is the one to write as the section's heading. Give the photograph's width and height; `alt` empty unless it shows something the words do not. */
|
|
10
|
+
first: SceneScrollScene;
|
|
11
|
+
/** Always. The scene the section changes over to, in the same shape as the first. A title of about the same length as the first, so the words change in place rather than jumping, and a photograph of the same composition where there is one, so the dissolve reads as one place changing rather than a cut. */
|
|
12
|
+
second: SceneScrollScene;
|
|
13
|
+
/** A way on for the reader who wants more — "See trading hours", "Learn more". A standalone Link under the words, and it stays put through the change-over: it belongs to the section rather than to either scene, so it never fades while the reader is reaching for it. */
|
|
14
|
+
link?: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export type SceneScrollProps = SceneScrollOwnProps;
|
|
17
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
18
|
+
export declare const sceneScrollParts: {
|
|
19
|
+
readonly root: "dds-scenescroll";
|
|
20
|
+
readonly stage: "dds-scenescroll__stage";
|
|
21
|
+
readonly scene: "dds-scenescroll__scene";
|
|
22
|
+
readonly media: "dds-scenescroll__media";
|
|
23
|
+
readonly image: "dds-scenescroll__image";
|
|
24
|
+
readonly content: "dds-scenescroll__content";
|
|
25
|
+
readonly title: "dds-scenescroll__title";
|
|
26
|
+
readonly description: "dds-scenescroll__description";
|
|
27
|
+
readonly link: "dds-scenescroll__link";
|
|
28
|
+
};
|
|
29
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
30
|
+
export declare const sceneScrollDefaults: {
|
|
31
|
+
readonly headingLevel: "h2";
|
|
32
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// GENERATED from scene-scroll.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const sceneScrollParts = {
|
|
4
|
+
root: 'dds-scenescroll',
|
|
5
|
+
stage: 'dds-scenescroll__stage',
|
|
6
|
+
scene: 'dds-scenescroll__scene',
|
|
7
|
+
media: 'dds-scenescroll__media',
|
|
8
|
+
image: 'dds-scenescroll__image',
|
|
9
|
+
content: 'dds-scenescroll__content',
|
|
10
|
+
title: 'dds-scenescroll__title',
|
|
11
|
+
description: 'dds-scenescroll__description',
|
|
12
|
+
link: 'dds-scenescroll__link',
|
|
13
|
+
};
|
|
14
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
15
|
+
export const sceneScrollDefaults = { headingLevel: 'h2' };
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* `:where([data-dds-context="marketing"])` confines these rules without contributing specificity,
|
|
5
|
+
* so each is decided against the generated rule on its own terms.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Each scene is a screen tall, the photograph behind and the words over it.
|
|
10
|
+
*
|
|
11
|
+
* This is the whole of the layout wherever the scroll does not drive the change-over — a browser
|
|
12
|
+
* with no scroll timeline, a reader who asked for less motion, the page before any script: two
|
|
13
|
+
* scenes one after the other, each its own screen, every word at full strength and nothing pinned.
|
|
14
|
+
* The rules further down only add the track, the pin and the dissolve on top of it.
|
|
15
|
+
*
|
|
16
|
+
* `100cqh` rather than `100svh`, LandingHero's reason: with no ancestor declaring size containment
|
|
17
|
+
* a container query length falls back to the small viewport, so on a real page the two are the same
|
|
18
|
+
* number — the small viewport, measured with the browser's chrome showing, so a phone's address bar
|
|
19
|
+
* coming and going never resizes the scene mid-scroll as `vh` would. What the container unit adds
|
|
20
|
+
* is a frame standing in for a window: the preview's frame declares `container-type: size`, and the
|
|
21
|
+
* scene measures against that rather than escaping it. The section's own `container-type` is
|
|
22
|
+
* `inline-size`, which answers no question about height, so the unit passes straight through it.
|
|
23
|
+
* A screen is a length no token holds, which is why it is written here.
|
|
24
|
+
*
|
|
25
|
+
* `min-block-size`, so a scene whose words run long grows rather than clipping them.
|
|
26
|
+
*/
|
|
27
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene {
|
|
28
|
+
min-block-size: 100cqh;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* The photograph fills its scene, edge to edge, cropped to fill — the scene is a shape the screen
|
|
33
|
+
* decided, and a photograph letterboxed in it would show the band through the gaps.
|
|
34
|
+
*
|
|
35
|
+
* Stacking order inside the scene, which `isolation` on the scene keeps to itself: the photograph
|
|
36
|
+
* at the back, the words over it. An integer with no unit, which is why it is here.
|
|
37
|
+
*/
|
|
38
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__media {
|
|
39
|
+
inset: 0;
|
|
40
|
+
z-index: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__image {
|
|
44
|
+
block-size: 100%;
|
|
45
|
+
inline-size: 100%;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__content {
|
|
49
|
+
z-index: 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* The scrim, the same over the whole scene.
|
|
54
|
+
*
|
|
55
|
+
* color.bg.overlay is ImageBanner cover's scrim, held here across the whole photograph rather than
|
|
56
|
+
* fading to clear: the words are centred over the scene from the fold and run its width on a phone,
|
|
57
|
+
* so there is no clear side to leave. White over it keeps AA over any photograph, a pale one
|
|
58
|
+
* included — a white photograph comes out a mid grey, which white words clear comfortably — so the
|
|
59
|
+
* words never depend on the photograph being dark, and neither scene's words change colour.
|
|
60
|
+
*
|
|
61
|
+
* A pseudo-element of the photograph's frame, so it dissolves in with the second photograph rather
|
|
62
|
+
* than being laid over the first a second time.
|
|
63
|
+
*/
|
|
64
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__media::after {
|
|
65
|
+
background-color: var(--color-bg-overlay);
|
|
66
|
+
content: '';
|
|
67
|
+
inset: 0;
|
|
68
|
+
pointer-events: none;
|
|
69
|
+
position: absolute;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* A title with nothing under it carries no step under it.
|
|
74
|
+
*/
|
|
75
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__title:last-child {
|
|
76
|
+
margin-block-end: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* Where the words sit, the reference design's arrangement.
|
|
81
|
+
*
|
|
82
|
+
* Below 62rem — the reference's 992px, the same bound FeatureCards takes from it — the words are at
|
|
83
|
+
* the top of the stage and start at the edge, under the room a navigation bar takes: size.bar-height
|
|
84
|
+
* and the section's own step over it, about the reference's 112. From 62rem they are centred in
|
|
85
|
+
* the stage, across and down — a centred title wraps to ragged lines whose edge the eye loses on a
|
|
86
|
+
* narrow screen, which is the section-title rule's reason too. The group and its line are capped
|
|
87
|
+
* narrower than the column, so `margin-inline: auto` centres those boxes as well as their words.
|
|
88
|
+
*
|
|
89
|
+
* Longhand because `var()` is not permitted in a container query condition; `61.9375rem` is the last
|
|
90
|
+
* width below that bound. The section declares the container, and these are rules on what is inside
|
|
91
|
+
* it, which is the only thing a container query can style.
|
|
92
|
+
*/
|
|
93
|
+
@container (max-width: 61.9375rem) {
|
|
94
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene {
|
|
95
|
+
justify-content: flex-start;
|
|
96
|
+
padding-block-start: calc(var(--size-bar-height) + var(--space-section-default));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@container (min-width: 62rem) {
|
|
101
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__content {
|
|
102
|
+
align-items: center;
|
|
103
|
+
margin-inline: auto;
|
|
104
|
+
text-align: center;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__description {
|
|
108
|
+
margin-inline: auto;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* The photographs are anchored at their foot, as the reference's are, so a crop takes from the sky
|
|
114
|
+
* rather than from the ground the scene stands on.
|
|
115
|
+
*/
|
|
116
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__image {
|
|
117
|
+
object-position: bottom;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* The change-over, scrubbed by the scroll.
|
|
122
|
+
*
|
|
123
|
+
* The section becomes the track: two and a half screens tall, `250cqh` (the small viewport on a
|
|
124
|
+
* real page, for the reason above). The stage pins to the top of the window for the length of it,
|
|
125
|
+
* a screen tall, with both scenes stacked in its one cell, the second over the first. That leaves a
|
|
126
|
+
* screen and a half of scrolling while the stage holds still, which is the reference design's
|
|
127
|
+
* 250vh track and its 150vh of travel, without `vh`.
|
|
128
|
+
*
|
|
129
|
+
* The section names a view timeline, and three things run down it over `contain` — the stretch in
|
|
130
|
+
* which the track covers the whole window, which is exactly the stretch the stage is pinned for:
|
|
131
|
+
*
|
|
132
|
+
* the second photograph, and its scrim with it, dissolves in from 20% to 80%;
|
|
133
|
+
* the first scene's words fade out from 20% to 45%;
|
|
134
|
+
* the second scene's words fade in from 55% to 80%.
|
|
135
|
+
*
|
|
136
|
+
* The words change one after the other rather than crossing, so two titles are never on screen
|
|
137
|
+
* half-drawn over each other; the photograph takes the whole stretch, so the place changes under
|
|
138
|
+
* them while they do. A fifth of the stretch is held still at each end, so a reader arriving sees
|
|
139
|
+
* the first scene settled and one leaving sees the second. The reference ran the change over the
|
|
140
|
+
* middle third of the section's whole pass; this is the same middle, measured on the pin.
|
|
141
|
+
*
|
|
142
|
+
* Linear, because the scroll is the easing. Only one end of each fade is written — the other is
|
|
143
|
+
* the element's own resting opacity — so nothing here restates full strength as a number, and
|
|
144
|
+
* opacity.hidden is the role for what a reveal fades from.
|
|
145
|
+
*
|
|
146
|
+
* Only for a reader who has not asked for less motion, and only where a scroll timeline exists —
|
|
147
|
+
* asked around the rules rather than undone after them, because an undoing reset that loses to a
|
|
148
|
+
* more specific rule leaves the movement running for exactly the reader who asked it not to. Both
|
|
149
|
+
* conditions false is the layout at the top of this file: two scenes, one after the other.
|
|
150
|
+
*
|
|
151
|
+
* The timeline and the pin both measure against the nearest scroll container, which is why nothing
|
|
152
|
+
* between the section and the page may clip with `overflow: hidden`: `hidden` makes a box a scroll
|
|
153
|
+
* container even when it never scrolls, which freezes the dissolve and unpins the stage. The stage
|
|
154
|
+
* clips with `overflow: clip`, which does neither.
|
|
155
|
+
*/
|
|
156
|
+
@keyframes dds-scenescroll-arrive {
|
|
157
|
+
from {
|
|
158
|
+
opacity: var(--opacity-hidden);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@keyframes dds-scenescroll-leave {
|
|
163
|
+
to {
|
|
164
|
+
opacity: var(--opacity-hidden);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@supports (animation-timeline: view()) {
|
|
169
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
170
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll {
|
|
171
|
+
block-size: 250cqh;
|
|
172
|
+
view-timeline: --dds-scenescroll-track block;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__stage {
|
|
176
|
+
inset-block-start: 0;
|
|
177
|
+
min-block-size: 100cqh;
|
|
178
|
+
overflow: clip;
|
|
179
|
+
position: sticky;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene[data-scene="second"] .dds-scenescroll__media {
|
|
183
|
+
animation: dds-scenescroll-arrive linear both;
|
|
184
|
+
animation-range: contain 20% contain 80%;
|
|
185
|
+
animation-timeline: --dds-scenescroll-track;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene[data-scene="first"] .dds-scenescroll__content {
|
|
189
|
+
animation: dds-scenescroll-leave linear both;
|
|
190
|
+
animation-range: contain 20% contain 45%;
|
|
191
|
+
animation-timeline: --dds-scenescroll-track;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene[data-scene="second"] .dds-scenescroll__content {
|
|
195
|
+
animation: dds-scenescroll-arrive linear both;
|
|
196
|
+
animation-range: contain 55% contain 80%;
|
|
197
|
+
animation-timeline: --dds-scenescroll-track;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/*
|
|
203
|
+
* The link sits right under the words, whichever scene's words are showing.
|
|
204
|
+
*
|
|
205
|
+
* It belongs to the section rather than to a scene, so it does not fade with either. While the
|
|
206
|
+
* scenes change over, both scenes' words are laid into one grid area of the stage — the scenes
|
|
207
|
+
* themselves step out of the way (`display: contents`), so their photographs and their words become
|
|
208
|
+
* the stage's own items — and that area is as tall as the taller of the two. The link is the row
|
|
209
|
+
* under it, at space.heading.description-actions, the step from words to what a reader can do: under
|
|
210
|
+
* the text on every screen, and still while the text changes over it.
|
|
211
|
+
*
|
|
212
|
+
* Below 62rem the words and the link sit at the top of the stage, under the room a navigation bar
|
|
213
|
+
* takes; from 62rem they are centred down the stage, the empty rows above and below sharing what is
|
|
214
|
+
* left. The stage carries the section's insets here, since the scenes that held them are contents.
|
|
215
|
+
*
|
|
216
|
+
* In the plain fallback, where the scenes stack, the link is the stage's last row, under the second
|
|
217
|
+
* scene, on the band's own ground, with its own insets.
|
|
218
|
+
*/
|
|
219
|
+
@container (min-width: 62rem) {
|
|
220
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__link {
|
|
221
|
+
justify-content: center;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@supports (animation-timeline: view()) {
|
|
226
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
227
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__stage {
|
|
228
|
+
grid-template-areas:
|
|
229
|
+
'words'
|
|
230
|
+
'link'
|
|
231
|
+
'.';
|
|
232
|
+
grid-template-columns: minmax(0, 1fr);
|
|
233
|
+
grid-template-rows: auto auto 1fr;
|
|
234
|
+
padding-block: calc(var(--size-bar-height) + var(--space-section-default)) var(--space-section-default);
|
|
235
|
+
padding-inline: var(--space-inset-page);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__scene {
|
|
239
|
+
display: contents;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__media {
|
|
243
|
+
inset: 0;
|
|
244
|
+
z-index: 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__content {
|
|
248
|
+
grid-area: words;
|
|
249
|
+
z-index: 1;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__link {
|
|
253
|
+
grid-area: link;
|
|
254
|
+
margin-block-start: var(--space-heading-description-actions);
|
|
255
|
+
padding: 0;
|
|
256
|
+
z-index: 1;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@container (min-width: 62rem) {
|
|
262
|
+
@supports (animation-timeline: view()) {
|
|
263
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
264
|
+
:where([data-dds-context="marketing"]) .dds-scenescroll .dds-scenescroll__stage {
|
|
265
|
+
grid-template-areas:
|
|
266
|
+
'.'
|
|
267
|
+
'words'
|
|
268
|
+
'link'
|
|
269
|
+
'.';
|
|
270
|
+
grid-template-rows: 1fr auto auto 1fr;
|
|
271
|
+
padding-block: var(--space-section-default);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* GENERATED from stats.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-stats {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
display: flex;
|
|
7
|
+
inline-size: 100%;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
overflow-wrap: anywhere;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__inner {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
inline-size: 100%;
|
|
17
|
+
min-inline-size: 0;
|
|
18
|
+
max-inline-size: var(--size-content-max);
|
|
19
|
+
padding-block: var(--space-section-default);
|
|
20
|
+
padding-inline: var(--space-inset-page);
|
|
21
|
+
row-gap: var(--space-heading-content);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__header {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
min-inline-size: 0;
|
|
28
|
+
max-inline-size: var(--size-measure-heading);
|
|
29
|
+
row-gap: var(--space-gap-none);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__title {
|
|
33
|
+
margin-block: 0;
|
|
34
|
+
text-wrap: balance;
|
|
35
|
+
font-family: var(--font-h2-family);
|
|
36
|
+
font-size: var(--font-h2-size);
|
|
37
|
+
font-weight: var(--font-h2-weight);
|
|
38
|
+
letter-spacing: var(--font-h2-letter-spacing);
|
|
39
|
+
line-height: var(--font-h2-line-height);
|
|
40
|
+
margin-block-end: var(--space-heading-title-description);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__description {
|
|
44
|
+
margin-block: 0;
|
|
45
|
+
font-family: var(--font-body-md-family);
|
|
46
|
+
font-size: var(--font-body-md-size);
|
|
47
|
+
font-weight: var(--font-body-md-weight);
|
|
48
|
+
letter-spacing: var(--font-body-md-letter-spacing);
|
|
49
|
+
line-height: var(--font-body-md-line-height);
|
|
50
|
+
max-inline-size: var(--size-measure-description);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__list {
|
|
54
|
+
display: grid;
|
|
55
|
+
list-style: none;
|
|
56
|
+
margin: 0;
|
|
57
|
+
min-inline-size: 0;
|
|
58
|
+
padding: 0;
|
|
59
|
+
column-gap: var(--space-grid-gutter);
|
|
60
|
+
row-gap: var(--space-grid-gutter);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__dots {
|
|
64
|
+
display: none;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
row-gap: var(--space-gap-sm);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__dot {
|
|
70
|
+
background-color: currentcolor;
|
|
71
|
+
display: block;
|
|
72
|
+
block-size: var(--size-dot-diameter);
|
|
73
|
+
border-radius: var(--radius-pill);
|
|
74
|
+
inline-size: var(--size-dot-diameter);
|
|
75
|
+
opacity: var(--opacity-dot-rest);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__item {
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
min-inline-size: 0;
|
|
82
|
+
row-gap: var(--space-gap-sm);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__value {
|
|
86
|
+
display: grid;
|
|
87
|
+
font-variant-numeric: tabular-nums;
|
|
88
|
+
font-family: var(--font-figure-family);
|
|
89
|
+
font-size: var(--font-figure-size);
|
|
90
|
+
font-weight: var(--font-figure-weight);
|
|
91
|
+
letter-spacing: var(--font-figure-letter-spacing);
|
|
92
|
+
line-height: var(--font-figure-line-height);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__amount {
|
|
96
|
+
display: block;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__count {
|
|
100
|
+
display: block;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:where([data-dds-context="marketing"]) .dds-stats .dds-stats__label {
|
|
104
|
+
display: block;
|
|
105
|
+
font-family: var(--font-body-md-family);
|
|
106
|
+
font-size: var(--font-body-md-size);
|
|
107
|
+
font-weight: var(--font-body-md-weight);
|
|
108
|
+
letter-spacing: var(--font-body-md-letter-spacing);
|
|
109
|
+
line-height: var(--font-body-md-line-height);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="page"] {
|
|
113
|
+
background-color: var(--color-bg-page);
|
|
114
|
+
color: var(--color-fg-default);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="page"] .dds-stats__label {
|
|
118
|
+
color: var(--color-fg-muted);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="strong"] {
|
|
122
|
+
background-color: var(--color-bg-brand-strong);
|
|
123
|
+
color: var(--color-fg-on-brand-strong);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="strong"] .dds-stats__label {
|
|
127
|
+
color: var(--color-fg-muted-inverse);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="subtle"] {
|
|
131
|
+
background-color: var(--color-bg-page);
|
|
132
|
+
background-image: linear-gradient(var(--color-bg-band-subtle), var(--color-bg-band-subtle));
|
|
133
|
+
color: var(--color-fg-default);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
:where([data-dds-context="marketing"]) .dds-stats[data-ground="subtle"] .dds-stats__label {
|
|
137
|
+
color: var(--color-fg-muted);
|
|
138
|
+
}
|
|
139
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import './Stats.css';
|
|
2
|
+
import './stats-impl.css';
|
|
3
|
+
import '../block-reveal.css';
|
|
4
|
+
import { type StatsProps } from './Stats.types.js';
|
|
5
|
+
export type { StatsProps };
|
|
6
|
+
/**
|
|
7
|
+
* A heading over a row of key numbers, each counting up once as the section arrives — the reference
|
|
8
|
+
* site's StatsSimple.
|
|
9
|
+
*
|
|
10
|
+
* The count is decoration over a fact that is already written. Every figure is rendered as the page
|
|
11
|
+
* wrote it, from the first render — in the server's HTML, to a reader with no script, to a search
|
|
12
|
+
* engine — and that text is what assistive technology reads throughout. While a figure counts, the
|
|
13
|
+
* running number is laid over it in the same cell, hidden from assistive technology, and the figure
|
|
14
|
+
* beneath turns transparent rather than leaving: it still holds the cell's width, so nothing beside
|
|
15
|
+
* it moves as the digits change.
|
|
16
|
+
*
|
|
17
|
+
* The count is started by the arrival every block shares, `useReveal`, and only by that hook having
|
|
18
|
+
* hidden the section first. A reader who asked for less movement is never hidden, and so never
|
|
19
|
+
* counted at; nor is a renderer that cannot observe. Each figure starts as its own arrival does, a
|
|
20
|
+
* step behind the one before, and runs for motion.duration.reveal — the figure lands as it settles.
|
|
21
|
+
*
|
|
22
|
+
* `'use client'` for the count, the arrival, and `useId`, which names the region by its heading.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Stats({ ground, title, description, stats }: StatsProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useId, useLayoutEffect, useRef, useState } from 'react';
|
|
4
|
+
import './Stats.css';
|
|
5
|
+
import './stats-impl.css';
|
|
6
|
+
import '../block-reveal.css';
|
|
7
|
+
import { given } from '../../given.js';
|
|
8
|
+
import { milliseconds } from '../../css-time.js';
|
|
9
|
+
import { arriving, useReveal } from '../use-reveal.js';
|
|
10
|
+
import { countable, easing, partway } from './stats-count.js';
|
|
11
|
+
import { slotOf, useWheel } from './use-wheel.js';
|
|
12
|
+
import { statsDefaults, statsParts } from './Stats.types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Where a figure comes in the arrival, capped so a long set does not keep a reader waiting.
|
|
15
|
+
*
|
|
16
|
+
* The heading and the line under it take the first two steps; the figures follow one step apart up
|
|
17
|
+
* to the fourth, and the rest arrive with it — FeatureCards' cap and its reason.
|
|
18
|
+
*/
|
|
19
|
+
const FIRST_FIGURE = 2;
|
|
20
|
+
const LAST_STEP = FIRST_FIGURE + 3;
|
|
21
|
+
const stepOf = (at) => Math.min(FIRST_FIGURE + at, LAST_STEP);
|
|
22
|
+
/**
|
|
23
|
+
* A heading over a row of key numbers, each counting up once as the section arrives — the reference
|
|
24
|
+
* site's StatsSimple.
|
|
25
|
+
*
|
|
26
|
+
* The count is decoration over a fact that is already written. Every figure is rendered as the page
|
|
27
|
+
* wrote it, from the first render — in the server's HTML, to a reader with no script, to a search
|
|
28
|
+
* engine — and that text is what assistive technology reads throughout. While a figure counts, the
|
|
29
|
+
* running number is laid over it in the same cell, hidden from assistive technology, and the figure
|
|
30
|
+
* beneath turns transparent rather than leaving: it still holds the cell's width, so nothing beside
|
|
31
|
+
* it moves as the digits change.
|
|
32
|
+
*
|
|
33
|
+
* The count is started by the arrival every block shares, `useReveal`, and only by that hook having
|
|
34
|
+
* hidden the section first. A reader who asked for less movement is never hidden, and so never
|
|
35
|
+
* counted at; nor is a renderer that cannot observe. Each figure starts as its own arrival does, a
|
|
36
|
+
* step behind the one before, and runs for motion.duration.reveal — the figure lands as it settles.
|
|
37
|
+
*
|
|
38
|
+
* `'use client'` for the count, the arrival, and `useId`, which names the region by its heading.
|
|
39
|
+
*/
|
|
40
|
+
export function Stats({ ground = statsDefaults.ground, title, description, stats }) {
|
|
41
|
+
const titleId = useId();
|
|
42
|
+
const [band, revealed] = useReveal();
|
|
43
|
+
const held = useRef(null);
|
|
44
|
+
const hold = useCallback((element) => {
|
|
45
|
+
held.current = element;
|
|
46
|
+
band(element);
|
|
47
|
+
}, [band]);
|
|
48
|
+
/** Milliseconds since the section arrived, while it counts; `null` at rest. */
|
|
49
|
+
const [elapsed, setElapsed] = useState(null);
|
|
50
|
+
const [timing, setTiming] = useState(null);
|
|
51
|
+
// Whether the section has been hidden to wait for its arrival. Only a section that waited counts:
|
|
52
|
+
// one shown from the start — reduced motion, no observer — was never at nought to count from.
|
|
53
|
+
const waited = useRef(false);
|
|
54
|
+
const figures = stats.length;
|
|
55
|
+
// On a phone the figures turn one at a time in a wheel rather than stacking — see useWheel.
|
|
56
|
+
const section = useRef(null);
|
|
57
|
+
const { wheeling, turn, hold: holdWheel } = useWheel(section, figures);
|
|
58
|
+
useLayoutEffect(() => {
|
|
59
|
+
if (!revealed) {
|
|
60
|
+
waited.current = true;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!waited.current)
|
|
64
|
+
return;
|
|
65
|
+
waited.current = false;
|
|
66
|
+
const element = held.current;
|
|
67
|
+
if (element === null)
|
|
68
|
+
return;
|
|
69
|
+
// Asked again here, defensively: the hook declines to hide under this preference, so this
|
|
70
|
+
// should never be reached with it set — and if it is, the figures simply show.
|
|
71
|
+
if (typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const style = getComputedStyle(element);
|
|
75
|
+
const duration = milliseconds(style.getPropertyValue('--motion-duration-reveal')) ?? 0;
|
|
76
|
+
const stagger = milliseconds(style.getPropertyValue('--motion-duration-stagger')) ?? 0;
|
|
77
|
+
if (duration <= 0)
|
|
78
|
+
return;
|
|
79
|
+
const curve = easing(style.getPropertyValue('--motion-easing-reveal'));
|
|
80
|
+
// The last figure starts a step behind the one before it, so the count is over when it lands.
|
|
81
|
+
const total = stepOf(Math.max(figures - 1, 0)) * stagger + duration;
|
|
82
|
+
// At nought before the first frame is painted, in this layout effect: the section is arriving
|
|
83
|
+
// from transparent, and a frame of the final figures first would be a flash of the answer.
|
|
84
|
+
setTiming({ duration, stagger, curve });
|
|
85
|
+
setElapsed(0);
|
|
86
|
+
let start = null;
|
|
87
|
+
let frame = window.requestAnimationFrame(function tick(now) {
|
|
88
|
+
start ??= now;
|
|
89
|
+
const since = now - start;
|
|
90
|
+
if (since >= total) {
|
|
91
|
+
frame = 0;
|
|
92
|
+
setElapsed(null);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
setElapsed(since);
|
|
96
|
+
frame = window.requestAnimationFrame(tick);
|
|
97
|
+
});
|
|
98
|
+
return () => {
|
|
99
|
+
if (frame !== 0)
|
|
100
|
+
window.cancelAnimationFrame(frame);
|
|
101
|
+
setElapsed(null);
|
|
102
|
+
};
|
|
103
|
+
}, [revealed, figures]);
|
|
104
|
+
// Nothing to show is nothing drawn: a named region with no figure in it leads nowhere.
|
|
105
|
+
if (figures === 0)
|
|
106
|
+
return null;
|
|
107
|
+
return (_jsx("section", { className: statsParts.root, ref: section, "data-ground": ground, "aria-labelledby": titleId, children: _jsxs("div", { className: statsParts.inner, ref: hold, "data-revealed": revealed, children: [_jsxs("div", { className: statsParts.header, children: [_jsx("h2", { className: statsParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: statsParts.description, ...arriving(1), children: description })) : null] }), _jsx("span", { className: statsParts.dots, "aria-hidden": "true", ...(wheeling ? arriving(FIRST_FIGURE) : {}), children: stats.map((_, at) => (_jsx("span", { className: statsParts.dot, "data-current": wheeling && at === turn % figures }, at))) }), _jsx("ul", { className: statsParts.list, role: "list", "data-wheel": wheeling || undefined, tabIndex: wheeling ? 0 : undefined, "aria-labelledby": wheeling ? titleId : undefined, ...(wheeling ? { ...arriving(FIRST_FIGURE), ...holdWheel } : {}), children: stats.map((figure, at) => {
|
|
108
|
+
const step = stepOf(at);
|
|
109
|
+
const number = elapsed === null || timing === null ? null : countable(figure.value);
|
|
110
|
+
// The share of its count this figure has run, from its own arrival rather than the
|
|
111
|
+
// section's — so each number starts climbing as it starts to rise.
|
|
112
|
+
const share = number === null || timing === null || elapsed === null
|
|
113
|
+
? 1
|
|
114
|
+
: timing.curve(Math.min(Math.max((elapsed - step * timing.stagger) / timing.duration, 0), 1));
|
|
115
|
+
const counting = number !== null && share < 1;
|
|
116
|
+
return (
|
|
117
|
+
// A figure's position is its identity: the set is a list, and nothing reorders it.
|
|
118
|
+
_jsxs("li", { className: statsParts.item, "data-slot": wheeling ? slotOf(at, turn, figures) : undefined, ...(wheeling ? {} : arriving(step)), children: [_jsxs("span", { className: statsParts.value, "data-counting": counting, children: [_jsx("span", { className: statsParts.amount, children: _jsx("bdi", { children: figure.value }) }), _jsx("span", { className: statsParts.count, "aria-hidden": "true", children: counting ? _jsx("bdi", { children: partway(number, share) }) : null })] }), _jsx("span", { className: statsParts.label, children: figure.label })] }, at));
|
|
119
|
+
}) })] }) }));
|
|
120
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StatsFigure } from '../../stats-data.js';
|
|
2
|
+
export interface StatsOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `page` — The default, and the page's own white. A row of figures between two sections that need nothing to separate them
|
|
5
|
+
* `subtle` — The grey band, for a row of figures that should read as a section of its own without changing the page's voice. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section
|
|
6
|
+
* `strong` — `color.bg.brand-strong`, the dark band, for a set of figures a reader should arrive at — a home page's "Trade with confidence". The heading and the figures turn white and the labels take color.fg.muted-inverse
|
|
7
|
+
*/
|
|
8
|
+
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
+
/** Always. What the numbers prove, in the fewest words — "Trade with confidence", "Deriv in numbers". */
|
|
10
|
+
title: string;
|
|
11
|
+
/** A line under the heading, when the heading alone does not say whose numbers these are or since when — "For over 25 years, a trusted partner of traders worldwide." */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Always. The figures, in the order they are read along the row — three to five, each a short `value` exactly as it is to be read and a `label` of a few words. A value holding one number counts up to it; '24/7', or a value with no number, simply shows. An empty list draws nothing. */
|
|
14
|
+
stats: StatsFigure[];
|
|
15
|
+
}
|
|
16
|
+
export type StatsProps = StatsOwnProps;
|
|
17
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
18
|
+
export declare const statsParts: {
|
|
19
|
+
readonly root: "dds-stats";
|
|
20
|
+
readonly inner: "dds-stats__inner";
|
|
21
|
+
readonly header: "dds-stats__header";
|
|
22
|
+
readonly title: "dds-stats__title";
|
|
23
|
+
readonly description: "dds-stats__description";
|
|
24
|
+
readonly list: "dds-stats__list";
|
|
25
|
+
readonly dots: "dds-stats__dots";
|
|
26
|
+
readonly dot: "dds-stats__dot";
|
|
27
|
+
readonly item: "dds-stats__item";
|
|
28
|
+
readonly value: "dds-stats__value";
|
|
29
|
+
readonly amount: "dds-stats__amount";
|
|
30
|
+
readonly count: "dds-stats__count";
|
|
31
|
+
readonly label: "dds-stats__label";
|
|
32
|
+
};
|
|
33
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
34
|
+
export declare const statsDefaults: {
|
|
35
|
+
readonly ground: "page";
|
|
36
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// GENERATED from stats.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const statsParts = {
|
|
4
|
+
root: 'dds-stats',
|
|
5
|
+
inner: 'dds-stats__inner',
|
|
6
|
+
header: 'dds-stats__header',
|
|
7
|
+
title: 'dds-stats__title',
|
|
8
|
+
description: 'dds-stats__description',
|
|
9
|
+
list: 'dds-stats__list',
|
|
10
|
+
dots: 'dds-stats__dots',
|
|
11
|
+
dot: 'dds-stats__dot',
|
|
12
|
+
item: 'dds-stats__item',
|
|
13
|
+
value: 'dds-stats__value',
|
|
14
|
+
amount: 'dds-stats__amount',
|
|
15
|
+
count: 'dds-stats__count',
|
|
16
|
+
label: 'dds-stats__label',
|
|
17
|
+
};
|
|
18
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
19
|
+
export const statsDefaults = { ground: 'page' };
|