@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
|
@@ -147,7 +147,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
147
147
|
|
|
148
148
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
149
149
|
Guidance only — cannot be checked automatically.
|
|
150
|
-
- **Never nest one interactive element inside another** — 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,
|
|
150
|
+
- **Never nest one interactive element inside another** — 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.
|
|
151
151
|
Guidance only — cannot be checked automatically.
|
|
152
152
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
153
153
|
|
|
@@ -199,6 +199,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
199
199
|
|
|
200
200
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
201
201
|
Guidance only — cannot be checked automatically.
|
|
202
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
203
|
+
|
|
204
|
+
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.
|
|
205
|
+
|
|
206
|
+
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.
|
|
207
|
+
|
|
208
|
+
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.
|
|
209
|
+
Guidance only — cannot be checked automatically.
|
|
202
210
|
|
|
203
211
|
## Anti-examples
|
|
204
212
|
|
|
@@ -128,7 +128,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
128
128
|
|
|
129
129
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
130
130
|
Guidance only — cannot be checked automatically.
|
|
131
|
-
- **Never nest one interactive element inside another** — 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,
|
|
131
|
+
- **Never nest one interactive element inside another** — 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.
|
|
132
132
|
Guidance only — cannot be checked automatically.
|
|
133
133
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
134
134
|
|
|
@@ -180,6 +180,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
180
180
|
|
|
181
181
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
182
182
|
Guidance only — cannot be checked automatically.
|
|
183
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
184
|
+
|
|
185
|
+
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.
|
|
186
|
+
|
|
187
|
+
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.
|
|
188
|
+
|
|
189
|
+
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.
|
|
190
|
+
Guidance only — cannot be checked automatically.
|
|
183
191
|
|
|
184
192
|
## Anti-examples
|
|
185
193
|
|
|
@@ -268,7 +268,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
268
268
|
|
|
269
269
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
270
270
|
Guidance only — cannot be checked automatically.
|
|
271
|
-
- **Never nest one interactive element inside another** — 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,
|
|
271
|
+
- **Never nest one interactive element inside another** — 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.
|
|
272
272
|
Guidance only — cannot be checked automatically.
|
|
273
273
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
274
274
|
|
|
@@ -320,6 +320,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
320
320
|
|
|
321
321
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
322
322
|
Guidance only — cannot be checked automatically.
|
|
323
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
324
|
+
|
|
325
|
+
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.
|
|
326
|
+
|
|
327
|
+
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.
|
|
328
|
+
|
|
329
|
+
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.
|
|
330
|
+
Guidance only — cannot be checked automatically.
|
|
323
331
|
|
|
324
332
|
## Anti-examples
|
|
325
333
|
|
|
@@ -9,6 +9,7 @@ A chip that opens a list of answers and keeps the one chosen, so a filter row sh
|
|
|
9
9
|
- A row narrows an index by one value out of a set, and has to keep showing which value that is
|
|
10
10
|
- The set is short enough to scan rather than search — a region, a language, a sort order
|
|
11
11
|
- The row has no space for a form field: nothing above the control, nothing beneath it, only the answer
|
|
12
|
+
- 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
|
|
12
13
|
|
|
13
14
|
## Do not use
|
|
14
15
|
|
|
@@ -24,9 +25,9 @@ A chip that opens a list of answers and keeps the one chosen, so a filter row sh
|
|
|
24
25
|
SelectChip renders 6 elements. A token binding names the part it applies to.
|
|
25
26
|
|
|
26
27
|
- `root` — `<div>`, class `dds-selectchip`. Holds the chip and the list, and nothing else. `position: relative`, which is what the list is absolute against — so it is pinned to the chip that opened it and travels with it rather than with the page. Inline, because a chip sits in a row of other chips: a block root would take the width of whatever contains it and put the chip alone on a line.
|
|
27
|
-
- `trigger` — `<button>`, class `dds-selectchip__trigger`. The chip itself, and the only thing pressed. A button inside the root rather than the root being one, because the list is a sibling that has to be positioned against something — and a button containing its own popup is a control inside a control. It says a list opens and whether it is open, which a chevron says to the eye and to nobody else. Whether anything has been chosen is this control's own to know rather than a prop it is handed, so it travels as a state on this element instead of an axis on the root: the answer comes from the value, and a prop beside it could disagree with it. At rest it wears the same white ground and hairline edge a FilterChip does, and once an answer is in it, the same dark ground a chosen FilterChip takes — the two say the same thing and should not say it two ways.
|
|
28
|
+
- `trigger` — `<button>`, class `dds-selectchip__trigger`. The chip itself, and the only thing pressed. A button inside the root rather than the root being one, because the list is a sibling that has to be positioned against something — and a button containing its own popup is a control inside a control. It says a list opens and whether it is open, which a chevron says to the eye and to nobody else. Whether anything has been chosen is this control's own to know rather than a prop it is handed, so it travels as a state on this element instead of an axis on the root: the answer comes from the value, and a prop beside it could disagree with it. At rest it wears the same white ground and hairline edge a FilterChip does, and once an answer is in it and the chip is highlight, the same dark ground a chosen FilterChip takes — the two say the same thing and should not say it two ways.
|
|
28
29
|
- `trigger-icon` — `<span>`, class `dds-selectchip__trigger-icon`. A glyph before the words, naming the kind of narrowing. Its own part because a Quill glyph ships width and height attributes on the svg and only a rule on that element overrides them. Rendered only when `leadingIcon` is set.
|
|
29
|
-
- `trigger-label` — `<span>`, class `dds-selectchip__trigger-label`. What is being narrowed by, and what is chosen where anything is. The value belongs here rather than in a second slot: a token reading "Sort: Newest" is one thing to read, and a name beside a separate value is two. It truncates rather than wrapping, because a chip is one line in a row of them. Its figures are tabular: a chip carrying a number — a year, a count — is one whose words change while the row around it stays put, and proportional digits are not the same width, so a 1 becoming a 2 would resize the chip and shift every chip after it.
|
|
30
|
+
- `trigger-label` — `<span>`, class `dds-selectchip__trigger-label`. What is being narrowed by, and what is chosen where anything is. A quiet chip shows both, as "Sort: Newest"; a highlight chip shows the answer alone, because its fill already says a narrowing is on. The value belongs here rather than in a second slot: a token reading "Sort: Newest" is one thing to read, and a name beside a separate value is two. It truncates rather than wrapping, because a chip is one line in a row of them. Its figures are tabular: a chip carrying a number — a year, a count — is one whose words change while the row around it stays put, and proportional digits are not the same width, so a 1 becoming a 2 would resize the chip and shift every chip after it.
|
|
30
31
|
- `chevron` — `<svg>`, class `dds-selectchip__chevron`. The chevron that says a list is behind this. Always drawn, and that is the whole promise the component makes: a chip without one is a toggle, and one that showed a chevron and opened nothing would teach the reader not to trust the row. It turns while the list is open, which is the same fact aria-expanded carries for a reader who cannot see it. Drawn through Icon rather than sized here — a Quill glyph ships width and height attributes, and only a rule on that element beats them. The step it takes is the chip's own, the same one its leading glyph takes, so the two ends of a chip are one size.
|
|
31
32
|
- `listbox` — `<ul>`, class `dds-selectchip__listbox`. The answers on offer. One element carrying the fill, the corner, the shadow, the inset and the ceiling before it scrolls. It takes the same surface a DropdownMenu takes in this package — same corner, same inset, same shadow — because two floating lists that differ by a few pixels read as a mistake rather than as a distinction. Announced as a listbox, which is what tells a reader these are things to choose between rather than things to do, and what makes the arrow keys mean what they mean. Absent when shut rather than hidden, so nothing beneath it is covered by something nobody can see and no answer is reachable by a reader running past a shut chip. As wide as its longest answer with the chip's width as a floor: this list is a different object from the chip that opened it, and an answer reading "Most recent first" cannot be cut to fit a chip reading "Sort". One edge is pinned and the other let go, and which one is the alignment axis. It always opens downwards — a chip near the foot of the screen should open upwards instead, and nothing here does that yet, the same gap DropdownMenu has. It is not a prop: which side a list opens on is a fact about the room left below the chip at that moment, which a page cannot assert and cannot keep true through a scroll. Rendered only when `open` is set.
|
|
32
33
|
|
|
@@ -60,9 +61,17 @@ Never for: Marking one chip in a row as more important. They are a set of equals
|
|
|
60
61
|
Use when: Which edge the list is pinned to. The other edge is let go, so the list is as wide as its longest answer with the chip's width as a floor.
|
|
61
62
|
Never for: Nudging the list into place a few pixels. It names an edge to line up, not an offset
|
|
62
63
|
|
|
64
|
+
### emphasis — `highlight` | `quiet` (default `highlight`)
|
|
65
|
+
|
|
66
|
+
- `highlight` — A filter. Choosing an answer hides part of the list, like a category, a topic or a product line. The chip fills to show a filter is on
|
|
67
|
+
- `quiet` — A setting that only changes how the page is shown, like a sort order, a language or a layout. Nothing is hidden, so the chip stays plain and reads "Label: Value". Always give it a starting value with value or defaultValue
|
|
68
|
+
|
|
69
|
+
Use when: Whether the chip fills once an answer is chosen. Ask one question: does choosing an answer hide anything? If it does, it is a filter and the chip is highlight. If it only changes how the page is shown, it is a setting and the chip is quiet.
|
|
70
|
+
Never for: Making one chip in a row look more important than the others. Decide by what the chip does to the page, not by how much it matters. Having a starting value does not make a chip quiet either: a status filter that starts on Open still hides the closed ones, so it stays highlight
|
|
71
|
+
|
|
63
72
|
### label — `string` **Required.**
|
|
64
73
|
|
|
65
|
-
Use when: Always, and required on that account — it names what is being chosen, and it is what the chip shows until something has been. Short enough to read at a glance in a row of other chips
|
|
74
|
+
Use when: Always, and required on that account — it names what is being chosen, and it is what the chip shows until something has been, and what a quiet chip goes on showing ahead of the answer. Short enough to read at a glance in a row of other chips
|
|
66
75
|
Never for: Describing what pressing it does. The chip names the narrowing, and what happens is that a list opens
|
|
67
76
|
|
|
68
77
|
### value — `string`
|
|
@@ -144,7 +153,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
144
153
|
|
|
145
154
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
146
155
|
Guidance only — cannot be checked automatically.
|
|
147
|
-
- **Never nest one interactive element inside another** — 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,
|
|
156
|
+
- **Never nest one interactive element inside another** — 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.
|
|
148
157
|
Guidance only — cannot be checked automatically.
|
|
149
158
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
150
159
|
|
|
@@ -196,6 +205,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
196
205
|
|
|
197
206
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
198
207
|
Guidance only — cannot be checked automatically.
|
|
208
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
209
|
+
|
|
210
|
+
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.
|
|
211
|
+
|
|
212
|
+
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.
|
|
213
|
+
|
|
214
|
+
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.
|
|
215
|
+
Guidance only — cannot be checked automatically.
|
|
199
216
|
|
|
200
217
|
## Anti-examples
|
|
201
218
|
|
|
@@ -219,7 +236,7 @@ Declared rather than emergent. Padding plus contents does clear 24px in several
|
|
|
219
236
|
```tsx
|
|
220
237
|
import { SelectChip, Option } from '@deriv-com/dds-marketing'
|
|
221
238
|
|
|
222
|
-
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" defaultValue="newest">
|
|
239
|
+
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" emphasis="quiet" defaultValue="newest">
|
|
223
240
|
<Option value="newest">Newest first</Option>
|
|
224
241
|
<Option value="oldest">Oldest first</Option>
|
|
225
242
|
<Option value="popular">Most read</Option>
|
|
@@ -232,7 +249,7 @@ import { SelectChip, Option } from '@deriv-com/dds-marketing'
|
|
|
232
249
|
|
|
233
250
|
// Controlled: SelectChip reports the value, not the event.
|
|
234
251
|
const [value, setValue] = useState('')
|
|
235
|
-
<SelectChip label="Sort" value={value} onChange={setValue} onOpenChange={(open) => { /* your handler */ }}>
|
|
252
|
+
<SelectChip label="Sort" emphasis="quiet" value={value} onChange={setValue} onOpenChange={(open) => { /* your handler */ }}>
|
|
236
253
|
<Option value="newest">Newest first</Option>
|
|
237
254
|
<Option value="oldest">Oldest first</Option>
|
|
238
255
|
<Option value="popular">Most read</Option>
|
|
@@ -241,26 +258,50 @@ const [value, setValue] = useState('')
|
|
|
241
258
|
|
|
242
259
|
## In use
|
|
243
260
|
|
|
261
|
+
Most rows below hold the same set, written once here:
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
import { Option } from '@deriv-com/dds-marketing'
|
|
265
|
+
|
|
266
|
+
const options = (
|
|
267
|
+
<>
|
|
268
|
+
<Option value="newest">Newest first</Option>
|
|
269
|
+
<Option value="oldest">Oldest first</Option>
|
|
270
|
+
<Option value="popular">Most read</Option>
|
|
271
|
+
</>
|
|
272
|
+
)
|
|
273
|
+
```
|
|
274
|
+
|
|
244
275
|
### Before and after an answer
|
|
245
276
|
|
|
246
277
|
The chip names the narrowing until one is chosen, and carries the answer afterwards. A row of these reads as decisions made rather than filters available.
|
|
247
278
|
|
|
248
279
|
```tsx
|
|
249
|
-
import {
|
|
280
|
+
import { SelectChip } from '@deriv-com/dds-marketing'
|
|
250
281
|
|
|
251
282
|
// Nothing chosen — the chip is the name of the filter
|
|
252
|
-
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort">
|
|
253
|
-
<Option value="newest">Newest first</Option>
|
|
254
|
-
<Option value="oldest">Oldest first</Option>
|
|
255
|
-
<Option value="popular">Most read</Option>
|
|
256
|
-
</SelectChip>
|
|
283
|
+
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" emphasis="quiet">{options}</SelectChip>
|
|
257
284
|
|
|
258
285
|
// Answered — the chip carries the answer
|
|
259
|
-
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" defaultValue="popular">
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
286
|
+
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" emphasis="quiet" defaultValue="popular">{options}</SelectChip>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### A filter, or a setting
|
|
290
|
+
|
|
291
|
+
Highlight is for a filter. Choosing hides some items, so the chip fills with colour. Quiet is for a setting that only changes the view, like sorting. The chip stays plain and reads "Sort: Most read".
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { Option, SelectChip } from '@deriv-com/dds-marketing'
|
|
295
|
+
|
|
296
|
+
// Highlight — a filter: shows one topic, hides the rest
|
|
297
|
+
<SelectChip onChange={(value) => { /* your handler */ }} label="Topic" emphasis="highlight" defaultValue="trading">
|
|
298
|
+
<Option value="trading">Trading</Option>
|
|
299
|
+
<Option value="markets">Markets</Option>
|
|
300
|
+
<Option value="company">Company news</Option>
|
|
263
301
|
</SelectChip>
|
|
302
|
+
|
|
303
|
+
// Quiet — a setting: changes the order, nothing is hidden
|
|
304
|
+
<SelectChip onChange={(value) => { /* your handler */ }} label="Sort" emphasis="quiet" defaultValue="popular">{options}</SelectChip>
|
|
264
305
|
```
|
|
265
306
|
|
|
266
307
|
### Which edge the list is pinned to
|
|
@@ -94,7 +94,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
94
94
|
|
|
95
95
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
96
96
|
Guidance only — cannot be checked automatically.
|
|
97
|
-
- **Never nest one interactive element inside another** — 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,
|
|
97
|
+
- **Never nest one interactive element inside another** — 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.
|
|
98
98
|
Guidance only — cannot be checked automatically.
|
|
99
99
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
100
100
|
|
|
@@ -146,6 +146,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
146
146
|
|
|
147
147
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
148
148
|
Guidance only — cannot be checked automatically.
|
|
149
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
150
|
+
|
|
151
|
+
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.
|
|
152
|
+
|
|
153
|
+
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.
|
|
154
|
+
|
|
155
|
+
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.
|
|
156
|
+
Guidance only — cannot be checked automatically.
|
|
149
157
|
|
|
150
158
|
## Anti-examples
|
|
151
159
|
|
package/.llm/components/stack.md
CHANGED
|
@@ -117,7 +117,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
117
117
|
|
|
118
118
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
119
119
|
Guidance only — cannot be checked automatically.
|
|
120
|
-
- **Never nest one interactive element inside another** — 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,
|
|
120
|
+
- **Never nest one interactive element inside another** — 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.
|
|
121
121
|
Guidance only — cannot be checked automatically.
|
|
122
122
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
123
123
|
|
|
@@ -169,6 +169,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
169
169
|
|
|
170
170
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
171
171
|
Guidance only — cannot be checked automatically.
|
|
172
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
173
|
+
|
|
174
|
+
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.
|
|
175
|
+
|
|
176
|
+
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.
|
|
177
|
+
|
|
178
|
+
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.
|
|
179
|
+
Guidance only — cannot be checked automatically.
|
|
172
180
|
|
|
173
181
|
## Anti-examples
|
|
174
182
|
|
|
@@ -81,7 +81,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
81
81
|
|
|
82
82
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
83
83
|
Guidance only — cannot be checked automatically.
|
|
84
|
-
- **Never nest one interactive element inside another** — 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,
|
|
84
|
+
- **Never nest one interactive element inside another** — 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.
|
|
85
85
|
Guidance only — cannot be checked automatically.
|
|
86
86
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
87
87
|
|
|
@@ -133,6 +133,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
133
133
|
|
|
134
134
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
135
135
|
Guidance only — cannot be checked automatically.
|
|
136
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
137
|
+
|
|
138
|
+
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.
|
|
139
|
+
|
|
140
|
+
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.
|
|
141
|
+
|
|
142
|
+
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.
|
|
143
|
+
Guidance only — cannot be checked automatically.
|
|
136
144
|
|
|
137
145
|
## Anti-examples
|
|
138
146
|
|
|
@@ -169,7 +169,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
169
169
|
|
|
170
170
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
171
171
|
Guidance only — cannot be checked automatically.
|
|
172
|
-
- **Never nest one interactive element inside another** — 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,
|
|
172
|
+
- **Never nest one interactive element inside another** — 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.
|
|
173
173
|
Guidance only — cannot be checked automatically.
|
|
174
174
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
175
175
|
|
|
@@ -221,6 +221,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
221
221
|
|
|
222
222
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
223
223
|
Guidance only — cannot be checked automatically.
|
|
224
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
225
|
+
|
|
226
|
+
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.
|
|
227
|
+
|
|
228
|
+
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.
|
|
229
|
+
|
|
230
|
+
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.
|
|
231
|
+
Guidance only — cannot be checked automatically.
|
|
224
232
|
|
|
225
233
|
## Anti-examples
|
|
226
234
|
|
package/.llm/components/tab.md
CHANGED
|
@@ -39,7 +39,7 @@ Tab renders 7 elements. A token binding names the part it applies to.
|
|
|
39
39
|
|
|
40
40
|
It takes the same ink as the label and changes with it, so a current tab is current in both. The size is Icon's: the tab hands it `sm` and an Icon arriving already sized is unwrapped rather than obeyed.
|
|
41
41
|
|
|
42
|
-
Solid when current and regular otherwise, which this component cannot do for you — a Quill glyph's weight is fixed at the import. That is the package's `icon-
|
|
42
|
+
Solid when current and regular otherwise, which this component cannot do for you — a Quill glyph's weight is fixed at the import. That is the package's `icon-weight-within-a-set` rule — the tabs are the set — and it is a rule rather than an axis for exactly that reason. Rendered only when `icon` is set.
|
|
43
43
|
- `label` — `<span>`, class `dds-tab__label`. The words, and where selection is actually carried. The ink steps from `fg.muted` to `fg.default` and the weight from `font.body.md` to `font.label.md` — 400 to 600.
|
|
44
44
|
|
|
45
45
|
Product steps 400 to 500, because Product's type set has a medium. This one does not: Marketing has one weight per role and `label` is 600 throughout, so the step here is the larger of the two. It is the same decision — the current tab is heavier — landing on the only weight the package owns.
|
|
@@ -94,7 +94,7 @@ Never for: A sentence. The strip is scanned across, and a tab as wide as a claus
|
|
|
94
94
|
Accepts: QuillSystemIcon
|
|
95
95
|
Use when: The tabs are things a mark tells apart faster than a word does — a platform, a market class. Pass the glyph; the tab draws it at its own step.
|
|
96
96
|
|
|
97
|
-
Solid when the tab is current and regular otherwise, which is the package's `icon-
|
|
97
|
+
Solid when the tab is current and regular otherwise, which is the package's `icon-weight-within-a-set` rule. Nothing here can enforce it: a Quill glyph's weight is chosen at the import, so a page that wants the swap passes a different glyph per state
|
|
98
98
|
Never for: Carrying the label. A tab whose meaning is a shape is a tab a screen reader reads as nothing, and the words are what the strip is scanned by
|
|
99
99
|
|
|
100
100
|
### badge — `node` **Required when content=badge.**
|
|
@@ -150,7 +150,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
150
150
|
|
|
151
151
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
152
152
|
Guidance only — cannot be checked automatically.
|
|
153
|
-
- **Never nest one interactive element inside another** — 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,
|
|
153
|
+
- **Never nest one interactive element inside another** — 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.
|
|
154
154
|
Guidance only — cannot be checked automatically.
|
|
155
155
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
156
156
|
|
|
@@ -202,6 +202,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
202
202
|
|
|
203
203
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
204
204
|
Guidance only — cannot be checked automatically.
|
|
205
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
206
|
+
|
|
207
|
+
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.
|
|
208
|
+
|
|
209
|
+
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.
|
|
210
|
+
|
|
211
|
+
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.
|
|
212
|
+
Guidance only — cannot be checked automatically.
|
|
205
213
|
|
|
206
214
|
## Anti-examples
|
|
207
215
|
|
package/.llm/components/table.md
CHANGED
|
@@ -162,7 +162,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
162
162
|
|
|
163
163
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
164
164
|
Guidance only — cannot be checked automatically.
|
|
165
|
-
- **Never nest one interactive element inside another** — 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,
|
|
165
|
+
- **Never nest one interactive element inside another** — 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.
|
|
166
166
|
Guidance only — cannot be checked automatically.
|
|
167
167
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
168
168
|
|
|
@@ -214,6 +214,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
214
214
|
|
|
215
215
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
216
216
|
Guidance only — cannot be checked automatically.
|
|
217
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
218
|
+
|
|
219
|
+
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.
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
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.
|
|
224
|
+
Guidance only — cannot be checked automatically.
|
|
217
225
|
|
|
218
226
|
## Anti-examples
|
|
219
227
|
|
|
@@ -73,7 +73,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
73
73
|
|
|
74
74
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
75
75
|
Guidance only — cannot be checked automatically.
|
|
76
|
-
- **Never nest one interactive element inside another** — 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,
|
|
76
|
+
- **Never nest one interactive element inside another** — 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.
|
|
77
77
|
Guidance only — cannot be checked automatically.
|
|
78
78
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
79
79
|
|
|
@@ -125,6 +125,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
125
125
|
|
|
126
126
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
127
127
|
Guidance only — cannot be checked automatically.
|
|
128
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
129
|
+
|
|
130
|
+
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.
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
Guidance only — cannot be checked automatically.
|
|
128
136
|
|
|
129
137
|
## Anti-examples
|
|
130
138
|
|
|
@@ -99,7 +99,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
99
99
|
|
|
100
100
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
101
101
|
Guidance only — cannot be checked automatically.
|
|
102
|
-
- **Never nest one interactive element inside another** — 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,
|
|
102
|
+
- **Never nest one interactive element inside another** — 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.
|
|
103
103
|
Guidance only — cannot be checked automatically.
|
|
104
104
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
105
105
|
|
|
@@ -151,6 +151,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
151
151
|
|
|
152
152
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
153
153
|
Guidance only — cannot be checked automatically.
|
|
154
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
155
|
+
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
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.
|
|
159
|
+
|
|
160
|
+
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.
|
|
161
|
+
Guidance only — cannot be checked automatically.
|
|
154
162
|
|
|
155
163
|
## Anti-examples
|
|
156
164
|
|
|
@@ -83,7 +83,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
83
83
|
|
|
84
84
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
85
85
|
Guidance only — cannot be checked automatically.
|
|
86
|
-
- **Never nest one interactive element inside another** — 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,
|
|
86
|
+
- **Never nest one interactive element inside another** — 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.
|
|
87
87
|
Guidance only — cannot be checked automatically.
|
|
88
88
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
89
89
|
|
|
@@ -135,6 +135,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
135
135
|
|
|
136
136
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
137
137
|
Guidance only — cannot be checked automatically.
|
|
138
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
139
|
+
|
|
140
|
+
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.
|
|
141
|
+
|
|
142
|
+
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.
|
|
143
|
+
|
|
144
|
+
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.
|
|
145
|
+
Guidance only — cannot be checked automatically.
|
|
138
146
|
|
|
139
147
|
## Anti-examples
|
|
140
148
|
|
|
@@ -143,7 +143,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
143
143
|
|
|
144
144
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
145
145
|
Guidance only — cannot be checked automatically.
|
|
146
|
-
- **Never nest one interactive element inside another** — 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,
|
|
146
|
+
- **Never nest one interactive element inside another** — 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.
|
|
147
147
|
Guidance only — cannot be checked automatically.
|
|
148
148
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
149
149
|
|
|
@@ -195,6 +195,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
195
195
|
|
|
196
196
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
197
197
|
Guidance only — cannot be checked automatically.
|
|
198
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
199
|
+
|
|
200
|
+
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.
|
|
201
|
+
|
|
202
|
+
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.
|
|
203
|
+
|
|
204
|
+
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.
|
|
205
|
+
Guidance only — cannot be checked automatically.
|
|
198
206
|
|
|
199
207
|
## Anti-examples
|
|
200
208
|
|
|
@@ -99,7 +99,7 @@ This is the phone's breakpoint, size.breakpoint.md, and not the wider one that d
|
|
|
99
99
|
|
|
100
100
|
What this is not about is every row of controls. A set of filter chips, a pagination strip, a toolbar, a link sitting after a sentence — none of these is the page asking for something, and stacking them to full width would turn a strip the eye skims into a list it has to read. The test is whether the row is the call to action the section was written for.
|
|
101
101
|
Guidance only — cannot be checked automatically.
|
|
102
|
-
- **Never nest one interactive element inside another** — 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,
|
|
102
|
+
- **Never nest one interactive element inside another** — 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.
|
|
103
103
|
Guidance only — cannot be checked automatically.
|
|
104
104
|
- **A section that paints a ground sets the ink to go with it** — A page sits on color.bg.page, and a section that separates itself from it takes one of three grounds. color.bg.subtle is the light one and needs nothing further — the page's own ink still reads on it. The other two are dark and do not: color.bg.brand-strong takes color.fg.on-brand-strong, and color.bg.brand takes color.fg.on-solid. Both are white, and both are written as the role rather than the white they resolve to. Set one of those backgrounds without its ink and the text inherits whatever the page was already using, which is near-black on a dark band — legible to nobody, and invisible to every check here, because each pair passes contrast on its own and nothing can tell whether a section used both.
|
|
105
105
|
|
|
@@ -151,6 +151,14 @@ The target and the mark are separate decisions, and conflating them is what prod
|
|
|
151
151
|
|
|
152
152
|
Declared rather than emergent. Padding plus contents does clear 24px in several components today, and it is the weaker statement: it is a size nobody wrote down, so it moves when the type scale or the glyph does, and nothing says it was meant to be a target at all.
|
|
153
153
|
Guidance only — cannot be checked automatically.
|
|
154
|
+
- **A component is written along the reading axis, not along the page's left and right** — 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.
|
|
155
|
+
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
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.
|
|
159
|
+
|
|
160
|
+
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.
|
|
161
|
+
Guidance only — cannot be checked automatically.
|
|
154
162
|
|
|
155
163
|
## Anti-examples
|
|
156
164
|
|