@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
|
@@ -4,6 +4,7 @@ import { useId } from 'react';
|
|
|
4
4
|
import './Steps.css';
|
|
5
5
|
import './steps-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 { useTurn } from './use-turn.js';
|
|
@@ -41,11 +42,11 @@ export function Steps({ ground = stepsDefaults.ground, mediaPosition = stepsDefa
|
|
|
41
42
|
// records as they are typed, and a number against nothing is a step the page did not write — so
|
|
42
43
|
// it is dropped before the count is taken, and the numbers close up rather than skipping one.
|
|
43
44
|
const shown = steps.filter((step) => given(step.title));
|
|
44
|
-
const { current, turning, playing, next, choose, section, hold } = useTurn(shown.length, autoplay);
|
|
45
|
+
const { current, going, turning, playing, next, choose, section, hold } = useTurn(shown.length, autoplay);
|
|
45
46
|
// The steps' own pictures replace the one picture only where every step has one: a turn that
|
|
46
47
|
// reached a step without a picture would show nothing beside it.
|
|
47
48
|
const pictured = shown.length > 0 && shown.every((step) => given(step.image?.src));
|
|
48
|
-
return (_jsx("section", { className: stepsParts.root, ref: section, "data-ground": ground, "data-media-position": mediaPosition, "data-autoplay": autoplay || undefined, "aria-labelledby": titleId, ...(autoplay ? hold : {}), children: _jsx("div", { className: stepsParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: stepsParts.split, children: [_jsx("div", { className: stepsParts.media, ...arriving(0), "aria-hidden": "true", children: pictured
|
|
49
|
+
return (_jsx("section", { className: stepsParts.root, ref: section, "data-ground": ground, "data-media-position": mediaPosition, "data-autoplay": autoplay || undefined, "data-going": going, "aria-labelledby": titleId, ...(autoplay ? hold : {}), children: _jsx("div", { className: stepsParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: stepsParts.split, children: [_jsx("div", { "data-dds-parallax": "", className: stepsParts.media, ...arriving(0), "aria-hidden": "true", children: pictured
|
|
49
50
|
? shown.map((step, at) => (_jsx("img", { className: stepsParts.image, src: step.image?.src, alt: "", width: step.image?.width, height: step.image?.height, "data-current": at === current, loading: at === 0 ? undefined : 'lazy' }, `${at}:${step.title}`)))
|
|
50
51
|
: media }), _jsxs("div", { className: stepsParts.content, children: [_jsx("h2", { className: stepsParts.title, ...arriving(0), id: titleId, children: title }), _jsx("ol", { className: stepsParts.list, role: "list", "data-turning": autoplay ? turning : undefined, "data-playing": autoplay ? playing : undefined, children: shown.map((step, at) => (
|
|
51
52
|
/* Keyed by the step's own name. An index would key the list by position, so
|
|
@@ -12,7 +12,7 @@ export interface StepsOwnProps {
|
|
|
12
12
|
* `end` — The steps first, for a section sitting under a split whose picture is already at the start
|
|
13
13
|
*/
|
|
14
14
|
mediaPosition?: 'start' | 'end';
|
|
15
|
-
/** Whether the steps take their turn on their own: one step is current, its rule fills over motion.duration.
|
|
15
|
+
/** Whether the steps take their turn on their own: one step is current, its rule fills over motion.duration.step, then the next takes over, and back to the first after the last. The current step's number is drawn at full strength and the rest recede; with an `image` on each step the picture changes to the current one's. Each step's title becomes a button that makes it current. Off by default, so a list nobody configured stays still. On, it holds while focus is inside the section — not under the pointer, so it keeps turning while a reader watches it — waits until the section is on screen, never moves for a reader who asked for less motion, and stops for good once the reader presses a step — the WAI carousel rule CtaBannerSlider follows: a reader who has chosen a step is reading it. That gives a reader a way to stop it, which WCAG 2.2.2 asks for, but not a visible one, so a page that needs 2.2.2 met plainly should leave it off. */
|
|
16
16
|
autoplay?: boolean;
|
|
17
17
|
/** Always. What the steps get a reader to, in the fewest words that say it — 'Get started in 3 steps' */
|
|
18
18
|
title: string;
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/*
|
|
155
|
-
* The fill: the current step's rule, drawn from the start edge over motion.duration.
|
|
155
|
+
* The fill: the current step's rule, drawn from the start edge over motion.duration.step. When it
|
|
156
156
|
* ends the next step takes over — the component listens for the end, so the bar and the turn are
|
|
157
157
|
* one clock. Paused wherever the turn is held; full and still where the turn has stopped or never
|
|
158
158
|
* runs, so the current step is still marked.
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__list[data-turning="true"] > .dds-steps__step[data-current="true"] > .dds-steps__progress {
|
|
178
|
-
animation: dds-steps-fill var(--motion-duration-
|
|
178
|
+
animation: dds-steps-fill var(--motion-duration-step) linear;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__list[data-playing="false"] > .dds-steps__step[data-current="true"] > .dds-steps__progress {
|
|
@@ -184,7 +184,20 @@
|
|
|
184
184
|
|
|
185
185
|
/*
|
|
186
186
|
* The steps' own pictures share the media cell, and the current step's is the one shown — the
|
|
187
|
-
* first while the list is still.
|
|
187
|
+
* first while the list is still.
|
|
188
|
+
*
|
|
189
|
+
* The next is uncovered over the last rather than faded into it, FeatureScroll's change. A fade put
|
|
190
|
+
* both pictures on screen at half strength at once — a double exposure that read as the two
|
|
191
|
+
* overlapping. Uncovered from an edge, every point of the square is one picture or the other at full
|
|
192
|
+
* strength: up from the foot as the turn moves on, the wrap to the first step included, and down
|
|
193
|
+
* from the head when a reader presses an earlier step.
|
|
194
|
+
*
|
|
195
|
+
* An animation rather than a transition, because an animation starts from its first frame and a
|
|
196
|
+
* transition from wherever the picture last rested. The current picture is brought to the front and
|
|
197
|
+
* uncovered over motion.duration.turn — the figure-to-figure step a turning set already takes — and
|
|
198
|
+
* the one it replaces stays beneath, whole, for that long, then goes: a zero-length transition
|
|
199
|
+
* delayed by the same role, so the two cannot drift into a gap. Every other picture is already gone.
|
|
200
|
+
* No `data-going` before the first change, so the picture a reader opens on is simply there.
|
|
188
201
|
*/
|
|
189
202
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__media:has(> .dds-steps__image) {
|
|
190
203
|
display: grid;
|
|
@@ -193,11 +206,66 @@
|
|
|
193
206
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__media > .dds-steps__image {
|
|
194
207
|
grid-area: 1 / 1;
|
|
195
208
|
opacity: 0;
|
|
196
|
-
transition
|
|
209
|
+
transition: opacity 0s linear var(--motion-duration-turn);
|
|
197
210
|
}
|
|
198
211
|
|
|
199
212
|
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
200
213
|
opacity: 1;
|
|
214
|
+
transition-delay: 0s;
|
|
215
|
+
z-index: 1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
:where([data-dds-context="marketing"]) .dds-steps[data-going="on"] .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
219
|
+
animation: dds-steps-from-foot var(--motion-duration-turn) var(--motion-easing-reveal);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
:where([data-dds-context="marketing"]) .dds-steps[data-going="back"] .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
223
|
+
animation: dds-steps-from-head var(--motion-duration-turn) var(--motion-easing-reveal);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/*
|
|
227
|
+
* The wipe and the parallax together. The current picture's wipe is an `animation`, and so is the
|
|
228
|
+
* drift block-parallax.css gives every picture in the frame — one shorthand would replace the other,
|
|
229
|
+
* and the current picture, the only one a reader sees, would stop drifting the moment it arrived. So
|
|
230
|
+
* both are listed here: the wipe on the document's clock, the drift on the frame's view timeline,
|
|
231
|
+
* where the browser can drive one and the reader has not asked for less motion.
|
|
232
|
+
*/
|
|
233
|
+
@supports (animation-timeline: view()) {
|
|
234
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
235
|
+
:where([data-dds-context="marketing"]) .dds-steps[data-going="on"] .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
236
|
+
animation:
|
|
237
|
+
dds-steps-from-foot var(--motion-duration-turn) var(--motion-easing-reveal),
|
|
238
|
+
dds-parallax linear both;
|
|
239
|
+
animation-range: normal, cover;
|
|
240
|
+
animation-timeline: auto, --dds-parallax;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
:where([data-dds-context="marketing"]) .dds-steps[data-going="back"] .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
244
|
+
animation:
|
|
245
|
+
dds-steps-from-head var(--motion-duration-turn) var(--motion-easing-reveal),
|
|
246
|
+
dds-parallax linear both;
|
|
247
|
+
animation-range: normal, cover;
|
|
248
|
+
animation-timeline: auto, --dds-parallax;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@keyframes dds-steps-from-foot {
|
|
254
|
+
from {
|
|
255
|
+
clip-path: inset(100% 0 0 0);
|
|
256
|
+
}
|
|
257
|
+
to {
|
|
258
|
+
clip-path: inset(0);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@keyframes dds-steps-from-head {
|
|
263
|
+
from {
|
|
264
|
+
clip-path: inset(0 0 100% 0);
|
|
265
|
+
}
|
|
266
|
+
to {
|
|
267
|
+
clip-path: inset(0);
|
|
268
|
+
}
|
|
201
269
|
}
|
|
202
270
|
|
|
203
271
|
/*
|
|
@@ -213,4 +281,8 @@
|
|
|
213
281
|
:where([data-dds-context="marketing"]) .dds-steps[data-autoplay] .dds-steps__number {
|
|
214
282
|
transition: none;
|
|
215
283
|
}
|
|
284
|
+
|
|
285
|
+
:where([data-dds-context="marketing"]) .dds-steps .dds-steps__media > .dds-steps__image[data-current="true"] {
|
|
286
|
+
animation: none;
|
|
287
|
+
}
|
|
216
288
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type FocusEvent
|
|
1
|
+
import { type FocusEvent } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* The steps taking their turn under `autoplay`: which step is current, and whether the turn is
|
|
4
4
|
* running.
|
|
5
5
|
*
|
|
6
|
-
* The timing is not here. The current step's rule fills over motion.duration.
|
|
6
|
+
* The timing is not here. The current step's rule fills over motion.duration.step as a CSS
|
|
7
7
|
* animation, and the turn moves on when that animation ends (`next`), so the bar a reader watches
|
|
8
8
|
* and the step changing are one clock rather than two that drift. Holding the turn is pausing that
|
|
9
9
|
* animation, which is what `playing` is for: the stylesheet pauses the fill wherever it is false.
|
|
@@ -12,21 +12,21 @@ import { type FocusEvent, type PointerEvent } from 'react';
|
|
|
12
12
|
* - `autoplay` is on and there are two steps or more;
|
|
13
13
|
* - the reader has not asked for less motion — asked live, so turning it on mid-visit stops it;
|
|
14
14
|
* - the section is on screen. A turn nobody can see does not run, and starts again where it was;
|
|
15
|
-
* - nothing holds it:
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* - nothing holds it: focus inside the section holds it for as long as it lasts, and pressing a
|
|
16
|
+
* step stops it for good — a reader who has chosen a step is reading it. The keyboard's way and
|
|
17
|
+
* the pointer's and a touch screen's, which WCAG 2.2.2 asks for of anything that moves on its own.
|
|
18
|
+
* A pointer merely resting over the section does not hold it: the list is meant to be watched as
|
|
19
|
+
* it turns, and pausing whenever the pointer crossed it read as the list having stopped.
|
|
19
20
|
*/
|
|
20
21
|
export declare function useTurn(count: number, autoplay: boolean): {
|
|
21
22
|
current: number;
|
|
23
|
+
going: "on" | "back" | undefined;
|
|
22
24
|
turning: boolean;
|
|
23
25
|
playing: boolean;
|
|
24
26
|
next: () => void;
|
|
25
27
|
choose: (at: number) => void;
|
|
26
28
|
section: import("react").RefObject<HTMLElement | null>;
|
|
27
29
|
hold: {
|
|
28
|
-
onPointerEnter: (event: PointerEvent<HTMLElement>) => void;
|
|
29
|
-
onPointerLeave: (event: PointerEvent<HTMLElement>) => void;
|
|
30
30
|
onFocus: () => void;
|
|
31
31
|
onBlur: (event: FocusEvent<HTMLElement>) => void;
|
|
32
32
|
};
|
|
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
4
4
|
* The steps taking their turn under `autoplay`: which step is current, and whether the turn is
|
|
5
5
|
* running.
|
|
6
6
|
*
|
|
7
|
-
* The timing is not here. The current step's rule fills over motion.duration.
|
|
7
|
+
* The timing is not here. The current step's rule fills over motion.duration.step as a CSS
|
|
8
8
|
* animation, and the turn moves on when that animation ends (`next`), so the bar a reader watches
|
|
9
9
|
* and the step changing are one clock rather than two that drift. Holding the turn is pausing that
|
|
10
10
|
* animation, which is what `playing` is for: the stylesheet pauses the fill wherever it is false.
|
|
@@ -13,13 +13,21 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
13
13
|
* - `autoplay` is on and there are two steps or more;
|
|
14
14
|
* - the reader has not asked for less motion — asked live, so turning it on mid-visit stops it;
|
|
15
15
|
* - the section is on screen. A turn nobody can see does not run, and starts again where it was;
|
|
16
|
-
* - nothing holds it:
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* - nothing holds it: focus inside the section holds it for as long as it lasts, and pressing a
|
|
17
|
+
* step stops it for good — a reader who has chosen a step is reading it. The keyboard's way and
|
|
18
|
+
* the pointer's and a touch screen's, which WCAG 2.2.2 asks for of anything that moves on its own.
|
|
19
|
+
* A pointer merely resting over the section does not hold it: the list is meant to be watched as
|
|
20
|
+
* it turns, and pausing whenever the pointer crossed it read as the list having stopped.
|
|
20
21
|
*/
|
|
21
22
|
export function useTurn(count, autoplay) {
|
|
22
23
|
const [current, setCurrent] = useState(0);
|
|
24
|
+
/*
|
|
25
|
+
Which way the last change went, for the picture to be uncovered from the matching edge: on, from
|
|
26
|
+
the foot, for every turn — the wrap from the last step to the first included, because the turn
|
|
27
|
+
still moves on — and back, from the head, when a reader presses an earlier step. Absent until the
|
|
28
|
+
first change, so the picture a reader opens on is simply there.
|
|
29
|
+
*/
|
|
30
|
+
const [going, setGoing] = useState(undefined);
|
|
23
31
|
const [seen, setSeen] = useState(false);
|
|
24
32
|
const [still, setStill] = useState(false);
|
|
25
33
|
const [held, setHeld] = useState(false);
|
|
@@ -46,24 +54,19 @@ export function useTurn(count, autoplay) {
|
|
|
46
54
|
}, [autoplay]);
|
|
47
55
|
/** The current step's fill has run: the next step takes over, and the first after the last. */
|
|
48
56
|
const next = useCallback(() => {
|
|
49
|
-
if (count > 0)
|
|
57
|
+
if (count > 0) {
|
|
58
|
+
setGoing('on');
|
|
50
59
|
setCurrent((at) => (at + 1) % count);
|
|
60
|
+
}
|
|
51
61
|
}, [count]);
|
|
52
62
|
/** A step pressed: it is current, and the turn stops for good. */
|
|
53
63
|
const choose = useCallback((at) => {
|
|
64
|
+
setGoing(at >= current ? 'on' : 'back');
|
|
54
65
|
setCurrent(at);
|
|
55
66
|
setStopped(true);
|
|
56
|
-
}, []);
|
|
67
|
+
}, [current]);
|
|
57
68
|
/** Spread on the section: what holds the turn. */
|
|
58
69
|
const hold = {
|
|
59
|
-
onPointerEnter: (event) => {
|
|
60
|
-
if (event.pointerType === 'mouse')
|
|
61
|
-
setHeld(true);
|
|
62
|
-
},
|
|
63
|
-
onPointerLeave: (event) => {
|
|
64
|
-
if (event.pointerType === 'mouse')
|
|
65
|
-
setHeld(false);
|
|
66
|
-
},
|
|
67
70
|
onFocus: () => setHeld(true),
|
|
68
71
|
onBlur: (event) => {
|
|
69
72
|
if (!event.currentTarget.contains(event.relatedTarget))
|
|
@@ -71,5 +74,5 @@ export function useTurn(count, autoplay) {
|
|
|
71
74
|
},
|
|
72
75
|
};
|
|
73
76
|
// A list that shrank under the current step falls back to its first.
|
|
74
|
-
return { current: current < count ? current : 0, turning, playing, next, choose, section, hold };
|
|
77
|
+
return { current: current < count ? current : 0, going, turning, playing, next, choose, section, hold };
|
|
75
78
|
}
|
|
@@ -4,6 +4,7 @@ import { useId, useState } from 'react';
|
|
|
4
4
|
import './TeamGrid.css';
|
|
5
5
|
import './team-grid-impl.css';
|
|
6
6
|
import '../block-reveal.css';
|
|
7
|
+
import '../block-parallax.css';
|
|
7
8
|
import { given } from '../../given.js';
|
|
8
9
|
import { Button } from '../../core/button/Button.js';
|
|
9
10
|
import { Link } from '../../core/link/Link.js';
|
|
@@ -69,6 +70,6 @@ export function TeamGrid({ ground = teamGridDefaults.ground, title, description,
|
|
|
69
70
|
style: { '--dds-teamgrid-extra-at': at - shown },
|
|
70
71
|
}
|
|
71
72
|
: arriving(Math.min(FIRST_PERSON + at, LAST_STEP));
|
|
72
|
-
return (_jsxs("li", { className: teamGridParts.item, hidden: extra && !expanded, ...motion, children: [_jsx("div", { className: teamGridParts.media, children: _jsx(AspectRatio, { ratio: "square", children: _jsx("img", { src: person.image.src, alt: person.image.alt, loading: "lazy", decoding: "async" }) }) }), _jsxs("div", { className: teamGridParts.text, children: [_jsx("h3", { className: teamGridParts.name, children: person.name }), _jsx("p", { className: teamGridParts.role, children: person.role }), person.profile !== undefined ? (_jsx("div", { className: teamGridParts.profile, children: _jsx(Link, { href: person.profile.href, external: true, tone: inverse ? 'inherit' : 'brand', "aria-label": `${profileName(person)} ${externalLabel}`, children: person.profile.label }) })) : null] })] }, `${person.name}-${at}`));
|
|
73
|
+
return (_jsxs("li", { className: teamGridParts.item, hidden: extra && !expanded, ...motion, children: [_jsx("div", { "data-dds-parallax": "", className: teamGridParts.media, children: _jsx(AspectRatio, { ratio: "square", children: _jsx("img", { src: person.image.src, alt: person.image.alt, loading: "lazy", decoding: "async" }) }) }), _jsxs("div", { className: teamGridParts.text, children: [_jsx("h3", { className: teamGridParts.name, children: person.name }), _jsx("p", { className: teamGridParts.role, children: person.role }), person.profile !== undefined ? (_jsx("div", { className: teamGridParts.profile, children: _jsx(Link, { href: person.profile.href, external: true, tone: inverse ? 'inherit' : 'brand', "aria-label": `${profileName(person)} ${externalLabel}`, children: person.profile.label }) })) : null] })] }, `${person.name}-${at}`));
|
|
73
74
|
}) }), longer ? (_jsx("div", { className: teamGridParts.actions, ...arriving(Math.min(FIRST_PERSON + shown, LAST_STEP + 1)), children: _jsx(Button, { variant: "secondary", size: "md", tone: inverse ? 'inverse' : 'default', "aria-expanded": expanded, "aria-controls": listId, onClick: () => setExpanded((open) => !open), children: expanded ? collapseLabel : expandLabel }) })) : null] })] }) }));
|
|
74
75
|
}
|
|
@@ -10,7 +10,7 @@ export interface SegmentedControlItemOwnProps {
|
|
|
10
10
|
value: string;
|
|
11
11
|
/** Always — it is the segment's accessible name as well as its words, and a radio with no name is announced as a control with nothing in it. One or two words: a row is scanned across, and the segment that needs a phrase is a choice that wanted a list */
|
|
12
12
|
label: string;
|
|
13
|
-
/** The glyph tells the modes apart faster than the words do — a card and a bank beside two payment methods. Import it from @deriv-com/
|
|
13
|
+
/** The glyph tells the modes apart faster than the words do — a card and a bank beside two payment methods. Import it from @deriv-com/dds-marketing/icons and pass the element */
|
|
14
14
|
icon?: ReactNode;
|
|
15
15
|
/** This segment reports its own presses — logging which plan a visitor looked at, say. It is called with this segment's value, and SegmentedControl chains its own handler after it rather than replacing it */
|
|
16
16
|
onSelect?: (value: string) => void;
|
|
@@ -151,6 +151,8 @@
|
|
|
151
151
|
gap: var(--space-gap-xs);
|
|
152
152
|
letter-spacing: var(--font-body-sm-letter-spacing);
|
|
153
153
|
line-height: var(--font-body-sm-line-height);
|
|
154
|
+
transition-duration: var(--motion-duration-fast);
|
|
155
|
+
transition-timing-function: var(--motion-easing-standard);
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
:where([data-dds-context="marketing"]) .dds-select .dds-select__message-icon {
|
|
@@ -112,3 +112,61 @@
|
|
|
112
112
|
animation: none;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* The status message fades in when it arrives.
|
|
118
|
+
*
|
|
119
|
+
* A contract binds transitions, and a transition needs a value to move from: the message is not
|
|
120
|
+
* in the DOM until a status is reported, so only a keyframe can bring it in. Opacity alone — the
|
|
121
|
+
* message takes the helper's place rather than pushing the row down, so there is no distance to
|
|
122
|
+
* travel, and moving it would shift the words being read. A status changing while the message is
|
|
123
|
+
* showing keeps the same element, and its colour moves with the transition the contract binds.
|
|
124
|
+
*/
|
|
125
|
+
@keyframes dds-select-message-in {
|
|
126
|
+
from {
|
|
127
|
+
opacity: 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__message {
|
|
132
|
+
animation: dds-select-message-in var(--motion-duration-normal) var(--motion-easing-enter);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
* The box shakes once when the field turns to an error, as TextInput's does.
|
|
137
|
+
*
|
|
138
|
+
* Once, on arrival: the animation is attached by the error status, so it plays when the status
|
|
139
|
+
* becomes error and not again while it stays one. Only the box moves; the label and the
|
|
140
|
+
* message hold still, so the words saying what went wrong can be read while it settles.
|
|
141
|
+
*
|
|
142
|
+
* Not while the list is open. The popup is drawn inside the box, so shaking the box would shake
|
|
143
|
+
* the answers being read along with it. A status that arrives while it is open shakes the box
|
|
144
|
+
* as the list closes, which is the moment the answer is handed in.
|
|
145
|
+
*/
|
|
146
|
+
@keyframes dds-select-shake {
|
|
147
|
+
20% {
|
|
148
|
+
translate: calc(var(--motion-distance-shake) * -1) 0;
|
|
149
|
+
}
|
|
150
|
+
40% {
|
|
151
|
+
translate: var(--motion-distance-shake) 0;
|
|
152
|
+
}
|
|
153
|
+
60% {
|
|
154
|
+
translate: calc(var(--motion-distance-shake) * -0.5) 0;
|
|
155
|
+
}
|
|
156
|
+
80% {
|
|
157
|
+
translate: calc(var(--motion-distance-shake) * 0.5) 0;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
:where([data-dds-context="marketing"]) .dds-select[data-status="error"]:not(:has([aria-expanded="true"])) .dds-select__control {
|
|
162
|
+
animation: dds-select-shake var(--motion-duration-slow) var(--motion-easing-standard);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* The generated reduce block is written from the token bindings and these are not. A reader who
|
|
166
|
+
has asked for less movement has asked for this too. */
|
|
167
|
+
@media (prefers-reduced-motion: reduce) {
|
|
168
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__message,
|
|
169
|
+
:where([data-dds-context="marketing"]) .dds-select[data-status="error"]:not(:has([aria-expanded="true"])) .dds-select__control {
|
|
170
|
+
animation: none;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -92,6 +92,8 @@
|
|
|
92
92
|
gap: var(--space-gap-xs);
|
|
93
93
|
letter-spacing: var(--font-body-sm-letter-spacing);
|
|
94
94
|
line-height: var(--font-body-sm-line-height);
|
|
95
|
+
transition-duration: var(--motion-duration-fast);
|
|
96
|
+
transition-timing-function: var(--motion-easing-standard);
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
:where([data-dds-context="marketing"]) .dds-textarea .dds-textarea__message-icon {
|
|
@@ -34,3 +34,57 @@
|
|
|
34
34
|
:where([data-dds-context="marketing"]) .dds-textarea__message-icon {
|
|
35
35
|
block-size: calc(var(--font-body-sm-size) * var(--font-body-sm-line-height));
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* The status message fades in when it arrives.
|
|
40
|
+
*
|
|
41
|
+
* A contract binds transitions, and a transition needs a value to move from: the message is not
|
|
42
|
+
* in the DOM until a status is reported, so only a keyframe can bring it in. Opacity alone — the
|
|
43
|
+
* message takes the helper's place rather than pushing the row down, so there is no distance to
|
|
44
|
+
* travel, and moving it would shift the words being read. A status changing while the message is
|
|
45
|
+
* showing keeps the same element, and its colour moves with the transition the contract binds.
|
|
46
|
+
*/
|
|
47
|
+
@keyframes dds-textarea-message-in {
|
|
48
|
+
from {
|
|
49
|
+
opacity: 0;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where([data-dds-context="marketing"]) .dds-textarea .dds-textarea__message {
|
|
54
|
+
animation: dds-textarea-message-in var(--motion-duration-normal) var(--motion-easing-enter);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* The box shakes once when the field turns to an error, as TextInput's does.
|
|
59
|
+
*
|
|
60
|
+
* Once, on arrival: the animation is attached by the error status, so it plays when the status
|
|
61
|
+
* becomes error and not again while it stays one. Only the box moves; the label and the
|
|
62
|
+
* message hold still, so the words saying what went wrong can be read while it settles.
|
|
63
|
+
*/
|
|
64
|
+
@keyframes dds-textarea-shake {
|
|
65
|
+
20% {
|
|
66
|
+
translate: calc(var(--motion-distance-shake) * -1) 0;
|
|
67
|
+
}
|
|
68
|
+
40% {
|
|
69
|
+
translate: var(--motion-distance-shake) 0;
|
|
70
|
+
}
|
|
71
|
+
60% {
|
|
72
|
+
translate: calc(var(--motion-distance-shake) * -0.5) 0;
|
|
73
|
+
}
|
|
74
|
+
80% {
|
|
75
|
+
translate: calc(var(--motion-distance-shake) * 0.5) 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:where([data-dds-context="marketing"]) .dds-textarea[data-status="error"] .dds-textarea__control {
|
|
80
|
+
animation: dds-textarea-shake var(--motion-duration-slow) var(--motion-easing-standard);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* The generated reduce block is written from the token bindings and these are not. A reader who
|
|
84
|
+
has asked for less movement has asked for this too. */
|
|
85
|
+
@media (prefers-reduced-motion: reduce) {
|
|
86
|
+
:where([data-dds-context="marketing"]) .dds-textarea .dds-textarea__message,
|
|
87
|
+
:where([data-dds-context="marketing"]) .dds-textarea[data-status="error"] .dds-textarea__control {
|
|
88
|
+
animation: none;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -118,6 +118,8 @@
|
|
|
118
118
|
gap: var(--space-gap-xs);
|
|
119
119
|
letter-spacing: var(--font-body-sm-letter-spacing);
|
|
120
120
|
line-height: var(--font-body-sm-line-height);
|
|
121
|
+
transition-duration: var(--motion-duration-fast);
|
|
122
|
+
transition-timing-function: var(--motion-easing-standard);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
:where([data-dds-context="marketing"]) .dds-textinput .dds-textinput__message-icon {
|
|
@@ -34,3 +34,66 @@
|
|
|
34
34
|
:where([data-dds-context="marketing"]) .dds-textinput__message-icon {
|
|
35
35
|
block-size: calc(var(--font-body-sm-size) * var(--font-body-sm-line-height));
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* The status message fades in when it arrives.
|
|
40
|
+
*
|
|
41
|
+
* A contract binds transitions, and a transition needs a value to move from: the message is not
|
|
42
|
+
* in the DOM until a status is reported, so there is nothing to transition and only a keyframe
|
|
43
|
+
* can bring it in. Opacity alone — the message takes the helper's place rather than pushing the
|
|
44
|
+
* row down, so there is no distance to travel, and moving it would shift the words being read.
|
|
45
|
+
*
|
|
46
|
+
* It plays once, on arrival. A status changing while the message is already showing keeps the
|
|
47
|
+
* same element, and its colour moves with the transition the contract binds rather than the
|
|
48
|
+
* whole message blinking out and back.
|
|
49
|
+
*/
|
|
50
|
+
@keyframes dds-textinput-message-in {
|
|
51
|
+
from {
|
|
52
|
+
opacity: 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:where([data-dds-context="marketing"]) .dds-textinput .dds-textinput__message {
|
|
57
|
+
animation: dds-textinput-message-in var(--motion-duration-normal) var(--motion-easing-enter);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* The box shakes once when the field turns to an error.
|
|
62
|
+
*
|
|
63
|
+
* Once, on arrival: the animation is attached by the error status, so it plays when the status
|
|
64
|
+
* becomes error and not again while it stays one — typing on in a field that is still wrong does
|
|
65
|
+
* not shake it at every keystroke. Leaving the error and coming back is a new refusal and shakes
|
|
66
|
+
* again. Only the box moves; the label above it and the message below hold still, so the words
|
|
67
|
+
* saying what went wrong can be read while it settles.
|
|
68
|
+
*
|
|
69
|
+
* Each swing is smaller than the last, so it reads as a shake that stops rather than a vibration
|
|
70
|
+
* that is cut off. The swing is symmetric, so it reads the same in either writing direction.
|
|
71
|
+
*/
|
|
72
|
+
@keyframes dds-textinput-shake {
|
|
73
|
+
20% {
|
|
74
|
+
translate: calc(var(--motion-distance-shake) * -1) 0;
|
|
75
|
+
}
|
|
76
|
+
40% {
|
|
77
|
+
translate: var(--motion-distance-shake) 0;
|
|
78
|
+
}
|
|
79
|
+
60% {
|
|
80
|
+
translate: calc(var(--motion-distance-shake) * -0.5) 0;
|
|
81
|
+
}
|
|
82
|
+
80% {
|
|
83
|
+
translate: calc(var(--motion-distance-shake) * 0.5) 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:where([data-dds-context="marketing"]) .dds-textinput[data-status="error"] .dds-textinput__control {
|
|
88
|
+
animation: dds-textinput-shake var(--motion-duration-slow) var(--motion-easing-standard);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* The generated reduce block is written from the token bindings and these are not. A reader who
|
|
92
|
+
has asked for less movement has asked for this too — and a shake is the movement most likely
|
|
93
|
+
to be the reason they asked. */
|
|
94
|
+
@media (prefers-reduced-motion: reduce) {
|
|
95
|
+
:where([data-dds-context="marketing"]) .dds-textinput .dds-textinput__message,
|
|
96
|
+
:where([data-dds-context="marketing"]) .dds-textinput[data-status="error"] .dds-textinput__control {
|
|
97
|
+
animation: none;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The figures an Estimator lays out once a reader has filled its inputs in.
|
|
3
|
+
*
|
|
4
|
+
* Exported from the package for the reason `stats-data.ts` and `comparison-cards-data.ts` are: a
|
|
5
|
+
* block whose content is a list is one whose consumer builds a value before passing it.
|
|
6
|
+
*
|
|
7
|
+
* A record rather than a component per figure, because a result is a number and the words that say
|
|
8
|
+
* what it is — nothing in it is an element a page composes. The page works the figures out, from a
|
|
9
|
+
* live feed, a formula or both; the block only sets them, so the same block serves a margin
|
|
10
|
+
* calculator, a crypto converter and an affiliate's income estimate without knowing which.
|
|
11
|
+
*/
|
|
12
|
+
/** One figure an Estimator shows: what it is, its value, and anything a reader needs to read it. */
|
|
13
|
+
export interface EstimatorResult {
|
|
14
|
+
/** What the figure is, in a few words: 'Margin required', 'You receive', 'Monthly income'. */
|
|
15
|
+
label: string;
|
|
16
|
+
/**
|
|
17
|
+
* The figure, written exactly as it is to be read: '1,240.50 USD', '0.0214 BTC', '$2,400'.
|
|
18
|
+
*
|
|
19
|
+
* A string rather than a number, because the way it is written is the page's: its currency, its
|
|
20
|
+
* digits, its grouping, its locale. The block draws it as given and isolates it, so a sign or a
|
|
21
|
+
* currency keeps its place in a right-to-left line.
|
|
22
|
+
*/
|
|
23
|
+
value: string;
|
|
24
|
+
/**
|
|
25
|
+
* A line under the figure, where it needs one to be read correctly: 'Per lot, at 1:500
|
|
26
|
+
* leverage', 'Estimate at the current price'. Optional; most figures need none.
|
|
27
|
+
*/
|
|
28
|
+
note?: string;
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The figures an Estimator lays out once a reader has filled its inputs in.
|
|
3
|
+
*
|
|
4
|
+
* Exported from the package for the reason `stats-data.ts` and `comparison-cards-data.ts` are: a
|
|
5
|
+
* block whose content is a list is one whose consumer builds a value before passing it.
|
|
6
|
+
*
|
|
7
|
+
* A record rather than a component per figure, because a result is a number and the words that say
|
|
8
|
+
* what it is — nothing in it is an element a page composes. The page works the figures out, from a
|
|
9
|
+
* live feed, a formula or both; the block only sets them, so the same block serves a margin
|
|
10
|
+
* calculator, a crypto converter and an affiliate's income estimate without knowing which.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -44,6 +44,8 @@ export { DownloadBanner, type DownloadBannerProps } from './blocks/download-bann
|
|
|
44
44
|
export { downloadBannerParts, downloadBannerDefaults } from './blocks/download-banner/DownloadBanner.types.js';
|
|
45
45
|
export { DropdownMenu, type DropdownMenuProps } from './core/dropdown-menu/DropdownMenu.js';
|
|
46
46
|
export { dropdownMenuParts, dropdownMenuDefaults } from './core/dropdown-menu/DropdownMenu.types.js';
|
|
47
|
+
export { Estimator, type EstimatorProps } from './blocks/estimator/Estimator.js';
|
|
48
|
+
export { estimatorParts, estimatorDefaults } from './blocks/estimator/Estimator.types.js';
|
|
47
49
|
export { FaqAccordion, type FaqAccordionProps } from './blocks/faq-accordion/FaqAccordion.js';
|
|
48
50
|
export { faqAccordionParts, faqAccordionDefaults } from './blocks/faq-accordion/FaqAccordion.types.js';
|
|
49
51
|
export { FeatureBullets, type FeatureBulletsProps } from './blocks/feature-bullets/FeatureBullets.js';
|
|
@@ -187,6 +189,7 @@ export type { ComparisonCardsCard } from './comparison-cards-data.js';
|
|
|
187
189
|
export type { ComparisonTableColumn, ComparisonTableRow } from './comparison-table-data.js';
|
|
188
190
|
export type { DataTableColumn, DataTableRow } from './data-table-data.js';
|
|
189
191
|
export type { DownloadBannerBadge, DownloadBannerQr } from './download-banner-data.js';
|
|
192
|
+
export type { EstimatorResult } from './estimator-data.js';
|
|
190
193
|
export type { LogoTile } from './logo-data.js';
|
|
191
194
|
export type { ResourceBannerLink } from './resource-banner-data.js';
|
|
192
195
|
export type { SceneScrollScene } from './scene-scroll-data.js';
|
package/dist/components/index.js
CHANGED
|
@@ -45,6 +45,8 @@ export { DownloadBanner } from './blocks/download-banner/DownloadBanner.js';
|
|
|
45
45
|
export { downloadBannerParts, downloadBannerDefaults } from './blocks/download-banner/DownloadBanner.types.js';
|
|
46
46
|
export { DropdownMenu } from './core/dropdown-menu/DropdownMenu.js';
|
|
47
47
|
export { dropdownMenuParts, dropdownMenuDefaults } from './core/dropdown-menu/DropdownMenu.types.js';
|
|
48
|
+
export { Estimator } from './blocks/estimator/Estimator.js';
|
|
49
|
+
export { estimatorParts, estimatorDefaults } from './blocks/estimator/Estimator.types.js';
|
|
48
50
|
export { FaqAccordion } from './blocks/faq-accordion/FaqAccordion.js';
|
|
49
51
|
export { faqAccordionParts, faqAccordionDefaults } from './blocks/faq-accordion/FaqAccordion.types.js';
|
|
50
52
|
export { FeatureBullets } from './blocks/feature-bullets/FeatureBullets.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/accounts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/accounts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/app-stores';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/app-stores';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/currency';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/currency';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/flag';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/flag';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@deriv-com/quill-icons-web/illustrative';
|