@deriv-com/dds-marketing 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.llm/components/accordion.md +6 -0
- package/.llm/components/accordionitem.md +6 -0
- package/.llm/components/aspectratio.md +6 -0
- package/.llm/components/awards.md +6 -0
- package/.llm/components/background.md +49 -10
- package/.llm/components/badge.md +6 -0
- package/.llm/components/bottomsheet.md +6 -0
- package/.llm/components/breadcrumb.md +6 -0
- package/.llm/components/breadcrumbitem.md +6 -0
- package/.llm/components/button.md +9 -3
- package/.llm/components/buttonicon.md +7 -1
- package/.llm/components/card.md +6 -0
- package/.llm/components/cardbody.md +7 -1
- package/.llm/components/cardbutton.md +6 -0
- package/.llm/components/checkbox.md +6 -0
- package/.llm/components/comparisoncards.md +9 -3
- package/.llm/components/comparisontable.md +6 -0
- package/.llm/components/ctabanner.md +6 -0
- package/.llm/components/ctabannerslider.md +6 -0
- package/.llm/components/datatable.md +6 -0
- package/.llm/components/divider.md +6 -0
- package/.llm/components/documentlink.md +237 -0
- package/.llm/components/documents.md +268 -0
- package/.llm/components/downloadbanner.md +7 -1
- package/.llm/components/dropdownmenu.md +6 -0
- package/.llm/components/estimator.md +6 -0
- package/.llm/components/faqaccordion.md +6 -0
- package/.llm/components/featurebullets.md +6 -0
- package/.llm/components/featurecards.md +42 -2
- package/.llm/components/featurecardscarousel.md +7 -1
- package/.llm/components/featurescroll.md +6 -0
- package/.llm/components/featuresplit.md +6 -0
- package/.llm/components/featurestack.md +6 -0
- package/.llm/components/featuretabs.md +369 -0
- package/.llm/components/filterchip.md +6 -0
- package/.llm/components/footer.md +6 -0
- package/.llm/components/footergroup.md +6 -0
- package/.llm/components/grid.md +30 -1
- package/.llm/components/icon.md +6 -0
- package/.llm/components/illustrationcard.md +52 -2
- package/.llm/components/illustrationcheck.md +193 -0
- package/.llm/components/illustrationchoice.md +187 -0
- package/.llm/components/illustrationcode.md +192 -0
- package/.llm/components/illustrationlist.md +175 -0
- package/.llm/components/illustrationscene.md +29 -3
- package/.llm/components/imagebanner.md +30 -5
- package/.llm/components/landinghero.md +6 -0
- package/.llm/components/link.md +7 -1
- package/.llm/components/logocolumns.md +7 -1
- package/.llm/components/logorows.md +42 -2
- package/.llm/components/menuitem.md +6 -0
- package/.llm/components/navbar.md +6 -0
- package/.llm/components/navbaritem.md +6 -0
- package/.llm/components/navbarmenu.md +6 -0
- package/.llm/components/navbarmenugroup.md +6 -0
- package/.llm/components/navbarpanel.md +6 -0
- package/.llm/components/navbarswitcher.md +6 -0
- package/.llm/components/navbarswitcheroption.md +6 -0
- package/.llm/components/option.md +6 -0
- package/.llm/components/pageheader.md +6 -0
- package/.llm/components/pagination.md +6 -0
- package/.llm/components/paginationdots.md +6 -0
- package/.llm/components/producthero.md +29 -4
- package/.llm/components/progressbar.md +305 -0
- package/.llm/components/removablechip.md +6 -0
- package/.llm/components/resourcebanner.md +6 -0
- package/.llm/components/row.md +6 -0
- package/.llm/components/scenescroll.md +38 -24
- package/.llm/components/scenescrollword.md +267 -0
- package/.llm/components/scroller.md +6 -0
- package/.llm/components/searchinput.md +6 -0
- package/.llm/components/segmentedcontrol.md +28 -1
- package/.llm/components/segmentedcontrolitem.md +6 -0
- package/.llm/components/select.md +6 -0
- package/.llm/components/selectchip.md +6 -0
- package/.llm/components/spinner.md +6 -0
- package/.llm/components/stack.md +6 -0
- package/.llm/components/stats.md +46 -1
- package/.llm/components/statscarousel.md +227 -0
- package/.llm/components/statusdot.md +41 -1
- package/.llm/components/steps.md +6 -0
- package/.llm/components/stickycards.md +6 -0
- package/.llm/components/subdomainnavbar.md +6 -0
- package/.llm/components/tab.md +6 -0
- package/.llm/components/table.md +6 -0
- package/.llm/components/tablebody.md +6 -0
- package/.llm/components/tablecell.md +6 -0
- package/.llm/components/tablehead.md +6 -0
- package/.llm/components/tableheadercell.md +6 -0
- package/.llm/components/tablerow.md +6 -0
- package/.llm/components/tablist.md +6 -0
- package/.llm/components/teamgrid.md +6 -0
- package/.llm/components/testimonialrow.md +43 -3
- package/.llm/components/testimonialslider.md +8 -2
- package/.llm/components/textarea.md +6 -0
- package/.llm/components/textinput.md +6 -0
- package/.llm/components/textscroll.md +6 -0
- package/.llm/components/tiers.md +13 -7
- package/.llm/components/tooltip.md +6 -0
- package/.llm/components/typography.md +63 -1
- package/.llm/digest/background.md +14 -6
- package/.llm/digest/button.md +1 -1
- package/.llm/digest/buttonicon.md +1 -1
- package/.llm/digest/documentlink.md +52 -0
- package/.llm/digest/documents.md +51 -0
- package/.llm/digest/downloadbanner.md +1 -1
- package/.llm/digest/featurecards.md +7 -0
- package/.llm/digest/featuretabs.md +50 -0
- package/.llm/digest/grid.md +1 -0
- package/.llm/digest/illustrationcard.md +6 -1
- package/.llm/digest/illustrationcheck.md +42 -0
- package/.llm/digest/illustrationchoice.md +43 -0
- package/.llm/digest/illustrationcode.md +41 -0
- package/.llm/digest/illustrationlist.md +38 -0
- package/.llm/digest/illustrationscene.md +4 -2
- package/.llm/digest/imagebanner.md +9 -3
- package/.llm/digest/logocolumns.md +1 -1
- package/.llm/digest/logorows.md +8 -1
- package/.llm/digest/producthero.md +8 -2
- package/.llm/digest/progressbar.md +56 -0
- package/.llm/digest/scenescroll.md +6 -5
- package/.llm/digest/scenescrollword.md +56 -0
- package/.llm/digest/segmentedcontrol.md +3 -0
- package/.llm/digest/stats.md +8 -0
- package/.llm/digest/statscarousel.md +48 -0
- package/.llm/digest/statusdot.md +7 -0
- package/.llm/digest/testimonialrow.md +8 -1
- package/.llm/digest/testimonialslider.md +1 -1
- package/.llm/digest/typography.md +18 -0
- package/.llm/index.md +14 -4
- package/.llm/rules.md +10 -0
- package/.llm/tokens.md +12 -3
- package/AGENTS.md +13 -2
- package/dist/components/arrival.d.ts +32 -0
- package/dist/components/arrival.js +140 -0
- package/dist/components/arrives.d.ts +17 -0
- package/dist/components/arrives.js +14 -0
- package/dist/components/blocks/awards/Awards.js +2 -27
- package/dist/components/blocks/block-pattern.css +23 -0
- package/dist/components/blocks/comparison-cards/comparison-cards-impl.css +29 -0
- package/dist/components/blocks/documents/Documents.css +90 -0
- package/dist/components/blocks/documents/Documents.d.ts +22 -0
- package/dist/components/blocks/documents/Documents.js +30 -0
- package/dist/components/blocks/documents/Documents.types.d.ts +37 -0
- package/dist/components/blocks/documents/Documents.types.js +14 -0
- package/dist/components/blocks/documents/documents-impl.css +103 -0
- package/dist/components/blocks/download-banner/DownloadBanner.css +1 -1
- package/dist/components/blocks/download-banner/DownloadBanner.types.d.ts +1 -1
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +2 -1
- package/dist/components/blocks/feature-cards/FeatureCards.js +10 -7
- package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +9 -1
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +15 -3
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.d.ts +1 -1
- package/dist/components/blocks/feature-cards-carousel/feature-cards-carousel-impl.css +12 -0
- package/dist/components/blocks/feature-tabs/FeatureTabs.css +100 -0
- package/dist/components/blocks/feature-tabs/FeatureTabs.d.ts +23 -0
- package/dist/components/blocks/feature-tabs/FeatureTabs.js +38 -0
- package/dist/components/blocks/feature-tabs/FeatureTabs.types.d.ts +35 -0
- package/dist/components/blocks/feature-tabs/FeatureTabs.types.js +14 -0
- package/dist/components/blocks/feature-tabs/feature-tabs-impl.css +53 -0
- package/dist/components/blocks/image-banner/ImageBanner.css +1 -1
- package/dist/components/blocks/image-banner/ImageBanner.d.ts +1 -1
- package/dist/components/blocks/image-banner/ImageBanner.js +2 -2
- package/dist/components/blocks/image-banner/ImageBanner.types.d.ts +9 -7
- package/dist/components/blocks/image-banner/ImageBanner.types.js +1 -1
- package/dist/components/blocks/image-banner/image-banner-impl.css +77 -26
- package/dist/components/blocks/laurel.d.ts +16 -0
- package/dist/components/blocks/laurel.js +28 -0
- package/dist/components/blocks/logo-columns/LogoColumns.css +1 -1
- package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +1 -1
- package/dist/components/blocks/logo-rows/LogoRows.css +1 -1
- package/dist/components/blocks/logo-rows/LogoRows.d.ts +2 -1
- package/dist/components/blocks/logo-rows/LogoRows.js +7 -4
- package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +9 -1
- package/dist/components/blocks/pattern-tone.d.ts +11 -0
- package/dist/components/blocks/pattern-tone.js +7 -0
- package/dist/components/blocks/product-hero/ProductHero.d.ts +1 -1
- package/dist/components/blocks/product-hero/ProductHero.js +2 -2
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +8 -3
- package/dist/components/blocks/product-hero/ProductHero.types.js +1 -1
- package/dist/components/blocks/product-hero/product-hero-impl.css +54 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.css +1 -1
- package/dist/components/blocks/scene-scroll/SceneScroll.css +1 -1
- package/dist/components/blocks/scene-scroll/SceneScroll.d.ts +6 -5
- package/dist/components/blocks/scene-scroll/SceneScroll.js +8 -7
- package/dist/components/blocks/scene-scroll/SceneScroll.types.d.ts +5 -5
- package/dist/components/blocks/scene-scroll/SceneScroll.types.js +1 -1
- package/dist/components/blocks/scene-scroll/scene-scroll-impl.css +61 -44
- package/dist/components/blocks/scene-scroll-word/SceneScrollWord.css +105 -0
- package/dist/components/blocks/scene-scroll-word/SceneScrollWord.d.ts +31 -0
- package/dist/components/blocks/scene-scroll-word/SceneScrollWord.js +67 -0
- package/dist/components/blocks/scene-scroll-word/SceneScrollWord.types.d.ts +39 -0
- package/dist/components/blocks/scene-scroll-word/SceneScrollWord.types.js +18 -0
- package/dist/components/blocks/scene-scroll-word/scene-scroll-word-impl.css +370 -0
- package/dist/components/blocks/stats/Stats.d.ts +2 -1
- package/dist/components/blocks/stats/Stats.js +17 -14
- package/dist/components/blocks/stats/Stats.types.d.ts +8 -0
- package/dist/components/blocks/stats/stats-impl.css +4 -1
- package/dist/components/blocks/stats/use-wheel.d.ts +1 -1
- package/dist/components/blocks/stats/use-wheel.js +8 -4
- package/dist/components/blocks/stats-carousel/StatsCarousel.css +209 -0
- package/dist/components/blocks/stats-carousel/StatsCarousel.d.ts +20 -0
- package/dist/components/blocks/stats-carousel/StatsCarousel.js +48 -0
- package/dist/components/blocks/stats-carousel/StatsCarousel.types.d.ts +43 -0
- package/dist/components/blocks/stats-carousel/StatsCarousel.types.js +23 -0
- package/dist/components/blocks/stats-carousel/stats-carousel-impl.css +233 -0
- package/dist/components/blocks/sticky-cards/sticky-cards-impl.css +8 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +1 -1
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +2 -1
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +16 -13
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +9 -1
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +1 -1
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +1 -1
- package/dist/components/blocks/tiers/Tiers.types.d.ts +1 -1
- package/dist/components/core/background/Background.css +19 -0
- package/dist/components/core/background/Background.types.d.ts +2 -1
- package/dist/components/core/background/background-impl.css +47 -15
- package/dist/components/core/background/halftone.js +1 -1
- package/dist/components/core/button/Button.css +5 -5
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +1 -1
- package/dist/components/core/card-body/CardBody.css +5 -0
- package/dist/components/core/card-body/CardBody.types.d.ts +1 -1
- package/dist/components/core/document-link/DocumentLink.css +59 -0
- package/dist/components/core/document-link/DocumentLink.d.ts +19 -0
- package/dist/components/core/document-link/DocumentLink.js +21 -0
- package/dist/components/core/document-link/DocumentLink.types.d.ts +41 -0
- package/dist/components/core/document-link/DocumentLink.types.js +11 -0
- package/dist/components/core/document-link/document-link-impl.css +23 -0
- package/dist/components/core/illustration-card/IllustrationCard.css +7 -0
- package/dist/components/core/illustration-card/IllustrationCard.d.ts +5 -1
- package/dist/components/core/illustration-card/IllustrationCard.js +34 -8
- package/dist/components/core/illustration-card/IllustrationCard.types.d.ts +8 -1
- package/dist/components/core/illustration-card/IllustrationCard.types.js +1 -0
- package/dist/components/core/illustration-card/illustration-card-impl.css +113 -0
- package/dist/components/core/illustration-check/IllustrationCheck.css +25 -0
- package/dist/components/core/illustration-check/IllustrationCheck.d.ts +16 -0
- package/dist/components/core/illustration-check/IllustrationCheck.js +22 -0
- package/dist/components/core/illustration-check/IllustrationCheck.types.d.ts +25 -0
- package/dist/components/core/illustration-check/IllustrationCheck.types.js +9 -0
- package/dist/components/core/illustration-check/illustration-check-impl.css +76 -0
- package/dist/components/core/illustration-choice/IllustrationChoice.css +62 -0
- package/dist/components/core/illustration-choice/IllustrationChoice.d.ts +16 -0
- package/dist/components/core/illustration-choice/IllustrationChoice.js +31 -0
- package/dist/components/core/illustration-choice/IllustrationChoice.types.d.ts +25 -0
- package/dist/components/core/illustration-choice/IllustrationChoice.types.js +11 -0
- package/dist/components/core/illustration-choice/illustration-choice-impl.css +103 -0
- package/dist/components/core/illustration-code/IllustrationCode.css +25 -0
- package/dist/components/core/illustration-code/IllustrationCode.d.ts +12 -0
- package/dist/components/core/illustration-code/IllustrationCode.js +20 -0
- package/dist/components/core/illustration-code/IllustrationCode.types.d.ts +23 -0
- package/dist/components/core/illustration-code/IllustrationCode.types.js +8 -0
- package/dist/components/core/illustration-code/illustration-code-impl.css +42 -0
- package/dist/components/core/illustration-list/IllustrationList.css +19 -0
- package/dist/components/core/illustration-list/IllustrationList.d.ts +16 -0
- package/dist/components/core/illustration-list/IllustrationList.js +18 -0
- package/dist/components/core/illustration-list/IllustrationList.types.d.ts +15 -0
- package/dist/components/core/illustration-list/IllustrationList.types.js +6 -0
- package/dist/components/core/illustration-list/illustration-list-impl.css +52 -0
- package/dist/components/core/illustration-scene/IllustrationScene.css +6 -0
- package/dist/components/core/illustration-scene/IllustrationScene.d.ts +3 -2
- package/dist/components/core/illustration-scene/IllustrationScene.js +4 -3
- package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +5 -1
- package/dist/components/core/illustration-scene/IllustrationScene.types.js +2 -1
- package/dist/components/core/illustration-scene/illustration-scene-impl.css +65 -0
- package/dist/components/core/link/link-impl.css +5 -19
- package/dist/components/core/progress-bar/ProgressBar.css +101 -0
- package/dist/components/core/progress-bar/ProgressBar.d.ts +5 -0
- package/dist/components/core/progress-bar/ProgressBar.js +34 -0
- package/dist/components/core/progress-bar/ProgressBar.types.d.ts +52 -0
- package/dist/components/core/progress-bar/ProgressBar.types.js +12 -0
- package/dist/components/core/progress-bar/progress-bar-impl.css +45 -0
- package/dist/components/core/segmented-control/SegmentedControl.d.ts +1 -1
- package/dist/components/core/segmented-control/SegmentedControl.js +13 -5
- package/dist/components/core/segmented-control/SegmentedControl.types.d.ts +5 -1
- package/dist/components/core/segmented-control/segmented-control-impl.css +35 -0
- package/dist/components/core/status-dot/StatusDot.d.ts +1 -1
- package/dist/components/core/status-dot/StatusDot.js +7 -4
- package/dist/components/core/status-dot/StatusDot.types.d.ts +9 -1
- package/dist/components/core/status-dot/status-dot-impl.css +101 -0
- package/dist/components/core/typography/Typography.d.ts +3 -283
- package/dist/components/core/typography/Typography.js +9 -1
- package/dist/components/core/typography/Typography.types.d.ts +9 -15
- package/dist/components/core/typography/TypographyMotion.d.ts +28 -0
- package/dist/components/core/typography/TypographyMotion.js +43 -0
- package/dist/components/core/typography/typography-impl.css +106 -0
- package/dist/components/illustration-data.d.ts +15 -0
- package/dist/components/illustration-data.js +7 -0
- package/dist/components/index.d.ts +22 -1
- package/dist/components/index.js +20 -0
- package/dist/components/layout/grid/Grid.css +5 -0
- package/dist/components/layout/grid/Grid.types.d.ts +2 -1
- package/dist/components/scene-scroll-data.d.ts +35 -0
- package/dist/components/tiers-data.d.ts +3 -2
- package/dist/marketing.css +24 -6
- package/package.json +1 -1
|
@@ -4,11 +4,14 @@ 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-pattern.css';
|
|
7
8
|
import '../block-parallax.css';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { cardsOf } from '../cards-of.js';
|
|
10
11
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
11
12
|
import { featureCardsDefaults, featureCardsParts } from './FeatureCards.types.js';
|
|
13
|
+
import { Background } from '../../core/background/Background.js';
|
|
14
|
+
import { PATTERN_TONE } from '../pattern-tone.js';
|
|
12
15
|
/**
|
|
13
16
|
* Where a card comes in the arrival, capped so a long set does not keep a reader waiting.
|
|
14
17
|
*
|
|
@@ -38,13 +41,13 @@ const LAST_STEP = FIRST_CARD + 3;
|
|
|
38
41
|
* a step behind the one before, in reading order. `'use client'` for that and for `useId`, which
|
|
39
42
|
* names the region by its heading.
|
|
40
43
|
*/
|
|
41
|
-
export function FeatureCards({ ground = featureCardsDefaults.ground, title, description, link, children, }) {
|
|
44
|
+
export function FeatureCards({ ground = featureCardsDefaults.ground, background, title, description, link, children, }) {
|
|
42
45
|
const titleId = useId();
|
|
43
46
|
const [band, revealed] = useReveal();
|
|
44
|
-
return (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
return (_jsxs("section", { className: featureCardsParts.root, "data-ground": ground, "data-background": background, "aria-labelledby": titleId, children: [background ? _jsx(Background, { tone: PATTERN_TONE[ground], pattern: background, children: null }) : null, _jsxs("div", { className: featureCardsParts.inner, ref: band, "data-revealed": revealed, children: [_jsxs("div", { className: featureCardsParts.header, children: [_jsx("h2", { className: featureCardsParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: featureCardsParts.description, ...arriving(1), children: description })) : null, link ? (_jsx("div", { className: featureCardsParts.link, ...arriving(2), children: link })) : null] }), _jsx("div", { className: featureCardsParts.grid, children: cardsOf(children).map(({ key, card }, at) => (
|
|
48
|
+
/* Each card in a cell of its own, and the cell is what arrives: the card is the page's
|
|
49
|
+
element and keeps its own transitions, which an arrival set on it would overwrite.
|
|
50
|
+
Keyed by the card's own key, made unique across fragments by cardsOf, so a set the
|
|
51
|
+
page reorders moves its cards rather than remounting them. */
|
|
52
|
+
_jsx("div", { className: featureCardsParts.item, ...arriving(Math.min(FIRST_CARD + at, LAST_STEP)), children: card }, key))) })] })] }));
|
|
50
53
|
}
|
|
@@ -2,10 +2,18 @@ import type { ReactNode } from 'react';
|
|
|
2
2
|
export interface FeatureCardsOwnProps {
|
|
3
3
|
/**
|
|
4
4
|
* `page` — The default, and the page's own white. A section that has nothing to separate itself from what is above it — most of them — and the ground a reader is already on
|
|
5
|
-
* `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice. The one to reach for first when two sections need telling apart. A light card — surface-light — turns white on it, color.bg.surface-card-light-raised, because its own gray.50 is the band's and would vanish into it. A dark card — accent-strong — is lifted to color.bg.surface-card-strong-raised, a step lighter in dark mode, where the band is within a shade of its
|
|
5
|
+
* `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice. The one to reach for first when two sections need telling apart. A light card — surface-light — turns white on it, color.bg.surface-card-light-raised, because its own gray.50 is the band's and would vanish into it. A dark card — accent-strong — is lifted to color.bg.surface-card-strong-raised, a step lighter in dark mode, where the band is within a shade of its slate.900. A plain surface card is raised off it the same way, to color.bg.surface-card-raised, because the recessed fill is the band's gray too. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section — in dark mode the tint alone took on whatever it was set against, and on a light surface it was light ink on white.
|
|
6
6
|
* `strong` — `color.bg.brand-strong`, the dark band. It stops the page rather than dividing it, so it is for a section a reader should arrive at — and one per page is usually one more than enough. The coloured cards keep their own grounds on it; a neutral card — surface or surface-raised — turns to Card's inverse fill and white ink, and a plain card takes the white ink alone, because their own would be dark ink on near-black; an eyebrow inside any of them takes the band's quieter ink
|
|
7
7
|
*/
|
|
8
8
|
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
+
/**
|
|
10
|
+
* `halftone` — A field of coral dots that grow towards a soft glow at the band's foot and settle to a fine screen away from it.
|
|
11
|
+
* `aurora` — Curtains of the brand's light rising from the band's foot and swaying slowly.
|
|
12
|
+
* `mesh` — The band in the brand's reds folded into one another like a liquid — the loudest of the five, for a dark band.
|
|
13
|
+
* `grid` — Hairlines a pitch apart rising from a soft bloom at the band's foot — the quietest, and the one to reach for first.
|
|
14
|
+
* `rings` — Hairline circles spreading out from the middle of the band's foot.
|
|
15
|
+
*/
|
|
16
|
+
background?: 'halftone' | 'aurora' | 'mesh' | 'grid' | 'rings';
|
|
9
17
|
/** Always. What the cards are, in the fewest words that name them — "Why trade with Deriv", "Markets you can trade". */
|
|
10
18
|
title: string;
|
|
11
19
|
/** A line saying what the set has in common, when the title alone does not. */
|
|
@@ -217,10 +217,10 @@
|
|
|
217
217
|
/*
|
|
218
218
|
* And a dark card is lifted a step in dark mode.
|
|
219
219
|
*
|
|
220
|
-
* accent-strong is
|
|
220
|
+
* accent-strong is slate.900, and in dark mode the subtle band is a white tint over near-black that
|
|
221
221
|
* lands within a shade of it — the card blended into the band the way the light card did in light
|
|
222
|
-
* mode. color.bg.surface-card-strong-raised is the same
|
|
223
|
-
* already stands off the band, and
|
|
222
|
+
* mode. color.bg.surface-card-strong-raised is the same slate.900 in light, where the dark card
|
|
223
|
+
* already stands off the band, and slate.800 in dark, a step up so it lifts off it. The ink is
|
|
224
224
|
* unchanged: white on either.
|
|
225
225
|
*/
|
|
226
226
|
:where([data-dds-context="marketing"])
|
|
@@ -230,6 +230,18 @@
|
|
|
230
230
|
background-color: var(--color-bg-surface-card-strong-raised);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/*
|
|
234
|
+
* On the strong band the dark card is lifted a step too. accent-strong paints the band's own
|
|
235
|
+
* slate.900, so on color.bg.brand-strong it was the band with a corner; it takes
|
|
236
|
+
* color.bg.surface-card-strong-on-brand-strong, a step lighter, in both modes.
|
|
237
|
+
*/
|
|
238
|
+
:where([data-dds-context="marketing"])
|
|
239
|
+
.dds-featurecards[data-ground="strong"]
|
|
240
|
+
.dds-featurecards__item
|
|
241
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="accent-strong"] {
|
|
242
|
+
background-color: var(--color-bg-surface-card-strong-on-brand-strong);
|
|
243
|
+
}
|
|
244
|
+
|
|
233
245
|
/*
|
|
234
246
|
* And a plain card is raised off it.
|
|
235
247
|
*
|
|
@@ -2,7 +2,7 @@ import type { ReactNode } from 'react';
|
|
|
2
2
|
export interface FeatureCardsCarouselOwnProps {
|
|
3
3
|
/**
|
|
4
4
|
* `page` — The default, and the page's own white. A section that has nothing to separate itself from what is above it — most of them — and the ground a reader is already on
|
|
5
|
-
* `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice. The one to reach for first when two sections need telling apart. A light card — surface-light — turns white on it, color.bg.surface-card-light-raised, because its own gray.50 is the band's and would vanish into it. A dark card — accent-strong — is lifted to color.bg.surface-card-strong-raised, a step lighter in dark mode, where the band is within a shade of its
|
|
5
|
+
* `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice. The one to reach for first when two sections need telling apart. A light card — surface-light — turns white on it, color.bg.surface-card-light-raised, because its own gray.50 is the band's and would vanish into it. A dark card — accent-strong — is lifted to color.bg.surface-card-strong-raised, a step lighter in dark mode, where the band is within a shade of its slate.900. A plain surface card is raised off it the same way, to color.bg.surface-card-raised, because the recessed fill is the band's gray too. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section — in dark mode the tint alone took on whatever it was set against, and on a light surface it was light ink on white.
|
|
6
6
|
* `strong` — `color.bg.brand-strong`, the dark band. It stops the page rather than dividing it, so it is for a section a reader should arrive at — and one per page is usually one more than enough. The coloured cards keep their own grounds on it; a neutral card — surface or surface-raised — turns to Card's inverse fill and white ink, and a plain card takes the white ink alone, because their own would be dark ink on near-black; an eyebrow inside any of them takes the band's quieter ink
|
|
7
7
|
*/
|
|
8
8
|
ground?: 'page' | 'subtle' | 'strong';
|
|
@@ -160,6 +160,18 @@
|
|
|
160
160
|
background-color: var(--color-bg-surface-card-strong-raised);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/*
|
|
164
|
+
* On the strong band the dark card is lifted a step too. accent-strong paints the band's own
|
|
165
|
+
* slate.900, so on color.bg.brand-strong it was the band with a corner; it takes
|
|
166
|
+
* color.bg.surface-card-strong-on-brand-strong, a step lighter, in both modes.
|
|
167
|
+
*/
|
|
168
|
+
:where([data-dds-context="marketing"])
|
|
169
|
+
.dds-featurecardscarousel[data-ground="strong"]
|
|
170
|
+
.dds-featurecardscarousel__item
|
|
171
|
+
> :is(.dds-card, .dds-cardbutton)[data-variant="accent-strong"] {
|
|
172
|
+
background-color: var(--color-bg-surface-card-strong-on-brand-strong);
|
|
173
|
+
}
|
|
174
|
+
|
|
163
175
|
:where([data-dds-context="marketing"])
|
|
164
176
|
.dds-featurecardscarousel[data-ground="subtle"]
|
|
165
177
|
.dds-featurecardscarousel__item
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* GENERATED from featuretabs.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
display: flex;
|
|
7
|
+
inline-size: 100%;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
overflow-wrap: anywhere;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__inner {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
inline-size: 100%;
|
|
17
|
+
min-inline-size: 0;
|
|
18
|
+
max-inline-size: var(--size-content-max);
|
|
19
|
+
padding-block: var(--space-section-default);
|
|
20
|
+
padding-inline: var(--space-inset-page);
|
|
21
|
+
row-gap: var(--space-heading-content);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__header {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
min-inline-size: 0;
|
|
28
|
+
row-gap: var(--space-heading-title-description);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__title {
|
|
32
|
+
margin-block: 0;
|
|
33
|
+
text-wrap: balance;
|
|
34
|
+
font-family: var(--font-h2-family);
|
|
35
|
+
font-size: var(--font-h2-size);
|
|
36
|
+
font-weight: var(--font-h2-weight);
|
|
37
|
+
letter-spacing: var(--font-h2-letter-spacing);
|
|
38
|
+
line-height: var(--font-h2-line-height);
|
|
39
|
+
max-inline-size: var(--size-measure-heading);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__description {
|
|
43
|
+
margin-block: 0;
|
|
44
|
+
font-family: var(--font-body-md-family);
|
|
45
|
+
font-size: var(--font-body-md-size);
|
|
46
|
+
font-weight: var(--font-body-md-weight);
|
|
47
|
+
letter-spacing: var(--font-body-md-letter-spacing);
|
|
48
|
+
line-height: var(--font-body-md-line-height);
|
|
49
|
+
max-inline-size: var(--size-measure-description);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__tabs {
|
|
53
|
+
display: flex;
|
|
54
|
+
max-inline-size: 100%;
|
|
55
|
+
min-inline-size: 0;
|
|
56
|
+
margin-block-start: var(--space-heading-description-actions);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__panel {
|
|
60
|
+
min-inline-size: 0;
|
|
61
|
+
row-gap: var(--space-gap-none);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__footnote {
|
|
65
|
+
margin-block: 0;
|
|
66
|
+
font-family: var(--font-body-sm-family);
|
|
67
|
+
font-size: var(--font-body-sm-size);
|
|
68
|
+
font-weight: var(--font-body-sm-weight);
|
|
69
|
+
letter-spacing: var(--font-body-sm-letter-spacing);
|
|
70
|
+
line-height: var(--font-body-sm-line-height);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="page"] {
|
|
74
|
+
background-color: var(--color-bg-page);
|
|
75
|
+
color: var(--color-fg-default);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="page"] .dds-featuretabs__footnote {
|
|
79
|
+
color: var(--color-fg-muted);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] {
|
|
83
|
+
background-color: var(--color-bg-brand-strong);
|
|
84
|
+
color: var(--color-fg-on-brand-strong);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-featuretabs__footnote {
|
|
88
|
+
color: var(--color-fg-muted-inverse);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="subtle"] {
|
|
92
|
+
background-color: var(--color-bg-page);
|
|
93
|
+
background-image: linear-gradient(var(--color-bg-band-subtle), var(--color-bg-band-subtle));
|
|
94
|
+
color: var(--color-fg-default);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="subtle"] .dds-featuretabs__footnote {
|
|
98
|
+
color: var(--color-fg-muted);
|
|
99
|
+
}
|
|
100
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import './FeatureTabs.css';
|
|
3
|
+
import './feature-tabs-impl.css';
|
|
4
|
+
import '../block-reveal.css';
|
|
5
|
+
import { type FeatureTabsProps } from './FeatureTabs.types.js';
|
|
6
|
+
export type { FeatureTabsProps };
|
|
7
|
+
/**
|
|
8
|
+
* Versions of one thing, one at a time — the reference design's OptionsTypes, made general.
|
|
9
|
+
*
|
|
10
|
+
* The section owns what the versions share — the heading, the tab strip and which tab is showing —
|
|
11
|
+
* and the page composes what each tab shows, one child per name in `labels`. A name without a child
|
|
12
|
+
* is not drawn, and neither is a child without a name. Two or more tabs get the strip; one is drawn
|
|
13
|
+
* with nothing to choose.
|
|
14
|
+
*
|
|
15
|
+
* Only the tab showing is in the page, so a picture playing in one stops when the reader turns to
|
|
16
|
+
* another — the reference stops its animations by hand, and an unmounted one has nothing to stop.
|
|
17
|
+
*
|
|
18
|
+
* It arrives the way every block does: the heading, its line, the tabs, then the content.
|
|
19
|
+
* `'use client'` for that, the selected tab, and `useId`, which names the region by its heading.
|
|
20
|
+
*/
|
|
21
|
+
export declare function FeatureTabs({ ground, title, description, labels, footnote, children, }: FeatureTabsProps & {
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Children, useId, useState } from 'react';
|
|
4
|
+
import './FeatureTabs.css';
|
|
5
|
+
import './feature-tabs-impl.css';
|
|
6
|
+
import '../block-reveal.css';
|
|
7
|
+
import { Tab } from '../../core/tab/Tab.js';
|
|
8
|
+
import { TabList } from '../../core/tab-list/TabList.js';
|
|
9
|
+
import { given } from '../../given.js';
|
|
10
|
+
import { arriving, useReveal } from '../use-reveal.js';
|
|
11
|
+
import { featureTabsDefaults, featureTabsParts } from './FeatureTabs.types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Versions of one thing, one at a time — the reference design's OptionsTypes, made general.
|
|
14
|
+
*
|
|
15
|
+
* The section owns what the versions share — the heading, the tab strip and which tab is showing —
|
|
16
|
+
* and the page composes what each tab shows, one child per name in `labels`. A name without a child
|
|
17
|
+
* is not drawn, and neither is a child without a name. Two or more tabs get the strip; one is drawn
|
|
18
|
+
* with nothing to choose.
|
|
19
|
+
*
|
|
20
|
+
* Only the tab showing is in the page, so a picture playing in one stops when the reader turns to
|
|
21
|
+
* another — the reference stops its animations by hand, and an unmounted one has nothing to stop.
|
|
22
|
+
*
|
|
23
|
+
* It arrives the way every block does: the heading, its line, the tabs, then the content.
|
|
24
|
+
* `'use client'` for that, the selected tab, and `useId`, which names the region by its heading.
|
|
25
|
+
*/
|
|
26
|
+
export function FeatureTabs({ ground = featureTabsDefaults.ground, title, description, labels, footnote, children, }) {
|
|
27
|
+
const titleId = useId();
|
|
28
|
+
const [band, revealed] = useReveal();
|
|
29
|
+
// The selected tab by its name rather than its place, so a list of names that changes under it
|
|
30
|
+
// keeps the reader on the same tab where it is still there, and goes to the first where it is not.
|
|
31
|
+
const [selected, setSelected] = useState(null);
|
|
32
|
+
// A record from a feed or an editor is not typed, so the names are checked rather than trusted.
|
|
33
|
+
const names = Array.isArray(labels) ? labels : [];
|
|
34
|
+
const panels = Children.toArray(children);
|
|
35
|
+
const count = Math.min(names.length, panels.length);
|
|
36
|
+
const at = Math.max(0, selected === null ? 0 : names.slice(0, count).indexOf(selected));
|
|
37
|
+
return (_jsx("section", { className: featureTabsParts.root, "data-ground": ground, "aria-labelledby": titleId, children: _jsxs("div", { className: featureTabsParts.inner, ref: band, "data-revealed": revealed, children: [_jsxs("div", { className: featureTabsParts.header, children: [_jsx("h2", { className: featureTabsParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: featureTabsParts.description, ...arriving(1), children: description })) : null, _jsx("div", { className: featureTabsParts.tabs, ...arriving(2), children: count > 1 ? (_jsx(TabList, { label: title, value: String(at), onChange: (value) => setSelected(names[Number(value)] ?? null), children: names.slice(0, count).map((name, index) => (_jsx(Tab, { value: String(index), label: name }, index))) })) : null })] }), _jsx("div", { className: featureTabsParts.panel, ...arriving(3), children: count > 0 ? panels[at] : null }), given(footnote) ? (_jsx("p", { className: featureTabsParts.footnote, ...arriving(4), children: footnote })) : null] }) }));
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface FeatureTabsOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `page` — The default, and the page's own white. A section that has nothing to separate itself from what is above it — most of them — and the ground a reader is already on
|
|
5
|
+
* `subtle` — A quiet step off the page, for a band that wants to read as its own section without changing the page's voice — the reference design's slate FAQ. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section.
|
|
6
|
+
* `strong` — `color.bg.brand-strong`, the dark band. It stops the page rather than dividing it, so it is for a section a reader should arrive at — and one per page is usually one more than enough. The tab strip turns round with it: white names, a rule in the band's own veil and a focus ring drawn for the dark, fixed like the band
|
|
7
|
+
*/
|
|
8
|
+
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
+
/** Always. What the versions are of, in a few words — "Types of digital options". It names the section and the tabs */
|
|
10
|
+
title: string;
|
|
11
|
+
/** A line under the heading saying what the tabs have in common */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Always. The tabs' names, in a word or two each, in the order of the children they choose between — the first names the first child. A name without a child is not drawn */
|
|
14
|
+
labels: string[];
|
|
15
|
+
/** Small print every tab shares — that what is offered varies by platform or device */
|
|
16
|
+
footnote?: string;
|
|
17
|
+
/** Allowed: any content */
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
export type FeatureTabsProps = FeatureTabsOwnProps;
|
|
21
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
22
|
+
export declare const featureTabsParts: {
|
|
23
|
+
readonly root: "dds-featuretabs";
|
|
24
|
+
readonly inner: "dds-featuretabs__inner";
|
|
25
|
+
readonly header: "dds-featuretabs__header";
|
|
26
|
+
readonly title: "dds-featuretabs__title";
|
|
27
|
+
readonly description: "dds-featuretabs__description";
|
|
28
|
+
readonly tabs: "dds-featuretabs__tabs";
|
|
29
|
+
readonly panel: "dds-featuretabs__panel";
|
|
30
|
+
readonly footnote: "dds-featuretabs__footnote";
|
|
31
|
+
};
|
|
32
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
33
|
+
export declare const featureTabsDefaults: {
|
|
34
|
+
readonly ground: "page";
|
|
35
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// GENERATED from feature-tabs.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const featureTabsParts = {
|
|
4
|
+
root: 'dds-featuretabs',
|
|
5
|
+
inner: 'dds-featuretabs__inner',
|
|
6
|
+
header: 'dds-featuretabs__header',
|
|
7
|
+
title: 'dds-featuretabs__title',
|
|
8
|
+
description: 'dds-featuretabs__description',
|
|
9
|
+
tabs: 'dds-featuretabs__tabs',
|
|
10
|
+
panel: 'dds-featuretabs__panel',
|
|
11
|
+
footnote: 'dds-featuretabs__footnote',
|
|
12
|
+
};
|
|
13
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
14
|
+
export const featureTabsDefaults = { ground: 'page' };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* The heading, the tabs and the footnote start on a phone, as every block's heading does there, and
|
|
5
|
+
* are centred from 48rem over the content they choose — Documents' and FaqAccordion's rule. `48rem`
|
|
6
|
+
* longhand because `var()` is not permitted in a container query condition.
|
|
7
|
+
*/
|
|
8
|
+
@container (min-width: 48rem) {
|
|
9
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__header {
|
|
10
|
+
align-items: center;
|
|
11
|
+
text-align: center;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__tabs {
|
|
15
|
+
justify-content: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__footnote {
|
|
19
|
+
text-align: center;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* A lone tab has no strip, and the strip it would have held is not left as a step in the
|
|
25
|
+
* header's rhythm: an empty part with a margin is a gap with nothing in it.
|
|
26
|
+
*/
|
|
27
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs .dds-featuretabs__tabs:empty {
|
|
28
|
+
display: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* On the strong band the tab strip takes the band's inks, as Documents' accordion does: TabList is
|
|
33
|
+
* drawn for a light ground, so a selected tab's near-black text would vanish on the dark one.
|
|
34
|
+
*/
|
|
35
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-tablist {
|
|
36
|
+
border-color: var(--color-border-subtle-inverse);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-tab[data-selected="true"] :is(.dds-tab__label, .dds-tab__icon, .dds-tab__trailing-icon) {
|
|
40
|
+
color: var(--color-fg-on-brand-strong);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-tab[data-selected="false"] :is(.dds-tab__label, .dds-tab__icon, .dds-tab__trailing-icon) {
|
|
44
|
+
color: var(--color-fg-muted-inverse);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-tab .dds-tab__surface:hover {
|
|
48
|
+
background-color: var(--color-bg-hover-on-brand-strong);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:where([data-dds-context="marketing"]) .dds-featuretabs[data-ground="strong"] .dds-tab:focus-visible {
|
|
52
|
+
outline-color: var(--color-border-focus-on-brand-strong);
|
|
53
|
+
}
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
:where([data-dds-context="marketing"]) .dds-imagebanner[data-ground="strong"] .dds-imagebanner__card {
|
|
99
|
-
background-color: var(--color-bg-surface-card-strong);
|
|
99
|
+
background-color: var(--color-bg-surface-card-strong-on-brand-strong);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
:where([data-dds-context="marketing"]) .dds-imagebanner[data-ground="subtle"] {
|
|
@@ -30,4 +30,4 @@ export type { ImageBannerProps };
|
|
|
30
30
|
* the photograph after them. A cover photograph is the card's ground rather than a part of what it
|
|
31
31
|
* says, so it is there from the start and only the words arrive over it.
|
|
32
32
|
*/
|
|
33
|
-
export declare function ImageBanner({ ground, variant, mediaPosition, parallax, title, headingLevel, description, action, media, }: ImageBannerProps): import("react").JSX.Element;
|
|
33
|
+
export declare function ImageBanner({ ground, variant, mediaPosition, parallax, stackOnPhone, title, headingLevel, description, action, media, }: ImageBannerProps): import("react").JSX.Element;
|
|
@@ -34,9 +34,9 @@ import { imageBannerDefaults, imageBannerParts } from './ImageBanner.types.js';
|
|
|
34
34
|
* the photograph after them. A cover photograph is the card's ground rather than a part of what it
|
|
35
35
|
* says, so it is there from the start and only the words arrive over it.
|
|
36
36
|
*/
|
|
37
|
-
export function ImageBanner({ ground = imageBannerDefaults.ground, variant = imageBannerDefaults.variant, mediaPosition = imageBannerDefaults.mediaPosition, parallax = imageBannerDefaults.parallax, title, headingLevel = imageBannerDefaults.headingLevel, description, action, media, }) {
|
|
37
|
+
export function ImageBanner({ ground = imageBannerDefaults.ground, variant = imageBannerDefaults.variant, mediaPosition = imageBannerDefaults.mediaPosition, parallax = imageBannerDefaults.parallax, stackOnPhone = imageBannerDefaults.stackOnPhone, title, headingLevel = imageBannerDefaults.headingLevel, description, action, media, }) {
|
|
38
38
|
const titleId = useId();
|
|
39
39
|
const Title = headingLevel;
|
|
40
40
|
const [band, revealed] = useReveal();
|
|
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
|
+
return (_jsx("section", { className: imageBannerParts.root, "data-ground": ground, "data-variant": variant, "data-media-position": mediaPosition, "data-parallax": parallax, "data-stack-on-phone": variant === 'cover' && stackOnPhone ? '' : undefined, "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 })] }) }) }));
|
|
42
42
|
}
|
|
@@ -3,14 +3,9 @@ export interface ImageBannerOwnProps {
|
|
|
3
3
|
/**
|
|
4
4
|
* `page` — The default, and the page's own white, with the dark card set into it. Most of the time: the card is already the break
|
|
5
5
|
* `subtle` — The grey band, for a card that follows a white section the page wants told apart from this one. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section
|
|
6
|
-
* `strong` — `color.bg.brand-strong`, the dark band, with the card a step lighter at color.bg.surface-card-strong so it still reads as a card. For a page whose dark band is already here and wants the card inside it
|
|
6
|
+
* `strong` — `color.bg.brand-strong`, the dark band, with the card a step lighter at color.bg.surface-card-strong-on-brand-strong so it still reads as a card. For a page whose dark band is already here and wants the card inside it
|
|
7
7
|
*/
|
|
8
8
|
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
-
/**
|
|
10
|
-
* `split` — The default. The words in one half and the photograph filling the other, edge to edge, with one action under the words. On a phone the card runs the width of the screen and the photograph stacks with the words
|
|
11
|
-
* `cover` — The photograph fills the whole card, with the words over it behind a scrim that darkens the side they are on and leaves the photograph clear on the other. For a photograph wide enough to be the band rather than half of it
|
|
12
|
-
*/
|
|
13
|
-
variant?: 'split' | 'cover';
|
|
14
9
|
/**
|
|
15
10
|
* `end` — The default. The words lead and the photograph follows, which is the order the card argues in
|
|
16
11
|
* `start` — The photograph leads — the second of two cards on a page, or a photograph whose subject faces the words. A split card puts it above the words on a phone as well, as the reference design does
|
|
@@ -32,7 +27,13 @@ export interface ImageBannerOwnProps {
|
|
|
32
27
|
/** 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
28
|
parallax?: boolean;
|
|
34
29
|
}
|
|
35
|
-
export type ImageBannerProps = ImageBannerOwnProps
|
|
30
|
+
export type ImageBannerProps = ImageBannerOwnProps & ({
|
|
31
|
+
variant?: 'split' | 'cover';
|
|
32
|
+
stackOnPhone?: false;
|
|
33
|
+
} | {
|
|
34
|
+
variant: Exclude<'split' | 'cover', 'split'>;
|
|
35
|
+
stackOnPhone?: boolean;
|
|
36
|
+
});
|
|
36
37
|
/** The class each part carries. Apply these — do not retype them. */
|
|
37
38
|
export declare const imageBannerParts: {
|
|
38
39
|
readonly root: "dds-imagebanner";
|
|
@@ -51,4 +52,5 @@ export declare const imageBannerDefaults: {
|
|
|
51
52
|
readonly mediaPosition: "end";
|
|
52
53
|
readonly headingLevel: "h2";
|
|
53
54
|
readonly parallax: true;
|
|
55
|
+
readonly stackOnPhone: false;
|
|
54
56
|
};
|
|
@@ -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: true };
|
|
14
|
+
export const imageBannerDefaults = { ground: 'page', variant: 'split', mediaPosition: 'end', headingLevel: 'h2', parallax: true, stackOnPhone: false };
|
|
@@ -173,54 +173,105 @@
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
/*
|
|
176
|
-
* The
|
|
176
|
+
* The shade under a cover card's words: their column, and just past it.
|
|
177
177
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* across
|
|
178
|
+
* White body copy has to keep AA over even a pale photograph, so the words' column is
|
|
179
|
+
* color.bg.overlay at full strength — darkest only at the words' edge was tried and left the end of a
|
|
180
|
+
* line at about 2:1. But the shade is the words', not the photograph's: it is drawn by the column the
|
|
181
|
+
* words take and fades to clear across the column's own margin and space.section.default past its
|
|
182
|
+
* edge — a long fade, so it never reads as an edge on the photograph — and the rest of the
|
|
183
|
+
* photograph is shown as it was taken. It once held across three fifths of the card and then thinned
|
|
184
|
+
* out to the far edge, which turned a bright photograph slate grey nearly all the way across; on a
|
|
185
|
+
* phone it ran down three fifths of the card's height however short the words were.
|
|
185
186
|
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
187
|
+
* Under the words inside their own stacking context — the column is lifted over the photograph — so
|
|
188
|
+
* it is always behind them and always over the photograph. Toward the photograph: across from the
|
|
189
|
+
* fold, mirrored for a photograph at the start and under `:dir(rtl)`, and downward on a phone, where
|
|
190
|
+
* the words are at the top across the whole width. A gradient takes a physical direction — there is
|
|
191
|
+
* no `to inline-end` — so the direction is a custom property set once per case, the package's rule for
|
|
192
|
+
* a pattern that must follow the reading direction.
|
|
191
193
|
*
|
|
192
194
|
* The words need no rule to change sides: the photograph is out of flow behind them, so the row
|
|
193
195
|
* `mediaPosition` sets holds the words alone, at the start or, reversed, at the end.
|
|
194
196
|
*/
|
|
195
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"] .dds-
|
|
197
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"] .dds-imagebanner__content {
|
|
198
|
+
--dds-imagebanner-shade-fade: var(--space-section-default);
|
|
199
|
+
/* The column's own inset, which the words end inside: space.inset.card, and space.inset.2xl from
|
|
200
|
+
64rem, where the column is given more room. The shade holds full strength to there. */
|
|
201
|
+
--dds-imagebanner-words-inset: var(--space-inset-card);
|
|
202
|
+
position: relative;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@container (min-width: 64rem) {
|
|
206
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"] .dds-imagebanner__content {
|
|
207
|
+
--dds-imagebanner-words-inset: var(--space-inset-2xl);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"] .dds-imagebanner__content::before {
|
|
196
212
|
background-image: linear-gradient(
|
|
197
|
-
var(--dds-imagebanner-
|
|
213
|
+
var(--dds-imagebanner-shade-toward, to bottom),
|
|
198
214
|
var(--color-bg-overlay),
|
|
199
|
-
var(--color-bg-overlay)
|
|
200
|
-
var(--color-bg-overlay-subtle) 80%,
|
|
215
|
+
var(--color-bg-overlay) calc(100% - var(--dds-imagebanner-shade-fade) - var(--dds-imagebanner-words-inset)),
|
|
201
216
|
transparent
|
|
202
217
|
);
|
|
203
218
|
content: '';
|
|
204
|
-
inset: 0;
|
|
219
|
+
inset: 0 0 calc(-1 * var(--dds-imagebanner-shade-fade));
|
|
205
220
|
pointer-events: none;
|
|
206
221
|
position: absolute;
|
|
222
|
+
z-index: -1;
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
@container (min-width: 48rem) {
|
|
210
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"]
|
|
211
|
-
|
|
226
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"] .dds-imagebanner__content::before {
|
|
227
|
+
inset-block-end: 0;
|
|
228
|
+
inset-inline-end: calc(-1 * var(--dds-imagebanner-shade-fade));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-media-position="start"] .dds-imagebanner__content::before {
|
|
232
|
+
inset-inline-end: 0;
|
|
233
|
+
inset-inline-start: calc(-1 * var(--dds-imagebanner-shade-fade));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-media-position="end"] .dds-imagebanner__content {
|
|
237
|
+
--dds-imagebanner-shade-toward: to right;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-media-position="start"] .dds-imagebanner__content {
|
|
241
|
+
--dds-imagebanner-shade-toward: to left;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-media-position="end"]:dir(rtl) .dds-imagebanner__content {
|
|
245
|
+
--dds-imagebanner-shade-toward: to left;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-media-position="start"]:dir(rtl) .dds-imagebanner__content {
|
|
249
|
+
--dds-imagebanner-shade-toward: to right;
|
|
212
250
|
}
|
|
251
|
+
}
|
|
213
252
|
|
|
214
|
-
|
|
215
|
-
|
|
253
|
+
/*
|
|
254
|
+
* `stackOnPhone`: below the fold the cover card stacks, as a split card does.
|
|
255
|
+
*
|
|
256
|
+
* A cover photograph is cropped to a 2.53:1 strip on a desktop and a near-square on a phone, both
|
|
257
|
+
* held to the photograph's side, and the two crops share only a third of it — so a person framed for
|
|
258
|
+
* the strip loses their head on the phone, or stands under the words. Stacked, the words stand on the
|
|
259
|
+
* card's own dark ground and need no shade, and the photograph follows them whole at the landscape
|
|
260
|
+
* shape, in flow rather than behind. From the fold it is the cover card again.
|
|
261
|
+
*/
|
|
262
|
+
@container (max-width: 47.9375rem) {
|
|
263
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-stack-on-phone] .dds-imagebanner__card {
|
|
264
|
+
min-block-size: 0;
|
|
216
265
|
}
|
|
217
266
|
|
|
218
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-
|
|
219
|
-
|
|
267
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-stack-on-phone] .dds-imagebanner__media {
|
|
268
|
+
aspect-ratio: var(--aspect-landscape);
|
|
269
|
+
inset: auto;
|
|
270
|
+
position: relative;
|
|
220
271
|
}
|
|
221
272
|
|
|
222
|
-
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-
|
|
223
|
-
|
|
273
|
+
:where([data-dds-context="marketing"]) .dds-imagebanner[data-variant="cover"][data-stack-on-phone] .dds-imagebanner__content::before {
|
|
274
|
+
content: none;
|
|
224
275
|
}
|
|
225
276
|
}
|
|
226
277
|
|