@deriv-com/dds-marketing 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.llm/components/accordion.md +9 -1
- package/.llm/components/accordionitem.md +9 -1
- package/.llm/components/aspectratio.md +9 -1
- package/.llm/components/badge.md +9 -1
- package/.llm/components/bottomsheet.md +9 -1
- package/.llm/components/breadcrumb.md +9 -1
- package/.llm/components/breadcrumbitem.md +9 -1
- package/.llm/components/button.md +55 -27
- package/.llm/components/buttonicon.md +16 -8
- package/.llm/components/card.md +16 -2
- package/.llm/components/cardbody.md +29 -3
- package/.llm/components/cardbutton.md +16 -2
- package/.llm/components/checkbox.md +9 -1
- package/.llm/components/ctabanner.md +186 -0
- package/.llm/components/ctabannerslider.md +204 -0
- package/.llm/components/divider.md +9 -1
- package/.llm/components/dropdownmenu.md +15 -7
- package/.llm/components/faqaccordion.md +217 -0
- package/.llm/components/featurebullets.md +254 -0
- package/.llm/components/featurecards.md +313 -0
- package/.llm/components/featurescroll.md +284 -0
- package/.llm/components/featuresplit.md +249 -0
- package/.llm/components/filterchip.md +9 -1
- package/.llm/components/footer.md +9 -1
- package/.llm/components/footergroup.md +9 -1
- package/.llm/components/grid.md +9 -1
- package/.llm/components/icon.md +21 -3
- package/.llm/components/landinghero.md +254 -0
- package/.llm/components/link.md +13 -5
- package/.llm/components/logocolumns.md +235 -0
- package/.llm/components/logorows.md +212 -0
- package/.llm/components/menuitem.md +9 -1
- package/.llm/components/navbar.md +80 -16
- package/.llm/components/navbaritem.md +10 -2
- package/.llm/components/navbarmenu.md +9 -1
- package/.llm/components/navbarmenugroup.md +9 -1
- package/.llm/components/navbarpanel.md +10 -2
- package/.llm/components/navbarswitcher.md +10 -2
- package/.llm/components/navbarswitcheroption.md +9 -1
- package/.llm/components/option.md +9 -1
- package/.llm/components/pageheader.md +231 -0
- package/.llm/components/pagination.md +27 -90
- package/.llm/components/paginationdots.md +215 -0
- package/.llm/components/producthero.md +248 -0
- package/.llm/components/removablechip.md +9 -1
- package/.llm/components/row.md +9 -1
- package/.llm/components/scroller.md +9 -1
- package/.llm/components/searchinput.md +9 -1
- package/.llm/components/segmentedcontrol.md +9 -1
- package/.llm/components/segmentedcontrolitem.md +9 -1
- package/.llm/components/select.md +9 -1
- package/.llm/components/selectchip.md +57 -16
- package/.llm/components/spinner.md +9 -1
- package/.llm/components/stack.md +9 -1
- package/.llm/components/statusdot.md +9 -1
- package/.llm/components/subdomainnavbar.md +9 -1
- package/.llm/components/tab.md +11 -3
- package/.llm/components/table.md +9 -1
- package/.llm/components/tablebody.md +9 -1
- package/.llm/components/tablecell.md +9 -1
- package/.llm/components/tablehead.md +9 -1
- package/.llm/components/tableheadercell.md +9 -1
- package/.llm/components/tablerow.md +9 -1
- package/.llm/components/tablist.md +9 -1
- package/.llm/components/testimonialrow.md +235 -0
- package/.llm/components/testimonialslider.md +254 -0
- package/.llm/components/textarea.md +9 -1
- package/.llm/components/textinput.md +9 -1
- package/.llm/components/tooltip.md +9 -1
- package/.llm/components/typography.md +9 -1
- package/.llm/digest/button.md +11 -6
- package/.llm/digest/buttonicon.md +2 -2
- package/.llm/digest/card.md +1 -0
- package/.llm/digest/cardbody.md +3 -1
- package/.llm/digest/cardbutton.md +1 -0
- package/.llm/digest/ctabanner.md +44 -0
- package/.llm/digest/ctabannerslider.md +45 -0
- package/.llm/digest/dropdownmenu.md +1 -1
- package/.llm/digest/faqaccordion.md +43 -0
- package/.llm/digest/featurebullets.md +52 -0
- package/.llm/digest/featurecards.md +49 -0
- package/.llm/digest/featurescroll.md +52 -0
- package/.llm/digest/featuresplit.md +54 -0
- package/.llm/digest/landinghero.md +53 -0
- package/.llm/digest/logocolumns.md +55 -0
- package/.llm/digest/logorows.md +48 -0
- package/.llm/digest/navbar.md +18 -3
- package/.llm/digest/pageheader.md +49 -0
- package/.llm/digest/pagination.md +6 -17
- package/.llm/digest/paginationdots.md +43 -0
- package/.llm/digest/producthero.md +53 -0
- package/.llm/digest/selectchip.md +6 -1
- package/.llm/digest/testimonialrow.md +51 -0
- package/.llm/digest/testimonialslider.md +51 -0
- package/.llm/index.md +24 -3
- package/.llm/rules.md +43 -9
- package/.llm/tokens.md +56 -12
- package/AGENTS.md +32 -8
- package/README.md +41 -21
- package/dist/components/banner-data.d.ts +38 -0
- package/dist/components/banner-data.js +15 -0
- package/dist/components/blocks/block-reveal.css +90 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
- package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
- package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
- package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
- package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
- package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
- package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
- package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
- package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
- package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
- package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
- package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
- package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
- package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
- package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
- package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
- package/dist/components/blocks/page-header/PageHeader.css +79 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
- package/dist/components/blocks/page-header/PageHeader.js +43 -0
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
- package/dist/components/blocks/page-header/page-header-impl.css +176 -0
- package/dist/components/blocks/product-hero/ProductHero.css +86 -0
- package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
- package/dist/components/blocks/product-hero/ProductHero.js +48 -0
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
- package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
- package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
- package/dist/components/blocks/use-reveal.d.ts +46 -0
- package/dist/components/blocks/use-reveal.js +120 -0
- package/dist/components/blocks/use-rotation.d.ts +62 -0
- package/dist/components/blocks/use-rotation.js +176 -0
- package/dist/components/core/accordion-item/AccordionItem.css +6 -5
- package/dist/components/core/bottom-sheet/BottomSheet.css +1 -1
- package/dist/components/core/button/Button.css +63 -16
- package/dist/components/core/button/Button.d.ts +14 -12
- package/dist/components/core/button/Button.js +43 -14
- package/dist/components/core/button/Button.types.d.ts +9 -14
- package/dist/components/core/button/button-impl.css +25 -0
- package/dist/components/core/button-icon/ButtonIcon.css +31 -15
- package/dist/components/core/button-icon/ButtonIcon.d.ts +2 -2
- package/dist/components/core/button-icon/ButtonIcon.js +2 -2
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +4 -4
- package/dist/components/core/card/Card.css +13 -4
- package/dist/components/core/card/Card.types.d.ts +2 -1
- package/dist/components/core/card-body/CardBody.css +11 -6
- package/dist/components/core/card-body/CardBody.d.ts +1 -1
- package/dist/components/core/card-body/CardBody.js +2 -2
- package/dist/components/core/card-body/CardBody.types.d.ts +4 -1
- package/dist/components/core/card-body/CardBody.types.js +1 -0
- package/dist/components/core/card-button/CardButton.css +13 -4
- package/dist/components/core/card-button/CardButton.types.d.ts +2 -1
- package/dist/components/core/checkbox/Checkbox.css +8 -1
- package/dist/components/core/dropdown-menu/DropdownMenu.css +13 -12
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +5 -3
- package/dist/components/core/dropdown-menu/DropdownMenu.js +5 -3
- package/dist/components/core/filter-chip/FilterChip.css +2 -1
- package/dist/components/core/footer/footer-impl.css +1 -1
- package/dist/components/core/footer-group/FooterGroup.css +8 -7
- package/dist/components/core/icon/Icon.css +1 -1
- package/dist/components/core/link/Link.css +1 -1
- package/dist/components/core/link/Link.js +5 -5
- package/dist/components/core/menu-item/MenuItem.css +1 -1
- package/dist/components/core/navbar/Navbar.css +7 -8
- package/dist/components/core/navbar/Navbar.d.ts +17 -1
- package/dist/components/core/navbar/Navbar.js +139 -12
- package/dist/components/core/navbar/Navbar.types.d.ts +23 -4
- package/dist/components/core/navbar/Navbar.types.js +1 -1
- package/dist/components/core/navbar/navbar-impl.css +10 -3
- package/dist/components/core/navbar/navbar-material.css +96 -0
- package/dist/components/core/navbar-item/NavbarItem.css +4 -4
- package/dist/components/core/navbar-menu/NavbarMenu.css +7 -5
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +1 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +1 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +7 -7
- package/dist/components/core/navbar-switcher/NavbarSwitcher.css +6 -5
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +1 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +2 -1
- package/dist/components/core/option/Option.css +1 -1
- package/dist/components/core/pagination/Pagination.css +1 -75
- package/dist/components/core/pagination/Pagination.d.ts +4 -4
- package/dist/components/core/pagination/Pagination.js +11 -51
- package/dist/components/core/pagination/Pagination.types.d.ts +5 -17
- package/dist/components/core/pagination/Pagination.types.js +1 -3
- package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
- package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -0
- package/dist/components/core/removable-chip/RemovableChip.css +3 -3
- package/dist/components/core/search-input/SearchInput.css +1 -1
- package/dist/components/core/segmented-control/SegmentedControl.css +1 -1
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +1 -1
- package/dist/components/core/select/Select.css +2 -1
- package/dist/components/core/select-chip/SelectChip.css +14 -7
- package/dist/components/core/select-chip/SelectChip.d.ts +1 -1
- package/dist/components/core/select-chip/SelectChip.js +7 -4
- package/dist/components/core/select-chip/SelectChip.types.d.ts +7 -1
- package/dist/components/core/select-chip/SelectChip.types.js +1 -1
- package/dist/components/core/select-chip/select-chip-impl.css +14 -3
- package/dist/components/core/status-dot/StatusDot.css +1 -1
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +3 -3
- package/dist/components/core/tab/Tab.css +1 -1
- package/dist/components/core/tab/Tab.types.d.ts +1 -1
- package/dist/components/core/tab-list/TabList.css +1 -1
- package/dist/components/core/table/table-impl.css +36 -14
- package/dist/components/core/table-header-cell/TableHeaderCell.css +5 -5
- package/dist/components/core/text-area/TextArea.css +1 -1
- package/dist/components/core/text-input/TextInput.css +1 -1
- package/dist/components/core/tooltip/Tooltip.css +1 -1
- package/dist/components/core/typography/Typography.css +5 -5
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +30 -0
- package/dist/components/logo-data.d.ts +24 -0
- package/dist/components/logo-data.js +11 -0
- package/dist/components/scroll-data.d.ts +64 -0
- package/dist/components/scroll-data.js +17 -0
- package/dist/components/testimonial-row-data.d.ts +51 -0
- package/dist/components/testimonial-row-data.js +11 -0
- package/dist/components/testimonial-slider-data.d.ts +26 -0
- package/dist/components/testimonial-slider-data.js +10 -0
- package/dist/marketing.css +385 -14
- package/package.json +1 -6
package/.llm/index.md
CHANGED
|
@@ -22,7 +22,7 @@ Domain-neutral building blocks.
|
|
|
22
22
|
| 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
23
|
| 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
24
|
| 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 |
|
|
25
|
-
| Button | The call to action on a marketing page — the one step you want a visitor to take next · Moving a visitor along a funnel: hero to signup, pricing to checkout, feature page to demo booking · A destination prominent enough that it has to read as a control rather than as words in a sentence | The action
|
|
25
|
+
| Button | The call to action on a marketing page — the one step you want a visitor to take next · Moving a visitor along a funnel: hero to signup, pricing to checkout, feature page to demo booking · A destination prominent enough that it has to read as a control rather than as words in a sentence | The action belongs to an application surface — a trade form, a settings panel, a confirmation that removes something → nothing here · The words belong inside a sentence or a paragraph of body copy → `Link` · The control is a glyph alone, with no words → `ButtonIcon` |
|
|
26
26
|
| ButtonIcon | One press with no room for words — a promotional bar's dismiss, a hero's play control, a carousel step, a footer's social links. Whether it navigates or acts in place is decided by href alone, so the same component covers both · A row of glyph-alone destinations where words would only repeat — social accounts in a footer, app stores in a download band, a region switch in a header · A control the page owns rather than a destination — dismissing a promotional bar, playing a hero video, advancing a carousel, opening a mobile nav. Leave href off and it is a button, which answers Space and fires what the page says · The glyph is one a visitor reads without being taught — a play triangle, a dismiss cross, a chevron, a social mark in its monochrome cut. A marketing page gets no onboarding and usually no second visit to learn in · Room is genuinely short and the words would be the same words several times over. One of these on its own beside prose is usually a Button that lost its label | The control has words, or needs them to be understood → `Button` · The whole surface is the target — a card standing for a feature, a market or a plan → `CardButton` · The mark is an ornament rather than a control → `Icon` · The mark reports a state the visitor sets and reads back — sound on or off, a light and dark switch → nothing here |
|
|
27
27
|
| Card | Content that is read as one thing — a feature and the sentence explaining it, a plan and what it costs, a step and what it asks for · A picture that reaches the card's edges, with or without copy inset beneath it — a screenshot, a photograph, a band of art. The corner clips it, and the card adds no inset that would leave it floating in a margin · A row or a column of such groups, where the fill is what separates one from the next · A measure a landing page should not be choosing for itself: the corner a card takes and the ground it sits on · An editorial card — an article, a post, a story — where the picture and the headline do the separating and a fill would be a second, weaker edge. That is `plain`, which paints no ground and keeps the corner | The whole surface is the thing the reader presses → `CardButton` |
|
|
28
28
|
| CardBody | Words, a picture, or both inside a Card — a feature and the sentence explaining it, a screenshot under the copy that describes it · A photograph, render or screenshot that should reach the card's edges while the copy above it stays inset · A picture that should absorb whatever height the copy leaves, so a row of cards ends flush no matter how much each one says · A mark above the words — the glyph a feature card leads with, sized and inset with the copy rather than reaching the card's edges · Copy that sits over the picture rather than beside it — a photograph as the card's ground, with a title and a sentence washed over it · A line above the title filing the card under something — the date an article ran, how long it takes to read, the category it belongs to. It is set in capitals at the eyebrow step, which is what tells it apart from the copy without it needing a colour of its own | The whole card is one picture, with no words at all → `Card` |
|
|
@@ -37,6 +37,7 @@ Domain-neutral building blocks.
|
|
|
37
37
|
| 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` |
|
|
38
38
|
| NavbarMenuGroup | A section's panel holds more destinations than a reader takes in at once, and they fall into sets — markets, tools, payments · Two lists in a panel would be told apart by nothing if the words above them were taken away | The panel holds few enough destinations that naming sets would be naming one thing each → `NavbarItem` · The set is a section of the site rather than a set within one → `NavbarMenu` |
|
|
39
39
|
| Option | An answer inside a control that opens a list — a SelectChip today. One of these per option in the set | Pressing it should do something rather than record an answer → `MenuItem` · The row is one of a few and all of them fit on the page → `FilterChip` |
|
|
40
|
+
| PaginationDots | Showing where the reader is in a short sequence they move through — a slider's slides, a carousel of cards, the steps of a walkthrough — and letting them jump to any of it | A set divided into pages of results → `Pagination` |
|
|
40
41
|
| SearchInput | A help centre, a knowledge base, or documentation — more pages than a menu can carry · A blog or resource index a reader arrives at knowing roughly what they want · A directory the page already holds and can filter as the reader types — markets, offices, partners | The field is part of a form the reader will submit → nothing here · The set is small enough to show at once → nothing here · The reader is choosing from known options rather than describing what they want → nothing here |
|
|
41
42
|
| SegmentedControlItem | One option in a SegmentedControl — the thing a reader presses to change which of a few mutually exclusive values is in force · A choice worth showing beside its alternatives rather than hiding in a list, so the reader compares and picks in one glance | The option names a slice of the page the reader moves to rather than a value they set → `Tab` · The choice is on or off rather than one of several → `Button` · The option leads somewhere → `Link` |
|
|
42
43
|
| Select | A form asks for one answer out of a set the visitor recognises — a country, a language, the reason they are getting in touch · An index or a table is worth narrowing, and the choice reshapes the page rather than being submitted — the sort on a list of articles, the market a pricing table shows · The set is long enough that showing it in full would crowd the page, which is what separates this from a row of chips or a segmented control | The set is a handful and worth comparing side by side → `SegmentedControl` · The choices are destinations rather than answers → `DropdownMenu` · The reader can pick more than one → nothing here · The answer is not on the list, and typing one should stand → nothing here |
|
|
@@ -67,10 +68,10 @@ Domain-neutral building blocks.
|
|
|
67
68
|
| NavbarPanel | Navbar is collapsing and its destinations have to go somewhere. This is where, and the bar puts them here without being asked · The same navigation has to be read down a phone rather than across a page | The surface is a sheet rising from the foot of the page rather than the site's navigation → `BottomSheet` · What is wanted is a list that opens beside the control that opened it → `DropdownMenu` |
|
|
68
69
|
| NavbarSwitcher | A bar needs a language or region switcher, which is the case this was drawn for · A set of choices changes how the page is drawn or worded rather than taking a reader anywhere · The set is long enough that a phone should give it the whole panel rather than a dropdown inside one | The control opens a set of commands rather than a set of choices → `DropdownMenu` · The control flips between two states → `ButtonIcon` · The items are places the site has → `NavbarMenu` |
|
|
69
70
|
| NavbarSwitcherOption | A NavbarSwitcher needs its choices · One of a set of options is in force and a reader should be able to see which | The row goes somewhere → `NavbarItem` · The row is a command in a dropdown → `MenuItem` |
|
|
70
|
-
| Pagination | An index or archive has been split across pages and the reader needs to move through it — a blog listing, a news archive, a resource library. It belongs below the results, because the decision to move on is one the reader makes after reading what is here · The reader needs to reach a particular page rather than step towards it — page fourteen of forty, in one press. That is the pages variant, and the only one offering a target with a number on it. Where the row has no room for that number, the break standing in for it opens a menu of the pages it hides, so a page the row cannot show is two presses away rather than a walk · The pages have addresses a search engine should follow. Numbered targets drawn as links are how an index gets crawled past its first page, which on a marketing site is usually the reason the index exists
|
|
71
|
+
| Pagination | An index or archive has been split across pages and the reader needs to move through it — a blog listing, a news archive, a resource library. It belongs below the results, because the decision to move on is one the reader makes after reading what is here · The reader needs to reach a particular page rather than step towards it — page fourteen of forty, in one press. That is the pages variant, and the only one offering a target with a number on it. Where the row has no room for that number, the break standing in for it opens a menu of the pages it hides, so a page the row cannot show is two presses away rather than a walk · The pages have addresses a search engine should follow. Numbered targets drawn as links are how an index gets crawled past its first page, which on a marketing site is usually the reason the index exists | A short sequence the reader moves through — a slider's slides, a carousel of cards, a walkthrough → `PaginationDots` · The reader is moving between views of one page rather than through one long set → `TabList` · More results are appended to the view as the reader reaches the end, rather than one page replacing another → `Button` · The reader is hunting for one row among thousands rather than walking the set → `SearchInput` |
|
|
71
72
|
| RemovableChip | An index shows the narrowings currently applied above its results, and each has to come off on its own without clearing the rest · The reader has assembled something across a page — markets on a comparison, topics on a subscription form — and needs to see and unpick what is in it · What was chosen is worth showing as a token rather than as a sentence, because the reader will act on individual pieces of it | The token is turned on and off rather than added and taken away → `FilterChip` · The thing named cannot be taken away and is there to be read — a category on a card, a status on a plan → `Badge` · The token is really a link to the thing it names → `Link` |
|
|
72
73
|
| SegmentedControl | Two to four alternatives that exclude one another, where the whole set is worth showing at once and the reader decides by weighing them side by side rather than recalling which exist · What the reader picks becomes a value something next to it consumes — a period against which prices are quoted, a unit, a plan — which puts the control beside whatever it alters rather than at the head of the page · The alternatives are short enough to read across in a glance. A row is scanned, not worked through | The choice swaps a whole slice of the page rather than setting a value → `TabList` · The alternatives are separate topics rather than values of one question → `Accordion` · There are more than about four, or the labels need more than a word or two → `SelectChip` · The choice is on or off → `Button` · The reader may pick several of the options at once, or none → `FilterChip` |
|
|
73
|
-
| SelectChip | A row narrows an index by one value out of a set, and has to keep showing which value that is · The set is short enough to scan rather than search — a region, a language, a sort order · The row has no space for a form field: nothing above the control, nothing beneath it, only the answer | Pressing an item does something rather than answering something → `DropdownMenu` · The chip answers on its own, or the set is short enough for every answer to sit in the row as a chip of its own → `FilterChip` · Each answer is a page with its own address → `Link` |
|
|
74
|
+
| SelectChip | A row narrows an index by one value out of a set, and has to keep showing which value that is · The set is short enough to scan rather than search — a region, a language, a sort order · The row has no space for a form field: nothing above the control, nothing beneath it, only the answer · A view setting that always has an answer — a sort order, a language — where every answer is a way of looking rather than a way of leaving out | Pressing an item does something rather than answering something → `DropdownMenu` · The chip answers on its own, or the set is short enough for every answer to sit in the row as a chip of its own → `FilterChip` · Each answer is a page with its own address → `Link` |
|
|
74
75
|
| SubdomainNavbar | A subdomain needs its top-level navigation — the mark, the places that subdomain has, and whatever sits at the far end · The bar should sit still. Nothing about it changes as the page scrolls, which is what a reader working in a page rather than reading down one wants of the chrome above it · The destinations belong at the far end with what a reader reaches for, rather than centred over the page: the mark holds one edge, everything a reader does holds the other, and the middle is left empty on purpose | The page is the marketing site itself → `Navbar` · The items are versions of one thing rather than places the subdomain has → `TabList` |
|
|
75
76
|
| TabList | Two or three versions of one offer differ in a way a reader wants to compare — monthly against yearly, one platform against another · The page has already written every version, and showing them at once would be repetition rather than information · The reader's choice changes what they see and nothing else — no route, no account, nothing the page has to remember | The sections are separate topics rather than versions of one thing → `Accordion` · Every version is worth reading → `Card` · The tabs would go to other pages → nothing here |
|
|
76
77
|
|
|
@@ -84,3 +85,23 @@ Arrange other components and decide no appearance of their own.
|
|
|
84
85
|
| Row | Two or more things are read across rather than down, and the space between them is the same all the way along — a glyph and its label, a title and the action beside it, a set of controls · The spacing is a fact about the group rather than about any member of it. Set here, every item agrees; set on the items, the group is only as consistent as the last person to add one · The items are of different heights and something has to decide how they meet — centred on the line, level at the top, or sitting on one another's baseline. That decision belongs to the line rather than to any item on it | The things are read one above the next → `Stack` · The things must line up down the page as well as across it → `Grid` · The set is longer than the line and has to stay on one line → `Scroller` · The things across are the fields of one record, and the record repeats down the page → `Table` |
|
|
85
86
|
| Scroller | A set is longer than the space and its order is worth keeping — steps in a sequence, results already ranked, a timeline, a run of chips a reader is scanning rather than comparing · The things are of a kind and of a size, so a line of them reads as a line rather than as a row of unrelated objects that happen to be beside one another · Seeing part of the next item is what tells the reader there is more. A rail cut off mid-item is the affordance, and it is the one thing a wrapped line and a grid cannot offer | Everything fits, or should be made to fit → `Row` · The set may break onto a second line and nothing is lost by it → `Row` · The items should line up in columns as well → `Grid` · The region scrolls down rather than across → nothing here |
|
|
86
87
|
| Stack | Two or more things are read down the page in order and the space between them is the same the whole way down — an eyebrow, a headline and a line of copy; the points of a feature list; the rows of a plan · The spacing is a fact about the group rather than about any member of it. Set here, every row agrees; set on the rows, the group is only as consistent as the last person to add one · The measure should tighten on a phone without anyone writing a breakpoint. The top three steps of this ramp already do, so a column set at one of them is narrower below 768px and nothing about the page says so | The things sit beside one another rather than one above the next → `Row` · The things must line up across as well as down → `Grid` · The set has to stay on one line and the reader moves along it → `Scroller` |
|
|
88
|
+
|
|
89
|
+
## Blocks
|
|
90
|
+
|
|
91
|
+
The sections a page is built from, and the rhythm between them.
|
|
92
|
+
| Component | Use when | Not for |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| 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` |
|
|
95
|
+
| CtaBannerSlider | Rotating between two or three genuinely different promotions without a hero's weight — open an account, try a tool, download the app | One promotion → `CtaBanner` · The band that opens the page → `LandingHero` · A message with more than a headline, a line and a button or two → `FeatureSplit` |
|
|
96
|
+
| FaqAccordion | The questions a reader asks before acting — fees, limits, how long a withdrawal takes — near the end of a landing page or on a help page · Objections a page has to answer without making every reader read every answer | The answers are short enough to read all at once → `FeatureBullets` · Each item is a feature, not a question → `FeatureCards` |
|
|
97
|
+
| FeatureBullets | A page has to list what a product or a plan includes, and the list is the argument · Several benefits are each one line long and are read by scanning rather than reading · A claim needs something beside it, and a picture is the only thing there is to put there | The items are two or three words and belong on one line → `Badge` · Each item needs a heading and a paragraph of its own → `Card` · The section opens the page → `ProductHero` |
|
|
98
|
+
| FeatureCards | Three or four things a product does, each a heading and a sentence, read side by side and compared at a glance · A set of destinations — markets, platforms, tools — each a card a reader presses to go there · One feature that deserves the whole row in a card of its own — the words beside a large picture, carded on the section's ground | Each item is one line, and the list is the argument → `FeatureBullets` · One claim beside a picture, with no card around it → `FeatureSplit` · The items are read in order, one leading to the next → `FeatureScroll` |
|
|
99
|
+
| FeatureScroll | A page has three or more things of the same kind to explain, each with a picture worth a screen — the markets a broker offers, the platforms it runs, the steps of an account opening · The set is meant to be walked through rather than compared, and a reader is expected to scroll it · The set comes from somewhere — a CMS, a registry, a filtered list — rather than being written out by hand | There are three or four items a reader is meant to compare → `FeatureCards` · The set is lines rather than things — what an account includes → `FeatureBullets` · There is one point to make → `FeatureSplit` · The section opens the page → `LandingHero` |
|
|
100
|
+
| FeatureSplit | A page needs one more point about something it has already introduced, with a picture to carry it · The point is a sentence rather than a list, and does not earn a set of cards · A section needs a way onward that is not a call to action — a link to the page that says more | The point is several things the reader gets, each one line long → `FeatureBullets` · There are three or four points and each needs its own picture → `FeatureCards` · The section opens the page → `ProductHero` |
|
|
101
|
+
| LandingHero | A main landing page needs its opening band — the front page, or a campaign page under it · The claim has room to range to the reading edge with a subject beside it, which is what the landing tier is for · The steps between an eyebrow, a title, a description and the actions under them have to be the same on every landing page | The page is a product or a market page → `ProductHero` · The page is a company or a legal one — contact, about, terms → `PageHeader` · The band closes the page rather than opening it → `Footer` |
|
|
102
|
+
| LogoColumns | Showing the partners, integrations or payment methods behind a claim — the names a reader recognises, as evidence for what the words say · Eight or more logos, enough that each column reads as running on past both edges of the wall | A handful of logos a reader should be able to count and compare → `Grid` · One picture beside the claim → `FeatureSplit` · Each logo needs to be pressed — a partner directory → `FeatureCards` |
|
|
103
|
+
| LogoRows | Showing the partners, integrations or payment methods behind a claim under it, where the words lead and the logos follow · Eight or more logos, enough that each of the two rows reads as running on past both edges of the band | The logos should stand beside the claim, as a wall that is half the section → `LogoColumns` · A handful of logos a reader should be able to count and compare → `Grid` |
|
|
104
|
+
| PageHeader | A company, legal or support page needs its opening band — contact, about, terms, a regulatory notice · The page is read rather than acted on, so its opening should name it and then get out of the way · The steps between an eyebrow, a title and a description have to be the same on every such page | The page is the front page, or a campaign page under it → `LandingHero` · The page is a product or a market page → `ProductHero` · The band closes the page rather than opening it → `Footer` |
|
|
105
|
+
| ProductHero | A product or a market page needs its opening band — a platform, an instrument, an asset class · The thing the page is about is worth showing whole, under the claim rather than beside it · The steps between an eyebrow, a title, a description and the actions under them have to be the same on every product page | The page is the front page, or a campaign page under it → `LandingHero` · The page is a company or a legal one — contact, about, terms → `PageHeader` · The band closes the page rather than opening it → `Footer` |
|
|
106
|
+
| TestimonialRow | Five to ten short, rated reviews collected by a review service, where seeing several at once is the point and the overall score is worth stating · A page that has made its claims and wants customers' own ratings to back them — a homepage's "What our customers say" | Two to five quotes the page chose, from partners or customers, each a few sentences and read one at a time → `TestimonialSlider` · A single review → `FeatureSplit` |
|
|
107
|
+
| TestimonialSlider | Two to five real quotes from partners or customers, each a few sentences, read one at a time · A page that has made its claims and wants someone other than the brand to back them | A single quote → `FeatureSplit` · Ratings and review counts from a review site → `TestimonialRow` |
|
package/.llm/rules.md
CHANGED
|
@@ -25,7 +25,7 @@ Guidance only — cannot be checked automatically.
|
|
|
25
25
|
|
|
26
26
|
### Never nest one interactive element inside another
|
|
27
27
|
|
|
28
|
-
Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link,
|
|
28
|
+
Nested interactive elements produce ambiguous hit targets and an unreachable inner control for keyboard and screen-reader users. This is why the rule cannot live on any single component — it constrains Button, Link, CardButton and TextInput simultaneously.
|
|
29
29
|
|
|
30
30
|
Guidance only — cannot be checked automatically.
|
|
31
31
|
|
|
@@ -95,28 +95,62 @@ Declared rather than emergent. Padding plus contents does clear 24px in several
|
|
|
95
95
|
|
|
96
96
|
Guidance only — cannot be checked automatically.
|
|
97
97
|
|
|
98
|
+
### A component is written along the reading axis, not along the page's left and right
|
|
99
|
+
|
|
100
|
+
Every measure, inset and placement in this package names an axis rather than a side: inline-size and block-size, padding-inline and padding-block, inset-inline-start and inset-block-end, margin-inline: auto, text-align: start. Written that way a component follows whichever direction the page is read in, and a band whose claim ranges to the leading edge with its subject on the trailing one is the same composition in Arabic as in English, mirrored, with nothing restated. Written as left and right it is the same pixels in both, which is a layout nobody designed for the second language.
|
|
101
|
+
|
|
102
|
+
The enum values follow the same rule and for the same reason. A prop that names where a picture sits takes start and end, never left and right — FeatureSplit, FeatureBullets and FeatureScroll all declare mediaPosition that way, and the flex directions they generate flip on their own because row already means the reading order. A value called left would have to be re-read as right by every author working in a mirrored page, which is a translation this system should be doing rather than asking for.
|
|
103
|
+
|
|
104
|
+
The guidance a contract carries is part of the component, so it follows too. Describing a claim as ranging left is describing one of the two languages, and it was written that way here for a while: three of the opening bands said so in their own intent. A reader in a mirrored page meets that sentence and has to decide whether the component is wrong or the sentence is, and neither answer is one documentation should force.
|
|
105
|
+
|
|
106
|
+
Two things genuinely have no logical form and are not covered by this. A CSS gradient takes a physical direction — there is no to inline-end — so a pattern that must mirror has to be stated twice under a direction query, and one that is periodic and centred, like PageHeader's rule grid, does not need to. A glyph that points the way onward is the other: an arrow is a picture of a direction, and mirroring it belongs to the icon set rather than to the component holding it.
|
|
107
|
+
|
|
108
|
+
Guidance only — cannot be checked automatically.
|
|
109
|
+
|
|
98
110
|
## Component rules
|
|
99
111
|
|
|
100
|
-
###
|
|
112
|
+
### Light weight needs size to survive, and the largest step wants it (`Icon`)
|
|
113
|
+
|
|
114
|
+
Quill ships every system glyph three times — light, regular and solid — as separate components chosen at the import site. Icon has no weight prop and cannot have one, so nothing in this system can observe the choice, let alone enforce it.
|
|
115
|
+
|
|
116
|
+
Size settles the light weight, from both ends. At xs its thinnest strokes fall below a pixel and drop out, leaving a shape that reads as broken rather than as light, so light belongs at md and above. At the top of the ramp it is the better weight rather than merely an allowed one: a glyph carries its stroke weight through any scale, so a regular glyph drawn for 24px renders its strokes at twice that width at xl, and reads as heavy rather than confident. A marketing page puts glyphs at that size — a callout, a highlighted block — where a product screen rarely does, which is why this half is Marketing's own. At rest, regular from sm through lg, and light at xl.
|
|
101
117
|
|
|
102
|
-
|
|
118
|
+
What size does not settle is regular against solid. That is a question about what the glyph means, and icon-weight-within-a-set answers it. This rule previously claimed size decided all three, and named steps above xl that the ramp no longer has — the first is the fault Product's version of this rule was corrected for.
|
|
103
119
|
|
|
104
120
|
Guidance only — cannot be checked automatically.
|
|
105
121
|
|
|
106
|
-
###
|
|
122
|
+
### In a set of icons, weight marks the current one (`Icon`)
|
|
107
123
|
|
|
108
|
-
|
|
124
|
+
Quill ships every system glyph three times — light, regular and solid — as separate components chosen at the import site, and Icon has no weight prop, so nothing here can observe the choice.
|
|
125
|
+
|
|
126
|
+
Within a set of sibling icons — a row of tabs, a segmented control — the weight is what says which one is current: regular at rest, solid once selected, the same glyph at the same size so the shape stays recognisable and simply fills in. That is the one cue for selection that does not depend on colour, and it survives only while nothing else in the set is solid. Reaching for solid inside a set because it looks better spends it.
|
|
127
|
+
|
|
128
|
+
Outside a set there is nothing to distinguish, and solid claims nothing about selection. The arrow after a standalone link, a mark beside a heading, an icon in a button — none of these sit among siblings competing to be current, and a filled shape is recognised faster than an outlined one, which is the reason to show a glyph rather than words.
|
|
129
|
+
|
|
130
|
+
This replaces a rule that said solid means selected everywhere. Marketing has more lone glyphs than Product and fewer sets, so the broad version cost it most: Link's solid arrow had to be recorded as an exception to it, when the arrow was never the case the rule protects.
|
|
109
131
|
|
|
110
132
|
Guidance only — cannot be checked automatically.
|
|
111
133
|
|
|
112
|
-
###
|
|
134
|
+
### A navigation bar holds at most two buttons: one primary, and one secondary beside it (`Button`)
|
|
135
|
+
|
|
136
|
+
The bar's actions are the conversion and the way back in for a reader who already has an account — sign up and log in. That is two things, and they rank: the one the site wants is primary and the other is secondary. A third button is a third thing the bar is asking for, and a row of three pills beside a mark and a set of destinations stops reading as a pair of actions and starts reading as a second navigation.
|
|
137
|
+
|
|
138
|
+
A single button is the primary. Alone, there is nothing for a secondary to be quieter than, and a bar whose only action is the quiet one has hidden the thing it exists to offer. Two buttons are one primary and one secondary, never two of either: two primaries are two demands, and two secondaries leave the reader to guess which one the site meant.
|
|
113
139
|
|
|
114
|
-
|
|
140
|
+
A switcher is not a button here — a DropdownMenu or a ButtonIcon for the language or the theme — and does not count against the two.
|
|
141
|
+
|
|
142
|
+
Guidance rather than a count. The bar is drawn with a second copy of an action in compactAction for narrow widths, and a count of Buttons under Navbar cannot tell that slot from utilities or a ranked pair from two primaries. Navbar checks the pair itself, on what utilities is handed, and says so in the console.
|
|
115
143
|
|
|
116
144
|
Guidance only — cannot be checked automatically.
|
|
117
145
|
|
|
118
|
-
### At most one primary button
|
|
146
|
+
### At most one primary button in a group of actions (`Button`)
|
|
147
|
+
|
|
148
|
+
Two brand fills side by side ask the visitor to choose between two things that look equally urgent, and nothing tells them which one the page wants. So a group of actions — a hero's pair, a banner's pair, the buttons in a navigation bar — leads with at most one primary, and whatever sits beside it is secondary.
|
|
149
|
+
|
|
150
|
+
The limit belongs to the group, not the page. A landing page asks for the same thing more than once on purpose: the sign-up in the bar, again under the opening claim, again in a banner halfway down and in the closing band. Each of those is one ask repeated where the reader has arrived, not a second ask competing with the first, and a rule that counted primaries across the page would forbid the thing a marketing page is built to do. This rule came from Product as one primary per view, and there it is right: a view is one screen with one task, and two primaries on it really are two tasks. On a page that scrolls through several sections the view is the wrong unit. The group is the one a reader compares.
|
|
151
|
+
|
|
152
|
+
The group can lose its primary without a second one appearing. Inverse on the ordinary page ground carries roughly six times the contrast of the brand, so the primary beside it stops reading as the primary — the same fault, reached from the other side.
|
|
119
153
|
|
|
120
|
-
|
|
154
|
+
A navigation bar is the group with the tightest limit, and navbar-actions-are-a-pair states it: two buttons at most, one of each.
|
|
121
155
|
|
|
122
156
|
Machine-checkable — `dds lint` will enforce this once built.
|
package/.llm/tokens.md
CHANGED
|
@@ -13,16 +13,19 @@ one value at every width.
|
|
|
13
13
|
|
|
14
14
|
- `--color-bg-active` — Pressed state for interactive elements. Alpha-based like the hover and one step heavier, so it tints whatever surface it lands on — ink on light and paper on dark.
|
|
15
15
|
- `--color-bg-active-inverse` — Pressed state for an interactive element on a surface that runs against the mode, one step heavier than color.bg.hover-inverse. The mirror of color.bg.active, and paired with it on the same reasoning.
|
|
16
|
-
- `--color-bg-brand` —
|
|
16
|
+
- `--color-bg-active-on-brand-strong` — Pressed state for an interactive element standing on color.bg.brand-strong, one step heavier than color.bg.hover-on-brand-strong. White at eight in both modes. For a surface that flips with the mode use color.bg.active-inverse.
|
|
17
|
+
- `--color-bg-band-subtle` — A recessed band across the page, e.g. a section of steps or features set apart from the ones around it. gray.50 in light, white at six in dark. For a fill inside a control — a secondary button, a badge — use color.bg.subtle.
|
|
18
|
+
- `--color-bg-brand` — Primary action surface, e.g. sign-up button, hero CTA, promotional banner. The same coral in light and dark; pair with color.fg.on-brand for text.
|
|
17
19
|
- `--color-bg-brand-active` — Pressed state for color.bg.brand. One step further along the ramp than the hover, in the same direction, so a press reads as more of what the hover began.
|
|
18
20
|
- `--color-bg-brand-hover` — Hover state for color.bg.brand.
|
|
19
|
-
- `--color-bg-brand-strong` — A dark
|
|
21
|
+
- `--color-bg-brand-strong` — A dark surface, for a band breaking a long page or a card carrying more weight than its neighbours, e.g. a feature band, the footer. gray.950 in light and dark alike, so the band is the same wherever it is drawn. Pair with color.fg.on-brand-strong for text.
|
|
20
22
|
- `--color-bg-brand-subtle` — A brand ground quiet enough to read dark ink on. The solid coral takes white at 3.39:1 and is waived for a word; this pairs with color.fg.brand well past the bar, so a mark can be brand-coloured without spending the waiver.
|
|
21
23
|
- `--color-bg-danger` — Destructive action surface, e.g. cancel subscription, delete account. Pair with color.fg.on-solid for text.
|
|
22
24
|
- `--color-bg-danger-subtle` — Lightweight danger fill, e.g. error banners, danger badges. Pair with color.fg.danger for text.
|
|
23
25
|
- `--color-bg-field` — The ground of a control a reader types into or picks from — a text field, a select, an upload zone. An alpha, so it can never come out the same colour as the container holding it, which a solid can. For the container itself use color.bg.surface.
|
|
24
26
|
- `--color-bg-hover` — Hover state for interactive elements. Alpha-based, so it tints whatever surface it lands on rather than replacing it — ink on light and paper on dark, because a black alpha on a dark surface darkens what is already dark and reads as nothing at all.
|
|
25
27
|
- `--color-bg-hover-inverse` — Hover for an interactive element on a surface that runs against the mode — a dark chip in light. The mirror of color.bg.hover, which tints with the mode and so shows nothing on a ground the mode did not paint. Use color.bg.hover where the mode paints the ground.
|
|
28
|
+
- `--color-bg-hover-on-brand-strong` — Hover for an interactive element standing on color.bg.brand-strong, e.g. a navigation item or a plain icon button on a dark hero. White at four in both modes, because the band does not change. For a surface that flips with the mode use color.bg.hover-inverse.
|
|
26
29
|
- `--color-bg-info` — Informational surface, e.g. info banners, tips. Pair with color.fg.on-solid for text.
|
|
27
30
|
- `--color-bg-info-subtle` — Lightweight info fill, e.g. info badges, inline notices. Pair with color.fg.info for text.
|
|
28
31
|
- `--color-bg-overlay` — Scrim behind modal dialogs and drawers. Blocks interaction with content beneath.
|
|
@@ -31,14 +34,26 @@ one value at every width.
|
|
|
31
34
|
- `--color-bg-readonly` — A field whose value is fixed but still worth reading. Lighter than the disabled ground and at full contrast, which is the distinction: readonly is legible and settled, disabled recedes because it is not actionable.
|
|
32
35
|
- `--color-bg-selected` — The active or current item in a set of choices, e.g. selected nav item, current tab, highlighted row. Not for recessive areas — use color.bg.subtle.
|
|
33
36
|
- `--color-bg-strong` — Inverted neutral fill for an action that has to outrank everything around it — near-black in light and pure white in dark, the highest contrast the page can carry. Not a section ground: a band takes bg.subtle, bg.brand-strong or bg.brand. Pair with color.fg.on-strong.
|
|
34
|
-
- `--color-bg-
|
|
37
|
+
- `--color-bg-strong-on-brand` — The solid fill of a control on color.bg.brand, e.g. the primary action on the coral band. Near-black in both modes, because the band does not change — unlike color.bg.strong, which turns white in dark.
|
|
38
|
+
- `--color-bg-subtle` — A recessive fill inside a control or a small area, e.g. a secondary button, a neutral badge. For a band across the page use color.bg.band-subtle; for selected items, color.bg.selected.
|
|
39
|
+
- `--color-bg-subtle-on-brand-strong` — A recessive fill on a painted band — color.bg.brand-strong or the coral color.bg.brand — e.g. a secondary button there. White at six in both modes; hover and press layer color.bg.hover-on-brand-strong and color.bg.active-on-brand-strong over it.
|
|
35
40
|
- `--color-bg-success` — Confirmation surface, e.g. sign-up complete, payment confirmed. Pair with color.fg.on-solid for text.
|
|
36
41
|
- `--color-bg-success-subtle` — Lightweight success fill, e.g. success banners, success badges. Pair with color.fg.success for text.
|
|
37
42
|
- `--color-bg-surface` — A card on the page: one step from the ground, so it reads as recessed against the page and raised on a subtle band. For a card that floats above the page, color.bg.surface-raised.
|
|
43
|
+
- `--color-bg-surface-card-light` — A light card that stays light whatever the theme, e.g. a surface-light Card or CardButton set among dark ones. gray.50 in both modes. Pair with color.fg.on-surface-card-light; for a card that follows the theme use color.bg.surface.
|
|
44
|
+
- `--color-bg-surface-card-light-raised` — The light card on a subtle band. White in light mode, where the band is the light card's own gray.50 and it would vanish; gray.50 in dark, where the band is a tint over near-black. Pair with color.fg.on-surface-card-light.
|
|
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
|
+
- `--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
|
+
- `--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.
|
|
38
48
|
- `--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.
|
|
39
49
|
- `--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.
|
|
40
50
|
- `--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.
|
|
41
51
|
- `--color-bg-surface-raised-inverse` — A raised surface on a ground that runs against the mode — a navigation bar's pill on a dark hero. An alpha rather than a grey step: a hero is often a photograph or a brand colour, which a solid surface would clash with.
|
|
52
|
+
- `--color-bg-surface-raised-on-brand-strong` — A raised surface on color.bg.brand-strong, e.g. the navigation bar's pill on a dark hero. White at twenty-four in both modes, because the band does not change. For one that flips with the mode use color.bg.surface-raised-inverse.
|
|
53
|
+
- `--color-bg-surface-translucent` — The base of a see-through surface with a blur behind it, e.g. the navigation bar's pill. Nearly opaque in its own ink — white in light, black in dark — so what scrolls behind cannot set its colour. color.bg.surface-translucent-tint goes over it.
|
|
54
|
+
- `--color-bg-surface-translucent-on-brand-strong` — The base of a see-through surface on color.bg.brand-strong, e.g. the navigation bar's pill on a dark hero. Black at eighty-eight in both modes, so a light photograph behind cannot wash it out.
|
|
55
|
+
- `--color-bg-surface-translucent-tint` — The lift laid over color.bg.surface-translucent, e.g. the navigation bar's pill. None in light, where the base is already the surface; white at sixteen in dark, which is what makes the pill read as a surface over the page.
|
|
56
|
+
- `--color-bg-surface-translucent-tint-on-brand-strong` — The lift laid over color.bg.surface-translucent-on-brand-strong, e.g. the navigation bar's pill on a dark hero. White at twelve in both modes, because the band does not change.
|
|
42
57
|
- `--color-bg-track` — The channel a thing travels or fills along — a grab handle on a sheet, a rail. An alpha rather than a ramp step, so it darkens whatever is behind it and stays a groove on a raised panel, where a fixed grey would stop matching the moment the surface changed.
|
|
43
58
|
- `--color-bg-track-active` — Pressed state for the same mark. One step further than the hover, in the same direction, so a press always reads as more than a hover.
|
|
44
59
|
- `--color-bg-track-hover` — Hover state for a mark drawn in color.bg.track, which is the only thing in this colour that hovers — a track itself never does. One step more ink, so a pointer over the mark reads as more, never less. An alpha like the track, so it keeps tinting what is behind it.
|
|
@@ -49,6 +64,7 @@ one value at every width.
|
|
|
49
64
|
- `--color-border-default` — Standard border for containers and controls, e.g. input outlines, grouped sections.
|
|
50
65
|
- `--color-border-focus` — The keyboard focus indicator — a border on some controls, a ring on others. Never remove: required for accessibility. Neutral rather than blue, so it is never mistaken for the danger a control is also able to show. Inverts by mode.
|
|
51
66
|
- `--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
|
+
- `--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.
|
|
52
68
|
- `--color-border-info` — Informational accent border, e.g. info banner edge, highlighted section.
|
|
53
69
|
- `--color-border-strong` — Emphasised border for active or prominent elements, e.g. active input, selected card edge.
|
|
54
70
|
- `--color-border-subtle` — A quiet separator, e.g. dividers, table rules. Alpha-based — works on any surface.
|
|
@@ -63,9 +79,12 @@ one value at every width.
|
|
|
63
79
|
- `--color-fg-info` — Informational text on neutral surfaces, e.g. links, tips, contextual help.
|
|
64
80
|
- `--color-fg-muted` — Supporting copy, e.g. subheadings, feature descriptions, form labels. Not for content the user must read to act.
|
|
65
81
|
- `--color-fg-muted-inverse` — Supporting copy on a dark ground, e.g. a footer's group labels. White at sixty-four, so it takes the hue of whatever the band is painted rather than sitting cool against a warm one — and so it stays muted on any dark ground instead of on one.
|
|
82
|
+
- `--color-fg-on-brand` — Text and marks on color.bg.brand, e.g. a primary button's label, a checked accent checkbox's tick. White in light and dark alike, because the brand fill does not change with the theme. For other solid fills — danger, success, info — use color.fg.on-solid.
|
|
66
83
|
- `--color-fg-on-brand-strong` — Text and glyphs on color.bg.brand-strong. White in both modes, that surface being dark in both — unlike color.fg.on-solid, which follows the theme.
|
|
67
|
-
- `--color-fg-on-solid` — Text on solid
|
|
84
|
+
- `--color-fg-on-solid` — Text on solid status fills, e.g. danger, success, info buttons and badges. For text on color.bg.brand use color.fg.on-brand; on neutral surfaces use color.fg.default.
|
|
68
85
|
- `--color-fg-on-strong` — Text on color.bg.strong. The opposite extreme from the fill, so the pair is always near-black on white or white on near-black.
|
|
86
|
+
- `--color-fg-on-strong-on-brand` — Text and glyphs on color.bg.strong-on-brand, the near-black fill on the coral band. White in both modes, because the fill does not change — unlike color.fg.on-strong, which follows the theme.
|
|
87
|
+
- `--color-fg-on-surface-card-light` — Text on color.bg.surface-card-light, e.g. a surface-light card's title and copy. gray.950 in both modes, because the card does not change. On the page's own ground use color.fg.default.
|
|
69
88
|
- `--color-fg-on-warning` — Text on a warning surface. Always dark because the warning background is bright in both modes.
|
|
70
89
|
- `--color-fg-required` — The mark that says a field must be filled. The same red as fg.danger and a role of its own, because required is not a verdict — a field carrying an asterisk has not failed anything yet.
|
|
71
90
|
- `--color-fg-success` — Positive text on neutral surfaces, e.g. profit values, confirmation messages.
|
|
@@ -74,7 +93,7 @@ one value at every width.
|
|
|
74
93
|
|
|
75
94
|
## space
|
|
76
95
|
|
|
77
|
-
- `--space-actions-gap`
|
|
96
|
+
- `--space-actions-gap` — The step between two calls to action standing side by side. Eight: they are one decision offered two ways, not two decisions, and the reference design sets them this close on every band. Sixteen read as two separate offers.
|
|
78
97
|
- `--space-control-lg` — Side padding inside a large pill control. Half of size.control.lg, on the same reasoning as the default step. It coincides with space.inset.lg today and is still its own role: one follows a control's height, the other a section's rhythm, and they are free to move apart.
|
|
79
98
|
- `--space-control-md` — Side padding inside a default-size pill control. Half of size.control.md, so the corner radius and the padding are one measure and a label starts where the curve stops. The inset scale has no step here — its steps answer to sections, not to a control's geometry.
|
|
80
99
|
- `--space-control-sm` — Side padding inside a small pill control. Half of size.control.sm, on the same reasoning as the default step — the corner radius and the padding are one measure, so a label starts where the curve stops.
|
|
@@ -88,7 +107,7 @@ one value at every width.
|
|
|
88
107
|
- `--space-gap-xs` — Tightest gap between related elements, e.g. icon and label, inline text pairs.
|
|
89
108
|
- `--space-grid-gutter` **adapts** — The space between two cards, across and down. One value on both axes, so a grid reads as an even field rather than as rows with a seam between them.
|
|
90
109
|
- `--space-heading-content` **adapts** — Between a heading group and the content it introduces, stacked or side by side. Measured from the last part the group actually shows, so a section opens the same way whether or not every part is present.
|
|
91
|
-
- `--space-heading-description-actions`
|
|
110
|
+
- `--space-heading-description-actions` — The step from a description down to what a reader can do about it. Twenty-four, which is the reference design's step on every opening band, and what the mobile override already said.
|
|
92
111
|
- `--space-heading-eyebrow-title` **adapts** — Between an eyebrow and the title under it. The tightest step in the group, because an eyebrow reads as the title's first line rather than as a line of its own.
|
|
93
112
|
- `--space-heading-title-description` — Between a display title and the description under it. Smaller than it looks: a title's leading and descender depth sit inside the gap, and both scale with the type, so a smaller title takes the compact step instead.
|
|
94
113
|
- `--space-heading-title-description-compact` — The same step under a title that is not a display size — a card's, a panel's. Half the measure because the leading above it is half as deep, and what the eye reads is this plus that leading.
|
|
@@ -108,6 +127,9 @@ one value at every width.
|
|
|
108
127
|
|
|
109
128
|
## size
|
|
110
129
|
|
|
130
|
+
- `--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
|
+
- `--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
|
+
- `--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.
|
|
111
133
|
- `--size-bar-height` — The height of a collapsed navigation bar, which both bars here take. Declared rather than left to what a page hands the bar: an action beside the mark would otherwise set it.
|
|
112
134
|
- `--size-breakpoint-lg` — Where a bar has room for its destinations. A value to read, not a condition to write: `var()` is not allowed in a query, so the seven stylesheets that bend here still carry 64rem themselves.
|
|
113
135
|
- `--size-breakpoint-md` — Where the phone's type layer stops — the mobile overrides resolve below it, so 767 is the last width that reads as a phone. A value to read, not a condition to write: `var()` is not allowed in a media query.
|
|
@@ -116,17 +138,25 @@ one value at every width.
|
|
|
116
138
|
- `--size-control-lg` — Height of a large control, for a hero or a conversion band. Twice space.control.lg, on the same reasoning as the default step.
|
|
117
139
|
- `--size-control-md` — Height of a default-size control, the same measure product gives its own default. Twice space.control.md, so on a pill the corner radius and the side padding are one measure and a label starts where the curve stops.
|
|
118
140
|
- `--size-control-sm` — Height of a small control — a picker in a navigation bar, a field in a filter row. Half of it is space.control.sm and a quarter is radius.control.sm, the ratio every step of this ramp holds. Desktop only: below what a finger reliably hits.
|
|
141
|
+
- `--size-dot-current` — How wide the current mark in a row of dots stretches, against size.dot.diameter for the rest — a pill three dots long, so where the reader is reads by shape.
|
|
119
142
|
- `--size-dot-diameter` — The mark standing in for one page of a short sequence, or for a status beside a name. Eight: small enough that a row of ten reads as a row rather than as ten controls, and large enough to find at arm's length.
|
|
120
143
|
- `--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.
|
|
121
144
|
- `--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.
|
|
122
145
|
- `--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.
|
|
123
146
|
- `--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
|
+
- `--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
|
+
- `--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.
|
|
124
149
|
- `--size-measure-description` — How wide a supporting description runs. Wider than a title because it is read rather than taken in, and narrower than long-form because it sits under something.
|
|
150
|
+
- `--size-measure-heading` — The width a centred heading block is held to. Narrower than the page measure, because a title centred across the full 1280 is read from a different edge on every line.
|
|
151
|
+
- `--size-measure-hero-description` — How wide the description under an opening band's title runs, e.g. in LandingHero, ProductHero, PageHeader. Wider than size.measure.description because it is set larger and read once, at the top.
|
|
152
|
+
- `--size-measure-hero-heading` — The width the text column of a band that opens a page is held to, e.g. PageHeader's title and actions. Wider than size.measure.heading because a page's name is set at h1 and 846 breaks it early.
|
|
125
153
|
- `--size-measure-long-form` — How wide running text runs. Past this the eye loses the line it was on when it returns to the left edge, which is the whole reason a measure exists.
|
|
126
154
|
- `--size-measure-title` — How wide a title runs before it wraps. A starting point — eighteen to twenty-four after a look. `ch` is the width of the font's zero, so it is a measure rather than a letter count, and typed string because a Figma variable carries a number.
|
|
127
155
|
- `--size-menu-panel-max` — The widest a section's menu panel gets. Narrower than the page's own measure on purpose: a panel is scanned across with a pointer already on it, and one as wide as the page leaves its last column a long way from the name that opened it.
|
|
128
156
|
- `--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.
|
|
129
157
|
- `--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
|
+
- `--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.
|
|
159
|
+
- `--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.
|
|
130
160
|
- `--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.
|
|
131
161
|
- `--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.
|
|
132
162
|
- `--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.
|
|
@@ -139,6 +169,7 @@ one value at every width.
|
|
|
139
169
|
- `--size-spinner-sm` — Spinner diameter at size sm. Sixteen, which is the size of the body copy it sits beside — an indicator in a line of text reads as part of the line rather than as something dropped into it.
|
|
140
170
|
- `--size-switcher-panel-width` — The width of a switcher's floating panel. Stated because the panel is out of flow and would otherwise shrink to the trigger it hangs from, wrapping every choice and running the set down the page.
|
|
141
171
|
- `--size-target-min` — The smallest a thing a pointer has to hit may be. Bind it as a minimum on any control whose size would otherwise come from its contents — a pressable card is as big as its words, and one holding a single short line is smaller than a fingertip.
|
|
172
|
+
- `--size-testimonial-art` — The decorative pictures in a TestimonialSlider's corners, as squares. Large enough to read as pictures, small enough to leave the card the quote's.
|
|
142
173
|
- `--size-tooltip-max` — The widest a tooltip gets before its text wraps. Short enough that the eye finds the start of the next line without hunting for it, which is the whole job of a measure — and a tooltip that needs more than two lines is a tooltip carrying something that belongs on the page.
|
|
143
174
|
|
|
144
175
|
## radius
|
|
@@ -189,12 +220,18 @@ one value at every width.
|
|
|
189
220
|
- `--font-body-sm-line-height`
|
|
190
221
|
- `--font-body-sm-size`
|
|
191
222
|
- `--font-body-sm-weight`
|
|
192
|
-
- `font.eyebrow` —
|
|
193
|
-
- `--font-eyebrow-family`
|
|
194
|
-
- `--font-eyebrow-letter-spacing`
|
|
195
|
-
- `--font-eyebrow-line-height`
|
|
196
|
-
- `--font-eyebrow-size`
|
|
197
|
-
- `--font-eyebrow-weight`
|
|
223
|
+
- `font.eyebrow.lg` — The line that leads into a display claim on an opening band, sized against the heading under it rather than against body text. Sentence case, unlike the small step: capitals are what make a twelve-pixel label a label, and at this size they shout.
|
|
224
|
+
- `--font-eyebrow-lg-family`
|
|
225
|
+
- `--font-eyebrow-lg-letter-spacing`
|
|
226
|
+
- `--font-eyebrow-lg-line-height`
|
|
227
|
+
- `--font-eyebrow-lg-size` **adapts**
|
|
228
|
+
- `--font-eyebrow-lg-weight`
|
|
229
|
+
- `font.eyebrow.sm` — Uppercase category labels above a headline — section tags, plan badges, feature categories. Carries the size, weight and wide tracking that setting needs; the capitals are the component's, through text-transform, which leaves the accessible name in the case it was written.
|
|
230
|
+
- `--font-eyebrow-sm-family`
|
|
231
|
+
- `--font-eyebrow-sm-letter-spacing`
|
|
232
|
+
- `--font-eyebrow-sm-line-height`
|
|
233
|
+
- `--font-eyebrow-sm-size`
|
|
234
|
+
- `--font-eyebrow-sm-weight`
|
|
198
235
|
- `font.field-label.lg` — The words naming a field in a large form, the step that pairs with a large control. Sized with the field it sits above, weighted like every other step of this role.
|
|
199
236
|
- `--font-field-label-lg-family`
|
|
200
237
|
- `--font-field-label-lg-letter-spacing`
|
|
@@ -310,7 +347,9 @@ one value at every width.
|
|
|
310
347
|
|
|
311
348
|
## motion
|
|
312
349
|
|
|
350
|
+
- `--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.
|
|
313
351
|
- `--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.
|
|
352
|
+
- `--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.
|
|
314
353
|
- `--motion-duration-fast` — Direct user actions that should feel instant, e.g. hover, press, toggle.
|
|
315
354
|
- `--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.
|
|
316
355
|
- `--motion-duration-media-hover` — How long art takes to settle inside a frame that holds still. Longer than duration.normal, which suits a card that lifts and is over; a picture that zooms is still on screen when it stops and the eye follows it the whole way.
|
|
@@ -320,6 +359,7 @@ one value at every width.
|
|
|
320
359
|
- `--motion-duration-shift` — A surface rearranging itself between two resting states on the reader's scroll — a navigation bar gathering, and ungathering on the way back. Longer than a UI element entering, because nobody asked for it.
|
|
321
360
|
- `--motion-duration-slow` — Large UI transitions, e.g. accordions expanding, page transitions, interactive demos.
|
|
322
361
|
- `--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
|
+
- `--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.
|
|
323
363
|
- `--motion-easing-enter` — UI elements arriving on screen — decelerates into place, e.g. dropdown opening, tooltip appearing.
|
|
324
364
|
- `--motion-easing-exit` — UI elements leaving the screen — accelerates away, e.g. menu closing, notification dismissing.
|
|
325
365
|
- `--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.
|
|
@@ -327,15 +367,19 @@ one value at every width.
|
|
|
327
367
|
- `--motion-easing-shift` — Symmetric, for a change that runs both ways: a bar gathering on scroll and ungathering on the way back should read the same in each direction, which easing.standard cannot do.
|
|
328
368
|
- `--motion-easing-spinner` — Constant-speed rotation for a spinner. Linear because a loop is the one case with no arrival to ease into — any acceleration lands a seam at the point the animation restarts, and the eye finds it on the second turn.
|
|
329
369
|
- `--motion-easing-standard` — Default easing for anything moving within the viewport. Use this unless the element is specifically entering, exiting, or revealing.
|
|
370
|
+
- `--motion-scale-band-exit` — How far an opening band draws back as it scrolls out. Its own role rather than motion.scale.enter, which is named for something arriving.
|
|
330
371
|
- `--motion-scale-enter` — What a component scales from when something reveals it — a tooltip appearing. Needs a transform origin on the edge nearest its anchor, or it grows out of its own middle. The counterpart to scale.hover, which is a response rather than an entrance.
|
|
331
372
|
- `--motion-scale-hover` — How much a control grows under the cursor on hover. Deliberately small — a control that grows past the pointer fires its own mouse-out.
|
|
332
373
|
- `--motion-scale-media-hover` — How much art grows inside a frame that holds still — an editorial card's picture under the cursor. Twice motion.scale.hover, which stays smaller because a control can outrun its own pointer and a framed picture cannot.
|
|
333
374
|
- `--motion-translate-enter` — Where a surface waits before something reveals it: level on the inline axis, its own full height down the block one. A share of the element rather than of the page, so a sheet travels exactly its own height whatever that turns out to be.
|
|
334
375
|
- `--motion-translate-hover` — How far a pressable surface rises under the cursor. A fixed distance rather than a share of the element, so a tall card and a short one lift by the same amount and a row of them stays level. Small enough that nothing it sits beside looks disturbed.
|
|
376
|
+
- `--motion-translate-reveal` — How far a section waits below where it lands, before the scroll brings it up. A fixed distance rather than a share of the block, so a hero a screen tall and a split half that arrive by the same movement. Pairs with motion.easing.reveal.
|
|
335
377
|
|
|
336
378
|
## opacity
|
|
337
379
|
|
|
338
380
|
- `--opacity-disabled` — How far a control recedes when it is unavailable. Applied to the control as a whole rather than re-colouring its parts, so what is inside keeps its relationships and the whole thing reads as one unavailable object.
|
|
381
|
+
- `--opacity-dot-current` — The position in a row of dots that the reader is on — the ground's own ink at full strength, stretched into a pill so the current one is told apart by shape as well as by weight.
|
|
382
|
+
- `--opacity-dot-rest` — The positions in a row of dots that the reader is not on, e.g. a slider's other slides. Drawn in the ground's own ink at forty-eight, so the row reads on any band without a colour of its own.
|
|
339
383
|
- `--opacity-hidden` — What a component fades from when something reveals it. Not a dimming treatment — something unavailable or quiet says so in its own colour role, where the contrast checker can see it. The first entry in a group this package had left empty.
|
|
340
384
|
- `--opacity-muted` — A mark at rest, before a pointer reaches it. For artwork that carries its own colours and so cannot be quietened by an ink role — a brand logo, a partner mark — where every other quiet thing in this system says so in colour.
|
|
341
385
|
- `--opacity-track` — How far a track recedes behind the thing travelling over it. Both are drawn in one colour, so this alpha is the only thing separating them — which is why it is a ratio and not a colour role.
|
package/AGENTS.md
CHANGED
|
@@ -32,9 +32,14 @@ and Red Hat Mono but cannot carry the files. An app that already self-hosts the
|
|
|
32
32
|
(next/font, Fontsource) skips `fonts.css` and sets `--font-family-sans` /
|
|
33
33
|
`--font-family-mono` instead; the README covers that path.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Dark is `data-theme="dark"` on any ancestor, usually `<html>`. Both themes live in that one
|
|
36
|
+
stylesheet — there is no second import and no provider. The two attributes are independent:
|
|
37
|
+
the theme can sit above the scope, on the same element as it, or below it.
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<html data-theme="dark">
|
|
41
|
+
<body><div data-dds-context="marketing"> <!-- dark, from here down --></div></body>
|
|
42
|
+
```
|
|
38
43
|
|
|
39
44
|
## Server Components
|
|
40
45
|
|
|
@@ -48,16 +53,17 @@ a component you give `onChange` or `onClick` to goes in a file of your own that
|
|
|
48
53
|
|
|
49
54
|
## Rules that span components
|
|
50
55
|
|
|
56
|
+
- **A component is written along the reading axis, not along the page's left and right**
|
|
57
|
+
- **A navigation bar holds at most two buttons: one primary, and one secondary beside it**
|
|
51
58
|
- **A section that paints a ground sets the ink to go with it**
|
|
52
59
|
- **A section's title is centred over stacked content, starts beside content in columns, and starts on a phone**
|
|
53
60
|
- **Anything a pointer has to hit is at least 24px in both directions**
|
|
54
|
-
- **At most one primary button
|
|
55
|
-
- **Destructive actions require a confirmation step**
|
|
61
|
+
- **At most one primary button in a group of actions**
|
|
56
62
|
- **Every gap inside a section names the relationship it expresses, and the same relationship keeps its measure when it turns on its side**
|
|
57
63
|
- **Never nest one interactive element inside another**
|
|
58
64
|
- **On a phone a section's actions stack and each fills the width, including when there is only one**
|
|
59
|
-
- **
|
|
60
|
-
- **
|
|
65
|
+
- **In a set of icons, weight marks the current one** *(guidance)*
|
|
66
|
+
- **Light weight needs size to survive, and the largest step wants it** *(guidance)*
|
|
61
67
|
|
|
62
68
|
Reasons and the cases each one turns on: `.llm/rules.md`.
|
|
63
69
|
|
|
@@ -101,6 +107,7 @@ screen is built in is not something to reach for while building a control.
|
|
|
101
107
|
- **NavbarSwitcherOption** — A NavbarSwitcher needs its choices
|
|
102
108
|
- **Option** — An answer inside a control that opens a list
|
|
103
109
|
- **Pagination** — An index or archive has been split across pages and the reader needs to move through it
|
|
110
|
+
- **PaginationDots** — Showing where the reader is in a short sequence they move through
|
|
104
111
|
- **RemovableChip** — An index shows the narrowings currently applied above its results, and each has to come off on its own without clearing the rest
|
|
105
112
|
- **SearchInput** — A help centre, a knowledge base, or documentation
|
|
106
113
|
- **SegmentedControl** — Two to four alternatives that exclude one another, where the whole set is worth showing at once and the reader decides by weighing them side by side rather than recalling which exist
|
|
@@ -131,6 +138,23 @@ screen is built in is not something to reach for while building a control.
|
|
|
131
138
|
- **Scroller** — A set is longer than the space and its order is worth keeping
|
|
132
139
|
- **Stack** — Two or more things are read down the page in order and the space between them is the same the whole way down
|
|
133
140
|
|
|
141
|
+
### Blocks — the sections a page is built from, and the rhythm between them
|
|
142
|
+
|
|
143
|
+
- **CtaBanner** — A short, high-contrast promotion with one clear action
|
|
144
|
+
- **CtaBannerSlider** — Rotating between two or three genuinely different promotions without a hero's weight
|
|
145
|
+
- **FaqAccordion** — The questions a reader asks before acting
|
|
146
|
+
- **FeatureBullets** — A page has to list what a product or a plan includes, and the list is the argument
|
|
147
|
+
- **FeatureCards** — Three or four things a product does, each a heading and a sentence, read side by side and compared at a glance
|
|
148
|
+
- **FeatureScroll** — A page has three or more things of the same kind to explain, each with a picture worth a screen
|
|
149
|
+
- **FeatureSplit** — A page needs one more point about something it has already introduced, with a picture to carry it
|
|
150
|
+
- **LandingHero** — A main landing page needs its opening band
|
|
151
|
+
- **LogoColumns** — Showing the partners, integrations or payment methods behind a claim
|
|
152
|
+
- **LogoRows** — Showing the partners, integrations or payment methods behind a claim under it, where the words lead and the logos follow
|
|
153
|
+
- **PageHeader** — A company, legal or support page needs its opening band
|
|
154
|
+
- **ProductHero** — A product or a market page needs its opening band
|
|
155
|
+
- **TestimonialRow** — Five to ten short, rated reviews collected by a review service, where seeing several at once is the point and the overall score is worth stating
|
|
156
|
+
- **TestimonialSlider** — Two to five real quotes from partners or customers, each a few sentences, read one at a time
|
|
157
|
+
|
|
134
158
|
## Components that need mounting
|
|
135
159
|
|
|
136
160
|
These do not work from the import alone. Each has a Behaviour section in its own document
|
|
@@ -143,7 +167,7 @@ saying what to mount and where.
|
|
|
143
167
|
## Reading order
|
|
144
168
|
|
|
145
169
|
1. This file.
|
|
146
|
-
2. `.llm/rules.md` before writing anything —
|
|
170
|
+
2. `.llm/rules.md` before writing anything — 5,200 tokens, and it is where the constraints
|
|
147
171
|
that no single component can state live.
|
|
148
172
|
3. `.llm/digest/<name>.md` for every component you are using — **all of it, not the part
|
|
149
173
|
you were looking for**. Around 1,400 tokens each: what it is for, what to reach for
|
package/README.md
CHANGED
|
@@ -6,10 +6,12 @@ pages, pricing, sign-up.
|
|
|
6
6
|
**Working with an AI agent?** Point it at [`AGENTS.md`](./AGENTS.md) in this package. It is
|
|
7
7
|
the short version of everything below and says which of the `.llm/` documents to open.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
It has two kinds of component: **core** components — Button, Navbar, Card, Link, the form
|
|
10
|
+
controls and the rest — and **blocks**, the bands a page is built from: `LandingHero`,
|
|
11
|
+
`ProductHero` and `PageHeader` to open a page, and `FeatureSplit`, `FeatureBullets` and
|
|
12
|
+
`FeatureScroll` for the sections under it. `AGENTS.md` lists every one of them with a line
|
|
13
|
+
on when to reach for it. Product apps want
|
|
14
|
+
[`@deriv-com/dds-product`](https://www.npmjs.com/package/@deriv-com/dds-product).
|
|
13
15
|
|
|
14
16
|
## Install
|
|
15
17
|
|
|
@@ -26,19 +28,37 @@ npm install react react-dom @deriv-com/quill-icons-web
|
|
|
26
28
|
|
|
27
29
|
## Use
|
|
28
30
|
|
|
29
|
-
Import the stylesheet once, at the root of your app
|
|
31
|
+
Import the stylesheet once, at the root of your app. It defines every token this package's
|
|
32
|
+
components bind to — without it they render unstyled.
|
|
30
33
|
|
|
31
34
|
```tsx
|
|
32
35
|
import '@deriv-com/dds-marketing/marketing.css'
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
Then put `data-dds-context="marketing"` on whatever wraps the components — the app root, or
|
|
39
|
+
the section, if marketing and product live on one page. Component rules are published only
|
|
40
|
+
inside that scope, because both packages emit classes like `.dds-button` and one would
|
|
41
|
+
otherwise paint the other. Without it the components render unstyled too.
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
Then import components by name:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { Button, LandingHero } from '@deriv-com/dds-marketing'
|
|
47
|
+
|
|
48
|
+
export function Home() {
|
|
49
|
+
return (
|
|
50
|
+
<div data-dds-context="marketing">
|
|
51
|
+
<LandingHero
|
|
52
|
+
title="Trade smarter with Deriv"
|
|
53
|
+
description="Access 250+ markets with tight spreads and powerful tools."
|
|
54
|
+
actions={<Button href="/signup">Get started free</Button>}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Each component brings its own stylesheet with it, so nothing else needs importing.
|
|
42
62
|
|
|
43
63
|
## Fonts
|
|
44
64
|
|
|
@@ -74,20 +94,20 @@ Every type role reads its family from these two variables, so this redirects the
|
|
|
74
94
|
system at once. Load weights 400–700 for Inter (a variable font covers this in one file);
|
|
75
95
|
a missing weight does not fall back visibly — the browser synthesises a faux bold instead.
|
|
76
96
|
|
|
77
|
-
##
|
|
78
|
-
|
|
79
|
-
`marketing.css` ships light only. It contains no `[data-theme="dark"]` block, so setting
|
|
80
|
-
that attribute — anywhere, including on `<html>` for the rest of your app — leaves these
|
|
81
|
-
components light. There is nothing to configure and nothing to guard against.
|
|
97
|
+
## Light and dark, and a viewport axis
|
|
82
98
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
publishes in its own manifest:
|
|
99
|
+
`marketing.css` defines both themes. Dark is selected by `data-theme="dark"` on any
|
|
100
|
+
ancestor — usually `<html>`:
|
|
86
101
|
|
|
87
|
-
```
|
|
88
|
-
|
|
102
|
+
```html
|
|
103
|
+
<html data-theme="dark">
|
|
104
|
+
<body>
|
|
105
|
+
<div data-dds-context="marketing"> <!-- dark, from here down -->
|
|
89
106
|
```
|
|
90
107
|
|
|
108
|
+
The theme attribute and the context attribute are independent, and the theme may sit above
|
|
109
|
+
the scope, on the same element, or below it. There is no provider and no second import.
|
|
110
|
+
|
|
91
111
|
Marketing does carry a mobile viewport axis: seven roles take different values below
|
|
92
112
|
768px, applied automatically and overridable with `data-dds-viewport="mobile"` or
|
|
93
113
|
`"desktop"` when a page renders a device frame inside a wider window.
|