@deriv-com/dds-marketing 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.llm/components/accordion.md +9 -1
- package/.llm/components/accordionitem.md +9 -1
- package/.llm/components/aspectratio.md +9 -1
- package/.llm/components/badge.md +9 -1
- package/.llm/components/bottomsheet.md +9 -1
- package/.llm/components/breadcrumb.md +9 -1
- package/.llm/components/breadcrumbitem.md +9 -1
- package/.llm/components/button.md +55 -27
- package/.llm/components/buttonicon.md +16 -8
- package/.llm/components/card.md +16 -2
- package/.llm/components/cardbody.md +29 -3
- package/.llm/components/cardbutton.md +16 -2
- package/.llm/components/checkbox.md +9 -1
- package/.llm/components/ctabanner.md +186 -0
- package/.llm/components/ctabannerslider.md +204 -0
- package/.llm/components/divider.md +9 -1
- package/.llm/components/dropdownmenu.md +15 -7
- package/.llm/components/faqaccordion.md +217 -0
- package/.llm/components/featurebullets.md +254 -0
- package/.llm/components/featurecards.md +313 -0
- package/.llm/components/featurescroll.md +284 -0
- package/.llm/components/featuresplit.md +249 -0
- package/.llm/components/filterchip.md +9 -1
- package/.llm/components/footer.md +9 -1
- package/.llm/components/footergroup.md +9 -1
- package/.llm/components/grid.md +9 -1
- package/.llm/components/icon.md +21 -3
- package/.llm/components/landinghero.md +254 -0
- package/.llm/components/link.md +13 -5
- package/.llm/components/logocolumns.md +235 -0
- package/.llm/components/logorows.md +212 -0
- package/.llm/components/menuitem.md +9 -1
- package/.llm/components/navbar.md +80 -16
- package/.llm/components/navbaritem.md +10 -2
- package/.llm/components/navbarmenu.md +9 -1
- package/.llm/components/navbarmenugroup.md +9 -1
- package/.llm/components/navbarpanel.md +10 -2
- package/.llm/components/navbarswitcher.md +10 -2
- package/.llm/components/navbarswitcheroption.md +9 -1
- package/.llm/components/option.md +9 -1
- package/.llm/components/pageheader.md +231 -0
- package/.llm/components/pagination.md +27 -90
- package/.llm/components/paginationdots.md +215 -0
- package/.llm/components/producthero.md +248 -0
- package/.llm/components/removablechip.md +9 -1
- package/.llm/components/row.md +9 -1
- package/.llm/components/scroller.md +9 -1
- package/.llm/components/searchinput.md +9 -1
- package/.llm/components/segmentedcontrol.md +9 -1
- package/.llm/components/segmentedcontrolitem.md +9 -1
- package/.llm/components/select.md +9 -1
- package/.llm/components/selectchip.md +57 -16
- package/.llm/components/spinner.md +9 -1
- package/.llm/components/stack.md +9 -1
- package/.llm/components/statusdot.md +9 -1
- package/.llm/components/subdomainnavbar.md +9 -1
- package/.llm/components/tab.md +11 -3
- package/.llm/components/table.md +9 -1
- package/.llm/components/tablebody.md +9 -1
- package/.llm/components/tablecell.md +9 -1
- package/.llm/components/tablehead.md +9 -1
- package/.llm/components/tableheadercell.md +9 -1
- package/.llm/components/tablerow.md +9 -1
- package/.llm/components/tablist.md +9 -1
- package/.llm/components/testimonialrow.md +235 -0
- package/.llm/components/testimonialslider.md +254 -0
- package/.llm/components/textarea.md +9 -1
- package/.llm/components/textinput.md +9 -1
- package/.llm/components/tooltip.md +9 -1
- package/.llm/components/typography.md +9 -1
- package/.llm/digest/button.md +11 -6
- package/.llm/digest/buttonicon.md +2 -2
- package/.llm/digest/card.md +1 -0
- package/.llm/digest/cardbody.md +3 -1
- package/.llm/digest/cardbutton.md +1 -0
- package/.llm/digest/ctabanner.md +44 -0
- package/.llm/digest/ctabannerslider.md +45 -0
- package/.llm/digest/dropdownmenu.md +1 -1
- package/.llm/digest/faqaccordion.md +43 -0
- package/.llm/digest/featurebullets.md +52 -0
- package/.llm/digest/featurecards.md +49 -0
- package/.llm/digest/featurescroll.md +52 -0
- package/.llm/digest/featuresplit.md +54 -0
- package/.llm/digest/landinghero.md +53 -0
- package/.llm/digest/logocolumns.md +55 -0
- package/.llm/digest/logorows.md +48 -0
- package/.llm/digest/navbar.md +18 -3
- package/.llm/digest/pageheader.md +49 -0
- package/.llm/digest/pagination.md +6 -17
- package/.llm/digest/paginationdots.md +43 -0
- package/.llm/digest/producthero.md +53 -0
- package/.llm/digest/selectchip.md +6 -1
- package/.llm/digest/testimonialrow.md +51 -0
- package/.llm/digest/testimonialslider.md +51 -0
- package/.llm/index.md +24 -3
- package/.llm/rules.md +43 -9
- package/.llm/tokens.md +56 -12
- package/AGENTS.md +32 -8
- package/README.md +41 -21
- package/dist/components/banner-data.d.ts +38 -0
- package/dist/components/banner-data.js +15 -0
- package/dist/components/blocks/block-reveal.css +90 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
- package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
- package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
- package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
- package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
- package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
- package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
- package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
- package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
- package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
- package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
- package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
- package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
- package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
- package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
- package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
- package/dist/components/blocks/page-header/PageHeader.css +79 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
- package/dist/components/blocks/page-header/PageHeader.js +43 -0
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
- package/dist/components/blocks/page-header/page-header-impl.css +176 -0
- package/dist/components/blocks/product-hero/ProductHero.css +86 -0
- package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
- package/dist/components/blocks/product-hero/ProductHero.js +48 -0
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
- package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
- package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
- package/dist/components/blocks/use-reveal.d.ts +46 -0
- package/dist/components/blocks/use-reveal.js +120 -0
- package/dist/components/blocks/use-rotation.d.ts +62 -0
- package/dist/components/blocks/use-rotation.js +176 -0
- package/dist/components/core/accordion-item/AccordionItem.css +6 -5
- package/dist/components/core/bottom-sheet/BottomSheet.css +1 -1
- package/dist/components/core/button/Button.css +63 -16
- package/dist/components/core/button/Button.d.ts +14 -12
- package/dist/components/core/button/Button.js +43 -14
- package/dist/components/core/button/Button.types.d.ts +9 -14
- package/dist/components/core/button/button-impl.css +25 -0
- package/dist/components/core/button-icon/ButtonIcon.css +31 -15
- package/dist/components/core/button-icon/ButtonIcon.d.ts +2 -2
- package/dist/components/core/button-icon/ButtonIcon.js +2 -2
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +4 -4
- package/dist/components/core/card/Card.css +13 -4
- package/dist/components/core/card/Card.types.d.ts +2 -1
- package/dist/components/core/card-body/CardBody.css +11 -6
- package/dist/components/core/card-body/CardBody.d.ts +1 -1
- package/dist/components/core/card-body/CardBody.js +2 -2
- package/dist/components/core/card-body/CardBody.types.d.ts +4 -1
- package/dist/components/core/card-body/CardBody.types.js +1 -0
- package/dist/components/core/card-button/CardButton.css +13 -4
- package/dist/components/core/card-button/CardButton.types.d.ts +2 -1
- package/dist/components/core/checkbox/Checkbox.css +8 -1
- package/dist/components/core/dropdown-menu/DropdownMenu.css +13 -12
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +5 -3
- package/dist/components/core/dropdown-menu/DropdownMenu.js +5 -3
- package/dist/components/core/filter-chip/FilterChip.css +2 -1
- package/dist/components/core/footer/footer-impl.css +1 -1
- package/dist/components/core/footer-group/FooterGroup.css +8 -7
- package/dist/components/core/icon/Icon.css +1 -1
- package/dist/components/core/link/Link.css +1 -1
- package/dist/components/core/link/Link.js +5 -5
- package/dist/components/core/menu-item/MenuItem.css +1 -1
- package/dist/components/core/navbar/Navbar.css +7 -8
- package/dist/components/core/navbar/Navbar.d.ts +17 -1
- package/dist/components/core/navbar/Navbar.js +139 -12
- package/dist/components/core/navbar/Navbar.types.d.ts +23 -4
- package/dist/components/core/navbar/Navbar.types.js +1 -1
- package/dist/components/core/navbar/navbar-impl.css +10 -3
- package/dist/components/core/navbar/navbar-material.css +96 -0
- package/dist/components/core/navbar-item/NavbarItem.css +4 -4
- package/dist/components/core/navbar-menu/NavbarMenu.css +7 -5
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +1 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +1 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +7 -7
- package/dist/components/core/navbar-switcher/NavbarSwitcher.css +6 -5
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +1 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +2 -1
- package/dist/components/core/option/Option.css +1 -1
- package/dist/components/core/pagination/Pagination.css +1 -75
- package/dist/components/core/pagination/Pagination.d.ts +4 -4
- package/dist/components/core/pagination/Pagination.js +11 -51
- package/dist/components/core/pagination/Pagination.types.d.ts +5 -17
- package/dist/components/core/pagination/Pagination.types.js +1 -3
- package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
- package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -0
- package/dist/components/core/removable-chip/RemovableChip.css +3 -3
- package/dist/components/core/search-input/SearchInput.css +1 -1
- package/dist/components/core/segmented-control/SegmentedControl.css +1 -1
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +1 -1
- package/dist/components/core/select/Select.css +2 -1
- package/dist/components/core/select-chip/SelectChip.css +14 -7
- package/dist/components/core/select-chip/SelectChip.d.ts +1 -1
- package/dist/components/core/select-chip/SelectChip.js +7 -4
- package/dist/components/core/select-chip/SelectChip.types.d.ts +7 -1
- package/dist/components/core/select-chip/SelectChip.types.js +1 -1
- package/dist/components/core/select-chip/select-chip-impl.css +14 -3
- package/dist/components/core/status-dot/StatusDot.css +1 -1
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +3 -3
- package/dist/components/core/tab/Tab.css +1 -1
- package/dist/components/core/tab/Tab.types.d.ts +1 -1
- package/dist/components/core/tab-list/TabList.css +1 -1
- package/dist/components/core/table/table-impl.css +36 -14
- package/dist/components/core/table-header-cell/TableHeaderCell.css +5 -5
- package/dist/components/core/text-area/TextArea.css +1 -1
- package/dist/components/core/text-input/TextInput.css +1 -1
- package/dist/components/core/tooltip/Tooltip.css +1 -1
- package/dist/components/core/typography/Typography.css +5 -5
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +30 -0
- package/dist/components/logo-data.d.ts +24 -0
- package/dist/components/logo-data.js +11 -0
- package/dist/components/scroll-data.d.ts +64 -0
- package/dist/components/scroll-data.js +17 -0
- package/dist/components/testimonial-row-data.d.ts +51 -0
- package/dist/components/testimonial-row-data.js +11 -0
- package/dist/components/testimonial-slider-data.d.ts +26 -0
- package/dist/components/testimonial-slider-data.js +10 -0
- package/dist/marketing.css +385 -14
- package/package.json +1 -6
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* GENERATED from featurecards.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-featurecards {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
display: flex;
|
|
7
|
+
inline-size: 100%;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__inner {
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
inline-size: 100%;
|
|
16
|
+
min-inline-size: 0;
|
|
17
|
+
max-inline-size: var(--size-content-max);
|
|
18
|
+
padding-block: var(--space-section-default);
|
|
19
|
+
padding-inline: var(--space-inset-page);
|
|
20
|
+
row-gap: var(--space-heading-content);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__header {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
min-inline-size: 0;
|
|
27
|
+
max-inline-size: var(--size-measure-heading);
|
|
28
|
+
row-gap: var(--space-gap-none);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__title {
|
|
32
|
+
margin-block: 0;
|
|
33
|
+
text-wrap: balance;
|
|
34
|
+
font-family: var(--font-h2-family);
|
|
35
|
+
font-size: var(--font-h2-size);
|
|
36
|
+
font-weight: var(--font-h2-weight);
|
|
37
|
+
letter-spacing: var(--font-h2-letter-spacing);
|
|
38
|
+
line-height: var(--font-h2-line-height);
|
|
39
|
+
margin-block-end: var(--space-heading-title-description);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__description {
|
|
43
|
+
margin-block: 0;
|
|
44
|
+
font-family: var(--font-body-md-family);
|
|
45
|
+
font-size: var(--font-body-md-size);
|
|
46
|
+
font-weight: var(--font-body-md-weight);
|
|
47
|
+
letter-spacing: var(--font-body-md-letter-spacing);
|
|
48
|
+
line-height: var(--font-body-md-line-height);
|
|
49
|
+
max-inline-size: var(--size-measure-description);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__link {
|
|
53
|
+
display: flex;
|
|
54
|
+
margin-block-start: var(--space-heading-description-actions);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid {
|
|
58
|
+
display: grid;
|
|
59
|
+
min-inline-size: 0;
|
|
60
|
+
column-gap: var(--space-grid-gutter);
|
|
61
|
+
row-gap: var(--space-grid-gutter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__item {
|
|
65
|
+
display: grid;
|
|
66
|
+
min-inline-size: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:where([data-dds-context="marketing"]) .dds-featurecards[data-ground="page"] {
|
|
70
|
+
background-color: var(--color-bg-page);
|
|
71
|
+
color: var(--color-fg-default);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:where([data-dds-context="marketing"]) .dds-featurecards[data-ground="strong"] {
|
|
75
|
+
background-color: var(--color-bg-brand-strong);
|
|
76
|
+
color: var(--color-fg-on-brand-strong);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:where([data-dds-context="marketing"]) .dds-featurecards[data-ground="subtle"] {
|
|
80
|
+
background-color: var(--color-bg-page);
|
|
81
|
+
background-image: linear-gradient(var(--color-bg-band-subtle), var(--color-bg-band-subtle));
|
|
82
|
+
color: var(--color-fg-default);
|
|
83
|
+
}
|
|
84
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import './FeatureCards.css';
|
|
2
|
+
import './feature-cards-impl.css';
|
|
3
|
+
import '../block-reveal.css';
|
|
4
|
+
import { type FeatureCardsProps } from './FeatureCards.types.js';
|
|
5
|
+
export type { FeatureCardsProps };
|
|
6
|
+
/**
|
|
7
|
+
* A heading over a grid of cards — the reference site's FeatureCards in its grid form.
|
|
8
|
+
*
|
|
9
|
+
* The cards are the page's own Card or CardButton, each holding a CardBody, rather than records
|
|
10
|
+
* this draws. A card already says everything a card can say — its fill, its picture, its mark,
|
|
11
|
+
* whether the whole of it is pressed — and a list of records here would be a second, smaller Card
|
|
12
|
+
* API to keep in step with the first. What this decides is the rest: the heading, the column, and
|
|
13
|
+
* how many cards share a row.
|
|
14
|
+
*
|
|
15
|
+
* The row is read from the cards. One column on a phone and two from the fold; at full width three,
|
|
16
|
+
* four when there are exactly four, and one or two held to two thirds of the row, centred. A card
|
|
17
|
+
* alone lays its words beside a portrait picture. The stylesheet asks all of it of the markup — the
|
|
18
|
+
* count is already there, and a prop restating it is a second place for the two to disagree.
|
|
19
|
+
*
|
|
20
|
+
* It arrives the way every block does: the heading, the line and the way on, then each card's cell
|
|
21
|
+
* a step behind the one before, in reading order. `'use client'` for that and for `useId`, which
|
|
22
|
+
* names the region by its heading.
|
|
23
|
+
*/
|
|
24
|
+
export declare function FeatureCards({ ground, title, description, link, children, }: FeatureCardsProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Children, Fragment, isValidElement, useId } from 'react';
|
|
4
|
+
import './FeatureCards.css';
|
|
5
|
+
import './feature-cards-impl.css';
|
|
6
|
+
import '../block-reveal.css';
|
|
7
|
+
import { given } from '../../given.js';
|
|
8
|
+
import { arriving, useReveal } from '../use-reveal.js';
|
|
9
|
+
import { featureCardsDefaults, featureCardsParts } from './FeatureCards.types.js';
|
|
10
|
+
/**
|
|
11
|
+
* The cards, with any fragment opened out.
|
|
12
|
+
*
|
|
13
|
+
* `Children.toArray` flattens arrays and leaves a fragment whole, so a page writing
|
|
14
|
+
* `<>{cards}</>` handed over one child: every card in a single cell, and the grid reading the set
|
|
15
|
+
* as one card alone. A fragment is the page grouping its own markup, never a card, so it is opened
|
|
16
|
+
* out here and the grid counts what is inside it.
|
|
17
|
+
*/
|
|
18
|
+
function cardsOf(children, within = '') {
|
|
19
|
+
return Children.toArray(children).flatMap((child, at) => {
|
|
20
|
+
// `toArray` keys a fragment's children afresh — `.0`, `.1` — so a card is keyed by the
|
|
21
|
+
// fragment it came out of as well as its own place, or two cards from different groups share a
|
|
22
|
+
// key and React reconciles one into the other's cell.
|
|
23
|
+
const key = `${within}${isValidElement(child) && child.key !== null ? child.key : at}`;
|
|
24
|
+
return isValidElement(child) && child.type === Fragment
|
|
25
|
+
? cardsOf(child.props.children, `${key}/`)
|
|
26
|
+
: [{ key, card: child }];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Where a card comes in the arrival, capped so a long set does not keep a reader waiting.
|
|
31
|
+
*
|
|
32
|
+
* The heading, the line and the way on take the first three steps. The cards follow one step
|
|
33
|
+
* apart up to the fourth, and the rest arrive with it: block-reveal.css keeps a block's trail
|
|
34
|
+
* inside its own movement, and eight cards a step apart would trail the heading by most of a
|
|
35
|
+
* second.
|
|
36
|
+
*/
|
|
37
|
+
const FIRST_CARD = 3;
|
|
38
|
+
const LAST_STEP = FIRST_CARD + 3;
|
|
39
|
+
/**
|
|
40
|
+
* A heading over a grid of cards — the reference site's FeatureCards in its grid form.
|
|
41
|
+
*
|
|
42
|
+
* The cards are the page's own Card or CardButton, each holding a CardBody, rather than records
|
|
43
|
+
* this draws. A card already says everything a card can say — its fill, its picture, its mark,
|
|
44
|
+
* whether the whole of it is pressed — and a list of records here would be a second, smaller Card
|
|
45
|
+
* API to keep in step with the first. What this decides is the rest: the heading, the column, and
|
|
46
|
+
* how many cards share a row.
|
|
47
|
+
*
|
|
48
|
+
* The row is read from the cards. One column on a phone and two from the fold; at full width three,
|
|
49
|
+
* four when there are exactly four, and one or two held to two thirds of the row, centred. A card
|
|
50
|
+
* alone lays its words beside a portrait picture. The stylesheet asks all of it of the markup — the
|
|
51
|
+
* count is already there, and a prop restating it is a second place for the two to disagree.
|
|
52
|
+
*
|
|
53
|
+
* It arrives the way every block does: the heading, the line and the way on, then each card's cell
|
|
54
|
+
* a step behind the one before, in reading order. `'use client'` for that and for `useId`, which
|
|
55
|
+
* names the region by its heading.
|
|
56
|
+
*/
|
|
57
|
+
export function FeatureCards({ ground = featureCardsDefaults.ground, title, description, link, children, }) {
|
|
58
|
+
const titleId = useId();
|
|
59
|
+
const [band, revealed] = useReveal();
|
|
60
|
+
return (_jsx("section", { className: featureCardsParts.root, "data-ground": ground, "aria-labelledby": titleId, children: _jsxs("div", { className: featureCardsParts.inner, ref: band, "data-revealed": revealed, children: [_jsxs("div", { className: featureCardsParts.header, children: [_jsx("h2", { className: featureCardsParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: featureCardsParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureCardsParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { className: featureCardsParts.grid, children: cardsOf(children).map(({ key, card }, at) => (
|
|
61
|
+
/* Each card in a cell of its own, and the cell is what arrives: the card is the page's
|
|
62
|
+
element and keeps its own transitions, which an arrival set on it would overwrite.
|
|
63
|
+
Keyed by the card's own key, made unique across fragments by cardsOf, so a set the
|
|
64
|
+
page reorders moves its cards rather than remounting them. */
|
|
65
|
+
_jsx("div", { className: featureCardsParts.item, ...arriving(Math.min(FIRST_CARD + at, LAST_STEP)), children: card }, key))) })] }) }));
|
|
66
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface FeatureCardsOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `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 — and the ground a reader is already on
|
|
5
|
+
* `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 one to reach for first when two sections need telling apart. A light card — surface-light — turns white on it, color.bg.surface-card-light-raised, because its own gray.50 is the band's and would vanish into it. A dark card — accent-strong — is lifted to color.bg.surface-card-strong-raised, a step lighter in dark mode, where the band is within a shade of its gray.900. A plain surface card is raised off it the same way, to color.bg.surface-card-raised, because the recessed fill is the band's gray too. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section — in dark mode the tint alone took on whatever it was set against, and on a light surface it was light ink on white.
|
|
6
|
+
* `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. The coloured cards keep their own grounds on it; a neutral card — surface or surface-raised — turns to Card's inverse fill and white ink, and a plain card takes the white ink alone, because their own would be dark ink on near-black; an eyebrow inside any of them takes the band's quieter ink
|
|
7
|
+
*/
|
|
8
|
+
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
+
/** Always. What the cards are, in the fewest words that name them — "Why trade with Deriv", "Markets you can trade". */
|
|
10
|
+
title: string;
|
|
11
|
+
/** A line saying what the set has in common, when the title alone does not. */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** A way on to the page the whole set belongs to — "See all markets". A standalone Link, under the line. */
|
|
14
|
+
link?: ReactNode;
|
|
15
|
+
/** Allowed: Card, CardButton */
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export type FeatureCardsProps = FeatureCardsOwnProps;
|
|
19
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
20
|
+
export declare const featureCardsParts: {
|
|
21
|
+
readonly root: "dds-featurecards";
|
|
22
|
+
readonly inner: "dds-featurecards__inner";
|
|
23
|
+
readonly header: "dds-featurecards__header";
|
|
24
|
+
readonly title: "dds-featurecards__title";
|
|
25
|
+
readonly description: "dds-featurecards__description";
|
|
26
|
+
readonly link: "dds-featurecards__link";
|
|
27
|
+
readonly grid: "dds-featurecards__grid";
|
|
28
|
+
readonly item: "dds-featurecards__item";
|
|
29
|
+
};
|
|
30
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
31
|
+
export declare const featureCardsDefaults: {
|
|
32
|
+
readonly ground: "page";
|
|
33
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// GENERATED from feature-cards.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const featureCardsParts = {
|
|
4
|
+
root: 'dds-featurecards',
|
|
5
|
+
inner: 'dds-featurecards__inner',
|
|
6
|
+
header: 'dds-featurecards__header',
|
|
7
|
+
title: 'dds-featurecards__title',
|
|
8
|
+
description: 'dds-featurecards__description',
|
|
9
|
+
link: 'dds-featurecards__link',
|
|
10
|
+
grid: 'dds-featurecards__grid',
|
|
11
|
+
item: 'dds-featurecards__item',
|
|
12
|
+
};
|
|
13
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
14
|
+
export const featureCardsDefaults = { ground: 'page' };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* The header starts on a phone and is centred once the band is wide enough to hold a line.
|
|
7
|
+
*
|
|
8
|
+
* PageHeader's rule and its reason: centred text starts every line at a different edge, which
|
|
9
|
+
* costs little across a wide measure and a great deal across a narrow one. The header and the
|
|
10
|
+
* line under it are capped narrower than the column, so `margin-inline: auto` is what centres
|
|
11
|
+
* those boxes rather than their words inside a box left at the start edge.
|
|
12
|
+
*
|
|
13
|
+
* `48rem` longhand because `var()` is not permitted in a container query condition, and it is
|
|
14
|
+
* the width the rest of this package folds at.
|
|
15
|
+
*/
|
|
16
|
+
@container (min-width: 48rem) {
|
|
17
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__header {
|
|
18
|
+
align-items: center;
|
|
19
|
+
margin-inline: auto;
|
|
20
|
+
text-align: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__description {
|
|
24
|
+
margin-inline: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__link {
|
|
28
|
+
justify-content: center;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* One column on a phone. `minmax(0, 1fr)` rather than `1fr`, so a card holding a long unbroken
|
|
34
|
+
* word or a wide picture shrinks to the column instead of pushing the grid past the page.
|
|
35
|
+
*/
|
|
36
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid {
|
|
37
|
+
grid-template-columns: minmax(0, 1fr);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* How many cards share a row, read from the cards.
|
|
42
|
+
*
|
|
43
|
+
* Two from the fold, three at full width, four when there are exactly four — the reference
|
|
44
|
+
* design's rule, so a set of four is one row rather than a row of three and an orphan — and a pair
|
|
45
|
+
* as two columns. `:has()` asks the markup how many there are; the count is already there, and a
|
|
46
|
+
* prop restating it would be a second place for the two to disagree. 62rem is the reference's
|
|
47
|
+
* desktop step.
|
|
48
|
+
*
|
|
49
|
+
* Where `:has()` is not supported every count takes the three columns and a single card stays
|
|
50
|
+
* stacked: the set still reads, only less exactly.
|
|
51
|
+
*/
|
|
52
|
+
@container (min-width: 48rem) {
|
|
53
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid {
|
|
54
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* One card takes the row. Above the three- and four-column rules below by specificity, not by
|
|
58
|
+
order — `:has()` counts the selector inside it — so it holds at every width from here up. */
|
|
59
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid:has(> :only-child) {
|
|
60
|
+
grid-template-columns: minmax(0, 1fr);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* And a card alone lays its words and its picture side by side.
|
|
65
|
+
*
|
|
66
|
+
* A card the width of the section with its picture under the words is a strip of copy over a
|
|
67
|
+
* letterbox. The reference design's single panel is a split instead — words at the start, the
|
|
68
|
+
* picture at the end — and the block is what knows the card is alone, so the row is said here
|
|
69
|
+
* rather than asked of CardBody. Its parts keep their own order: a body whose picture leads
|
|
70
|
+
* (mediaPosition="above") leads with it here too. Only a body with its picture in the column;
|
|
71
|
+
* one whose copy sits over its picture is already the whole card and has nothing to split.
|
|
72
|
+
*
|
|
73
|
+
* The two halves share the width, and the words start at the top of theirs, level with the top
|
|
74
|
+
* of the picture, the way a card's words start at the top when they are stacked.
|
|
75
|
+
*/
|
|
76
|
+
:where([data-dds-context="marketing"])
|
|
77
|
+
.dds-featurecards
|
|
78
|
+
.dds-featurecards__grid:has(> :only-child)
|
|
79
|
+
.dds-cardbody[data-over-media="false"] {
|
|
80
|
+
flex-direction: row;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
:where([data-dds-context="marketing"])
|
|
84
|
+
.dds-featurecards
|
|
85
|
+
.dds-featurecards__grid:has(> :only-child)
|
|
86
|
+
.dds-cardbody[data-over-media="false"]
|
|
87
|
+
> :is(.dds-cardbody__content, .dds-cardbody__media-frame) {
|
|
88
|
+
flex: 1 1 0;
|
|
89
|
+
min-inline-size: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/*
|
|
93
|
+
* The picture beside a single card's words is portrait, aspect.portrait.
|
|
94
|
+
*
|
|
95
|
+
* Half a wide card is a tall column, and a landscape picture in it is a letterbox with the words
|
|
96
|
+
* running past its lower edge. Portrait fills the half the way the reference's single panel does.
|
|
97
|
+
* `align-self: flex-start` so the ratio decides the frame's height rather than the row stretching
|
|
98
|
+
* it to the words; the picture inside covers, so whatever shape the source is, the frame is
|
|
99
|
+
* portrait — unless the page set CardBody's `aspect`, whose inline ratio is the page's to choose.
|
|
100
|
+
*/
|
|
101
|
+
:where([data-dds-context="marketing"])
|
|
102
|
+
.dds-featurecards
|
|
103
|
+
.dds-featurecards__grid:has(> :only-child)
|
|
104
|
+
.dds-cardbody[data-over-media="false"]
|
|
105
|
+
> .dds-cardbody__media-frame {
|
|
106
|
+
align-self: flex-start;
|
|
107
|
+
aspect-ratio: var(--aspect-portrait);
|
|
108
|
+
/* Half the card when CardBody's own `aspect` is set: that writes `flex: none` and the page's
|
|
109
|
+
ratio inline, which win over the rule above, and a frame with no flex and no width sizes to
|
|
110
|
+
the picture's own pixels — eight hundred of them, past the card's edge. The width is what
|
|
111
|
+
holds it to its half; where the flex rule does apply, its zero basis overrides this. */
|
|
112
|
+
inline-size: 50%;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@container (min-width: 62rem) {
|
|
117
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid {
|
|
118
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid:has(> :nth-child(4):last-child) {
|
|
122
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* A pair as two columns of their own, rather than two of three with an empty third beside them —
|
|
126
|
+
the rule below then holds the pair to the width two columns take in a row of three. */
|
|
127
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid:has(> :nth-child(2):last-child) {
|
|
128
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* One or two cards hold to two thirds of the row, centred, rather than the whole of it.
|
|
133
|
+
*
|
|
134
|
+
* Two cards across the full width are each half as wide again as a card in a row of three, and
|
|
135
|
+
* one alone is a banner. Two thirds is exactly two of the three columns and the gutter between
|
|
136
|
+
* them, so a pair is the width a pair is in any other set, and a single card the width of that
|
|
137
|
+
* pair. Computed from the row's own width and gutter rather than a fixed measure, so it follows
|
|
138
|
+
* the grid wherever the grid is.
|
|
139
|
+
*/
|
|
140
|
+
:where([data-dds-context="marketing"]) .dds-featurecards .dds-featurecards__grid:is(:has(> :only-child), :has(> :nth-child(2):last-child)) {
|
|
141
|
+
margin-inline: auto;
|
|
142
|
+
max-inline-size: calc((100% - 2 * var(--space-grid-gutter)) * 2 / 3 + var(--space-grid-gutter));
|
|
143
|
+
inline-size: 100%;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/*
|
|
148
|
+
* A light card turns white on the subtle band.
|
|
149
|
+
*
|
|
150
|
+
* surface-light is gray.50 in both themes so it stays light beside a dark card, and the subtle
|
|
151
|
+
* band is gray.50 too — so on that band the light card had no edge at all. The block knows its
|
|
152
|
+
* ground and the card does not, so the answer is here rather than in Card: the card keeps its
|
|
153
|
+
* variant, its ink and its hover (a lift, which this leaves alone), and only its fill moves to
|
|
154
|
+
* color.bg.surface-card-light-raised. White in light mode; in dark mode the band is a white tint
|
|
155
|
+
* over near-black rather than gray.50, so the role is the card's own gray.50 there and nothing
|
|
156
|
+
* changes — a white card on the dark band was brighter than every card beside it.
|
|
157
|
+
*/
|
|
158
|
+
:where([data-dds-context="marketing"])
|
|
159
|
+
.dds-featurecards[data-ground="subtle"]
|
|
160
|
+
.dds-featurecards__item
|
|
161
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="surface-light"] {
|
|
162
|
+
background-color: var(--color-bg-surface-card-light-raised);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* A neutral card turns round on the dark band.
|
|
167
|
+
*
|
|
168
|
+
* surface and surface-raised carry the page's dark ink and a fill made for a light page, which on
|
|
169
|
+
* color.bg.brand-strong is dark words on near-black. Card answers that with tone="inverse", and
|
|
170
|
+
* CardButton has no tone to answer with — so the block, which knows its ground, gives both the
|
|
171
|
+
* values Card's own inverse uses: the inverse surface, the raised veil, and white ink. The coloured
|
|
172
|
+
* cards — surface-light, accent, accent-strong — already paint their own ground and ink and are
|
|
173
|
+
* left as they are.
|
|
174
|
+
*/
|
|
175
|
+
:where([data-dds-context="marketing"])
|
|
176
|
+
.dds-featurecards[data-ground="strong"]
|
|
177
|
+
.dds-featurecards__item
|
|
178
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="surface"] {
|
|
179
|
+
background-color: var(--color-bg-surface-inverse);
|
|
180
|
+
color: var(--color-fg-on-brand-strong);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
:where([data-dds-context="marketing"])
|
|
184
|
+
.dds-featurecards[data-ground="strong"]
|
|
185
|
+
.dds-featurecards__item
|
|
186
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="surface-raised"] {
|
|
187
|
+
background-color: var(--color-bg-surface-raised-on-brand-strong);
|
|
188
|
+
color: var(--color-fg-on-brand-strong);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/*
|
|
192
|
+
* A plain card has no ground of its own, so on the dark band it is the band's words: white ink,
|
|
193
|
+
* the value Card's own plain-and-inverse takes. Without it a plain CardButton drew the page's
|
|
194
|
+
* near-black ink on the near-black band.
|
|
195
|
+
*/
|
|
196
|
+
:where([data-dds-context="marketing"])
|
|
197
|
+
.dds-featurecards[data-ground="strong"]
|
|
198
|
+
.dds-featurecards__item
|
|
199
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="plain"] {
|
|
200
|
+
color: var(--color-fg-on-brand-strong);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
* And the eyebrow inside a card turned round. CardBody quietens its eyebrow by its own tone, which
|
|
205
|
+
* a card recoloured here does not change, so the eyebrow kept the page's muted grey on a dark card.
|
|
206
|
+
* It takes the band's own quieter ink, the value CardBody's inverse tone uses.
|
|
207
|
+
*/
|
|
208
|
+
:where([data-dds-context="marketing"])
|
|
209
|
+
.dds-featurecards[data-ground="strong"]
|
|
210
|
+
.dds-featurecards__item
|
|
211
|
+
> :is(.dds-card, .dds-cardbutton):is([data-variant="surface"], [data-variant="surface-raised"], [data-variant="plain"])
|
|
212
|
+
.dds-cardbody__eyebrow {
|
|
213
|
+
color: var(--color-fg-muted-inverse);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/*
|
|
217
|
+
* And a dark card is lifted a step in dark mode.
|
|
218
|
+
*
|
|
219
|
+
* accent-strong is gray.900, and in dark mode the subtle band is a white tint over near-black that
|
|
220
|
+
* lands within a shade of it — the card blended into the band the way the light card did in light
|
|
221
|
+
* mode. color.bg.surface-card-strong-raised is the same gray.900 in light, where the dark card
|
|
222
|
+
* already stands off the band, and gray.800 in dark, a step up so it lifts off it. The ink is
|
|
223
|
+
* unchanged: white on either.
|
|
224
|
+
*/
|
|
225
|
+
:where([data-dds-context="marketing"])
|
|
226
|
+
.dds-featurecards[data-ground="subtle"]
|
|
227
|
+
.dds-featurecards__item
|
|
228
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="accent-strong"] {
|
|
229
|
+
background-color: var(--color-bg-surface-card-strong-raised);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* And a plain card is raised off it.
|
|
234
|
+
*
|
|
235
|
+
* surface is the recessed fill for a card on the page, color.bg.surface — the same gray the subtle
|
|
236
|
+
* band is, so on the band it vanished exactly as the light card did. It takes the raised fill,
|
|
237
|
+
* color.bg.surface-card-raised, which is what Card's surface-raised variant paints: white on the
|
|
238
|
+
* light band and the raised veil on the dark one, following the theme as surface does.
|
|
239
|
+
*/
|
|
240
|
+
:where([data-dds-context="marketing"])
|
|
241
|
+
.dds-featurecards[data-ground="subtle"]
|
|
242
|
+
.dds-featurecards__item
|
|
243
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="surface"] {
|
|
244
|
+
background-color: var(--color-bg-surface-card-raised);
|
|
245
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* GENERATED from featurescroll.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
display: flex;
|
|
7
|
+
inline-size: 100%;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__inner {
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
inline-size: 100%;
|
|
16
|
+
min-inline-size: 0;
|
|
17
|
+
max-inline-size: var(--size-content-max);
|
|
18
|
+
padding-block: var(--space-section-default);
|
|
19
|
+
padding-inline: var(--space-inset-page);
|
|
20
|
+
row-gap: var(--space-heading-content);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__heading {
|
|
24
|
+
margin-block: 0;
|
|
25
|
+
text-wrap: balance;
|
|
26
|
+
font-family: var(--font-h2-family);
|
|
27
|
+
font-size: var(--font-h2-size);
|
|
28
|
+
font-weight: var(--font-h2-weight);
|
|
29
|
+
letter-spacing: var(--font-h2-letter-spacing);
|
|
30
|
+
line-height: var(--font-h2-line-height);
|
|
31
|
+
max-inline-size: var(--size-measure-heading);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__steps {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
min-inline-size: 0;
|
|
38
|
+
column-gap: var(--space-gap-3xl);
|
|
39
|
+
row-gap: var(--space-gap-2xl);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__step {
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
display: flex;
|
|
45
|
+
min-inline-size: 0;
|
|
46
|
+
row-gap: var(--space-gap-md);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__content {
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
min-inline-size: 0;
|
|
54
|
+
row-gap: var(--space-gap-none);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__title {
|
|
58
|
+
margin-block: 0;
|
|
59
|
+
text-wrap: balance;
|
|
60
|
+
font-family: var(--font-h3-family);
|
|
61
|
+
font-size: var(--font-h3-size);
|
|
62
|
+
font-weight: var(--font-h3-weight);
|
|
63
|
+
letter-spacing: var(--font-h3-letter-spacing);
|
|
64
|
+
line-height: var(--font-h3-line-height);
|
|
65
|
+
margin-block-end: var(--space-heading-title-description);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__description {
|
|
69
|
+
margin-block: 0;
|
|
70
|
+
font-family: var(--font-body-md-family);
|
|
71
|
+
font-size: var(--font-body-md-size);
|
|
72
|
+
font-weight: var(--font-body-md-weight);
|
|
73
|
+
letter-spacing: var(--font-body-md-letter-spacing);
|
|
74
|
+
line-height: var(--font-body-md-line-height);
|
|
75
|
+
margin-block-end: var(--space-heading-description-actions);
|
|
76
|
+
max-inline-size: var(--size-measure-description);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__link {
|
|
80
|
+
display: flex;
|
|
81
|
+
margin-block-start: var(--space-gap-none);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__media {
|
|
85
|
+
align-items: center;
|
|
86
|
+
display: flex;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
min-inline-size: 0;
|
|
89
|
+
padding-block: var(--space-gap-lg);
|
|
90
|
+
transition-duration: var(--motion-duration-media-hover);
|
|
91
|
+
transition-timing-function: var(--motion-easing-media-hover);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__picture {
|
|
95
|
+
display: block;
|
|
96
|
+
object-fit: cover;
|
|
97
|
+
aspect-ratio: var(--aspect-square);
|
|
98
|
+
border-radius: var(--radius-container);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-media-position="end"] .dds-featurescroll__content {
|
|
102
|
+
grid-column: words;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-media-position="start"] .dds-featurescroll__content {
|
|
106
|
+
grid-column: picture;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-media-position="end"] .dds-featurescroll__media {
|
|
110
|
+
grid-column: picture;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-media-position="start"] .dds-featurescroll__media {
|
|
114
|
+
grid-column: words;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-ground="page"] {
|
|
118
|
+
background-color: var(--color-bg-page);
|
|
119
|
+
color: var(--color-fg-default);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-ground="strong"] {
|
|
123
|
+
background-color: var(--color-bg-brand-strong);
|
|
124
|
+
color: var(--color-fg-on-brand-strong);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-ground="subtle"] {
|
|
128
|
+
background-color: var(--color-bg-page);
|
|
129
|
+
background-image: linear-gradient(var(--color-bg-band-subtle), var(--color-bg-band-subtle));
|
|
130
|
+
color: var(--color-fg-default);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@media (prefers-reduced-motion: reduce) {
|
|
134
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll,
|
|
135
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll * { transition: none !important; }
|
|
136
|
+
}
|
|
137
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import './FeatureScroll.css';
|
|
2
|
+
import './feature-scroll-impl.css';
|
|
3
|
+
import '../block-reveal.css';
|
|
4
|
+
import { type FeatureScrollProps } from './FeatureScroll.types.js';
|
|
5
|
+
export type { FeatureScrollProps };
|
|
6
|
+
/**
|
|
7
|
+
* A section that gives a set of things one screen each, with the picture pinned beside the words.
|
|
8
|
+
*
|
|
9
|
+
* Two mechanisms, and which does what is the thing to understand here. Holding a picture in place
|
|
10
|
+
* while words move past it is `position: sticky`, and nothing in this file measures it. Knowing
|
|
11
|
+
* *which* picture belongs to the words a reader has reached is a question about where each title
|
|
12
|
+
* has got to, and no stylesheet can ask it — so that much is below, and only that much.
|
|
13
|
+
*
|
|
14
|
+
* The rule the reference design settles on: a stop's picture is the one showing once the *next*
|
|
15
|
+
* stop's title has risen to the line the pictures are pinned at. Read as "the last title at or
|
|
16
|
+
* above the line" plus one, clamped to the end. It means the square changes at the moment a reader
|
|
17
|
+
* reaches a new heading rather than at some fraction of the way through, which is the only moment
|
|
18
|
+
* they would notice either way.
|
|
19
|
+
*
|
|
20
|
+
* Throttled to one read per frame through `requestAnimationFrame`, on a passive listener, and the
|
|
21
|
+
* read itself is `getBoundingClientRect` on the titles — no layout is written back, so the loop
|
|
22
|
+
* cannot thrash. `useLayoutEffect` rather than `useEffect` so the first measurement lands before
|
|
23
|
+
* the browser paints; the effect otherwise ran after the first frame and the section opened on
|
|
24
|
+
* step one for that frame however far down the page a reader had already scrolled.
|
|
25
|
+
*
|
|
26
|
+
* It measures the section's own width rather than the window's, because the fold is a container
|
|
27
|
+
* query on the section and the two disagree wherever a frame stands in for a window. The fold is
|
|
28
|
+
* the stylesheet's own `48rem`, turned into pixels against the root font size each time it is
|
|
29
|
+
* asked: a fixed 768 agreed with it only while the root stayed at sixteen, and a page that set it
|
|
30
|
+
* smaller pinned the picture on the first stop for the width in between.
|
|
31
|
+
*
|
|
32
|
+
* The parts of a stop are in the order a phone reads them, which is the order they are written:
|
|
33
|
+
* name, picture, line, way onward. At full width each stop gives up its box — `display: contents`
|
|
34
|
+
* — and the grid places the words in one column and every picture in the other, stacked, so the
|
|
35
|
+
* change is a change in one square rather than one picture leaving and another arriving. The
|
|
36
|
+
* reference design ships two DOM trees to get that; one tree means a reader's assistive technology
|
|
37
|
+
* and anybody reading the markup meet each stop once.
|
|
38
|
+
*/
|
|
39
|
+
export declare function FeatureScroll({ ground, title, steps, mediaPosition, }: FeatureScrollProps): import("react").JSX.Element;
|