@deriv-com/dds-marketing 1.0.1 → 1.0.2
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/background.md +371 -0
- package/.llm/components/ctabanner.md +25 -0
- package/.llm/components/ctabannerslider.md +21 -0
- package/.llm/components/illustrationcard.md +236 -0
- package/.llm/components/illustrationscene.md +233 -0
- package/.llm/components/landinghero.md +24 -0
- package/.llm/components/pageheader.md +21 -0
- package/.llm/digest/background.md +52 -0
- package/.llm/digest/ctabanner.md +4 -0
- package/.llm/digest/ctabannerslider.md +3 -0
- package/.llm/digest/illustrationcard.md +46 -0
- package/.llm/digest/illustrationscene.md +51 -0
- package/.llm/digest/landinghero.md +7 -0
- package/.llm/digest/pageheader.md +3 -0
- package/.llm/index.md +7 -0
- package/.llm/tokens.md +11 -0
- package/AGENTS.md +3 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +1 -1
- package/dist/components/blocks/cta-banner/CtaBanner.js +3 -2
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +5 -0
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +8 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +1 -1
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +5 -4
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +4 -0
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +8 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +1 -1
- package/dist/components/blocks/landing-hero/LandingHero.js +4 -3
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +7 -3
- package/dist/components/blocks/page-header/PageHeader.d.ts +1 -1
- package/dist/components/blocks/page-header/PageHeader.js +3 -2
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +4 -0
- package/dist/components/blocks/page-header/page-header-impl.css +8 -0
- package/dist/components/core/background/Background.css +69 -0
- package/dist/components/core/background/Background.d.ts +21 -0
- package/dist/components/core/background/Background.js +36 -0
- package/dist/components/core/background/Background.types.d.ts +36 -0
- package/dist/components/core/background/Background.types.js +9 -0
- package/dist/components/core/background/background-impl.css +427 -0
- package/dist/components/core/background/halftone.d.ts +123 -0
- package/dist/components/core/background/halftone.js +682 -0
- package/dist/components/core/background/use-halftone.d.ts +15 -0
- package/dist/components/core/background/use-halftone.js +27 -0
- package/dist/components/core/background/use-offscreen.d.ts +10 -0
- package/dist/components/core/background/use-offscreen.js +30 -0
- package/dist/components/core/background/use-spotlight.d.ts +13 -0
- package/dist/components/core/background/use-spotlight.js +65 -0
- package/dist/components/core/illustration-card/IllustrationCard.css +40 -0
- package/dist/components/core/illustration-card/IllustrationCard.d.ts +22 -0
- package/dist/components/core/illustration-card/IllustrationCard.js +82 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.d.ts +23 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.js +8 -0
- package/dist/components/core/illustration-card/illustration-card-impl.css +27 -0
- package/dist/components/core/illustration-scene/IllustrationScene.css +44 -0
- package/dist/components/core/illustration-scene/IllustrationScene.d.ts +14 -0
- package/dist/components/core/illustration-scene/IllustrationScene.js +16 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +33 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.js +8 -0
- package/dist/components/core/illustration-scene/illustration-scene-impl.css +40 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +6 -0
- package/dist/marketing.css +24 -0
- package/package.json +1 -1
package/.llm/digest/ctabanner.md
CHANGED
|
@@ -33,6 +33,10 @@ A full-bleed coral band carrying one short promotion and the action it asks for
|
|
|
33
33
|
- never: A paragraph. A banner is read at a glance, on the way down a page; copy a reader has to work through is copy they scroll past
|
|
34
34
|
- **actions** `node` · optional — The one action the message asks for, or two at most. …
|
|
35
35
|
- never: A third action, or a primary Button: coral on the coral ground is a button nobody can see
|
|
36
|
+
- **background** `enum` · optional — The band is the page's one standout moment and wants more than a flat fill. Leave it out and the band is its flat ground, as it always was
|
|
37
|
+
- `halftone` — A halftone drawn behind the band's content: white dots on the band's own coral, following the pointer over the band. …
|
|
38
|
+
- `grid` — A fine rule grid behind the band's content: white hairlines on the coral, fading in towards the foot, brightening in a soft circle around the pointer. …
|
|
39
|
+
- never: More than one band on a page. The pattern is what makes a band the one a reader remembers, and two of them make neither
|
|
36
40
|
|
|
37
41
|
## Inside it
|
|
38
42
|
|
|
@@ -34,6 +34,9 @@ CtaBanner's layout with a slider in it: the same full-bleed coral band, rotating
|
|
|
34
34
|
- **label** `string` · default "Promotions" — The name the banner is announced by — a region a screen reader can jump to and skip. Name what it holds, not that it is a banner: 'Promotions', 'Offers'. Translate it with the page
|
|
35
35
|
- **controlsLabel** `string` · default "Slides" — The name the dots are announced by, as a group inside the banner. Its own name rather than the banner's, so a screen reader moving into the dots hears what they are rather than 'Promotions' a second time. …
|
|
36
36
|
- **slideLabel** `string` · default "Slide" — The word each dot is announced by, before its number — 'Slide 2'. Translate it with the page, as controlsLabel is; a page that translates only the group's name still has every dot announced in English
|
|
37
|
+
- **background** `enum` · optional — The band is the page's one standout promotion and wants more than a flat fill. Leave it out and the band is its flat coral, as it always was
|
|
38
|
+
- `grid` — A fine rule grid behind the slides: white hairlines on the coral, fading in towards the foot, brightening in a soft circle around the pointer. …
|
|
39
|
+
- never: More than one patterned band on a page. The pattern is what makes a band the one a reader remembers, and two of them make neither
|
|
37
40
|
|
|
38
41
|
## Inside it
|
|
39
42
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!-- GENERATED from illustrationcard.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# IllustrationCard
|
|
4
|
+
|
|
5
|
+
A pane of glass holding a piece of product information — a market's price, a balance, a status — in one of three shapes, used as a picture: laid over a photograph or a piece of art, or standing on its own as the image a section shows beside its words. …
|
|
6
|
+
|
|
7
|
+
`import { IllustrationCard } from '@deriv-com/dds-marketing'`
|
|
8
|
+
|
|
9
|
+
## Reach for it when
|
|
10
|
+
|
|
11
|
+
- Product information laid over a photograph or a piece of art — a market's price and status over a picture of a trader, a balance over a device
|
|
12
|
+
- A standalone image of the product beside a section's words, where a screenshot would be too literal: the pane is the picture the section shows
|
|
13
|
+
- Several such pictures across a site that have to agree in shape and surface without each page deciding
|
|
14
|
+
|
|
15
|
+
## Something else, when
|
|
16
|
+
|
|
17
|
+
- A section has content to present — features, benefits, steps, a list → **FeatureCards**
|
|
18
|
+
- The content is something a reader acts on — a link, a form, a set of options → **Card**
|
|
19
|
+
- There is only a photograph → **AspectRatio**
|
|
20
|
+
|
|
21
|
+
## Never
|
|
22
|
+
|
|
23
|
+
- A section's content. Headings, descriptions, features and lists belong in the section's own blocks and type; a pane of them reads as a picture, and a reader skims past what the page meant them to read
|
|
24
|
+
- A container for anything other than product information — a quote, a call to action, a form, navigation. It is an illustration of the product and nothing else
|
|
25
|
+
- Live readings presented as a picture. What the pane shows is illustrative — a price, a status drawn to explain — and a reader takes a number in it at face value; anything relied on belongs in the page's text
|
|
26
|
+
- Any other shape. The three ratios are the whole of the choice, so every picture on a site agrees; one that needed a fourth is a different component
|
|
27
|
+
- A real interface a reader is meant to operate. The pane makes everything in it inert — a button in it is a picture of a button — so anything a reader must press belongs outside it, in the section's own actions
|
|
28
|
+
|
|
29
|
+
## Props
|
|
30
|
+
|
|
31
|
+
- **ratio** `enum` · default "landscape" — The panel's shape. One of three, so panels across a site agree
|
|
32
|
+
- `landscape` — Four by three, and the default. For a panel beside words in a wide section
|
|
33
|
+
- `square` — One by one. For a grid of panels, or a column no wider than it is tall
|
|
34
|
+
- `upright` — Three by four. For a phone, or a narrow column beside a tall run of words
|
|
35
|
+
- never: Fitting a particular piece of UI. The shape is a decision about the layout; the UI is laid out for it
|
|
36
|
+
- **label** `string` · required — Always. What the picture shows, in a sentence — "Trade ticket: buy Gold to rise over 5 minutes, staking 10 USD". The pane is one image to assistive technology and this is its whole description; nothing inside it is read out on its own
|
|
37
|
+
- never: A title or a caption the page shows. It is never drawn; a heading the reader sees belongs to the section beside the picture
|
|
38
|
+
|
|
39
|
+
## Inside it
|
|
40
|
+
|
|
41
|
+
- 2 components are refused inside it; the list and the reasons are in the long document.
|
|
42
|
+
- Renders 2 parts: root, content.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
The reasoning behind each of these, the parts this renders, its states and snippets that compile: `.llm/components/illustrationcard.md`.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!-- GENERATED from illustrationscene.contract.json. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# IllustrationScene
|
|
4
|
+
|
|
5
|
+
A photograph with an IllustrationCard laid over it — the product shown in the hands of the people who use it: a trade ticket over a trader on the move, a balance over someone at a desk. …
|
|
6
|
+
|
|
7
|
+
`import { IllustrationScene } from '@deriv-com/dds-marketing'`
|
|
8
|
+
|
|
9
|
+
## Reach for it when
|
|
10
|
+
|
|
11
|
+
- Product information shown over a photograph — a trade ticket, a balance, a market's status — where the photograph sets the scene and the card says what the product does …
|
|
12
|
+
- A hero or a feature section needs a picture of the product in use rather than a screenshot or a photograph alone
|
|
13
|
+
|
|
14
|
+
## Something else, when
|
|
15
|
+
|
|
16
|
+
- The card stands on its own, with no photograph behind it → **IllustrationCard**
|
|
17
|
+
- There is only a photograph → **AspectRatio**
|
|
18
|
+
|
|
19
|
+
## Never
|
|
20
|
+
|
|
21
|
+
- A section's content. Like the card it holds, the scene is a picture of the product, and what a section says belongs in its own blocks
|
|
22
|
+
- More than one card over one photograph. A second card is a second picture competing for the same eye; two scenes side by side say two things clearly
|
|
23
|
+
- A photograph whose subject sits where the card goes. The card covers the middle of the frame, or one side of it with `placement`; choose or crop the photograph so the person or the object stays clear of it
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
- **ratio** `enum` · default "square" — The scene's shape. One of three, the same three IllustrationCard takes, so scenes and cards across a site agree
|
|
28
|
+
- `landscape` — Four by three. A scene beside words in a wide section; the card takes a little under half the width
|
|
29
|
+
- `square` — One by one, and the default — the shape most such scenes are drawn in. The card takes a little over half the width
|
|
30
|
+
- `upright` — Three by four. A scene on a phone or in a narrow column; the card takes most of the width
|
|
31
|
+
- never: Fitting a particular photograph. The shape is a decision about the layout; the photograph is chosen or cropped for it
|
|
32
|
+
- **placement** `enum` · default "center" — Where the card sits over the photograph, so the subject of the photograph stays clear of it
|
|
33
|
+
- `center` — The default: the card in the middle of the frame. For a photograph whose subject frames the middle — a person looking down at what the card shows
|
|
34
|
+
- `start` — The card towards the start edge, for a photograph whose subject is at the end
|
|
35
|
+
- `end` — The card towards the end edge, for a photograph whose subject is at the start
|
|
36
|
+
- never: Anything but keeping the photograph's subject clear. The card's size is fixed by the shape; placement moves it and nothing else
|
|
37
|
+
- **src** `string` · required — Always. The photograph the scene is set in
|
|
38
|
+
- never: A data URI holding a photograph. A scene's photograph is the heaviest thing on its page and belongs in a file the browser can cache
|
|
39
|
+
- **alt** `string` · default "" — Empty by default, because the card's `label` describes the whole picture and the photograph is decoration. Write one only where the photograph says something the label does not
|
|
40
|
+
- never: Repeating the card's label. A screen reader would hear the picture described twice
|
|
41
|
+
|
|
42
|
+
## Inside it
|
|
43
|
+
|
|
44
|
+
- Takes only IllustrationCard.
|
|
45
|
+
- At least 1, at most 1 — fewer is not this component and more is a different one.
|
|
46
|
+
- 2 components are refused inside it; the list and the reasons are in the long document.
|
|
47
|
+
- Renders 2 parts: root, image.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
The reasoning behind each of these, the parts this renders, its states and snippets that compile: `.llm/components/illustrationscene.md`.
|
|
@@ -42,6 +42,13 @@ The band that opens a main landing page: the one thing the page is about, said o
|
|
|
42
42
|
- never: The background. A photograph filling the band is `backgroundImage`; this sits in front of it and is placed against the band's edge
|
|
43
43
|
- **backgroundImage** `string` · optional — A photograph filling the whole band. It is shown as it is — nothing is painted over it, so choose one already dark enough that the title reads on it
|
|
44
44
|
- never: A flat colour, or a bright photograph. The band already paints its ground, and nothing here darkens an image on the page's behalf — a pale one leaves the claim unreadable
|
|
45
|
+
- **background** `enum` · optional — The band is the page's one standout moment and wants more than a flat fill. Leave it out and the band is its flat ground, as it always was
|
|
46
|
+
- `halftone` — A halftone drawn behind the band's content: coral dots blending to white at the glow's heart, on the band's own dark ground, following the pointer over the band. …
|
|
47
|
+
- never: More than one band on a page. The pattern is what makes a band the one a reader remembers, and two of them make neither
|
|
48
|
+
|
|
49
|
+
## The type refuses
|
|
50
|
+
|
|
51
|
+
- background="halftone" with backgroundImage="*" — Two grounds on one band: the photograph would paint over the pattern, or the pattern over the photograph. A hero is a picture or a pattern, never both
|
|
45
52
|
|
|
46
53
|
## Inside it
|
|
47
54
|
|
|
@@ -38,6 +38,9 @@ The band that opens a company or a legal page: the page's name, a line saying wh
|
|
|
38
38
|
- never: A paragraph. It is held to a readable measure and set at body size; past a couple of sentences a reader scrolls rather than reads, and the actions go under the fold
|
|
39
39
|
- **actions** `node` · optional — The one or two things the page wants a reader to do. Composed by the page rather than described to this component, so a call to action is the same Button here as anywhere else on the site
|
|
40
40
|
- never: A row of destinations. Three or more controls under a title is a menu, and a reader who has to choose between five things chooses none
|
|
41
|
+
- **background** `enum` · optional — The band is the page's one standout moment and wants more than a flat fill. Leave it out and the band is its flat ground, as it always was
|
|
42
|
+
- `halftone` — A halftone drawn behind the band's content: coral dots blending to white at the glow's heart, on the band's own dark ground, following the pointer over the band. …
|
|
43
|
+
- never: More than one band on a page. The pattern is what makes a band the one a reader remembers, and two of them make neither
|
|
41
44
|
|
|
42
45
|
## Inside it
|
|
43
46
|
|
package/.llm/index.md
CHANGED
|
@@ -9,6 +9,8 @@ need — loading all of them dilutes the relevant one.
|
|
|
9
9
|
Paths here are from the package root, so they resolve whether this file is read in place
|
|
10
10
|
or its content handed over on its own.
|
|
11
11
|
|
|
12
|
+
Sections: Core (54) · Layout (5) · Blocks (14)
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
## Core
|
|
14
16
|
|
|
@@ -19,6 +21,7 @@ Domain-neutral building blocks.
|
|
|
19
21
|
| Component | Use when | Not for |
|
|
20
22
|
|---|---|---|
|
|
21
23
|
| AccordionItem | One row inside an Accordion — every row of a set is one of these · A single disclosure with no set around it: one topic whose detail is worth offering and not worth showing. The row is whole on its own, and it keeps its own open state when nothing is injecting one | The heading goes somewhere rather than opening something → `CardButton` |
|
|
24
|
+
| Background | A band that has to stand apart from the page around it with more than a change of fill — the opening of a landing page, a call to action, a section that closes a long page · A dark band that would otherwise be a flat slab. The glow gives it a centre for the eye, which is where the band's heading or its action should sit · A light page that wants one moment of brand colour without a coral block: the dots carry the colour at a fraction of the area a fill would | The band only needs separating from the page around it → nothing here · The ground is a picture or a video → `AspectRatio` |
|
|
22
25
|
| Badge | One of a set is the one the page wants read first — the plan most people choose, the market most people start with · Something is new or has changed, and saying so is worth a word rather than a sentence · A number the page is promoting is worth marking as a saving rather than left in the copy — a percentage off, a period free | What it says is a state the reader's account is in → nothing here · The words are the point rather than the mark → `CardBody` |
|
|
23
26
|
| Breadcrumb | The page sits inside a section hierarchy, and the levels above it are places the visitor can navigate to — a product page inside a markets section, a blog post inside a category · A visitor who arrived by search, social link or campaign URL needs to learn where they landed and how the site is organised around them | The visitor is moving through the stages of a sign-up or onboarding flow rather than standing in a hierarchy → nothing here · There is exactly one place to go back to, and it is the previous page rather than a parent section → nothing here |
|
|
24
27
|
| BreadcrumbItem | Rendering one level of a Breadcrumb — every level in a trail is one of these · The level needs a short name the visitor recognises as a place: the section name, not a sentence about it | The destination is somewhere the visitor goes to act rather than a level they climb back to → nothing here |
|
|
@@ -32,6 +35,8 @@ Domain-neutral building blocks.
|
|
|
32
35
|
| DropdownMenu | A set of destinations too long for the navigation bar and too short to be a page of its own — languages, regions, the parts of a long index · The set is short enough to read at a glance, where a visitor is choosing rather than searching | The set reports a choice the visitor should find marked when they return → nothing here · The destinations belong in the page's navigation → nothing here · It is one destination rather than one of a set → nothing here · The set is long enough that a visitor would rather type than read → nothing here |
|
|
33
36
|
| FooterGroup | A set of a footer's destinations belong under one word — Markets, Support, Legal · The footer has enough links that a reader scanning it needs sets rather than a list | The destinations are the ones a visitor most likely wants → `Navbar` · The group is a named set inside a navigation panel → `NavbarMenuGroup` · There is one link rather than a set → `Link` |
|
|
34
37
|
| Icon | A glyph stands beside words to speed recognition — a mark on a feature card, a chevron on a row, a separator in a trail · A page is composing something a component offers a slot for, and the slot takes a mark rather than a component that draws one | The mark identifies a company or a product — a payment method, an app store, a social network → `Logo` *(not built yet)* · The artwork is a scene rather than a symbol → `Illustration` *(not built yet)* |
|
|
38
|
+
| IllustrationCard | Product information laid over a photograph or a piece of art — a market's price and status over a picture of a trader, a balance over a device · A standalone image of the product beside a section's words, where a screenshot would be too literal: the pane is the picture the section shows · Several such pictures across a site that have to agree in shape and surface without each page deciding | A section has content to present — features, benefits, steps, a list → `FeatureCards` · The content is something a reader acts on — a link, a form, a set of options → `Card` · There is only a photograph → `AspectRatio` |
|
|
39
|
+
| IllustrationScene | Product information shown over a photograph — a trade ticket, a balance, a market's status — where the photograph sets the scene and the card says what the product does · A hero or a feature section needs a picture of the product in use rather than a screenshot or a photograph alone | The card stands on its own, with no photograph behind it → `IllustrationCard` · There is only a photograph → `AspectRatio` |
|
|
35
40
|
| Link | A term inside running copy has a page of its own — a market named in a paragraph, a fee mentioned in a sentence, a product referred to in passing · The page must offer a destination without pushing it: terms, a full fee schedule, a regulatory notice. A pill would give it the weight of the thing the page is actually asking for · A second destination beside the call to action, where a second pill would be two things asking to be pressed and a reader would have to choose between them before reading either | The destination is the step the page was built to produce → `Button` · Pressing it does something on this page rather than going somewhere → nothing here · The whole card or panel is the target rather than some words in it → `CardButton` |
|
|
36
41
|
| MenuItem | A row in a menu of destinations — a language, a region, a page number an index skipped · A set short enough to read at a glance, where a reader is choosing rather than searching | The row reports a choice the reader should find marked when they return → nothing here · The destination belongs in the page's navigation → nothing here · It is one action rather than one of a set → nothing here |
|
|
37
42
|
| NavbarItem | A section of the site, in a Navbar — the ordinary case and what this is for · A destination that leaves the site, which it marks as a change of context rather than leaving the reader to find out · The same destination inside the panel a narrow bar collapses into: a page writes its navigation once, and what changes with the width is how it is drawn | The destination opens a panel of further destinations rather than going somewhere → `NavbarMenu` · The destination is a phrase inside a sentence, or a call to action beneath a paragraph → `Link` · The item is one of a set of alternatives rather than a place → `Tab` |
|
|
@@ -78,6 +83,7 @@ Domain-neutral building blocks.
|
|
|
78
83
|
## Layout
|
|
79
84
|
|
|
80
85
|
Arrange other components and decide no appearance of their own.
|
|
86
|
+
|
|
81
87
|
| Component | Use when | Not for |
|
|
82
88
|
|---|---|---|
|
|
83
89
|
| AspectRatio | A picture whose proportions have to match the ones beside it — a row of cards, a grid of markets, a set of logos. One shape asked for once is what keeps a row from settling on whichever image is tallest · Room that must be reserved before the thing filling it arrives — art loaded late, an embed, anything fetched. The box is the right height from the first paint, so the page under it never moves · An embed that brings its own proportion and no height — a video, a map, a third-party frame. The ratio is the only way to give it one without guessing a pixel measure that is wrong at some width | The picture is the media region of a card → `CardBody` · The thing inside has a size of its own and should keep it → nothing here · The shape changes with the viewport → nothing here |
|
|
@@ -89,6 +95,7 @@ Arrange other components and decide no appearance of their own.
|
|
|
89
95
|
## Blocks
|
|
90
96
|
|
|
91
97
|
The sections a page is built from, and the rhythm between them.
|
|
98
|
+
|
|
92
99
|
| Component | Use when | Not for |
|
|
93
100
|
|---|---|---|
|
|
94
101
|
| CtaBanner | A short, high-contrast promotion with one clear action — open an account, start trading, download the app · The band that closes a page, or breaks a long one, on the action the page exists to produce | Two or three promotions to rotate between → `CtaBannerSlider` · The band that opens the page → `LandingHero` · A message that needs a picture beside it → `FeatureSplit` |
|
package/.llm/tokens.md
CHANGED
|
@@ -45,6 +45,7 @@ one value at every width.
|
|
|
45
45
|
- `--color-bg-surface-card-raised` — A card lifting off the ground behind it, e.g. a Card or CardButton on a color.bg.subtle band. White in light, white at six in dark, so a dark card tints the band instead of sitting on it as grey. Menus and popovers take color.bg.surface-raised.
|
|
46
46
|
- `--color-bg-surface-card-strong` — The dark fill of a card weightier than its neighbours, e.g. an accent-strong Card or CardButton. gray.900 in both modes, a step lighter than color.bg.brand-strong so it reads as a card, not a band.
|
|
47
47
|
- `--color-bg-surface-card-strong-raised` — The strong card on a subtle band. gray.900 in light mode, the strong card's own fill, which already stands off the gray.50 band; gray.800 in dark, where the band is a near-black tint the strong card would blend into. Pair with color.fg.on-brand-strong.
|
|
48
|
+
- `--color-bg-surface-glass` — A pane of glass over whatever is behind it, e.g. an IllustrationCard on a band. Light glass in light mode, a faint frosted white in dark, with a blur behind it in both; ink is color.fg.default.
|
|
48
49
|
- `--color-bg-surface-inverse` — The quieter of the two surfaces on a dark ground, for a panel rather than a pill. color.bg.surface-raised-inverse is the stronger lift and is right on a control the size of a navbar's; at that weight a card-sized box reads as a pale patch rather than a surface.
|
|
49
50
|
- `--color-bg-surface-modal` — A surface that covers the page behind a scrim — dialogs, drawers, bottom sheets. The topmost plane there is, so it stays white in light where color.bg.surface is recessed. For one that floats without dimming what is under it use color.bg.surface-raised.
|
|
50
51
|
- `--color-bg-surface-raised` — A surface that lifts off the one behind it, e.g. a dropdown, a popover, a card on a color.bg.subtle band. A card on the page itself takes color.bg.surface, which reads as recessed against it instead.
|
|
@@ -66,6 +67,8 @@ one value at every width.
|
|
|
66
67
|
- `--color-border-focus-inverse` — The focus ring on a ground that runs against the mode. color.border.focus is near-black, which is invisible on a dark bar — and a focus ring that cannot be seen is the one affordance a keyboard reader has nothing to fall back on.
|
|
67
68
|
- `--color-border-focus-on-brand-strong` — The focus ring on color.bg.brand-strong, e.g. a navigation bar's controls on a dark hero, a footer's links. White in both modes, because the band does not change. For a surface that flips with the mode use color.border.focus-inverse.
|
|
68
69
|
- `--color-border-info` — Informational accent border, e.g. info banner edge, highlighted section.
|
|
70
|
+
- `--color-border-pattern` — The resting lines of a decorative rule grid on the page's ground. A step above color.border.subtle, which a hairline across a whole band thins to nothing; well below the default border, so the grid reads as texture.
|
|
71
|
+
- `--color-border-pattern-inverse` — The resting lines of a decorative rule grid on a dark or coral ground. White at a quarter in both modes, as those grounds are; a step above color.border.subtle-inverse, which a hairline grid thins to nothing.
|
|
69
72
|
- `--color-border-strong` — Emphasised border for active or prominent elements, e.g. active input, selected card edge.
|
|
70
73
|
- `--color-border-subtle` — A quiet separator, e.g. dividers, table rules. Alpha-based — works on any surface.
|
|
71
74
|
- `--color-border-subtle-inverse` — A quiet rule on a dark ground. The counterpart to color.border.subtle, which is black at 5% and invisible on one.
|
|
@@ -127,6 +130,7 @@ one value at every width.
|
|
|
127
130
|
|
|
128
131
|
## size
|
|
129
132
|
|
|
133
|
+
- `--size-aurora-spotlight` — How far the pool of light trailing the pointer across an aurora reaches, as a radius. Small enough to read as light the pointer carries rather than a wash over the band.
|
|
130
134
|
- `--size-avatar` — A person's picture beside their words — the author of a testimonial. Forty-eight, round: large enough to recognise a face, small enough to stay a signature under the quote rather than a portrait above it.
|
|
131
135
|
- `--size-backdrop-blur` — How far a see-through surface blurs what is behind it, e.g. the navigation bar over the page it scrolls across. Enough that the words behind it stop reading as words, so the bar's own stay legible.
|
|
132
136
|
- `--size-band-compact` — The least height an opening band takes when it is not a screen tall — a company, legal or support page, where a full viewport would be a wall before the first sentence. Deep enough that the band reads as a band rather than a gap the title fell into.
|
|
@@ -143,6 +147,8 @@ one value at every width.
|
|
|
143
147
|
- `--size-grid-track-lg` — For a cell holding a picture as well as words, or a pricing plan with a list under it. Three fit the page's measure and four do not, which is what makes this the floor for a grid meant to read as three across.
|
|
144
148
|
- `--size-grid-track-md` — The default track floor, for a feature card: a heading and a line or two beneath it. Four of these fit the page's measure, so a grid asking for three has room to spare and drops to two on a tablet rather than at the first sign of pressure.
|
|
145
149
|
- `--size-grid-track-sm` — The narrowest a grid track goes before the grid drops a column. For a cell holding a logo, an icon and a word, or one short claim — six of them clear the page's measure with the page gutter still on both sides.
|
|
150
|
+
- `--size-halftone-dot` — The widest a halftone dot grows, at the brightest point of the glow. Six against size.halftone.pitch's twenty, so even the largest dots stand well apart and the pattern reads as a fine screen of light rather than a field of discs.
|
|
151
|
+
- `--size-halftone-pitch` — How far apart a halftone background's dots sit, centre to centre. A pitch rather than a gap, as size.rule-grid.pitch is: how often a decorative mark recurs. Twenty, against a six-pixel dot: a fine screen that reads as a tone across a band.
|
|
146
152
|
- `--size-heading-group-max` — How wide an eyebrow, a title and a description may run as a block. Independent or centred groups take this; one that has to sit on the grid takes eight columns instead, which is a span rather than a measure.
|
|
147
153
|
- `--size-logo-columns-height` — How much of a LogoColumns wall shows at once, from the fold. Tall enough that a column reads as running on past both edges; half of it on a phone.
|
|
148
154
|
- `--size-logo-rows-tile` — The width of a tile on a LogoRows, from the fold; three quarters of it on a phone. Wide enough for a wordmark, narrow enough that a row shows several at once.
|
|
@@ -156,7 +162,10 @@ one value at every width.
|
|
|
156
162
|
- `--size-menu-panel-min` — The shortest a section's menu panel gets, whatever it holds. A bar's sections rarely have the same number of destinations, and panels that each took their own height would change size as the reader moved along the row.
|
|
157
163
|
- `--size-menu-max` — The tallest a menu's surface gets before its commands scroll. Product's measure, and counted in rows: five whole and part of a sixth at either size. Neither lands on a row boundary — a ceiling cutting clean at the last full row looks like the whole set.
|
|
158
164
|
- `--size-review-card-min` — The shortest a TestimonialRow card gets. A floor, not a height: a one-line review keeps a card's shape, and a longer one still grows it.
|
|
165
|
+
- `--size-rings-pitch` — How far apart the rings on a band sit, counted out from the middle of its foot. A pitch, as size.rule-grid.pitch is; tighter than the grid's, because rings spaced that wide read as a target rather than a ripple.
|
|
166
|
+
- `--size-rings-spotlight` — How far the pointer's light reaches on the rings: the radius within which they brighten around the pointer and fade to the resting rings. The rule grid's reach, so the two answer the pointer alike.
|
|
159
167
|
- `--size-rule-grid-pitch` — How often the rule grid repeats on a band that paints one. A pitch rather than a gap: it is how far apart a decorative line recurs, not the space between two things a reader is comparing.
|
|
168
|
+
- `--size-rule-grid-spotlight` — How far the pointer's light reaches on a rule grid: the radius within which the lines brighten around the pointer and fade to the resting grid. A little over a square either way: light under the pointer, not a lit band.
|
|
160
169
|
- `--size-sheet-handle-height` — The thickness of that handle. At the smallest step the scale has, because a grab bar is a hint that the sheet moves rather than a part of what it holds.
|
|
161
170
|
- `--size-sheet-handle-width` — The width of the grab handle at the top of a BottomSheet. Wide enough to take hold of, narrow enough to read as a grip rather than as a rule across the sheet.
|
|
162
171
|
- `--size-sheet-max` — The widest a BottomSheet gets before it stops growing and centres. A sheet is a small-screen pattern, and one running the width of a desktop is a dialog that arrived from the wrong edge.
|
|
@@ -349,6 +358,7 @@ one value at every width.
|
|
|
349
358
|
|
|
350
359
|
- `--motion-distance-drift` — How far decoration travels against the scroll while its section passes through the view, one way or the other. Far enough to be seen moving as the reader scrolls past, so it reads as depth.
|
|
351
360
|
- `--motion-duration-dramatic` — Editorial hero entrances for visual impact, e.g. hero headline revealing, landing page title appearing. Not for scroll reveals — use motion.duration.reveal.
|
|
361
|
+
- `--motion-duration-drift` — One way of a slow drift that runs while something is on screen — an aurora wandering along a band's foot and back. Ten seconds, so the movement is felt rather than watched.
|
|
352
362
|
- `--motion-duration-dwell` — How long a rotating message holds before the next one moves in, e.g. a CTA banner's slides. Long enough to read a headline and a line under it; the reference site's 2000 moved before a reader reached the button.
|
|
353
363
|
- `--motion-duration-fast` — Direct user actions that should feel instant, e.g. hover, press, toggle.
|
|
354
364
|
- `--motion-duration-instant` — A change the reader has already moved past — a tooltip leaving once the pointer is elsewhere. Not a short duration but no duration: animating a dismissal keeps a thing on screen after the reason for it has gone.
|
|
@@ -360,6 +370,7 @@ one value at every width.
|
|
|
360
370
|
- `--motion-duration-slow` — Large UI transitions, e.g. accordions expanding, page transitions, interactive demos.
|
|
361
371
|
- `--motion-duration-spinner` — One full rotation of a spinner. Fast enough to read as working, slow enough that the stroke does not blur into a solid ring.
|
|
362
372
|
- `--motion-duration-stagger` — The step between one part of a section arriving and the next. A gap rather than a length: five parts at this step trail the first by less than half a second, so a block still arrives as one thing rather than assembling itself while a reader waits.
|
|
373
|
+
- `--motion-duration-trail` — How long something takes to catch up with a pointer it trails — a background's glow following the pointer across a band. Half a second, so the light drifts after the hand rather than sticking to it: a trail is felt, a cursor is tracked.
|
|
363
374
|
- `--motion-easing-enter` — UI elements arriving on screen — decelerates into place, e.g. dropdown opening, tooltip appearing.
|
|
364
375
|
- `--motion-easing-exit` — UI elements leaving the screen — accelerates away, e.g. menu closing, notification dismissing.
|
|
365
376
|
- `--motion-easing-media-hover` — Art moving inside a frame that holds still. Symmetric, unlike easing.standard: a hover runs forward on enter and backward on leave, so a one-way curve that settles hard reads as a snap going one way and a drift the other.
|
package/AGENTS.md
CHANGED
|
@@ -80,6 +80,7 @@ screen is built in is not something to reach for while building a control.
|
|
|
80
80
|
|
|
81
81
|
- **Accordion** — Questions a reader asks near a decision
|
|
82
82
|
- **AccordionItem** — One row inside an Accordion
|
|
83
|
+
- **Background** — A band that has to stand apart from the page around it with more than a change of fill
|
|
83
84
|
- **Badge** — One of a set is the one the page wants read first
|
|
84
85
|
- **BottomSheet** — A task needs the screen's full width and the reader's undivided attention
|
|
85
86
|
- **Breadcrumb** — The page sits inside a section hierarchy, and the levels above it are places the visitor can navigate to
|
|
@@ -96,6 +97,8 @@ screen is built in is not something to reach for while building a control.
|
|
|
96
97
|
- **Footer** — A marketing page needs its closing band
|
|
97
98
|
- **FooterGroup** — A set of a footer's destinations belong under one word
|
|
98
99
|
- **Icon** — A glyph stands beside words to speed recognition
|
|
100
|
+
- **IllustrationCard** — Product information laid over a photograph or a piece of art
|
|
101
|
+
- **IllustrationScene** — Product information shown over a photograph
|
|
99
102
|
- **Link** — A term inside running copy has a page of its own
|
|
100
103
|
- **MenuItem** — A row in a menu of destinations
|
|
101
104
|
- **Navbar** — A marketing page needs its top-level navigation
|
|
@@ -19,4 +19,4 @@ export type { CtaBannerProps };
|
|
|
19
19
|
* It arrives the way every block does, and the way CtaBannerSlider's slides do: block-reveal.css
|
|
20
20
|
* brings the headline, the line and the actions up a step apart once the band is in view.
|
|
21
21
|
*/
|
|
22
|
-
export declare function CtaBanner({ title, headingLevel, description, actions, }: CtaBannerProps): import("react").JSX.Element;
|
|
22
|
+
export declare function CtaBanner({ title, headingLevel, description, actions, background, }: CtaBannerProps): import("react").JSX.Element;
|
|
@@ -6,6 +6,7 @@ import './cta-banner-impl.css';
|
|
|
6
6
|
import '../block-reveal.css';
|
|
7
7
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
8
|
import { given } from '../../given.js';
|
|
9
|
+
import { Background } from '../../core/background/Background.js';
|
|
9
10
|
import { ctaBannerDefaults, ctaBannerParts } from './CtaBanner.types.js';
|
|
10
11
|
/**
|
|
11
12
|
* A full-bleed coral band carrying one promotion and the action it asks for.
|
|
@@ -23,9 +24,9 @@ import { ctaBannerDefaults, ctaBannerParts } from './CtaBanner.types.js';
|
|
|
23
24
|
* It arrives the way every block does, and the way CtaBannerSlider's slides do: block-reveal.css
|
|
24
25
|
* brings the headline, the line and the actions up a step apart once the band is in view.
|
|
25
26
|
*/
|
|
26
|
-
export function CtaBanner({ title, headingLevel = ctaBannerDefaults.headingLevel, description, actions, }) {
|
|
27
|
+
export function CtaBanner({ title, headingLevel = ctaBannerDefaults.headingLevel, description, actions, background, }) {
|
|
27
28
|
const titleId = useId();
|
|
28
29
|
const [band, revealed] = useReveal();
|
|
29
30
|
const Title = headingLevel === 'h3' ? 'h3' : 'h2';
|
|
30
|
-
return (
|
|
31
|
+
return (_jsxs("section", { className: ctaBannerParts.root, "data-background": background, "aria-labelledby": titleId, children: [background === undefined ? null : (_jsx(Background, { tone: "brand", pattern: background, children: null })), _jsx("div", { className: ctaBannerParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: ctaBannerParts.content, children: [_jsxs("div", { className: ctaBannerParts.text, children: [_jsx(Title, { className: ctaBannerParts.title, id: titleId, ...arriving(0), children: title }), given(description) ? (_jsx("p", { className: ctaBannerParts.description, ...arriving(1), children: description })) : null] }), actions ? (_jsx("div", { className: ctaBannerParts.actions, ...arriving(2), children: actions })) : null] }) })] }));
|
|
31
32
|
}
|
|
@@ -11,6 +11,11 @@ export interface CtaBannerOwnProps {
|
|
|
11
11
|
description?: string;
|
|
12
12
|
/** The one action the message asks for, or two at most. The coral is the banner's ground, so the primary is Button variant="inverse" tone="brand" — a primary Button is coral on coral, and the tone keeps it near-black in both themes — and a second is Button variant="secondary" tone="brand" — a white tint with a white label, fixed in both themes like the band. */
|
|
13
13
|
actions?: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* `halftone` — A halftone drawn behind the band's content: white dots on the band's own coral, following the pointer over the band. Drawn by Background, placed as a layer under the content, so the band's own layout is untouched.
|
|
16
|
+
* `grid` — A fine rule grid behind the band's content: white hairlines on the coral, fading in towards the foot, brightening in a soft circle around the pointer. Drawn by Background as a layer under the band's own content, by the stylesheet alone — quieter than the halftone, and nothing runs at rest
|
|
17
|
+
*/
|
|
18
|
+
background?: 'halftone' | 'grid';
|
|
14
19
|
}
|
|
15
20
|
export type CtaBannerProps = CtaBannerOwnProps;
|
|
16
21
|
/** The class each part carries. Apply these — do not retype them. */
|
|
@@ -27,3 +27,11 @@
|
|
|
27
27
|
justify-content: center;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* The banner's column, lifted over the pattern layer. It is not positioned otherwise — the banner
|
|
33
|
+
* has no other layer to clear — so it is lifted only where the pattern is drawn.
|
|
34
|
+
*/
|
|
35
|
+
:where([data-dds-context="marketing"]) .dds-ctabanner[data-background] .dds-ctabanner__inner {
|
|
36
|
+
position: relative;
|
|
37
|
+
}
|
|
@@ -36,4 +36,4 @@ export type { CtaBannerSliderProps };
|
|
|
36
36
|
* the same rise, a step apart. The slide leaving drops to waiting at once, as that sheet has every
|
|
37
37
|
* part do, so the outgoing words never travel.
|
|
38
38
|
*/
|
|
39
|
-
export declare function CtaBannerSlider({ slides, headingLevel, autoplay, label, controlsLabel, slideLabel, }: CtaBannerSliderProps): import("react").JSX.Element | null;
|
|
39
|
+
export declare function CtaBannerSlider({ slides, headingLevel, autoplay, label, controlsLabel, slideLabel, background, }: CtaBannerSliderProps): import("react").JSX.Element | null;
|
|
@@ -4,6 +4,7 @@ import './CtaBannerSlider.css';
|
|
|
4
4
|
import './cta-banner-slider-impl.css';
|
|
5
5
|
import '../block-reveal.css';
|
|
6
6
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
7
|
+
import { Background } from '../../core/background/Background.js';
|
|
7
8
|
import { useRotation } from '../use-rotation.js';
|
|
8
9
|
import { given } from '../../given.js';
|
|
9
10
|
import { Button } from '../../core/button/Button.js';
|
|
@@ -42,7 +43,7 @@ import { ctaBannerSliderDefaults, ctaBannerSliderParts, } from './CtaBannerSlide
|
|
|
42
43
|
* the same rise, a step apart. The slide leaving drops to waiting at once, as that sheet has every
|
|
43
44
|
* part do, so the outgoing words never travel.
|
|
44
45
|
*/
|
|
45
|
-
export function CtaBannerSlider({ slides, headingLevel = ctaBannerSliderDefaults.headingLevel, autoplay = ctaBannerSliderDefaults.autoplay, label = ctaBannerSliderDefaults.label, controlsLabel = ctaBannerSliderDefaults.controlsLabel, slideLabel = ctaBannerSliderDefaults.slideLabel, }) {
|
|
46
|
+
export function CtaBannerSlider({ slides, headingLevel = ctaBannerSliderDefaults.headingLevel, autoplay = ctaBannerSliderDefaults.autoplay, label = ctaBannerSliderDefaults.label, controlsLabel = ctaBannerSliderDefaults.controlsLabel, slideLabel = ctaBannerSliderDefaults.slideLabel, background, }) {
|
|
46
47
|
const Title = headingLevel === 'h3' ? 'h3' : 'h2';
|
|
47
48
|
const count = slides.length;
|
|
48
49
|
// The band arriving on screen, as every block does; until then no slide has arrived.
|
|
@@ -54,7 +55,7 @@ export function CtaBannerSlider({ slides, headingLevel = ctaBannerSliderDefaults
|
|
|
54
55
|
// leads a screen reader to an empty band.
|
|
55
56
|
if (count === 0)
|
|
56
57
|
return null;
|
|
57
|
-
return (
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
return (_jsxs("section", { ref: root, className: ctaBannerSliderParts.root, "aria-label": label, "data-background": background, ...region, children: [background === undefined ? null : (_jsx(Background, { tone: "brand", pattern: background, children: null })), _jsxs("div", { className: ctaBannerSliderParts.inner, ref: band, children: [_jsx("div", { className: ctaBannerSliderParts.track, ...track, children: slides.map((slide, at) => (_jsxs("div", { className: ctaBannerSliderParts.slide, ...item(at), "data-revealed": revealed && !away(at), children: [_jsxs("div", { className: ctaBannerSliderParts.text, children: [_jsx(Title, { className: ctaBannerSliderParts.title, ...arriving(0), children: slide.title }), given(slide.description) ? (_jsx("p", { className: ctaBannerSliderParts.description, ...arriving(1), children: slide.description })) : null] }), slide.primaryAction ? (_jsxs("div", { className: ctaBannerSliderParts.actions, ...arriving(2), children: [_jsx(Button, { variant: "inverse", tone: "brand", href: slide.primaryAction.href, children: slide.primaryAction.label }), slide.secondaryAction ? (_jsx(Button, { variant: "secondary", tone: "brand", href: slide.secondaryAction.href, children: slide.secondaryAction.label })) : null] })) : null] }, at))) }), rotating ? (_jsx("div", { className: ctaBannerSliderParts.controls, children: _jsx(PaginationDots, { ...dots,
|
|
59
|
+
/* A dot pressed stops the dots' own rotation; the band's press handler stops this. */
|
|
60
|
+
label: controlsLabel, itemLabel: slideLabel }) })) : null] })] }));
|
|
60
61
|
}
|
|
@@ -17,6 +17,10 @@ export interface CtaBannerSliderOwnProps {
|
|
|
17
17
|
controlsLabel?: string;
|
|
18
18
|
/** The word each dot is announced by, before its number — 'Slide 2'. Translate it with the page, as controlsLabel is; a page that translates only the group's name still has every dot announced in English. */
|
|
19
19
|
slideLabel?: string;
|
|
20
|
+
/**
|
|
21
|
+
* `grid` — A fine rule grid behind the slides: white hairlines on the coral, fading in towards the foot, brightening in a soft circle around the pointer. Drawn by Background as a layer under the band's content, by the stylesheet alone, so it holds still while the slides move and costs nothing at rest
|
|
22
|
+
*/
|
|
23
|
+
background?: 'grid';
|
|
20
24
|
}
|
|
21
25
|
export type CtaBannerSliderProps = CtaBannerSliderOwnProps;
|
|
22
26
|
/** The class each part carries. Apply these — do not retype them. */
|
|
@@ -71,3 +71,11 @@
|
|
|
71
71
|
justify-content: center;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* The band's column, lifted over the pattern layer when `background` asks for one. Not positioned
|
|
77
|
+
* otherwise — the band has no other layer for it to clear.
|
|
78
|
+
*/
|
|
79
|
+
:where([data-dds-context="marketing"]) .dds-ctabannerslider[data-background] .dds-ctabannerslider__inner {
|
|
80
|
+
position: relative;
|
|
81
|
+
}
|
|
@@ -38,4 +38,4 @@ export type { LandingHeroProps };
|
|
|
38
38
|
* title and the description; a photograph that carried meaning they do not would be a hero that
|
|
39
39
|
* reads as empty to anyone who cannot see it, and the contract says so.
|
|
40
40
|
*/
|
|
41
|
-
export declare function LandingHero({ eyebrow, title, headingLevel, description, actions, media, backgroundImage, }: LandingHeroProps): import("react").JSX.Element;
|
|
41
|
+
export declare function LandingHero({ eyebrow, title, headingLevel, description, actions, media, backgroundImage, background, }: LandingHeroProps): import("react").JSX.Element;
|
|
@@ -6,6 +6,7 @@ import './landing-hero-impl.css';
|
|
|
6
6
|
import '../block-reveal.css';
|
|
7
7
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
8
|
import { given } from '../../given.js';
|
|
9
|
+
import { Background } from '../../core/background/Background.js';
|
|
9
10
|
import { landingHeroDefaults, landingHeroParts, } from './LandingHero.types.js';
|
|
10
11
|
/**
|
|
11
12
|
* The band that opens a marketing page.
|
|
@@ -42,13 +43,13 @@ import { landingHeroDefaults, landingHeroParts, } from './LandingHero.types.js';
|
|
|
42
43
|
* title and the description; a photograph that carried meaning they do not would be a hero that
|
|
43
44
|
* reads as empty to anyone who cannot see it, and the contract says so.
|
|
44
45
|
*/
|
|
45
|
-
export function LandingHero({ eyebrow, title, headingLevel = landingHeroDefaults.headingLevel, description, actions, media, backgroundImage, }) {
|
|
46
|
+
export function LandingHero({ eyebrow, title, headingLevel = landingHeroDefaults.headingLevel, description, actions, media, backgroundImage, background, }) {
|
|
46
47
|
const titleId = useId();
|
|
47
48
|
const [band, revealed] = useReveal();
|
|
48
49
|
const Title = headingLevel === 'h2' ? 'h2' : 'h1';
|
|
49
|
-
return (_jsxs("section", { className: landingHeroParts.root, "aria-labelledby": titleId,
|
|
50
|
+
return (_jsxs("section", { className: landingHeroParts.root, "data-background": background, "aria-labelledby": titleId,
|
|
50
51
|
/* The one inline style here, and it is a value rather than a decision: which photograph,
|
|
51
52
|
supplied by the page. Everything about how it is drawn — the cover fit and the position — is in the stylesheet, where it can be reasoned about. A background shorthand
|
|
52
53
|
would have reset those four properties every time the page passed an image. */
|
|
53
|
-
style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: [media ? (_jsx("div", { className: landingHeroParts.media, "aria-hidden": "true", children: media })) : null, _jsx("div", { className: landingHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: landingHeroParts.content, children: [_jsxs("div", { className: landingHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: landingHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: landingHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: landingHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: landingHeroParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
|
|
54
|
+
style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: [background === 'halftone' ? _jsx(Background, { tone: "dark", children: null }) : null, media ? (_jsx("div", { className: landingHeroParts.media, "aria-hidden": "true", children: media })) : null, _jsx("div", { className: landingHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: landingHeroParts.content, children: [_jsxs("div", { className: landingHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: landingHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: landingHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: landingHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: landingHeroParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
|
|
54
55
|
}
|
|
@@ -15,10 +15,14 @@ export interface LandingHeroOwnProps {
|
|
|
15
15
|
actions?: ReactNode;
|
|
16
16
|
/** The band's visual — the subject standing beside the claim, cropped by the band's own inline edge rather than floating clear of it */
|
|
17
17
|
media?: ReactNode;
|
|
18
|
-
/** A photograph filling the whole band. It is shown as it is — nothing is painted over it, so choose one already dark enough that the title reads on it */
|
|
19
|
-
backgroundImage?: string;
|
|
20
18
|
}
|
|
21
|
-
export type LandingHeroProps = LandingHeroOwnProps
|
|
19
|
+
export type LandingHeroProps = LandingHeroOwnProps & ({
|
|
20
|
+
background?: 'halftone';
|
|
21
|
+
backgroundImage?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
background?: undefined;
|
|
24
|
+
backgroundImage?: string;
|
|
25
|
+
});
|
|
22
26
|
/** The class each part carries. Apply these — do not retype them. */
|
|
23
27
|
export declare const landingHeroParts: {
|
|
24
28
|
readonly root: "dds-landinghero";
|
|
@@ -31,4 +31,4 @@ export type { PageHeaderProps };
|
|
|
31
31
|
* region landmark once it has a name, and a band that announced itself as an unnamed section is one
|
|
32
32
|
* more thing a screen reader user walks through rather than a place they can skip to.
|
|
33
33
|
*/
|
|
34
|
-
export declare function PageHeader({ eyebrow, title, headingLevel, description, actions, }: PageHeaderProps): import("react").JSX.Element;
|
|
34
|
+
export declare function PageHeader({ eyebrow, title, headingLevel, description, actions, background, }: PageHeaderProps): import("react").JSX.Element;
|
|
@@ -6,6 +6,7 @@ import './page-header-impl.css';
|
|
|
6
6
|
import '../block-reveal.css';
|
|
7
7
|
import { arriving, useReveal } from '../use-reveal.js';
|
|
8
8
|
import { given } from '../../given.js';
|
|
9
|
+
import { Background } from '../../core/background/Background.js';
|
|
9
10
|
import { pageHeaderDefaults, pageHeaderParts } from './PageHeader.types.js';
|
|
10
11
|
/**
|
|
11
12
|
* The band that opens a company or a legal page.
|
|
@@ -35,9 +36,9 @@ import { pageHeaderDefaults, pageHeaderParts } from './PageHeader.types.js';
|
|
|
35
36
|
* region landmark once it has a name, and a band that announced itself as an unnamed section is one
|
|
36
37
|
* more thing a screen reader user walks through rather than a place they can skip to.
|
|
37
38
|
*/
|
|
38
|
-
export function PageHeader({ eyebrow, title, headingLevel = pageHeaderDefaults.headingLevel, description, actions, }) {
|
|
39
|
+
export function PageHeader({ eyebrow, title, headingLevel = pageHeaderDefaults.headingLevel, description, actions, background, }) {
|
|
39
40
|
const titleId = useId();
|
|
40
41
|
const [band, revealed] = useReveal();
|
|
41
42
|
const Title = headingLevel === 'h2' ? 'h2' : 'h1';
|
|
42
|
-
return (
|
|
43
|
+
return (_jsxs("section", { className: pageHeaderParts.root, "data-background": background, "aria-labelledby": titleId, children: [background === 'halftone' ? _jsx(Background, { tone: "dark", children: null }) : null, _jsx("div", { className: pageHeaderParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: pageHeaderParts.content, children: [_jsxs("div", { className: pageHeaderParts.text, children: [given(eyebrow) ? (_jsx("p", { className: pageHeaderParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: pageHeaderParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: pageHeaderParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: pageHeaderParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
|
|
43
44
|
}
|
|
@@ -13,6 +13,10 @@ export interface PageHeaderOwnProps {
|
|
|
13
13
|
description?: string;
|
|
14
14
|
/** The one or two things the page wants a reader to do. Composed by the page rather than described to this component, so a call to action is the same Button here as anywhere else on the site */
|
|
15
15
|
actions?: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* `halftone` — A halftone drawn behind the band's content: coral dots blending to white at the glow's heart, on the band's own dark ground, following the pointer over the band. Drawn by Background, placed as a layer under the content, so the band's own layout is untouched. It replaces the rule grid rather than joining it: two patterns on one band are texture fighting texture.
|
|
18
|
+
*/
|
|
19
|
+
background?: 'halftone';
|
|
16
20
|
}
|
|
17
21
|
export type PageHeaderProps = PageHeaderOwnProps;
|
|
18
22
|
/** The class each part carries. Apply these — do not retype them. */
|
|
@@ -174,3 +174,11 @@
|
|
|
174
174
|
inline-size: auto;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
+
|
|
178
|
+
/*
|
|
179
|
+
* With the halftone the rule grid steps aside. Two patterns on one band are texture fighting
|
|
180
|
+
* texture, and the halftone is the one that was asked for.
|
|
181
|
+
*/
|
|
182
|
+
:where([data-dds-context="marketing"]) .dds-pageheader[data-background='halftone'] {
|
|
183
|
+
background-image: none;
|
|
184
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* GENERATED from background.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-background {
|
|
4
|
+
align-content: center;
|
|
5
|
+
display: grid;
|
|
6
|
+
inline-size: 100%;
|
|
7
|
+
isolation: isolate;
|
|
8
|
+
justify-items: center;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
position: relative;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:where([data-dds-context="marketing"]) .dds-background .dds-background__content {
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
inline-size: 100%;
|
|
16
|
+
text-align: center;
|
|
17
|
+
max-inline-size: var(--size-content-max);
|
|
18
|
+
padding-inline: var(--space-inset-page);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:where([data-dds-context="marketing"]) .dds-background .dds-background__canvas {
|
|
22
|
+
transition-duration: var(--motion-duration-trail);
|
|
23
|
+
transition-timing-function: var(--motion-easing-enter);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="brand"] {
|
|
27
|
+
background-color: var(--color-bg-brand);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="brand"] .dds-background__canvas {
|
|
31
|
+
color: var(--color-fg-on-brand);
|
|
32
|
+
outline-color: var(--color-fg-on-brand);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="brand"] .dds-background__content {
|
|
36
|
+
color: var(--color-fg-on-brand);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="dark"] {
|
|
40
|
+
background-color: var(--color-bg-brand-strong);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="dark"] .dds-background__canvas {
|
|
44
|
+
color: var(--color-bg-brand);
|
|
45
|
+
outline-color: var(--color-fg-on-brand-strong);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="dark"] .dds-background__content {
|
|
49
|
+
color: var(--color-fg-on-brand-strong);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="light"] {
|
|
53
|
+
background-color: var(--color-bg-page);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="light"] .dds-background__canvas {
|
|
57
|
+
color: var(--color-bg-brand);
|
|
58
|
+
outline-color: var(--color-bg-brand);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
:where([data-dds-context="marketing"]) .dds-background[data-tone="light"] .dds-background__content {
|
|
62
|
+
color: var(--color-fg-default);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (prefers-reduced-motion: reduce) {
|
|
66
|
+
:where([data-dds-context="marketing"]) .dds-background,
|
|
67
|
+
:where([data-dds-context="marketing"]) .dds-background * { transition: none !important; }
|
|
68
|
+
}
|
|
69
|
+
|