@deriv-com/dds-marketing 1.0.2 → 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 +89 -40
- 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 +9 -12
- package/.llm/components/ctabannerslider.md +15 -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 +2 -2
- package/.llm/components/illustrationscene.md +6 -10
- package/.llm/components/imagebanner.md +278 -0
- package/.llm/components/navbar.md +1 -1
- package/.llm/components/navbaritem.md +4 -0
- package/.llm/components/pageheader.md +4 -3
- 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 +11 -10
- 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 -4
- package/.llm/digest/ctabannerslider.md +4 -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/illustrationscene.md +2 -3
- package/.llm/digest/imagebanner.md +64 -0
- package/.llm/digest/navbaritem.md +1 -0
- package/.llm/digest/pageheader.md +2 -1
- 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 +19 -3
- package/.llm/tokens.md +26 -1
- package/AGENTS.md +17 -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.js +2 -2
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +4 -3
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +1 -1
- 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 +6 -2
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +8 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +1 -1
- 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/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.js +2 -2
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +4 -2
- package/dist/components/blocks/page-header/PageHeader.types.js +1 -1
- package/dist/components/blocks/page-header/page-header-impl.css +5 -3
- 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 +23 -0
- package/dist/components/core/background/Background.d.ts +10 -4
- package/dist/components/core/background/Background.js +16 -7
- package/dist/components/core/background/Background.types.d.ts +11 -8
- package/dist/components/core/background/Background.types.js +3 -1
- package/dist/components/core/background/background-impl.css +334 -1
- package/dist/components/core/background/halftone.d.ts +11 -0
- package/dist/components/core/background/halftone.js +43 -3
- 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-shader.d.ts +11 -0
- package/dist/components/core/background/use-shader.js +25 -0
- package/dist/components/core/background/use-spotlight.d.ts +2 -1
- package/dist/components/core/background/use-spotlight.js +9 -1
- 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.js +1 -1
- package/dist/components/core/illustration-card/illustration-card-impl.css +20 -0
- package/dist/components/core/illustration-scene/IllustrationScene.css +4 -7
- package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +2 -3
- package/dist/components/core/illustration-scene/illustration-scene-impl.css +7 -1
- 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 +45 -0
- package/dist/components/index.js +32 -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 +77 -28
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<!-- GENERATED from stats.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Stats
|
|
4
|
+
|
|
5
|
+
A trust and credibility section of key numbers: a heading, a line under it where the heading needs one, and the figures — each a number and the few words that say what it counts. From the fold they are a row read all at once; on a phone they turn one at a time in a wheel, the one in place large with its neighbours smaller above and below, a dot for each down the start edge — the reference site's mobile stats. The wheel holds while the reader hovers on it or focuses it, and stops for good once they press it; a reader who asked for less motion gets the figures two to a row instead. Each figure counts up from nought, once, as the section arrives on screen, and lands on the value exactly as the page wrote it — on a phone that is the figure in place when the section arrives; the ones that turn in later are already final.
|
|
6
|
+
|
|
7
|
+
The reference design's StatsSimple. The figure is written in the page's first HTML and is what assistive technology reads, so the count is decoration over a fact that is already there: a reader with no script, a search engine and a reader who asked for less movement all get the final number and nothing else.
|
|
8
|
+
|
|
9
|
+
## Use when
|
|
10
|
+
|
|
11
|
+
- Three to five headline numbers that prove scale or credibility — traders, markets, years, the smallest deposit — where the set is the point — read along a row from the fold, turned through one at a time on a phone
|
|
12
|
+
- A break between two heavier sections, when the numbers alone tell the story
|
|
13
|
+
|
|
14
|
+
## Do not use
|
|
15
|
+
|
|
16
|
+
- Each item needs a sentence of its own, or a picture → `FeatureCards`
|
|
17
|
+
- The number is part of a claim the page is making in words → `FeatureSplit`
|
|
18
|
+
- Numbers that change while the page is open — a price, a live count. The figures are written once and counted once. The phone's wheel turns between them, but no figure changes once written — a value that does is a ticker this does not draw
|
|
19
|
+
- A number nobody can stand behind. The figures are claims in the company's name; keep each one in step with its source
|
|
20
|
+
- More than six figures. Past two rows the set stops being taken in at a glance
|
|
21
|
+
|
|
22
|
+
## Anatomy
|
|
23
|
+
|
|
24
|
+
Stats renders 13 elements. A token binding names the part it applies to.
|
|
25
|
+
|
|
26
|
+
- `root` — `<section>`, class `dds-stats`. The section. It paints the ground and the ink to go with it — see `ground` — and asks its own width, so the row folds on the section's measure rather than the window's. A region named by its heading.
|
|
27
|
+
- `inner` — `<div>`, class `dds-stats__inner`. The measure and the gutter, the same column every band holds its content in, and the step from the heading to the figures: space.heading.content.
|
|
28
|
+
- `header` — `<div>`, class `dds-stats__header`. The heading and the line under it, FeatureCards' header and its arrangement: ranged to the start on a phone and centred from the fold. It sets no gap: each part's own margin is the step, so a heading with no line under it closes up.
|
|
29
|
+
- `title` — `<h2>`, class `dds-stats__title`. What the numbers prove. `h2` because a section sits under the page's own heading.
|
|
30
|
+
- `description` — `<p>`, class `dds-stats__description`. The line under the heading, at the description measure. Rendered only when `description` is set.
|
|
31
|
+
- `list` — `<ul>`, class `dds-stats__list`. The figures, as a list a screen reader counts. On a phone, a wheel: one figure in place, the one before it smaller above and the next smaller below, turning on to the next every motion.duration.hold and motion.duration.turn — the reference site's mobile stats. It turns only while on screen, for two figures or more, and never for a reader who asked for less motion, who gets the figures two to a row instead; every figure stays in the list wherever it stands. From the fold the whole set on one row when there are two or three, two rows of two for four until full width takes all four, and three to a row for five or six — read from the children, FeatureCards' way, so a set is never a row and an orphan. The space between figures, across and down, is the page grid's gutter, space.grid.gutter.
|
|
32
|
+
- `dots` — `<span>`, class `dds-stats__dots`. The wheel's dots, a column on its start edge, one to a figure with the one in place drawn long — PaginationDots stood on end. In the markup always and shown only while the wheel turns, on a phone — the stylesheet's call, as the wheel's own layout is — and hidden from assistive technology: they show where the wheel has got to, and the list beside them is read in full whatever is in place.
|
|
33
|
+
- `dot` — `<span>`, class `dds-stats__dot`. One figure's dot: size.dot.diameter round in the words' ink at opacity.dot-rest, and size.dot.diameter by size.dot.current at opacity.dot-current in the brand's coral, color.bg.brand, for the figure in place — the pagination dots' pair, so the wheel reads as every other rotating block does.
|
|
34
|
+
- `item` — `<li>`, class `dds-stats__item`. One figure: the number over the words that say what it counts, held together at space.gap.sm. Ranged to the start on a phone and centred from the fold, under a centred heading. It is what arrives, a step behind the one before it, in reading order.
|
|
35
|
+
- `value` — `<span>`, class `dds-stats__value`. The number, at font.figure: a heading's size and a lighter weight, so it reads as a fact rather than a claim. Its two layers share one cell — the figure as written and, while it counts, the running number laid over it — so the cell is always as wide as the final figure and nothing beside it moves as the digits change. Tabular numerals, so every digit takes the same width while it counts.
|
|
36
|
+
- `amount` — `<span>`, class `dds-stats__amount`. The figure exactly as the page wrote it — in the first HTML, before any script, and what assistive technology reads at every moment. While the running number is drawn over it, it is transparent rather than gone: still read, still holding the cell's width.
|
|
37
|
+
- `count` — `<span>`, class `dds-stats__count`. The running number while the figure counts up, with whatever is written either side of it kept as it is — '$' and 'M+' stay while the digits climb. Hidden from assistive technology, which hears the final figure once rather than every number on the way, and empty at rest.
|
|
38
|
+
- `label` — `<span>`, class `dds-stats__label`. What the figure counts, at the body step in the band's quieter ink: color.fg.muted on the page and the grey band, color.fg.muted-inverse on the dark one.
|
|
39
|
+
|
|
40
|
+
Apply these classes from the generated `statsParts` constant rather than writing the strings by hand.
|
|
41
|
+
|
|
42
|
+
## Composition
|
|
43
|
+
|
|
44
|
+
- Takes no children. Everything it renders comes from props
|
|
45
|
+
- Never contains: `Stats`, `LandingHero`, `ProductHero`, `PageHeader`, `Footer`, `Navbar` — in children or in any prop that takes a node
|
|
46
|
+
|
|
47
|
+
## Props
|
|
48
|
+
|
|
49
|
+
### ground — `page` | `subtle` | `strong` (default `page`)
|
|
50
|
+
|
|
51
|
+
- `page` — The default, and the page's own white. A row of figures between two sections that need nothing to separate them
|
|
52
|
+
- `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
|
|
53
|
+
- `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
|
|
54
|
+
|
|
55
|
+
Use when: Which of the page's three grounds this section paints, FeatureCards' axis and its reason: a band that wants to be seen as a band takes one of the other two, and the page decides the rhythm. The ink follows the ground — the heading and the figures in the band's own ink, the labels in its quieter one.
|
|
56
|
+
Never for: Marking importance. Every section on a page painted a ground is a page with no emphasis left. And never the brand's own coral, which is not offered: that ground belongs to the band that asks a reader to do something.
|
|
57
|
+
|
|
58
|
+
### title — `string` **Required.**
|
|
59
|
+
|
|
60
|
+
Use when: Always. What the numbers prove, in the fewest words — "Trade with confidence", "Deriv in numbers".
|
|
61
|
+
Never for: A figure. The figures are the content; the heading says what they add up to.
|
|
62
|
+
|
|
63
|
+
### description — `string`
|
|
64
|
+
|
|
65
|
+
Use when: 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."
|
|
66
|
+
Never for: A paragraph, or the figures again in words.
|
|
67
|
+
|
|
68
|
+
### stats — `data` `StatsFigure[]` **Required.**
|
|
69
|
+
|
|
70
|
+
Use when: 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.
|
|
71
|
+
Never for: A long value. "2.5M+" holds a row; "over two and a half million" breaks it on a phone. And a label longer than one line on a phone: the wheel steps by one figure's height, measured with a one-line label, so a label that wraps runs into the figure beside it.
|
|
72
|
+
|
|
73
|
+
## Accessibility
|
|
74
|
+
|
|
75
|
+
Guaranteed by the component. Write none of it by hand: the ids these attributes point at are generated per instance, so an attribute set from outside either says the same thing twice or points at nothing.
|
|
76
|
+
|
|
77
|
+
- Announced as: `region`
|
|
78
|
+
- `Tab` — Moves past the section, from the fold. On a phone, while the wheel turns, Tab lands on the wheel — focus holds it still — and moves on from there; nothing in it is operable.
|
|
79
|
+
- accessible name from title, so the section is a named region a reader can jump to and skip
|
|
80
|
+
- Each figure is read as written, once — the final value is in the markup from the first render and the running number is hidden from assistive technology, so a screen reader never announces the numbers on the way.
|
|
81
|
+
- A reader who asked for less movement sees the final figures from the start, with no count.
|
|
82
|
+
- On a phone the wheel moves on its own, so it can be held and stopped (WCAG 2.2.2): it holds while a pointer rests on it or it has focus — it is a tab stop named by the heading while it turns — and stops for good once it is pressed. It turns only while on screen, and never for a reader who asked for less motion. Every figure stays in the list a screen reader counts, wherever it stands on the wheel; the dots are hidden from assistive technology.
|
|
83
|
+
|
|
84
|
+
## Rules
|
|
85
|
+
|
|
86
|
+
- **On a phone a section's actions stack and each fills the width, including when there is only one** — On a phone a page's actions stack, and each one fills the width. Not most of it, and not the width its label happens to need — the whole column.
|
|
87
|
+
|
|
88
|
+
Two side by side is what this replaces. On the narrowest screen each gets half a column minus the gap, which is rarely enough for a real label: the words wrap inside the pills, the two buttons come out different heights, and the pair reads as a broken row rather than as a choice. Stacked, each has the whole width and neither has to shorten its words to fit.
|
|
89
|
+
|
|
90
|
+
A single action fills too, and that is the part worth saying, because it is the one that looks unnecessary. A lone button has the room to sit at its natural width and still should not: a full-width control is the phone's convention for the thing the screen is asking you to do, and a pill hugging its label reads as one option among others that are not there. It also makes the target predictable — the whole width, wherever the thumb lands — which a centred pill does not.
|
|
91
|
+
|
|
92
|
+
Filling is the row's job rather than the button's. A button has no width of its own and is not given one; the row it sits in becomes a column and stretches its children, so nothing about the control changes and the same button is full width here and its own size on a desktop.
|
|
93
|
+
|
|
94
|
+
This is the phone's breakpoint, size.breakpoint.md, and not the wider one that decides whether a heading is centred. Those are different questions and they break at different widths: a heading stops being centred when the measure is the screen, while a button stops being full width much sooner than that — stretched across a tablet it is a long way from its own label, and a label centred in a metre of pill is harder to hit than one in a pill the size of the words.
|
|
95
|
+
|
|
96
|
+
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
97
|
+
Guidance only — cannot be checked automatically.
|
|
98
|
+
- **Never nest one interactive element inside another** — Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link, CardButton and TextInput simultaneously.
|
|
99
|
+
Guidance only — cannot be checked automatically.
|
|
100
|
+
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
101
|
+
|
|
102
|
+
color.bg.brand carries a second limit that is not about forgetting. Its ink measures 3.39:1, which clears the 3:1 a heading needs and misses the 4.5:1 running copy needs. A coral band may carry a headline and a call to action; a paragraph on one is text the reader has to work through at a ratio the waiver on that role does not cover — the waiver says so itself. A section with copy in it takes color.bg.brand-strong, which is near-black and carries white at full contrast.
|
|
103
|
+
|
|
104
|
+
color.bg.strong is not a section ground. It is the inverted fill for an action that has to outrank what surrounds it, and the components that paint it — Button and ButtonIcon in their inverse form — already set both halves in one rule, which is the pattern a hand-painted section has to copy.
|
|
105
|
+
Guidance only — cannot be checked automatically.
|
|
106
|
+
- **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side** — A section's spacing is named by the relationship it expresses, not chosen by size. Every gap in a section has a role token, and reaching for a step off the generic scale because it happens to be the right number is how two sections written by two people stop lining up: the numbers agree today and drift the first time one of them is tuned.
|
|
107
|
+
|
|
108
|
+
The heading group is three steps, not one gap. An eyebrow sits nearer its title than the title sits to its description, and the actions sit further from the description than either — space.heading.eyebrow-title, space.heading.title-description, space.heading.description-actions, in that order. A single `gap` on the group cannot say this; it sets all three the same and the block reads as evenly spaced lines rather than as a mark, a name and a paragraph. The eyebrow has to identify itself for this to work, because a group that opens with a title must not give its description the eyebrow's tighter step.
|
|
109
|
+
|
|
110
|
+
The step between a title and its description follows the size of the title, which is why there are two of it. What a reader sees is not the gap but the gap plus the leading above it, and leading scales with the type: under a display title the leading is most of the space, under a card's title it is half as deep. One value for both makes a card look loose at the size that made a section look right. So space.heading.title-description is the display step and space.heading.title-description-compact is the step at a card's size, and the choice is made by how big the title is rather than by what kind of block it sits in.
|
|
111
|
+
|
|
112
|
+
Every one of those steps is smaller than the gap below the group, and that ordering is what holds the group together as one thing. space.heading.content is the step between a heading group and the content it introduces, and it is the widest measure inside a section: the one gap the eye reads as a change of subject rather than as a continuation.
|
|
113
|
+
|
|
114
|
+
That step is the same whether the content is under the heading or beside it. A split is the same relationship turned on its side — a heading group and the content it introduces — so the space between the two halves is space.heading.content, not a gutter. When the split collapses to one column on a phone the gap becomes vertical again, which is where it started, and nothing has to change for that to be right.
|
|
115
|
+
|
|
116
|
+
space.grid.gutter is between two things of the same kind. Two cards in a row are the same kind; the two halves of a split are not, which is why the gutter is the wrong measure there even when the number would have looked acceptable. The gutter runs on both axes, so a grid reads as an even field rather than as rows with a seam down them.
|
|
117
|
+
|
|
118
|
+
space.inset.card is the card's, not the page's. A row of cards padded differently is a row of different cards, and the fill is the only edge they have. A page composing a row does not get to choose it.
|
|
119
|
+
|
|
120
|
+
Column count is not a breakpoint decision. A row holds as many columns as fit before a column would be narrower than size.grid.column-min, and drops one when they would not. Written as a fixed count that collapses at a breakpoint, a four-up row keeps four columns at every width above the phone and sets its copy two or three words to a line through the whole of the tablet range — and on a narrow desktop, which no breakpoint sits on at all. The threshold is a property of the row rather than of a card: a card fills whatever cell it is given.
|
|
121
|
+
|
|
122
|
+
What this does not cover is the space above and below a section, which is space.section.default and space.section.compact, and the page's own side margin, which is space.inset.page. Those are the section's outside; everything here is its inside.
|
|
123
|
+
Guidance only — cannot be checked automatically.
|
|
124
|
+
- **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone** — Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
|
|
125
|
+
|
|
126
|
+
Content stacked under the title — a row of cards, an accordion, a set of steps — takes a centred title. The heading group and the block below it share one axis, so a centred title is symmetric with the thing it names, and the eye drops from the middle of the words to the middle of the set. A title starting at the left over a centred or full-width block reads as belonging to the first column rather than to all of them.
|
|
127
|
+
|
|
128
|
+
Content beside the title — a split, a picture in the other half, anything laid out in columns — takes a title that starts where its content starts. The two share a left edge, and that edge is what says they are one thing read across rather than two stacked. Centring the title there breaks the only alignment the reader has to hold the halves together, and it drifts further from its content the wider the page gets.
|
|
129
|
+
|
|
130
|
+
The heading group is what carries this, not the heading alone. An eyebrow, a title and a description are read as one block and align together; aligning the title without them leaves a centred heading over start-aligned copy, which reads as a mistake rather than as a choice.
|
|
131
|
+
|
|
132
|
+
Centred means all of it, not just the words. A badge, a row of actions, a picture — these are flex children, and a flex child is placed by align-items rather than by text-align, so a block that only sets the text leaves everything that is not text at the start. A hero is the case that shows it: its title and copy centred while its badge and its buttons did not.
|
|
133
|
+
|
|
134
|
+
A capped block centres itself as well as its words. A heading group takes size.heading-group.max, and a cap that is not centred leaves the measure at the start of the column with the words centred inside it — composed, and a long way left of the middle it appears to be in.
|
|
135
|
+
|
|
136
|
+
Both arrangements go to the start on a phone. A centred block reverts below the breakpoint, and the reason is the measure: on a phone the measure is the screen, so a centred title wraps to three or four ragged lines and the eye loses the left edge it was tracking — the same symmetry that reads as composure on a desktop is what makes it hard to scan on a phone. Centring there has to be asked for twice, and a section title is not one of the things that asks: it is centred because there is room for it, and on a phone there is not. Going back to the start means all of it too, and a capped block is the one that hides a leftover: its words go to the start while its measure stays in the middle of the column, which reads as a title still centred over a badge and buttons that are not — the box in the middle and the line inside it at the edge.
|
|
137
|
+
|
|
138
|
+
A hero is a section like any other: its badge, title, copy and actions are one stacked block, so it is centred on a desktop and starts on a phone with everything else.
|
|
139
|
+
|
|
140
|
+
What this is not about is a page whose body is a form or a document. A title over a sign-up form or a guide is not introducing a set of content — it is the first line of the thing itself, and it keeps the alignment the body has, which for running text is the start. The distinction is whether the block below is content the title names or content the title is part of.
|
|
141
|
+
Guidance only — cannot be checked automatically.
|
|
142
|
+
- **Anything a pointer has to hit is at least 24px in both directions** — A control sized by its contents is as big as its contents, and a glyph is chosen for how it reads rather than for how easily it is hit. An icon-only button with no padding is a 16px target — smaller than the pad of a finger, and smaller than the tremor of a hand using a mouse.
|
|
143
|
+
|
|
144
|
+
WCAG 2.2 asks for 24 by 24 CSS pixels at AA. The exceptions are narrower than they look: inline targets inside a sentence are exempt, and so is a small target with 24px of clear space around it — but a clear button sits against the field it empties, and a field is itself a target, so the spacing exemption does not apply to the case that keeps arising.
|
|
145
|
+
|
|
146
|
+
The target and the mark are separate decisions, and conflating them is what produces both faults. Growing the glyph to 24px makes it shout; leaving the button at 16px makes it hard to hit. So the glyph keeps the size that reads correctly beside its text, and the box around it declares a minimum of its own — which is what size.target.min is for.
|
|
147
|
+
|
|
148
|
+
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
149
|
+
Guidance only — cannot be checked automatically.
|
|
150
|
+
- **A component is written along the reading axis, not along the page's left and right** — Every measure, inset and placement in this package names an axis rather than a side: inline-size and block-size, padding-inline and padding-block, inset-inline-start and inset-block-end, margin-inline: auto, text-align: start. Written that way a component follows whichever direction the page is read in, and a band whose claim ranges to the leading edge with its subject on the trailing one is the same composition in Arabic as in English, mirrored, with nothing restated. Written as left and right it is the same pixels in both, which is a layout nobody designed for the second language.
|
|
151
|
+
|
|
152
|
+
The enum values follow the same rule and for the same reason. A prop that names where a picture sits takes start and end, never left and right — FeatureSplit, FeatureBullets and FeatureScroll all declare mediaPosition that way, and the flex directions they generate flip on their own because row already means the reading order. A value called left would have to be re-read as right by every author working in a mirrored page, which is a translation this system should be doing rather than asking for.
|
|
153
|
+
|
|
154
|
+
The guidance a contract carries is part of the component, so it follows too. Describing a claim as ranging left is describing one of the two languages, and it was written that way here for a while: three of the opening bands said so in their own intent. A reader in a mirrored page meets that sentence and has to decide whether the component is wrong or the sentence is, and neither answer is one documentation should force.
|
|
155
|
+
|
|
156
|
+
Two things genuinely have no logical form and are not covered by this. A CSS gradient takes a physical direction — there is no to inline-end — so a pattern that must mirror has to be stated twice under a direction query, and one that is periodic and centred, like PageHeader's rule grid, does not need to. A glyph that points the way onward is the other: an arrow is a picture of a direction, and mirroring it belongs to the icon set rather than to the component holding it.
|
|
157
|
+
Guidance only — cannot be checked automatically.
|
|
158
|
+
|
|
159
|
+
## Anti-examples
|
|
160
|
+
|
|
161
|
+
❌ Stats for: Each item needs a sentence of its own, or a picture
|
|
162
|
+
A figure is read at a glance; something that needs explaining is a card
|
|
163
|
+
→ use `FeatureCards` instead.
|
|
164
|
+
|
|
165
|
+
❌ Stats for: The number is part of a claim the page is making in words
|
|
166
|
+
A figure in a sentence is copy; this sets figures on their own, where the number is the whole of what is said
|
|
167
|
+
→ use `FeatureSplit` instead.
|
|
168
|
+
|
|
169
|
+
## Example
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { Stats } from '@deriv-com/dds-marketing'
|
|
173
|
+
|
|
174
|
+
<Stats title="Trade with confidence" description="For over 25 years, a trusted partner of traders worldwide." stats={[{"value":"3M+","label":"Traders worldwide"},{"value":"250+","label":"Markets to trade"},{"value":"24/7","label":"Support in your language"},{"value":"$5","label":"Minimum deposit"}]} />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## In use
|
|
178
|
+
|
|
179
|
+
### Grounds
|
|
180
|
+
|
|
181
|
+
The same figures on the page, the grey band and the dark band. The heading and the figures take the band's ink, the labels its quieter one.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { Stats } from '@deriv-com/dds-marketing'
|
|
185
|
+
|
|
186
|
+
// On the page
|
|
187
|
+
<Stats title="Deriv in numbers" stats={[{"value":"3M+","label":"Traders worldwide"},{"value":"250+","label":"Markets to trade"},{"value":"$5","label":"Minimum deposit"}]} />
|
|
188
|
+
|
|
189
|
+
// On the grey band
|
|
190
|
+
<Stats ground="subtle" title="Deriv in numbers" stats={[{"value":"3M+","label":"Traders worldwide"},{"value":"250+","label":"Markets to trade"},{"value":"$5","label":"Minimum deposit"}]} />
|
|
191
|
+
|
|
192
|
+
// On the dark band
|
|
193
|
+
<Stats ground="strong" title="Deriv in numbers" stats={[{"value":"3M+","label":"Traders worldwide"},{"value":"250+","label":"Markets to trade"},{"value":"$5","label":"Minimum deposit"}]} />
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### How a set fills the row
|
|
197
|
+
|
|
198
|
+
Four figures are one row at full width and two rows of two on a tablet; five are three and two. Narrow the window to see each set fold.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { Stats } from '@deriv-com/dds-marketing'
|
|
202
|
+
|
|
203
|
+
// Four figures
|
|
204
|
+
<Stats title="Trade with confidence" description="For over 25 years, a trusted partner of traders worldwide." stats={[{"value":"168M+","label":"Monthly deals"},{"value":"3M+","label":"Traders worldwide"},{"value":"$700B+","label":"Monthly trading volume"},{"value":"1999","label":"Established in"}]} />
|
|
205
|
+
|
|
206
|
+
// Five figures
|
|
207
|
+
<Stats title="Why traders choose Deriv" stats={[{"value":"3M+","label":"Traders worldwide"},{"value":"250+","label":"Markets to trade"},{"value":"24/7","label":"Support in your language"},{"value":"$5","label":"Minimum deposit"},{"value":"20+","label":"Offices worldwide"}]} />
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### What counts
|
|
211
|
+
|
|
212
|
+
A value with one number counts up to it, keeping what is either side. '24/7' and words show as written. Every figure is in the first HTML.
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
import { Stats } from '@deriv-com/dds-marketing'
|
|
216
|
+
|
|
217
|
+
// Prefixes, suffixes and decimals
|
|
218
|
+
<Stats title="Deriv at a glance" stats={[{"value":"$1.2B","label":"Paid out to traders"},{"value":"99.9%","label":"Platform uptime"},{"value":"24/7","label":"Synthetic markets open"}]} />
|
|
219
|
+
```
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
<!-- GENERATED from steps.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Steps
|
|
4
|
+
|
|
5
|
+
A two-column how-it-works section pairing a supporting picture with a numbered, ordered list of steps, each a title and a line describing it.
|
|
6
|
+
|
|
7
|
+
It walks a reader through a sequence they are about to follow — opening an account, funding it, placing a first trade — and the numbers are the argument: they say the order matters and how far there is to go. The list is a real ordered list, so the count and the order reach a screen reader too, and the numbers drawn beside each step are the section's own rather than the page's.
|
|
8
|
+
|
|
9
|
+
It sits on the page's own ground by default; `ground` paints the grey or the dark band where the section needs setting apart from the ones around it.
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
- A page explains a get-started or onboarding flow — opening an account, funding it, starting to trade
|
|
14
|
+
- A process has three to six steps that a reader follows in one order, each a short imperative and a sentence
|
|
15
|
+
- A setup or a how-to page — a platform's install, a deposit or a withdrawal — needs its sequence shown beside one picture
|
|
16
|
+
- The same how-it-works list, walked through on its own: with `autoplay` each step takes its turn, its rule filling as it holds, and the picture changes to that step's — a sequence shown in sequence rather than all at once
|
|
17
|
+
|
|
18
|
+
## Do not use
|
|
19
|
+
|
|
20
|
+
- The items have no order a reader follows — they are things a product includes → `FeatureBullets`
|
|
21
|
+
- Three or four things side by side, each with its own picture → `FeatureCards`
|
|
22
|
+
- Each stage needs a screen and a picture of its own → `FeatureScroll`
|
|
23
|
+
- A list without an order. Numbers against items that could be read in any sequence claim a sequence the page does not have, and a reader follows them anyway
|
|
24
|
+
- A sequence longer than six steps. Past that the list runs well past the picture beside it, and a process that long wants a page of its own rather than a section
|
|
25
|
+
- An article or a guide's body. This is a section in the middle of a marketing page, and carries no navigation of its own
|
|
26
|
+
|
|
27
|
+
## Anatomy
|
|
28
|
+
|
|
29
|
+
Steps renders 15 elements. A token binding names the part it applies to.
|
|
30
|
+
|
|
31
|
+
- `root` — `<section>`, class `dds-steps`. The section. It paints the ground that separates it from the page above and below, and asks its own width so the split folds on the section's measure rather than the window's.
|
|
32
|
+
|
|
33
|
+
It paints one of the page's three grounds and the ink that goes with it, in one decision — see `ground`. The ink is set here and inherited by everything inside.
|
|
34
|
+
- `inner` — `<div>`, class `dds-steps__inner`. The measure and the gutter, holding the section's content in the same column as every other section on the page.
|
|
35
|
+
- `split` — `<div>`, class `dds-steps__split`. The two halves. A row at full width with the picture on whichever side `mediaPosition` names, and one column below the fold with the picture first — the order the reference design takes and the one a sequence reads in.
|
|
36
|
+
- `media` — `<div>`, class `dds-steps__media`. The picture, and one of the section's two halves rather than an addition to it. Held to a square and cropped to fill it, so the section is the same shape whatever the page passes. With pictures on the steps it holds all of them in one cell, and the current step's is the one shown: the first while the list is still, each in turn under `autoplay`, crossing over in motion.duration.shift.
|
|
37
|
+
- `image` — `<img>`, class `dds-steps__image`. One step's picture, from its `image`, stacked in the media cell with the others and shown while its step is current. Decoration, as the media cell is: what the step says is its title and its line.
|
|
38
|
+
- `content` — `<div>`, class `dds-steps__content`. The title and the steps under it.
|
|
39
|
+
|
|
40
|
+
It sets no gap of its own. The step from the title to the list is the title's own `margin-block-end`, which is how FeatureSplit and FeatureBullets carry theirs.
|
|
41
|
+
- `title` — `<h2>`, class `dds-steps__title`. Where the steps lead. `h2` because a section in the middle of a page sits under the page's own heading.
|
|
42
|
+
- `list` — `<ol>`, class `dds-steps__list`. The steps, as an ordered list — a screen reader announces how many there are and where each sits, which is the sequence the section exists to say. The browser's own numbers are switched off because the section draws its own, larger, beside each step.
|
|
43
|
+
|
|
44
|
+
Nothing separates the rows: each carries its own rule on its start edge and its own padding inside it. `space.gap.none` is that said rather than left out.
|
|
45
|
+
- `step` — `<li>`, class `dds-steps__step`. One step: its number, then its title and line. Ruled above rather than below, as FeatureBullets' rows are, so the lines fall between the steps and none is left under the last.
|
|
46
|
+
|
|
47
|
+
The number is centred on the title's first line. It is set larger than the title, so a shared baseline left it standing a third taller above the title's capitals and a shared top left it hanging below; given a line exactly as tall as the title's, its figure sits centred on the line it numbers, reaching as far above the title's capitals as below its baseline.
|
|
48
|
+
|
|
49
|
+
The steps arrive one after another as the section comes up, in the order they are taken, so a sequence appears in sequence.
|
|
50
|
+
- `number` — `<span>`, class `dds-steps__number`. The step's place in the sequence, drawn large in the brand's colour. Decoration, and hidden from assistive technology: the ordered list already says where each step sits, and announcing the number as well says it twice.
|
|
51
|
+
|
|
52
|
+
Tabular figures, so a 1 is as wide as a 4 and every title starts on the same line down the list. The reference design reserved a fixed column for the same reason; at six steps at most there is only ever one digit, and figures of one width are the column.
|
|
53
|
+
|
|
54
|
+
Its colour follows the ground, as FeatureBullets' mark does: `color.fg.brand-accent` only on the bare page, `color.fg.brand` on the grey band, and the band's own ink on the dark one.
|
|
55
|
+
- `body` — `<div>`, class `dds-steps__body`. The step's title and the line under it, held together at a card's title-to-description step.
|
|
56
|
+
- `step-title` — `<h3>`, class `dds-steps__step-title`. What the reader does at this step. `h3` under the section's `h2`, so a reader moving by heading walks the steps one at a time.
|
|
57
|
+
- `trigger` — `<button>`, class `dds-steps__trigger`. Under `autoplay`, the step's title as a button: pressing it makes the step current and stops the turn for good. Inside the heading, so a reader moving by heading still walks the steps; `aria-current="step"` on the current one says which step is shown. Rendered only when `autoplay` is set.
|
|
58
|
+
- `step-description` — `<p>`, class `dds-steps__step-description`. What the step involves, in a sentence.
|
|
59
|
+
- `progress` — `<span>`, class `dds-steps__progress`. Under `autoplay`, the current step's rule filling from the start edge over motion.duration.dwell — how long until the next step — in the brand's coral. Held where the turn holds, full and still once it stops or for a reader who asked for less motion. Hidden from assistive technology: the current step is said by `aria-current`.
|
|
60
|
+
|
|
61
|
+
Apply these classes from the generated `stepsParts` constant rather than writing the strings by hand.
|
|
62
|
+
|
|
63
|
+
## Composition
|
|
64
|
+
|
|
65
|
+
- Takes no children. Everything it renders comes from props
|
|
66
|
+
- Never contains: `Steps`, `FeatureSplit`, `FeatureBullets`, `LandingHero`, `ProductHero`, `PageHeader`, `Footer`, `Navbar`, `Table`, `Accordion` — in children or in any prop that takes a node
|
|
67
|
+
|
|
68
|
+
## Props
|
|
69
|
+
|
|
70
|
+
### ground — `page` | `subtle` | `strong` (default `page`)
|
|
71
|
+
|
|
72
|
+
- `page` — The default, and the page's own white. A section that has nothing to separate itself from what is above it — most of them
|
|
73
|
+
- `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice. The reference design paints this section grey, and a page following it closely takes this. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section.
|
|
74
|
+
- `strong` — `color.bg.brand-strong`, the dark band. It stops the page rather than dividing it, so it is for a section a reader should arrive at — and one per page is usually one more than enough
|
|
75
|
+
|
|
76
|
+
Use when: Which of the page's three grounds this section paints. A marketing page is white, and a band that wants to be seen as a band takes one of the other two — so this is how a page builds its rhythm: white, white, grey, white, dark. The section above knows nothing about the one below it, so the page is the only thing that can decide.
|
|
77
|
+
|
|
78
|
+
The ink follows the ground and is not a second decision: a dark band carries white type because this sets both halves in one value, and the numbers change with it.
|
|
79
|
+
Never for: Marking importance. Every section on a page painted dark is a page with no emphasis left. And never the brand's own coral, `color.bg.brand`, which is not offered here: that ground belongs to the band that asks a reader to do something, and a how-it-works section wearing it is a page with two calls to action, one of which does nothing.
|
|
80
|
+
|
|
81
|
+
### mediaPosition — `start` | `end` (default `start`)
|
|
82
|
+
|
|
83
|
+
- `start` — The default, and the reference design's: the picture first, then the steps it introduces
|
|
84
|
+
- `end` — The steps first, for a section sitting under a split whose picture is already at the start
|
|
85
|
+
|
|
86
|
+
Use when: Which side the picture takes at full width. Alternating it against the split sections around it is what stops two in a row reading as one long column, and it is the page's decision rather than this section's.
|
|
87
|
+
|
|
88
|
+
Below the fold there is one column and the picture leads it, whichever side it takes on a desktop — the reference design's order, and the right one for a sequence: the picture sets the scene the steps then walk through, and one left under the last step is a picture nobody scrolls back up to connect.
|
|
89
|
+
Never for: Moving the picture on a phone. There is one column there and the picture leads it
|
|
90
|
+
|
|
91
|
+
### autoplay — `boolean` (default `false`)
|
|
92
|
+
|
|
93
|
+
Use when: Whether the steps take their turn on their own: one step is current, its rule fills over motion.duration.dwell, then the next takes over, and back to the first after the last. The current step's number is drawn at full strength and the rest recede; with an `image` on each step the picture changes to the current one's. Each step's title becomes a button that makes it current. Off by default, so a list nobody configured stays still. On, it holds while the pointer is over the section or focus is inside it, waits until the section is on screen, never moves for a reader who asked for less motion, and stops for good once the reader presses a step — the WAI carousel rule CtaBannerSlider follows: a reader who has chosen a step is reading it. That gives a reader a way to stop it, which WCAG 2.2.2 asks for, but not a visible one, so a page that needs 2.2.2 met plainly should leave it off.
|
|
94
|
+
Never for: Steps whose descriptions take longer to read than motion.duration.dwell — leave it off rather than cut the copy to the timer. And a list with no picture per step, where the only thing that moves is a rule: the turn is worth it when the picture changes with it.
|
|
95
|
+
|
|
96
|
+
### title — `string` **Required.**
|
|
97
|
+
|
|
98
|
+
Use when: Always. What the steps get a reader to, in the fewest words that say it — 'Get started in 3 steps'
|
|
99
|
+
Never for: A sentence. The steps underneath are the argument; this only has to name where they lead
|
|
100
|
+
|
|
101
|
+
### steps — `data` `StepsItem[]` **Required.**
|
|
102
|
+
|
|
103
|
+
Use when: Always. The steps, in the order a reader takes them — three or four is right, six the most. Each is a short imperative and a sentence under about two hundred characters. The number in front of each is drawn from its place in the list, so reordering the list renumbers it. Give each step an `image` — a screenshot of that step — and the picture beside the list is the current step's: the first while the list is still, and each in turn under `autoplay`.
|
|
104
|
+
Never for: Items that could be taken in any order, or a step that is two steps. Each number is a claim that this comes after the one above it and is one thing to do
|
|
105
|
+
|
|
106
|
+
### media — `node`
|
|
107
|
+
|
|
108
|
+
Accepts: *
|
|
109
|
+
Use when: The one picture beside the steps, where they have no pictures of their own — a screenshot, a photograph. The section is a split and the picture is one half of it: give this or an `image` on each step, because without either the list runs to a measure it was never sized for. Steps that carry their own pictures win over this.
|
|
110
|
+
Never for: Anything a reader has to read or press. It is held to a square and cropped to fill it, so words in it are cropped too
|
|
111
|
+
|
|
112
|
+
## Accessibility
|
|
113
|
+
|
|
114
|
+
Guaranteed by the component. Write none of it by hand: the ids these attributes point at are generated per instance, so an attribute set from outside either says the same thing twice or points at nothing.
|
|
115
|
+
|
|
116
|
+
- Announced as: `region`
|
|
117
|
+
- `Tab` — Moves past the section when it is still: nothing in it is operable then. Under `autoplay` it moves through the steps' titles, each a button, in order.
|
|
118
|
+
- `Enter` — Under `autoplay`, on a step's title: makes that step current and stops the turn for good.
|
|
119
|
+
- `Space` — The same as Enter.
|
|
120
|
+
- accessible name from title, so the section is a named region a screen reader can jump to and skip rather than an unlabelled section a reader has to walk
|
|
121
|
+
- The steps are an ordered list, so a screen reader announces how many there are and each one's place in the sequence. A stack of divs with numbers drawn in them reads as prose and loses the order, which is what the section is for
|
|
122
|
+
- The number drawn beside each step is decoration and is hidden from assistive technology. The ordered list already announces each step's place, and reading the drawn number as well says it twice
|
|
123
|
+
- Each step's title is a heading one level under the section's, so a reader moving by heading walks the steps one at a time
|
|
124
|
+
- The picture is decoration and is hidden from assistive technology — the one picture and every step's alike. What the section says is the title and the steps; a picture carrying something they do not is a section that reads as half empty to anyone who cannot see it
|
|
125
|
+
- Under autoplay, a hold while the pointer is over the section or focus is inside it, no turn until the section is on screen, no movement for a reader who asked for less motion, and a stop for good once a step is pressed — the way to stop a list that would otherwise turn for as long as it is shown, which WCAG 2.2.2 asks for. The current step's title carries aria-current="step", so the step a reader is shown is the step a screen reader names
|
|
126
|
+
|
|
127
|
+
## Rules
|
|
128
|
+
|
|
129
|
+
- **On a phone a section's actions stack and each fills the width, including when there is only one** — On a phone a page's actions stack, and each one fills the width. Not most of it, and not the width its label happens to need — the whole column.
|
|
130
|
+
|
|
131
|
+
Two side by side is what this replaces. On the narrowest screen each gets half a column minus the gap, which is rarely enough for a real label: the words wrap inside the pills, the two buttons come out different heights, and the pair reads as a broken row rather than as a choice. Stacked, each has the whole width and neither has to shorten its words to fit.
|
|
132
|
+
|
|
133
|
+
A single action fills too, and that is the part worth saying, because it is the one that looks unnecessary. A lone button has the room to sit at its natural width and still should not: a full-width control is the phone's convention for the thing the screen is asking you to do, and a pill hugging its label reads as one option among others that are not there. It also makes the target predictable — the whole width, wherever the thumb lands — which a centred pill does not.
|
|
134
|
+
|
|
135
|
+
Filling is the row's job rather than the button's. A button has no width of its own and is not given one; the row it sits in becomes a column and stretches its children, so nothing about the control changes and the same button is full width here and its own size on a desktop.
|
|
136
|
+
|
|
137
|
+
This is the phone's breakpoint, size.breakpoint.md, and not the wider one that decides whether a heading is centred. Those are different questions and they break at different widths: a heading stops being centred when the measure is the screen, while a button stops being full width much sooner than that — stretched across a tablet it is a long way from its own label, and a label centred in a metre of pill is harder to hit than one in a pill the size of the words.
|
|
138
|
+
|
|
139
|
+
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
140
|
+
Guidance only — cannot be checked automatically.
|
|
141
|
+
- **Never nest one interactive element inside another** — Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link, CardButton and TextInput simultaneously.
|
|
142
|
+
Guidance only — cannot be checked automatically.
|
|
143
|
+
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
144
|
+
|
|
145
|
+
color.bg.brand carries a second limit that is not about forgetting. Its ink measures 3.39:1, which clears the 3:1 a heading needs and misses the 4.5:1 running copy needs. A coral band may carry a headline and a call to action; a paragraph on one is text the reader has to work through at a ratio the waiver on that role does not cover — the waiver says so itself. A section with copy in it takes color.bg.brand-strong, which is near-black and carries white at full contrast.
|
|
146
|
+
|
|
147
|
+
color.bg.strong is not a section ground. It is the inverted fill for an action that has to outrank what surrounds it, and the components that paint it — Button and ButtonIcon in their inverse form — already set both halves in one rule, which is the pattern a hand-painted section has to copy.
|
|
148
|
+
Guidance only — cannot be checked automatically.
|
|
149
|
+
- **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side** — A section's spacing is named by the relationship it expresses, not chosen by size. Every gap in a section has a role token, and reaching for a step off the generic scale because it happens to be the right number is how two sections written by two people stop lining up: the numbers agree today and drift the first time one of them is tuned.
|
|
150
|
+
|
|
151
|
+
The heading group is three steps, not one gap. An eyebrow sits nearer its title than the title sits to its description, and the actions sit further from the description than either — space.heading.eyebrow-title, space.heading.title-description, space.heading.description-actions, in that order. A single `gap` on the group cannot say this; it sets all three the same and the block reads as evenly spaced lines rather than as a mark, a name and a paragraph. The eyebrow has to identify itself for this to work, because a group that opens with a title must not give its description the eyebrow's tighter step.
|
|
152
|
+
|
|
153
|
+
The step between a title and its description follows the size of the title, which is why there are two of it. What a reader sees is not the gap but the gap plus the leading above it, and leading scales with the type: under a display title the leading is most of the space, under a card's title it is half as deep. One value for both makes a card look loose at the size that made a section look right. So space.heading.title-description is the display step and space.heading.title-description-compact is the step at a card's size, and the choice is made by how big the title is rather than by what kind of block it sits in.
|
|
154
|
+
|
|
155
|
+
Every one of those steps is smaller than the gap below the group, and that ordering is what holds the group together as one thing. space.heading.content is the step between a heading group and the content it introduces, and it is the widest measure inside a section: the one gap the eye reads as a change of subject rather than as a continuation.
|
|
156
|
+
|
|
157
|
+
That step is the same whether the content is under the heading or beside it. A split is the same relationship turned on its side — a heading group and the content it introduces — so the space between the two halves is space.heading.content, not a gutter. When the split collapses to one column on a phone the gap becomes vertical again, which is where it started, and nothing has to change for that to be right.
|
|
158
|
+
|
|
159
|
+
space.grid.gutter is between two things of the same kind. Two cards in a row are the same kind; the two halves of a split are not, which is why the gutter is the wrong measure there even when the number would have looked acceptable. The gutter runs on both axes, so a grid reads as an even field rather than as rows with a seam down them.
|
|
160
|
+
|
|
161
|
+
space.inset.card is the card's, not the page's. A row of cards padded differently is a row of different cards, and the fill is the only edge they have. A page composing a row does not get to choose it.
|
|
162
|
+
|
|
163
|
+
Column count is not a breakpoint decision. A row holds as many columns as fit before a column would be narrower than size.grid.column-min, and drops one when they would not. Written as a fixed count that collapses at a breakpoint, a four-up row keeps four columns at every width above the phone and sets its copy two or three words to a line through the whole of the tablet range — and on a narrow desktop, which no breakpoint sits on at all. The threshold is a property of the row rather than of a card: a card fills whatever cell it is given.
|
|
164
|
+
|
|
165
|
+
What this does not cover is the space above and below a section, which is space.section.default and space.section.compact, and the page's own side margin, which is space.inset.page. Those are the section's outside; everything here is its inside.
|
|
166
|
+
Guidance only — cannot be checked automatically.
|
|
167
|
+
- **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone** — Two arrangements, and the title's alignment is decided by which one it is introducing rather than chosen per section.
|
|
168
|
+
|
|
169
|
+
Content stacked under the title — a row of cards, an accordion, a set of steps — takes a centred title. The heading group and the block below it share one axis, so a centred title is symmetric with the thing it names, and the eye drops from the middle of the words to the middle of the set. A title starting at the left over a centred or full-width block reads as belonging to the first column rather than to all of them.
|
|
170
|
+
|
|
171
|
+
Content beside the title — a split, a picture in the other half, anything laid out in columns — takes a title that starts where its content starts. The two share a left edge, and that edge is what says they are one thing read across rather than two stacked. Centring the title there breaks the only alignment the reader has to hold the halves together, and it drifts further from its content the wider the page gets.
|
|
172
|
+
|
|
173
|
+
The heading group is what carries this, not the heading alone. An eyebrow, a title and a description are read as one block and align together; aligning the title without them leaves a centred heading over start-aligned copy, which reads as a mistake rather than as a choice.
|
|
174
|
+
|
|
175
|
+
Centred means all of it, not just the words. A badge, a row of actions, a picture — these are flex children, and a flex child is placed by align-items rather than by text-align, so a block that only sets the text leaves everything that is not text at the start. A hero is the case that shows it: its title and copy centred while its badge and its buttons did not.
|
|
176
|
+
|
|
177
|
+
A capped block centres itself as well as its words. A heading group takes size.heading-group.max, and a cap that is not centred leaves the measure at the start of the column with the words centred inside it — composed, and a long way left of the middle it appears to be in.
|
|
178
|
+
|
|
179
|
+
Both arrangements go to the start on a phone. A centred block reverts below the breakpoint, and the reason is the measure: on a phone the measure is the screen, so a centred title wraps to three or four ragged lines and the eye loses the left edge it was tracking — the same symmetry that reads as composure on a desktop is what makes it hard to scan on a phone. Centring there has to be asked for twice, and a section title is not one of the things that asks: it is centred because there is room for it, and on a phone there is not. Going back to the start means all of it too, and a capped block is the one that hides a leftover: its words go to the start while its measure stays in the middle of the column, which reads as a title still centred over a badge and buttons that are not — the box in the middle and the line inside it at the edge.
|
|
180
|
+
|
|
181
|
+
A hero is a section like any other: its badge, title, copy and actions are one stacked block, so it is centred on a desktop and starts on a phone with everything else.
|
|
182
|
+
|
|
183
|
+
What this is not about is a page whose body is a form or a document. A title over a sign-up form or a guide is not introducing a set of content — it is the first line of the thing itself, and it keeps the alignment the body has, which for running text is the start. The distinction is whether the block below is content the title names or content the title is part of.
|
|
184
|
+
Guidance only — cannot be checked automatically.
|
|
185
|
+
- **Anything a pointer has to hit is at least 24px in both directions** — A control sized by its contents is as big as its contents, and a glyph is chosen for how it reads rather than for how easily it is hit. An icon-only button with no padding is a 16px target — smaller than the pad of a finger, and smaller than the tremor of a hand using a mouse.
|
|
186
|
+
|
|
187
|
+
WCAG 2.2 asks for 24 by 24 CSS pixels at AA. The exceptions are narrower than they look: inline targets inside a sentence are exempt, and so is a small target with 24px of clear space around it — but a clear button sits against the field it empties, and a field is itself a target, so the spacing exemption does not apply to the case that keeps arising.
|
|
188
|
+
|
|
189
|
+
The target and the mark are separate decisions, and conflating them is what produces both faults. Growing the glyph to 24px makes it shout; leaving the button at 16px makes it hard to hit. So the glyph keeps the size that reads correctly beside its text, and the box around it declares a minimum of its own — which is what size.target.min is for.
|
|
190
|
+
|
|
191
|
+
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
192
|
+
Guidance only — cannot be checked automatically.
|
|
193
|
+
- **A component is written along the reading axis, not along the page's left and right** — Every measure, inset and placement in this package names an axis rather than a side: inline-size and block-size, padding-inline and padding-block, inset-inline-start and inset-block-end, margin-inline: auto, text-align: start. Written that way a component follows whichever direction the page is read in, and a band whose claim ranges to the leading edge with its subject on the trailing one is the same composition in Arabic as in English, mirrored, with nothing restated. Written as left and right it is the same pixels in both, which is a layout nobody designed for the second language.
|
|
194
|
+
|
|
195
|
+
The enum values follow the same rule and for the same reason. A prop that names where a picture sits takes start and end, never left and right — FeatureSplit, FeatureBullets and FeatureScroll all declare mediaPosition that way, and the flex directions they generate flip on their own because row already means the reading order. A value called left would have to be re-read as right by every author working in a mirrored page, which is a translation this system should be doing rather than asking for.
|
|
196
|
+
|
|
197
|
+
The guidance a contract carries is part of the component, so it follows too. Describing a claim as ranging left is describing one of the two languages, and it was written that way here for a while: three of the opening bands said so in their own intent. A reader in a mirrored page meets that sentence and has to decide whether the component is wrong or the sentence is, and neither answer is one documentation should force.
|
|
198
|
+
|
|
199
|
+
Two things genuinely have no logical form and are not covered by this. A CSS gradient takes a physical direction — there is no to inline-end — so a pattern that must mirror has to be stated twice under a direction query, and one that is periodic and centred, like PageHeader's rule grid, does not need to. A glyph that points the way onward is the other: an arrow is a picture of a direction, and mirroring it belongs to the icon set rather than to the component holding it.
|
|
200
|
+
Guidance only — cannot be checked automatically.
|
|
201
|
+
|
|
202
|
+
## Anti-examples
|
|
203
|
+
|
|
204
|
+
❌ Steps for: The items have no order a reader follows — they are things a product includes
|
|
205
|
+
The same split with a checked list, which says every line is included rather than that one comes before the next
|
|
206
|
+
→ use `FeatureBullets` instead.
|
|
207
|
+
|
|
208
|
+
❌ Steps for: Three or four things side by side, each with its own picture
|
|
209
|
+
A grid of cards is compared across; a numbered list is followed down, and one picture is all this section has
|
|
210
|
+
→ use `FeatureCards` instead.
|
|
211
|
+
|
|
212
|
+
❌ Steps for: Each stage needs a screen and a picture of its own
|
|
213
|
+
A pinned picture per stop, for a set where each stage is worth showing rather than naming
|
|
214
|
+
→ use `FeatureScroll` instead.
|
|
215
|
+
|
|
216
|
+
## Example
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { Steps, AspectRatio } from '@deriv-com/dds-marketing'
|
|
220
|
+
|
|
221
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} />
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## In use
|
|
225
|
+
|
|
226
|
+
### The ground it sits on
|
|
227
|
+
|
|
228
|
+
The three grounds a page can put a section on. A band painting one of the other two says it is its own section, and the ink and the numbers follow the ground.
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { AspectRatio, Steps } from '@deriv-com/dds-marketing'
|
|
232
|
+
|
|
233
|
+
// On the page itself
|
|
234
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} ground="page" />
|
|
235
|
+
|
|
236
|
+
// On the quiet ground
|
|
237
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} ground="subtle" />
|
|
238
|
+
|
|
239
|
+
// On the dark band
|
|
240
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} ground="strong" />
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Which side the picture takes
|
|
244
|
+
|
|
245
|
+
Alternate it against the splits around it so two in a row do not read as one column. Below the fold there is one column and the picture leads it either way.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { AspectRatio, Steps } from '@deriv-com/dds-marketing'
|
|
249
|
+
|
|
250
|
+
// Picture first — the default
|
|
251
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} mediaPosition="start" />
|
|
252
|
+
|
|
253
|
+
// Steps first — under a split with its picture first
|
|
254
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} mediaPosition="end" />
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### How long the sequence runs
|
|
258
|
+
|
|
259
|
+
Three or four steps is right and six the most. The numbers come from each step's place, so adding one renumbers the rest.
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
import { AspectRatio, Steps } from '@deriv-com/dds-marketing'
|
|
263
|
+
|
|
264
|
+
// Three steps
|
|
265
|
+
<Steps title="Get started in 3 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} />
|
|
266
|
+
|
|
267
|
+
// Four steps
|
|
268
|
+
<Steps title="Get started in 4 steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details. No deposit needed to look around."},{"title":"Fund it","description":"Deposit with the local payment method you already use, from cards and e-wallets to bank transfer."},{"title":"Practise on demo","description":"Try your strategy with virtual funds first, on the same platform and the same markets."},{"title":"Start trading","description":"Pick a market, set your stake and place your first trade on Deriv MT5, web or mobile."}]} media={<AspectRatio ratio="square" />} />
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Taking turns
|
|
272
|
+
|
|
273
|
+
With `autoplay` each step takes its turn: its rule fills, its picture shows, then the next. Hover or focus holds it; pressing a step chooses it and stops the turn.
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { Steps } from '@deriv-com/dds-marketing'
|
|
277
|
+
|
|
278
|
+
// autoplay, a picture on each step
|
|
279
|
+
<Steps title="Get started in three steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details.","image":{"src":"/sample-stop-brand.svg","alt":"","width":800,"height":600}},{"title":"Fund it","description":"Deposit with the local payment method you already use.","image":{"src":"/sample-stop-teal.svg","alt":"","width":800,"height":600}},{"title":"Start trading","description":"Pick a market and place your first trade.","image":{"src":"/sample-stop-amber.svg","alt":"","width":800,"height":600}}]} autoplay />
|
|
280
|
+
|
|
281
|
+
// autoplay on the dark band
|
|
282
|
+
<Steps title="Get started in three steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details.","image":{"src":"/sample-stop-brand.svg","alt":"","width":800,"height":600}},{"title":"Fund it","description":"Deposit with the local payment method you already use.","image":{"src":"/sample-stop-teal.svg","alt":"","width":800,"height":600}},{"title":"Start trading","description":"Pick a market and place your first trade.","image":{"src":"/sample-stop-amber.svg","alt":"","width":800,"height":600}}]} autoplay ground="strong" mediaPosition="end" />
|
|
283
|
+
|
|
284
|
+
// still, a picture on each step — the first is shown
|
|
285
|
+
<Steps title="Get started in three steps" steps={[{"title":"Open an account","description":"Sign up in minutes with your email and a few details.","image":{"src":"/sample-stop-brand.svg","alt":"","width":800,"height":600}},{"title":"Fund it","description":"Deposit with the local payment method you already use.","image":{"src":"/sample-stop-teal.svg","alt":"","width":800,"height":600}},{"title":"Start trading","description":"Pick a market and place your first trade.","image":{"src":"/sample-stop-amber.svg","alt":"","width":800,"height":600}}]} />
|
|
286
|
+
```
|