ExampleDesignSystem · XDS V4
Component and token reference
Every component and token in ExampleDesignSystem, with the rules that hold the two together. The page is generated from the files the products build from, so the specimens are the live components and the values in the tables are the values that ship.
For designers choosing a component, engineers taking its markup and token names, and anyone checking what was decided. Sections start closed — open one, or use the chips to go straight to a component.
Laws
Every system law, one sentence each, grouped by topic. The label names the check that enforces it when the system is built. A rule about one component lives on that component's record.
Token tiers
Three tiers, one direction. A component reaches a c- token; the token reaches
an s- intent; the intent reaches a g- value. Dark is not a mode: it is a
variant, data-surface="dark", allowed only on the components the registry marks
dark-capable. Inside one, the s- tier re-points and every dark-capable child follows;
inputs never do.
the chain, for one token
.xds-button[data-variant="primary"] { background-color: var(--c-button-primary-fill); }
--c-button-primary-fill : var(--s-color-action-base) /* tokens/c.json */
--s-color-action-base : var(--g-color-brand-vivid-50) /* tokens/s.json */
--g-color-brand-vivid-50 : #017097 /* tokens/g.json */Color
Eleven families from the core swatches. Each cell states its contrast against white and against black, drawn in that ink — the line you cannot read is the pairing you cannot use. The carry flips at 50 in every ramp.
Semantic tokens
Every s- token, what it points at, and what it resolves to on each ground.
| token | → g- | light | dark | intent |
|---|
Icons
Forty marks from IBM Carbon (@carbon/icons, Apache 2.0), mapped to our names. One mark costs a <use>: the sprite is injected once per document by xds.js, so a page with sixty icons carries one copy of the paths. Size is a token, color is currentColor.
The geometry
- Set
- IBM Carbon,
@carbon/icons, Apache 2.0.assets/icons/icon-data.jsrecords the upstream Carbon name behind every one of our names, so the mapping is auditable and a swap is a data change, not a redraw. - Grid
- 32 × 32 — IBM Carbon's grid. Its marks sit inside a 2px safe margin, so they read a little quieter than a full-bleed set at the same box size.
- Stroke
- None. Carbon converts its outlines to FILLED paths, so there is no stroke to weight and nothing to tune. A mark paints with
fill: currentColor. - Radius
- Carbon's own. Not ours to set.
- Curves
- Carbon's decision, not ours. Its marks curve where the subject is round and cut where it is not.
- Logos
- No longer a separate case — every Carbon mark, logos included, fills the same way.
Sizes
Five rungs, all bound to s.size.icon-*. Pick by what the mark sits next to, not by taste: a mark beside 13.5px text is sm; a mark inside a control is md; a mark standing alone is xl or larger.
xs*12pxsm16pxmd20pxlg24pxxl32px2xl48px* icon-xs (12px) is a token but not a data-size: it exists for separator furniture set in CSS, like the breadcrumb chevron.
Tones
A mark takes the ink of whatever it sits in. data-tone is an override for the cases where it must not — a status mark, a mark on a filled control.
defaultsecondarytertiarydisabledactionaccenterrorwarningsuccessinfoemergencyAccessibility
A mark that repeats the words beside it is decorative and takes aria-hidden="true". Most marks in a real interface are decorative.
A mark carrying meaning nothing else carries takes role="img" and an aria-label saying what it MEANS, not what it depicts — the external mark is labeled “Opens in a new tab”, never “arrow”.
An icon-only control labels the control, not the mark; the mark inside stays hidden.
Never a <title> inside a symbol — every instance on the page would share it.
Status
Five marks, five silhouettes. No two statuses may share a shape — that is the ruling, and it is why error sits in a circle while close is a bare X. Color is never the only signal: every status mark sits beside real words.
errorSomething failed. It has to be fixed.
STATUS. Circle plus X. The circle is what separates it from close, which is a bare X — that distinction is the whole reason the enclosure exists.
warningSomething needs attention but has not failed.
STATUS. Triangle plus bar. The only status on a triangle.
infoNeutral context. Nothing is wrong.
STATUS. Circle plus i.
successIt worked.
STATUS. Circle plus check.
emergencyStop. The highest interrupt rank.
STATUS. Hexagon plus bar. The only status on a hexagon, and never used for anything less than rank 1. Carbon has no octagon carrying a mark, and a bare octagon is a blob at 16px — the hexagon keeps a distinct silhouette AND a readable bar, which is what the ruling was for.
Navigation and direction
Chevrons move through hierarchy; arrows move through a journey. They are not interchangeable, and doubling a chevron means paging, not nesting.
chevron-downThis will expand. Disclosure, accordion, select, footer sitemap.
Rotates 180° when open — the rotation is the state, not a second mark.
chevron-upThis will collapse; or scroll back to the top.
The mirror of chevron-down for the cases where rotation is not available.
chevron-rightGo one level in. Breadcrumb separator, in-page-nav, list rows.
As a separator it takes the 12px rung: the set draws edge to edge, so a 16px box puts it above the weight of the text it divides.
chevrons-leftPrevious page.
Doubled, so it cannot be confused with a single-step chevron used for hierarchy.
chevrons-rightNext page.
Doubled, same reason. Pagination only.
arrow-leftBack — to the previous step or the referring page.
A journey, not a hierarchy. Use a chevron for hierarchy.
arrow-rightForward — continue, next step, read on.
The trailing mark on a call to action.
menuOpen the navigation drawer. The compact header only.
Three full-bleed rules. Pairs with close, which replaces it while the drawer is open.
externalThis link leaves the site, or opens a new tab.
Trailing, at the end of the link text. It carries meaning nothing else carries, so it is labeled 'Opens in a new tab' — never 'arrow'.
Action
Things a person does. Each one names an act, and the pairs (download/upload, thumb-up/thumb-down) are never used alone.
searchFind within this page or this collection.
The lens is one of the two places a curve is allowed — the subject IS a circle. Pairs with the search component; never use it as a generic 'magnify' or 'zoom'.
closeDismiss this thing. Modal, toast, drawer, removable chip.
A BARE X — it never sits inside an enclosure, so it can never be misread as error. Not the same act as clear.
clearEmpty this field.
A backspace hexagon, not an X. Clearing what you typed and dismissing a thing are different acts and get different marks.
checkDone, selected, included.
A bare check with no enclosure — the mark inside a checkbox or a selected option. For a status message use success.
copyPut this on the clipboard.
Two offset rectangles. Pairs with a toast confirming the copy actually happened.
downloadTake a copy of this file.
Arrow into a tray. The direction is the whole meaning; do not mirror it for upload.
uploadSend a file from your machine.
Arrow out of a tray. The mirror of download, and they must never be swapped.
printPrint this page or this record.
The physical device, because print is still a physical act to the person doing it.
sendSubmit this message.
The conversational composer. Not a generic submit — a form's submit is a button with a word on it.
retryTry that again.
A broken loop with an arrowhead. Failure recovery — pair it with an error alert, never with a plain refresh.
thumb-upThis answer helped.
Conversational feedback. Always paired with thumb-down; a single thumb is a trap.
thumb-downThis answer did not help.
The pair. Offering only one direction makes the control useless as a signal.
Object and attribute
What a thing IS, rather than what you do to it.
fileA document, of unstated type.
Generic. If the type matters, say the type in words — the set does not carry per-format marks.
calendarA date, a deadline, a schedule.
Never a date PICKER trigger on its own — a date field is a field with a label.
lockSecure, or restricted.
The shackle is round because the object IS round — squaring it turns the lock into a suitcase. One of the four sanctioned curves.
helpExplain this.
Circle plus question mark. Reads as an offer, not a status — pair it with a disclosure or a tooltip, never with an alert.
quoteA pulled quotation.
Two marks, not one. The pull-quote component; never decoration inside running prose.
filterNarrow this set.
A funnel. Distinct from sort, which reorders rather than removes.
sortThis column can be sorted. Nothing is applied yet.
The neutral state of a sortable table head. Must be replaced by sort-asc or sort-desc once a direction is chosen.
sort-ascSorted A→Z, low→high, old→new.
Table heads. aria-sort='ascending' on the th is what a screen reader hears; the mark is decorative.
sort-descSorted Z→A, high→low, new→old.
The mirror. Same aria rule.
Brand
Supplied artwork. Filled, unstroked, and exempt from every geometry rule above. Do not redraw them in the house hand — a brand mark that is not the brand's mark is worse than no mark.
social-facebookFacebook.
BRAND. Supplied artwork, filled and unstroked, exempt from every geometry rule. Do not restyle into the house hand.
social-instagramInstagram.
BRAND. Same rule.
social-linkedinLinkedIn.
BRAND. Same rule.
social-xX.
BRAND. Same rule.
social-youtubeYouTube.
BRAND. Same rule.
Component index
Every component, one row each, grouped by family: named for the end the user has in mind, not for how the component is built. The families follow this index in the order manifest.families gives them, each opening with what the user does with it. Every entry shows the same markup twice — on a light ground and on a dark one — then its props, its states, its HTML, and the component-tier tokens it binds. If a value is not in that table, the component does not get to have it.
| component | family | dark | radius | composes | props | tokens |
|---|
Patterns
Rulings that live on a component rather than in a token — read from manifest.patterns. A builder can apply these without reading prose: each has an id and a rule.
Files
design-system/tokens.json every token; tokens.css is compiled from it design-system/tokens.css the compiled tokens: themes Light, Dark surface, Alternate pack design-system/components/ bundle.css (the component tier and the components), bundle.js (behavior) design-system/components/<Name>/ a guide (README.md) and a live preview per component and template design-system/README.md the brand book; choosing.md and laws.md beside it documentation/ this page, the style guide, and the data they read (data/*.js) gallery/ every preview as a page How-To-Docs/ the how-to guide tools/ compile tokens.css, build the gallery, remove branding, rebuild from source