@deriv-com/dds-marketing 1.1.1 → 1.1.3
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 +4 -0
- package/.llm/components/accordionitem.md +4 -0
- package/.llm/components/aspectratio.md +4 -0
- package/.llm/components/awards.md +4 -0
- package/.llm/components/background.md +4 -0
- package/.llm/components/badge.md +7 -3
- package/.llm/components/bottomsheet.md +7 -3
- package/.llm/components/breadcrumb.md +4 -0
- package/.llm/components/breadcrumbitem.md +4 -0
- package/.llm/components/button.md +4 -0
- package/.llm/components/buttonicon.md +10 -6
- package/.llm/components/card.md +5 -1
- package/.llm/components/cardbody.md +5 -1
- package/.llm/components/cardbutton.md +4 -0
- package/.llm/components/checkbox.md +1 -1
- package/.llm/components/comparisoncards.md +4 -0
- package/.llm/components/comparisontable.md +4 -0
- package/.llm/components/ctabanner.md +4 -0
- package/.llm/components/ctabannerslider.md +4 -0
- package/.llm/components/datatable.md +4 -0
- package/.llm/components/divider.md +4 -0
- package/.llm/components/downloadbanner.md +4 -0
- package/.llm/components/dropdownmenu.md +9 -5
- package/.llm/components/estimator.md +336 -0
- package/.llm/components/faqaccordion.md +4 -0
- package/.llm/components/featurebullets.md +4 -0
- package/.llm/components/featurecards.md +5 -1
- package/.llm/components/featurecardscarousel.md +4 -0
- package/.llm/components/featurescroll.md +5 -1
- package/.llm/components/featuresplit.md +4 -0
- package/.llm/components/featurestack.md +4 -0
- package/.llm/components/filterchip.md +5 -1
- package/.llm/components/footer.md +4 -0
- package/.llm/components/footergroup.md +4 -0
- package/.llm/components/grid.md +4 -0
- package/.llm/components/icon.md +9 -5
- package/.llm/components/illustrationcard.md +4 -0
- package/.llm/components/illustrationscene.md +4 -0
- package/.llm/components/imagebanner.md +6 -2
- package/.llm/components/landinghero.md +4 -0
- package/.llm/components/link.md +5 -1
- package/.llm/components/logocolumns.md +4 -0
- package/.llm/components/logorows.md +4 -0
- package/.llm/components/menuitem.md +6 -2
- package/.llm/components/navbar.md +5 -1
- package/.llm/components/navbaritem.md +4 -0
- package/.llm/components/navbarmenu.md +4 -0
- package/.llm/components/navbarmenugroup.md +4 -0
- package/.llm/components/navbarpanel.md +4 -0
- package/.llm/components/navbarswitcher.md +10 -6
- package/.llm/components/navbarswitcheroption.md +4 -0
- package/.llm/components/option.md +5 -1
- package/.llm/components/pageheader.md +4 -0
- package/.llm/components/pagination.md +4 -0
- package/.llm/components/paginationdots.md +4 -0
- package/.llm/components/producthero.md +4 -0
- package/.llm/components/removablechip.md +5 -1
- package/.llm/components/resourcebanner.md +4 -0
- package/.llm/components/row.md +4 -0
- package/.llm/components/scenescroll.md +4 -0
- package/.llm/components/scroller.md +4 -0
- package/.llm/components/searchinput.md +4 -0
- package/.llm/components/segmentedcontrol.md +5 -1
- package/.llm/components/segmentedcontrolitem.md +6 -2
- package/.llm/components/select.md +4 -0
- package/.llm/components/selectchip.md +4 -0
- package/.llm/components/spinner.md +4 -0
- package/.llm/components/stack.md +4 -0
- package/.llm/components/stats.md +4 -0
- package/.llm/components/statusdot.md +4 -0
- package/.llm/components/steps.md +18 -6
- package/.llm/components/stickycards.md +4 -0
- package/.llm/components/subdomainnavbar.md +5 -1
- package/.llm/components/tab.md +6 -2
- package/.llm/components/table.md +4 -0
- package/.llm/components/tablebody.md +4 -0
- package/.llm/components/tablecell.md +4 -0
- package/.llm/components/tablehead.md +4 -0
- package/.llm/components/tableheadercell.md +4 -0
- package/.llm/components/tablerow.md +4 -0
- package/.llm/components/tablist.md +4 -0
- package/.llm/components/teamgrid.md +4 -0
- package/.llm/components/testimonialrow.md +4 -0
- package/.llm/components/testimonialslider.md +4 -0
- package/.llm/components/textarea.md +4 -0
- package/.llm/components/textinput.md +5 -1
- package/.llm/components/textscroll.md +4 -0
- package/.llm/components/tiers.md +4 -0
- package/.llm/components/typography.md +4 -0
- package/.llm/digest/accordion.md +1 -1
- package/.llm/digest/accordionitem.md +1 -1
- package/.llm/digest/aspectratio.md +1 -1
- package/.llm/digest/awards.md +1 -1
- package/.llm/digest/background.md +1 -1
- package/.llm/digest/badge.md +1 -1
- package/.llm/digest/bottomsheet.md +1 -1
- package/.llm/digest/breadcrumb.md +1 -1
- package/.llm/digest/breadcrumbitem.md +1 -1
- package/.llm/digest/button.md +1 -1
- package/.llm/digest/buttonicon.md +1 -1
- package/.llm/digest/card.md +1 -1
- package/.llm/digest/cardbody.md +1 -1
- package/.llm/digest/cardbutton.md +1 -1
- package/.llm/digest/checkbox.md +1 -1
- package/.llm/digest/comparisoncards.md +1 -1
- package/.llm/digest/comparisontable.md +1 -1
- package/.llm/digest/ctabanner.md +1 -1
- package/.llm/digest/ctabannerslider.md +1 -1
- package/.llm/digest/datatable.md +1 -1
- package/.llm/digest/divider.md +1 -1
- package/.llm/digest/downloadbanner.md +1 -1
- package/.llm/digest/dropdownmenu.md +1 -1
- package/.llm/digest/estimator.md +66 -0
- package/.llm/digest/faqaccordion.md +1 -1
- package/.llm/digest/featurebullets.md +1 -1
- package/.llm/digest/featurecards.md +1 -1
- package/.llm/digest/featurecardscarousel.md +1 -1
- package/.llm/digest/featurescroll.md +1 -1
- package/.llm/digest/featuresplit.md +1 -1
- package/.llm/digest/featurestack.md +1 -1
- package/.llm/digest/filterchip.md +1 -1
- package/.llm/digest/footer.md +1 -1
- package/.llm/digest/footergroup.md +1 -1
- package/.llm/digest/grid.md +1 -1
- package/.llm/digest/icon.md +1 -1
- package/.llm/digest/illustrationcard.md +1 -1
- package/.llm/digest/illustrationscene.md +1 -1
- package/.llm/digest/imagebanner.md +2 -2
- package/.llm/digest/landinghero.md +1 -1
- package/.llm/digest/link.md +1 -1
- package/.llm/digest/logocolumns.md +1 -1
- package/.llm/digest/logorows.md +1 -1
- package/.llm/digest/menuitem.md +1 -1
- package/.llm/digest/navbar.md +1 -1
- package/.llm/digest/navbaritem.md +1 -1
- package/.llm/digest/navbarmenu.md +1 -1
- package/.llm/digest/navbarmenugroup.md +1 -1
- package/.llm/digest/navbarpanel.md +1 -1
- package/.llm/digest/navbarswitcher.md +1 -1
- package/.llm/digest/navbarswitcheroption.md +1 -1
- package/.llm/digest/option.md +1 -1
- package/.llm/digest/pageheader.md +1 -1
- package/.llm/digest/pagination.md +1 -1
- package/.llm/digest/paginationdots.md +1 -1
- package/.llm/digest/producthero.md +1 -1
- package/.llm/digest/removablechip.md +1 -1
- package/.llm/digest/resourcebanner.md +1 -1
- package/.llm/digest/row.md +1 -1
- package/.llm/digest/scenescroll.md +1 -1
- package/.llm/digest/scroller.md +1 -1
- package/.llm/digest/searchinput.md +1 -1
- package/.llm/digest/segmentedcontrol.md +1 -1
- package/.llm/digest/segmentedcontrolitem.md +2 -2
- package/.llm/digest/select.md +1 -1
- package/.llm/digest/selectchip.md +1 -1
- package/.llm/digest/spinner.md +1 -1
- package/.llm/digest/stack.md +1 -1
- package/.llm/digest/stats.md +1 -1
- package/.llm/digest/statusdot.md +1 -1
- package/.llm/digest/steps.md +3 -3
- package/.llm/digest/stickycards.md +1 -1
- package/.llm/digest/subdomainnavbar.md +1 -1
- package/.llm/digest/tab.md +1 -1
- package/.llm/digest/table.md +1 -1
- package/.llm/digest/tablebody.md +1 -1
- package/.llm/digest/tablecell.md +1 -1
- package/.llm/digest/tablehead.md +1 -1
- package/.llm/digest/tableheadercell.md +1 -1
- package/.llm/digest/tablerow.md +1 -1
- package/.llm/digest/tablist.md +1 -1
- package/.llm/digest/teamgrid.md +1 -1
- package/.llm/digest/testimonialrow.md +1 -1
- package/.llm/digest/testimonialslider.md +1 -1
- package/.llm/digest/textarea.md +1 -1
- package/.llm/digest/textinput.md +1 -1
- package/.llm/digest/textscroll.md +1 -1
- package/.llm/digest/tiers.md +1 -1
- package/.llm/digest/typography.md +1 -1
- package/.llm/index.md +2 -1
- package/.llm/tokens.md +5 -0
- package/AGENTS.md +1 -0
- package/README.md +28 -3
- package/dist/components/blocks/block-parallax.css +62 -0
- package/dist/components/blocks/comparison-cards/comparison-cards-impl.css +0 -12
- package/dist/components/blocks/download-banner/DownloadBanner.d.ts +1 -0
- package/dist/components/blocks/download-banner/DownloadBanner.js +2 -1
- package/dist/components/blocks/estimator/Estimator.css +206 -0
- package/dist/components/blocks/estimator/Estimator.d.ts +27 -0
- package/dist/components/blocks/estimator/Estimator.js +61 -0
- package/dist/components/blocks/estimator/Estimator.types.d.ts +63 -0
- package/dist/components/blocks/estimator/Estimator.types.js +25 -0
- package/dist/components/blocks/estimator/estimator-impl.css +159 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +1 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.js +2 -1
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +1 -0
- package/dist/components/blocks/feature-cards/FeatureCards.js +1 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.js +9 -3
- package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +63 -40
- package/dist/components/blocks/feature-split/FeatureSplit.d.ts +1 -0
- package/dist/components/blocks/feature-split/FeatureSplit.js +2 -1
- package/dist/components/blocks/feature-stack/FeatureStack.d.ts +1 -0
- package/dist/components/blocks/feature-stack/FeatureStack.js +2 -1
- package/dist/components/blocks/image-banner/ImageBanner.d.ts +1 -0
- package/dist/components/blocks/image-banner/ImageBanner.js +2 -1
- package/dist/components/blocks/image-banner/ImageBanner.types.d.ts +2 -2
- package/dist/components/blocks/image-banner/ImageBanner.types.js +1 -1
- package/dist/components/blocks/image-banner/image-banner-impl.css +7 -51
- package/dist/components/blocks/landing-hero/LandingHero.css +1 -1
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +1 -0
- package/dist/components/blocks/landing-hero/LandingHero.js +2 -1
- package/dist/components/blocks/product-hero/ProductHero.css +1 -1
- package/dist/components/blocks/product-hero/ProductHero.d.ts +1 -0
- package/dist/components/blocks/product-hero/ProductHero.js +2 -1
- package/dist/components/blocks/steps/Steps.css +2 -2
- package/dist/components/blocks/steps/Steps.d.ts +1 -0
- package/dist/components/blocks/steps/Steps.js +3 -2
- package/dist/components/blocks/steps/Steps.types.d.ts +1 -1
- package/dist/components/blocks/steps/steps-impl.css +76 -4
- package/dist/components/blocks/steps/use-turn.d.ts +8 -8
- package/dist/components/blocks/steps/use-turn.js +19 -16
- package/dist/components/blocks/team-grid/TeamGrid.d.ts +1 -0
- package/dist/components/blocks/team-grid/TeamGrid.js +2 -1
- package/dist/components/core/card/Card.css +1 -1
- package/dist/components/core/segmented-control-item/SegmentedControlItem.types.d.ts +1 -1
- package/dist/components/core/select/Select.css +2 -0
- package/dist/components/core/select/select-impl.css +58 -0
- package/dist/components/core/text-area/TextArea.css +2 -0
- package/dist/components/core/text-area/text-area-impl.css +54 -0
- package/dist/components/core/text-input/TextInput.css +2 -0
- package/dist/components/core/text-input/text-input-impl.css +63 -0
- package/dist/components/estimator-data.d.ts +29 -0
- package/dist/components/estimator-data.js +12 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +2 -0
- package/dist/icons/accounts.d.ts +1 -0
- package/dist/icons/accounts.js +1 -0
- package/dist/icons/app-stores.d.ts +1 -0
- package/dist/icons/app-stores.js +1 -0
- package/dist/icons/currency.d.ts +1 -0
- package/dist/icons/currency.js +1 -0
- package/dist/icons/flag.d.ts +1 -0
- package/dist/icons/flag.js +1 -0
- package/dist/icons/illustrative.d.ts +1 -0
- package/dist/icons/illustrative.js +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +4 -0
- package/dist/icons/markets.d.ts +1 -0
- package/dist/icons/markets.js +1 -0
- package/dist/icons/social.d.ts +1 -0
- package/dist/icons/social.js +1 -0
- package/dist/icons/system.d.ts +1 -0
- package/dist/icons/system.js +1 -0
- package/dist/icons/trade.d.ts +1 -0
- package/dist/icons/trade.js +1 -0
- package/dist/marketing.css +10 -0
- package/package.json +44 -2
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* `:where([data-dds-context="marketing"])` confines these rules without contributing specificity,
|
|
5
|
+
* so each is decided against the generated rule on its own terms.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* The Card fills the tool. The tool part is the box in the section's layout; the Card inside it is
|
|
10
|
+
* the surface, and it takes the whole of the tool's width rather than its content's.
|
|
11
|
+
*/
|
|
12
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__tool > .dds-card {
|
|
13
|
+
flex: auto;
|
|
14
|
+
/*
|
|
15
|
+
* Card clips so a picture meets its corner; this card holds no picture, and the clip cut the
|
|
16
|
+
* results panel's shadow off where the panel sits close to the card's edge, which left it flat.
|
|
17
|
+
*/
|
|
18
|
+
overflow: visible;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* The page's fields wrap their words only when a word does not fit. The section breaks anywhere so a
|
|
23
|
+
* long title cannot push the page wide, and that is inherited — but in a field it let the suffix
|
|
24
|
+
* and the panel heading give up their width a letter at a time whenever the panel was tight, "lots"
|
|
25
|
+
* stood on its end beside the box. `break-word` still wraps a word too long for the line, and keeps
|
|
26
|
+
* every word whole while there is room for it.
|
|
27
|
+
*/
|
|
28
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__inputs {
|
|
29
|
+
overflow-wrap: break-word;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* A centred heading centres its measure too, so the line under it sits under the title. */
|
|
33
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="stacked"] .dds-estimator__description {
|
|
34
|
+
margin-inline: auto;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* The figures read along a row of digits that change as a reader types, so the digits keep one
|
|
39
|
+
* width: a value going from 1,111 to 8,888 does not shuffle the currency beside it.
|
|
40
|
+
*/
|
|
41
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__result-value {
|
|
42
|
+
font-variant-numeric: tabular-nums;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* The figures in two columns from the fold, each ruled off beneath — four read as a block of answers
|
|
47
|
+
* beside the fields that made them, and the figures at h4 keep a column each rather than a line
|
|
48
|
+
* each. One column on a phone, where half the panel is too narrow for a figure at that size.
|
|
49
|
+
*/
|
|
50
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__list {
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-columns: minmax(0, 1fr);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@container (min-width: 48rem) {
|
|
56
|
+
/*
|
|
57
|
+
* Calculate and Reset share the row under the fields, a half each: neither is the smaller one, and
|
|
58
|
+
* two buttons of different widths under a column of full-width fields read as unfinished. Only
|
|
59
|
+
* from the fold, where they sit side by side — in the phone's column a zero basis is a zero
|
|
60
|
+
* height, and the buttons collapsed to a sliver.
|
|
61
|
+
*/
|
|
62
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__input-actions > * {
|
|
63
|
+
flex: 1 1 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__list {
|
|
67
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* A figure left on its own — the one figure of a converter, the last of an odd set — takes the
|
|
71
|
+
whole row rather than half of it beside an empty cell. */
|
|
72
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__result:last-child:nth-child(odd) {
|
|
73
|
+
grid-column: 1 / -1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
* The white panel sits close to the card's edge — space.inset.xs from it, where the fields keep the
|
|
79
|
+
* card's full inset. The panel is a surface of its own, and a wide grey margin round it read as a
|
|
80
|
+
* card inside a card; close to the edge it reads as the card's other half.
|
|
81
|
+
*
|
|
82
|
+
* Pulled out by the difference between the two insets. In a column — a phone, and `split` — that is
|
|
83
|
+
* both sides and the foot; beside the fields it is the top, the foot and the far side.
|
|
84
|
+
*/
|
|
85
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__results {
|
|
86
|
+
margin-block-end: calc(var(--space-inset-xs) - var(--space-inset-card));
|
|
87
|
+
margin-inline: calc(var(--space-inset-xs) - var(--space-inset-card));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@container (min-width: 48rem) {
|
|
91
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="stacked"] .dds-estimator__results {
|
|
92
|
+
margin-block: calc(var(--space-inset-xs) - var(--space-inset-card));
|
|
93
|
+
margin-inline-start: 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* From the fold, under `stacked`: the inputs beside the results, two equal panels. A calculator's
|
|
99
|
+
* fields and its figures are read side by side — change one, watch the other.
|
|
100
|
+
*
|
|
101
|
+
* `48rem` longhand because `var()` is not permitted in a container query condition, and it is the
|
|
102
|
+
* width the rest of this package folds at.
|
|
103
|
+
*/
|
|
104
|
+
@container (min-width: 48rem) {
|
|
105
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="stacked"] .dds-estimator__panels {
|
|
106
|
+
flex-direction: row;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="stacked"] :is(.dds-estimator__inputs, .dds-estimator__results) {
|
|
110
|
+
flex: 1 1 0;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* At full width, under `split`: the heading beside the card, two equal halves — the reference
|
|
116
|
+
* converter's columns, so the tool reads as wide as the words that introduce it. The panels stay one
|
|
117
|
+
* column inside the card, the inputs above the figures.
|
|
118
|
+
*
|
|
119
|
+
* `64rem`, the width a split of words and a tool can both breathe in; below it the heading goes back
|
|
120
|
+
* above the card, at the start.
|
|
121
|
+
*/
|
|
122
|
+
@container (min-width: 64rem) {
|
|
123
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="split"] .dds-estimator__inner {
|
|
124
|
+
align-items: center;
|
|
125
|
+
flex-direction: row;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-layout="split"] :is(.dds-estimator__header, .dds-estimator__tool) {
|
|
129
|
+
flex: 1 1 0;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* On a phone the way onward fills the panel, as every section's actions do — the package's rule:
|
|
135
|
+
* a thumb reaches a full-width button, and a short one stranded at the start reads as an aside.
|
|
136
|
+
*/
|
|
137
|
+
@container (max-width: 47.9375rem) {
|
|
138
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__action > * {
|
|
139
|
+
inline-size: 100%;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* And the inputs' own buttons stack, each the full width. */
|
|
143
|
+
:where([data-dds-context="marketing"]) .dds-estimator .dds-estimator__input-actions {
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
* The card on the grey band — ComparisonCards' rule for the same card. Card's recessed fill is the
|
|
150
|
+
* band's grey and vanishes, so it takes the raised fill. The block knows its ground and the card does
|
|
151
|
+
* not, so the answer is here rather than in Card.
|
|
152
|
+
*
|
|
153
|
+
* Nothing for the dark band: there the tool is drawn in the dark theme (see Estimator.tsx), which
|
|
154
|
+
* turns the card, the rules between figures, the muted ink and the page's own fields round together.
|
|
155
|
+
*/
|
|
156
|
+
:where([data-dds-context="marketing"]) .dds-estimator[data-ground="subtle"] .dds-estimator__tool > .dds-card {
|
|
157
|
+
background-color: var(--color-bg-surface-card-raised);
|
|
158
|
+
}
|
|
159
|
+
|
|
@@ -5,6 +5,7 @@ import { CircleCheckSolidIcon } from '@deriv-com/quill-icons-web';
|
|
|
5
5
|
import './FeatureBullets.css';
|
|
6
6
|
import './feature-bullets-impl.css';
|
|
7
7
|
import '../block-reveal.css';
|
|
8
|
+
import '../block-parallax.css';
|
|
8
9
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
9
10
|
import { featureBulletsDefaults, featureBulletsParts, } from './FeatureBullets.types.js';
|
|
10
11
|
/**
|
|
@@ -51,5 +52,5 @@ export function FeatureBullets({ ground = featureBulletsDefaults.ground, mediaPo
|
|
|
51
52
|
|
|
52
53
|
Two behind the claim, which the picture beside them takes — the two halves of
|
|
53
54
|
the split arrive first and the list follows them. */
|
|
54
|
-
_jsxs("li", { className: featureBulletsParts.item, ...arriving(2 + at), children: [_jsx("span", { className: featureBulletsParts.mark, "aria-hidden": "true", children: _jsx(CircleCheckSolidIcon, {}) }), _jsx("span", { className: featureBulletsParts.text, children: bullet })] }, bullet))) })] }), _jsx("div", { className: featureBulletsParts.media, ...arriving(1), "aria-hidden": "true", children: media })] }) }) }));
|
|
55
|
+
_jsxs("li", { className: featureBulletsParts.item, ...arriving(2 + at), children: [_jsx("span", { className: featureBulletsParts.mark, "aria-hidden": "true", children: _jsx(CircleCheckSolidIcon, {}) }), _jsx("span", { className: featureBulletsParts.text, children: bullet })] }, bullet))) })] }), _jsx("div", { "data-dds-parallax": "", className: featureBulletsParts.media, ...arriving(1), "aria-hidden": "true", children: media })] }) }) }));
|
|
55
56
|
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './FeatureCards.css';
|
|
5
5
|
import './feature-cards-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { given } from '../../given.js';
|
|
8
9
|
import { cardsOf } from '../cards-of.js';
|
|
9
10
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
@@ -52,7 +52,13 @@ export function FeatureScroll({ ground = featureScrollDefaults.ground, title, st
|
|
|
52
52
|
const root = useRef(null);
|
|
53
53
|
const titles = useRef([]);
|
|
54
54
|
const band = useRef(null);
|
|
55
|
-
|
|
55
|
+
/*
|
|
56
|
+
Which stop's picture is showing, and which way the reader went to reach it. The way is held with
|
|
57
|
+
the stop rather than worked out after it, so the picture arriving and the edge it is uncovered
|
|
58
|
+
from change in the same render — a step behind, it would open from the wrong side for a frame.
|
|
59
|
+
*/
|
|
60
|
+
// `going` is absent until the first change, so the picture a reader opens on is simply there.
|
|
61
|
+
const [{ at: showing, going }, setShowing] = useState({ at: 0 });
|
|
56
62
|
const count = steps.length;
|
|
57
63
|
useLayoutEffect(() => {
|
|
58
64
|
if (count === 0)
|
|
@@ -92,7 +98,7 @@ export function FeatureScroll({ ground = featureScrollDefaults.ground, title, st
|
|
|
92
98
|
reached = i;
|
|
93
99
|
}
|
|
94
100
|
const next = Math.min(count - 1, reached + 1);
|
|
95
|
-
setShowing((held) => (held === next ? held : next));
|
|
101
|
+
setShowing((held) => (held.at === next ? held : { at: next, going: next > held.at ? 'down' : 'up' }));
|
|
96
102
|
};
|
|
97
103
|
const schedule = () => {
|
|
98
104
|
if (frame !== 0)
|
|
@@ -127,7 +133,7 @@ export function FeatureScroll({ ground = featureScrollDefaults.ground, title, st
|
|
|
127
133
|
window.cancelAnimationFrame(frame);
|
|
128
134
|
};
|
|
129
135
|
}, [count]);
|
|
130
|
-
return (_jsx("section", { className: featureScrollParts.root, "data-ground": ground, "data-media-position": mediaPosition, "aria-labelledby": titleId, ref: root, children: _jsxs("div", { className: featureScrollParts.inner, children: [_jsx("h2", { className: featureScrollParts.heading, ref: heading, "data-revealed": revealed, ...arriving(0), id: titleId, children: title }), _jsx("div", { className: featureScrollParts.steps, style: { '--dds-featurescroll-stops': count }, children: steps.map((step, index) => (
|
|
136
|
+
return (_jsx("section", { className: featureScrollParts.root, "data-ground": ground, "data-media-position": mediaPosition, "data-going": going, "aria-labelledby": titleId, ref: root, children: _jsxs("div", { className: featureScrollParts.inner, children: [_jsx("h2", { className: featureScrollParts.heading, ref: heading, "data-revealed": revealed, ...arriving(0), id: titleId, children: title }), _jsx("div", { className: featureScrollParts.steps, style: { '--dds-featurescroll-stops': count }, children: steps.map((step, index) => (
|
|
131
137
|
/* Keyed by the title. An index would key the set by position, so filtering a stop out
|
|
132
138
|
would renumber every stop under it and React would reconcile the wrong ones — and
|
|
133
139
|
these are the content, so two the same would be a duplicate stop rather than a key
|
|
@@ -226,53 +226,50 @@
|
|
|
226
226
|
* The duration and the curve are bound on the part, so the generated sheet writes the
|
|
227
227
|
* reduced-motion block that turns this into a cut.
|
|
228
228
|
*/
|
|
229
|
+
/*
|
|
230
|
+
* One of them is shown, and the next is uncovered over it rather than faded in.
|
|
231
|
+
*
|
|
232
|
+
* The only thing the component's own listener writes is which stop's picture belongs to the words
|
|
233
|
+
* a reader has reached, and which way they went to reach it — a question about where each title
|
|
234
|
+
* has got to, which no query asks. The pinning and the change are this stylesheet's.
|
|
235
|
+
*
|
|
236
|
+
* A wipe rather than a dissolve. Fading the arriving picture in over the last one put both on
|
|
237
|
+
* screen at once for the whole of the change — at its middle the square was two photographs at
|
|
238
|
+
* half strength each, a double exposure that read as the pictures overlapping. Uncovered from an
|
|
239
|
+
* edge instead, every point of the square is one picture or the other at full strength, and the
|
|
240
|
+
* line between them moves the way the page does: up from the foot as a reader scrolls on, down
|
|
241
|
+
* from the head as they scroll back. Nothing is mixed, so nothing overlaps.
|
|
242
|
+
*
|
|
243
|
+
* An animation rather than a transition, because an animation starts from its first frame. A
|
|
244
|
+
* transition starts from wherever the picture last rested, so a reader who turned back mid-section
|
|
245
|
+
* had the next picture open from the edge they were no longer moving towards.
|
|
246
|
+
*
|
|
247
|
+
* The shown picture is brought to the front and uncovered; the one it replaces stays beneath,
|
|
248
|
+
* whole, for the same duration and then goes — a step at the end of a zero-length transition,
|
|
249
|
+
* delayed by the uncovering's own duration, read from the same role so the two cannot drift
|
|
250
|
+
* apart into a gap. Every other picture is already gone.
|
|
251
|
+
*
|
|
252
|
+
* `z-index` is a bare integer, the one kind of value this system keeps out of its tokens: a
|
|
253
|
+
* stacking order inside a component is not a decision any brand or mode has an opinion about.
|
|
254
|
+
*/
|
|
255
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__media {
|
|
256
|
+
transition: opacity 0s linear var(--motion-duration-media-hover);
|
|
257
|
+
}
|
|
258
|
+
|
|
229
259
|
:where([data-dds-context="marketing"])
|
|
230
260
|
.dds-featurescroll
|
|
231
261
|
.dds-featurescroll__media[data-showing="true"] {
|
|
232
262
|
opacity: 1;
|
|
233
|
-
/*
|
|
234
|
-
* On top, and that is what makes this a dissolve rather than a dip.
|
|
235
|
-
*
|
|
236
|
-
* The arriving picture fades in over whatever is beneath it, so at every moment of the change
|
|
237
|
-
* the square is covered by something opaque. Fading both at once instead leaves them near half
|
|
238
|
-
* way together, the section's own ground shows through the pair, and the square brightens and
|
|
239
|
-
* darkens — a pulse, from nothing but two opacities crossing.
|
|
240
|
-
*
|
|
241
|
-
* It has to be the shown one rather than the later one in the document, because a reader
|
|
242
|
-
* scrolls back as well as forward. Going up, the arriving picture is earlier in the markup and
|
|
243
|
-
* would fade in underneath the one it is replacing: invisible until that one left, which is a
|
|
244
|
-
* cut with a pause in front of it.
|
|
245
|
-
*
|
|
246
|
-
* A bare integer, which is the one kind of value this system keeps out of its tokens: a
|
|
247
|
-
* stacking order inside a component is not a decision any brand or mode has an opinion about.
|
|
248
|
-
*/
|
|
249
|
-
z-index: 1;
|
|
250
|
-
/* No wait on the way in. The pair of delays is the whole mechanism — see the rule below. */
|
|
251
263
|
transition-delay: 0s;
|
|
264
|
+
z-index: 1;
|
|
252
265
|
}
|
|
253
266
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
* behind the new one does it drop, which costs nothing to look at because nobody can see it.
|
|
261
|
-
*
|
|
262
|
-
* The delay is the arriving picture's own duration, read from the same role, so the two cannot
|
|
263
|
-
* drift apart into a gap or an overlap.
|
|
264
|
-
*
|
|
265
|
-
* There is no scale here any more. It read as a pulse, which is what it was: a square this large
|
|
266
|
-
* carries a change of picture on its own, and a sixth of a second of zoom on top of it is the
|
|
267
|
-
* section drawing attention to its own machinery.
|
|
268
|
-
*/
|
|
269
|
-
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__media {
|
|
270
|
-
transition-delay: var(--motion-duration-media-hover);
|
|
271
|
-
/* Named here rather than in the contract because `staticCss` takes keywords, and this is the
|
|
272
|
-
one property the pair of rules is about. The duration and the curve stay bound there, which
|
|
273
|
-
is what the generated reduced-motion block is written from — so a reader who asked for less
|
|
274
|
-
still gets a cut. */
|
|
275
|
-
transition-property: opacity;
|
|
267
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-going="down"] .dds-featurescroll__media[data-showing="true"] {
|
|
268
|
+
animation: dds-featurescroll-from-foot var(--motion-duration-media-hover) var(--motion-easing-media-hover);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll[data-going="up"] .dds-featurescroll__media[data-showing="true"] {
|
|
272
|
+
animation: dds-featurescroll-from-head var(--motion-duration-media-hover) var(--motion-easing-media-hover);
|
|
276
273
|
}
|
|
277
274
|
|
|
278
275
|
/*
|
|
@@ -290,3 +287,29 @@
|
|
|
290
287
|
);
|
|
291
288
|
}
|
|
292
289
|
}
|
|
290
|
+
|
|
291
|
+
@keyframes dds-featurescroll-from-foot {
|
|
292
|
+
from {
|
|
293
|
+
clip-path: inset(100% 0 0 0);
|
|
294
|
+
}
|
|
295
|
+
to {
|
|
296
|
+
clip-path: inset(0);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@keyframes dds-featurescroll-from-head {
|
|
301
|
+
from {
|
|
302
|
+
clip-path: inset(0 0 100% 0);
|
|
303
|
+
}
|
|
304
|
+
to {
|
|
305
|
+
clip-path: inset(0);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Less movement is a cut: no uncovering, and the last picture gone at once. The generated sheet
|
|
310
|
+
already drops every transition here; the animation is this sheet's to drop. */
|
|
311
|
+
@media (prefers-reduced-motion: reduce) {
|
|
312
|
+
:where([data-dds-context="marketing"]) .dds-featurescroll .dds-featurescroll__media[data-showing="true"] {
|
|
313
|
+
animation: none;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './FeatureSplit.css';
|
|
5
5
|
import './feature-split-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { featureSplitDefaults, featureSplitParts, } from './FeatureSplit.types.js';
|
|
@@ -34,5 +35,5 @@ import { featureSplitDefaults, featureSplitParts, } from './FeatureSplit.types.j
|
|
|
34
35
|
export function FeatureSplit({ ground = featureSplitDefaults.ground, mediaPosition = featureSplitDefaults.mediaPosition, title, description, link, media, }) {
|
|
35
36
|
const titleId = useId();
|
|
36
37
|
const [band, revealed] = useReveal();
|
|
37
|
-
return (_jsx("section", { className: featureSplitParts.root, "data-ground": ground, "data-media-position": mediaPosition, "aria-labelledby": titleId, children: _jsx("div", { className: featureSplitParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: featureSplitParts.split, children: [_jsxs("div", { className: featureSplitParts.content, children: [_jsx("h2", { className: featureSplitParts.title, ...arriving(0), id: titleId, children: title }), given(description) ? (_jsx("p", { className: featureSplitParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureSplitParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { className: featureSplitParts.media, ...arriving(3), "aria-hidden": "true", children: media })] }) }) }));
|
|
38
|
+
return (_jsx("section", { className: featureSplitParts.root, "data-ground": ground, "data-media-position": mediaPosition, "aria-labelledby": titleId, children: _jsx("div", { className: featureSplitParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: featureSplitParts.split, children: [_jsxs("div", { className: featureSplitParts.content, children: [_jsx("h2", { className: featureSplitParts.title, ...arriving(0), id: titleId, children: title }), given(description) ? (_jsx("p", { className: featureSplitParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureSplitParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { "data-dds-parallax": "", className: featureSplitParts.media, ...arriving(3), "aria-hidden": "true", children: media })] }) }) }));
|
|
38
39
|
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './FeatureStack.css';
|
|
5
5
|
import './feature-stack-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { given } from '../../given.js';
|
|
8
9
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
9
10
|
import { featureStackDefaults, featureStackParts, } from './FeatureStack.types.js';
|
|
@@ -23,5 +24,5 @@ import { featureStackDefaults, featureStackParts, } from './FeatureStack.types.j
|
|
|
23
24
|
export function FeatureStack({ ground = featureStackDefaults.ground, title, description, link, image, }) {
|
|
24
25
|
const titleId = useId();
|
|
25
26
|
const [band, revealed] = useReveal();
|
|
26
|
-
return (_jsx("section", { className: featureStackParts.root, "data-ground": ground, "aria-labelledby": titleId, children: _jsxs("div", { className: featureStackParts.inner, ref: band, "data-revealed": revealed, children: [_jsxs("div", { className: featureStackParts.header, children: [_jsx("h2", { className: featureStackParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: featureStackParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureStackParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { className: featureStackParts.media, ...arriving(3), children: image ? (_jsx("img", { className: featureStackParts.image, src: image.src, alt: image.alt, width: image.width, height: image.height, loading: "lazy", decoding: "async" })) : null })] }) }));
|
|
27
|
+
return (_jsx("section", { className: featureStackParts.root, "data-ground": ground, "aria-labelledby": titleId, children: _jsxs("div", { className: featureStackParts.inner, ref: band, "data-revealed": revealed, children: [_jsxs("div", { className: featureStackParts.header, children: [_jsx("h2", { className: featureStackParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: featureStackParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureStackParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { "data-dds-parallax": "", className: featureStackParts.media, ...arriving(3), children: image ? (_jsx("img", { className: featureStackParts.image, src: image.src, alt: image.alt, width: image.width, height: image.height, loading: "lazy", decoding: "async" })) : null })] }) }));
|
|
27
28
|
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './ImageBanner.css';
|
|
5
5
|
import './image-banner-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { imageBannerDefaults, imageBannerParts } from './ImageBanner.types.js';
|
|
@@ -37,5 +38,5 @@ export function ImageBanner({ ground = imageBannerDefaults.ground, variant = ima
|
|
|
37
38
|
const titleId = useId();
|
|
38
39
|
const Title = headingLevel;
|
|
39
40
|
const [band, revealed] = useReveal();
|
|
40
|
-
return (_jsx("section", { className: imageBannerParts.root, "data-ground": ground, "data-variant": variant, "data-media-position": mediaPosition, "data-parallax": parallax, "aria-labelledby": titleId, children: _jsx("div", { className: imageBannerParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: imageBannerParts.card, children: [_jsxs("div", { className: imageBannerParts.content, children: [_jsx(Title, { className: imageBannerParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: imageBannerParts.description, ...arriving(1), children: description })) : null, action ? (_jsx("div", { className: imageBannerParts.action, ...arriving(2), children: action })) : null] }), _jsx("div", { className: imageBannerParts.media, ...(variant === 'cover' ? {} : arriving(3)), children: media })] }) }) }));
|
|
41
|
+
return (_jsx("section", { className: imageBannerParts.root, "data-ground": ground, "data-variant": variant, "data-media-position": mediaPosition, "data-parallax": parallax, "aria-labelledby": titleId, children: _jsx("div", { className: imageBannerParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: imageBannerParts.card, children: [_jsxs("div", { className: imageBannerParts.content, children: [_jsx(Title, { className: imageBannerParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: imageBannerParts.description, ...arriving(1), children: description })) : null, action ? (_jsx("div", { className: imageBannerParts.action, ...arriving(2), children: action })) : null] }), _jsx("div", { className: imageBannerParts.media, "data-dds-parallax": parallax ? '' : undefined, ...(variant === 'cover' ? {} : arriving(3)), children: media })] }) }) }));
|
|
41
42
|
}
|
|
@@ -29,7 +29,7 @@ export interface ImageBannerOwnProps {
|
|
|
29
29
|
action?: ReactNode;
|
|
30
30
|
/** Always. The page's photograph, through AspectRatio or as an image — people or product. Split and cover crop it to fill the space they give it. Alt text is the page's to give, empty where the photograph is decoration. */
|
|
31
31
|
media: ReactNode;
|
|
32
|
-
/** The photograph drifts against the scroll as the card passes through the view,
|
|
32
|
+
/** The photograph drifts against the scroll as the card passes through the view, the drift every block's picture shares — drawn at motion.scale.parallax and moved from motion.translate.parallax-from to motion.translate.parallax-to over the whole pass — so it reads as further away than the card — the reference design's ParallaxBanner, which this replaces. On by default, as every block's picture drifts: pass false for a card whose photograph must hold still under its button. */
|
|
33
33
|
parallax?: boolean;
|
|
34
34
|
}
|
|
35
35
|
export type ImageBannerProps = ImageBannerOwnProps;
|
|
@@ -50,5 +50,5 @@ export declare const imageBannerDefaults: {
|
|
|
50
50
|
readonly variant: "split";
|
|
51
51
|
readonly mediaPosition: "end";
|
|
52
52
|
readonly headingLevel: "h2";
|
|
53
|
-
readonly parallax:
|
|
53
|
+
readonly parallax: true;
|
|
54
54
|
};
|
|
@@ -11,4 +11,4 @@ export const imageBannerParts = {
|
|
|
11
11
|
media: 'dds-imagebanner__media',
|
|
12
12
|
};
|
|
13
13
|
/** Generated so defaults cannot drift from the contract. */
|
|
14
|
-
export const imageBannerDefaults = { ground: 'page', variant: 'split', mediaPosition: 'end', headingLevel: 'h2', parallax:
|
|
14
|
+
export const imageBannerDefaults = { ground: 'page', variant: 'split', mediaPosition: 'end', headingLevel: 'h2', parallax: true };
|
|
@@ -226,56 +226,12 @@
|
|
|
226
226
|
|
|
227
227
|
/*
|
|
228
228
|
* `parallax`: the photograph drifts against the scroll as the card passes through the view — the
|
|
229
|
-
* reference design's ParallaxBanner, folded in
|
|
229
|
+
* reference design's ParallaxBanner, folded in as an option. The drift is the one every block's
|
|
230
|
+
* picture shares, in block-parallax.css: the component marks the frame and the picture is scaled
|
|
231
|
+
* and moved rather than resized.
|
|
230
232
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* that
|
|
234
|
-
*
|
|
235
|
-
* Scroll-driven, the way LogoColumns moves its wall: the frame names a view timeline and the image
|
|
236
|
-
* runs down it from half the drift above centre to half below, over the whole pass (`cover`), so as
|
|
237
|
-
* the page carries the card up the photograph falls behind a little and reads as further away.
|
|
238
|
-
* Linear, because the scroll is the easing. The card and the frame clip with `overflow: clip`, not
|
|
239
|
-
* `hidden`: `hidden` makes a box a scroll container, and a view timeline measured against one that
|
|
240
|
-
* never scrolls stands still.
|
|
241
|
-
*
|
|
242
|
-
* A browser with no scroll timeline, and a reader who asked for less motion, get the photograph
|
|
243
|
-
* still and centred, as with `parallax` off.
|
|
233
|
+
* This card once drew its own, by making the photograph taller than the frame with `block-size`.
|
|
234
|
+
* A picture that sets its height inline — Next.js's Image with `fill` writes `height: 100%` on the
|
|
235
|
+
* element — beat that, so the photograph stayed the frame's height and the drift pulled its lower
|
|
236
|
+
* edge up off the card. `scale` is a property nothing sets inline, so the shared drift holds.
|
|
244
237
|
*/
|
|
245
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-parallax="true"]:is([data-variant="split"], [data-variant="cover"]) .dds-imagebanner__media img {
|
|
246
|
-
block-size: calc(100% + var(--motion-distance-drift));
|
|
247
|
-
margin-block-start: calc(var(--motion-distance-drift) / -2);
|
|
248
|
-
object-position: center top;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
@keyframes dds-imagebanner-drift {
|
|
252
|
-
from {
|
|
253
|
-
translate: 0 calc(var(--motion-distance-drift) / -2);
|
|
254
|
-
}
|
|
255
|
-
to {
|
|
256
|
-
translate: 0 calc(var(--motion-distance-drift) / 2);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
@supports (animation-timeline: view()) {
|
|
261
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner .dds-imagebanner__media {
|
|
262
|
-
view-timeline: --dds-imagebanner-frame block;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/* Only for a reader who has not asked for less motion — asked here, around the rule, rather than
|
|
266
|
-
undone after it: the drift's selector outweighs any plain reset, and a reset that loses to it
|
|
267
|
-
leaves the photograph moving for exactly the reader who asked it not to. */
|
|
268
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
269
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-parallax="true"]:is([data-variant="split"], [data-variant="cover"]) .dds-imagebanner__media img {
|
|
270
|
-
animation: dds-imagebanner-drift linear both;
|
|
271
|
-
animation-range: cover;
|
|
272
|
-
animation-timeline: --dds-imagebanner-frame;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
@media (prefers-reduced-motion: reduce) {
|
|
278
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-parallax="true"]:is([data-variant="split"], [data-variant="cover"]) .dds-imagebanner__media img {
|
|
279
|
-
animation: none;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './LandingHero.css';
|
|
5
5
|
import './landing-hero-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { Background } from '../../core/background/Background.js';
|
|
@@ -51,5 +52,5 @@ export function LandingHero({ eyebrow, title, headingLevel = landingHeroDefaults
|
|
|
51
52
|
/* The one inline style here, and it is a value rather than a decision: which photograph,
|
|
52
53
|
supplied by the page. Everything about how it is drawn — the cover fit and the position — is in the stylesheet, where it can be reasoned about. A background shorthand
|
|
53
54
|
would have reset those four properties every time the page passed an image. */
|
|
54
|
-
style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: [background === 'halftone' ? _jsx(Background, { tone: "dark", children: null }) : null, media ? (_jsx("div", { className: landingHeroParts.media, "aria-hidden": "true", children: media })) : null, _jsx("div", { className: landingHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: landingHeroParts.content, children: [_jsxs("div", { className: landingHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: landingHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: landingHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: landingHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: landingHeroParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
|
|
55
|
+
style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: [background === 'halftone' ? _jsx(Background, { tone: "dark", children: null }) : null, media ? (_jsx("div", { "data-dds-parallax": "", className: landingHeroParts.media, "aria-hidden": "true", children: media })) : null, _jsx("div", { className: landingHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: landingHeroParts.content, children: [_jsxs("div", { className: landingHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: landingHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: landingHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: landingHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: landingHeroParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
|
|
55
56
|
}
|
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './ProductHero.css';
|
|
5
5
|
import './product-hero-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { productHeroDefaults, productHeroParts, } from './ProductHero.types.js';
|
|
@@ -47,5 +48,5 @@ export function ProductHero({ eyebrow, title, headingLevel = productHeroDefaults
|
|
|
47
48
|
style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: _jsx("div", { className: productHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: productHeroParts.content, children: [_jsxs("div", { className: productHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: productHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: productHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: productHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: productHeroParts.actions, ...arriving(3), children: actions })) : null, image ? (
|
|
48
49
|
// The picture at its own shape: drawn here so the band can size it, and read for its
|
|
49
50
|
// `alt`, which the page leaves empty where the claim already names it.
|
|
50
|
-
_jsx("div", { className: productHeroParts.media, ...arriving(4), children: _jsx("img", { className: productHeroParts.image, src: image.src, alt: image.alt, width: image.width, height: image.height, decoding: "async" }) })) : media ? (_jsx("div", { className: productHeroParts.media, ...arriving(4), "aria-hidden": "true", children: media })) : null] }) }) }));
|
|
51
|
+
_jsx("div", { "data-dds-parallax": "", className: productHeroParts.media, ...arriving(4), children: _jsx("img", { className: productHeroParts.image, src: image.src, alt: image.alt, width: image.width, height: image.height, decoding: "async" }) })) : media ? (_jsx("div", { "data-dds-parallax": "", className: productHeroParts.media, ...arriving(4), "aria-hidden": "true", children: media })) : null] }) }) }));
|
|
51
52
|
}
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
|
|
39
39
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__image {
|
|
40
40
|
display: block;
|
|
41
|
-
transition-duration: var(--motion-duration-
|
|
42
|
-
transition-timing-function: var(--motion-easing-
|
|
41
|
+
transition-duration: var(--motion-duration-turn);
|
|
42
|
+
transition-timing-function: var(--motion-easing-reveal);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__content {
|