Components
Every element in this system renders light DOM and emits the sds-
classes the stylesheet defines. There is no shadow root to pierce, no slot to
name and nothing to theme twice: the element is a shorter, safer way to write
markup the class layer already describes.
The reference pages follow the concerns named in the navigation rather than the implementation directories. That grouping is for browsing; the index below remains alphabetical, because somebody looking up an element already knows its name and should not have to know which concern owns it.
Element index#
Alphabetical, because a reader looking one up already knows its name and not which group it was filed under.
sds-accordion, sds-accordion-itemsds-badgesds-buttonsds-bylinesds-cardsds-checkboxsds-codesds-confvalsds-dialogsds-diffsds-embedsds-fieldsds-field-errorsds-figuresds-footersds-form-errorssds-gridsds-iconsds-imagesds-lightboxsds-link<a> with an hrefsds-modalsds-nav-breadcrumbsds-nav-mainsds-nav-pagersds-nav-paginationsds-nav-pillssds-nav-railsds-nav-tocsds-notesds-overlaysds-quotesds-radiosds-searchsds-search-hitssds-search-resultsds-statsds-surfacesds-tablesds-tabs, sds-tab-itemsds-theme| Element | What it is | Reference |
|---|---|---|
sds-accordion, sds-accordion-item |
questions with their answers folded behind them | Navigation — sds-accordion, sds-accordion-item |
sds-badge |
a small, named piece of state | Controls — sds-badge |
sds-button |
the action that starts work, or the press that is a link | Controls — sds-button |
sds-byline |
who wrote it, and when | Content — sds-byline |
sds-card |
a way into something: a chapter, a product, a news entry, a page | Content — sds-card |
sds-checkbox |
one thing that is either so or not | Forms — sds-checkbox |
sds-code |
a fenced block, its head and its copy button | Data — sds-code |
sds-confval |
one configuration value in a reference | Data — sds-confval |
sds-dialog |
a surface that opens over the page, and what opens it | Overlays — sds-dialog |
sds-diff |
a file's changes | Data — sds-diff |
sds-embed |
a document from somewhere else, in a frame this page controls | Media — sds-embed |
sds-field |
a text field, a text area and a select, in one element | Forms — sds-field |
sds-field-error |
the message under an invalid field | Forms — sds-field-error |
sds-figure |
a picture and the claim it makes | Media — sds-figure |
sds-footer |
how a page ends, and where the rest of the site is | Navigation — sds-footer |
sds-form-errors |
what stopped the form, at the top of it | Forms — sds-form-errors |
sds-grid |
the wall a set is read in | Content — sds-grid |
sds-icon |
one icon from the set, in the document rather than linked | Controls — sds-icon |
sds-image |
a picture, and nothing around it | Media — sds-image |
sds-lightbox |
a drawing opened at the size it was drawn | Media — sds-lightbox |
sds-link |
a link, and always an <a> with an href |
Controls — sds-link |
sds-modal |
the surface alone, with nothing that opens or closes it | Overlays — sds-modal |
sds-nav-breadcrumb |
where the page sits, as a trail | Navigation — sds-nav-breadcrumb |
sds-nav-main |
the bar at the top of a page | Navigation — sds-nav-main |
sds-nav-pager |
the way on from a page that is read in order | Navigation — sds-nav-pager |
sds-nav-pagination |
where a list continues | Navigation — sds-nav-pagination |
sds-nav-pills |
navigation for the sections of a page | Navigation — sds-nav-pills |
sds-nav-rail |
the navigation rail beside a column | Navigation — sds-nav-rail |
sds-nav-toc |
what is on this page, and where in it the reader is | Navigation — sds-nav-toc |
sds-note |
what an answer carries besides the answer | Content — sds-note |
sds-overlay |
the wash a floating surface sits on | Overlays — sds-overlay |
sds-quote |
a sentence borrowed from somewhere, with where it came from | Content — sds-quote |
sds-radio |
one answer out of a few, all of them visible | Forms — sds-radio |
sds-search |
finding a page in a site that has no server | Navigation — sds-search |
sds-search-hits |
what a query was answered with | Navigation — sds-search-hits |
sds-search-result |
one hit in a list of them | Navigation — sds-search-result |
sds-stat |
a number stated as a fact | Content — sds-stat |
sds-surface |
a filled plane holding a statement | Content — sds-surface |
sds-table |
rows and columns, with the scroll a wide one needs | Data — sds-table |
sds-tabs, sds-tab-item |
one set of panels, one of them shown | Navigation — sds-tabs, sds-tab-item |
sds-theme |
light or dark, as two segments with the chosen one filled | Controls — sds-theme |
Addressed, never rebuilt#
Everything that fits in a string is a property. Between the tags goes only what an attribute cannot carry — and that is content, never structure: the paragraphs of a summary, the blocks behind a question, the picture a renderer already wrote.
<!-- Addressed. -->
<sds-card heading="Release 1.4" tag="news" label="12 May" href="/news/1-4">
<p>What changed, in the two lines that decide whether it is opened.</p>
</sds-card>
<!-- Rebuilt. This is the failure the system exists to prevent. -->
<article class="sds-card">
<div class="sds-card__body">…</div>
</article><!-- Addressed. -->
<sds-card heading="Release 1.4" tag="news" label="12 May" href="/news/1-4">
<p>What changed, in the two lines that decide whether it is opened.</p>
</sds-card>
<!-- Rebuilt. This is the failure the system exists to prevent. -->
<article class="sds-card">
<div class="sds-card__body">…</div>
</article>
A sds-x__y class is sds-x's own name for its own node. A page may write
.sds-card and .sds-note--warn; it may not write .sds-card__foot,
because the day that node changes, every hand-written copy of it is a surface
nobody will fix.
If an element cannot say something a page needs, the gap is closed in the element. A consumer writing three declarations into their own stylesheet is the outcome this system exists to prevent — see Design system.
If an element cannot say something a page needs, the gap is closed in the element. A consumer writing three declarations into their own stylesheet is the outcome this system exists to prevent — see Design system.
Properties and attributes#
Strings, numbers and booleans are attributes and a server writes them directly. Anything that is a list or a piece of markup is a property, set from JavaScript or from a template that binds one:
<sds-table density="compact" scrollable
.columns="${[{ head: 'Tool' }, { head: 'Answers', cls: 'sds-td-meta' }]}"
.rows="${[{ cells: ['search', 'yes'] }]}"></sds-table><sds-table density="compact" scrollable
.columns="${[{ head: 'Tool' }, { head: 'Answers', cls: 'sds-td-meta' }]}"
.rows="${[{ cells: ['search', 'yes'] }]}"></sds-table>
A renderer that holds markup rather than data has the other route: write the markup between the tags and let the element take it. That is how the Guides theme emits a code block that is already coloured, a rail that is already resolved, and a figure whose picture is on the page before any script runs.
Where a property's name is more than one word, its attribute is spelled out rather than left to be lower-cased:
iconOnlyicon-onlysds-buttonlangcode-langsds-codeboxStylebox-stylesds-surfacefieldIdfield-idsds-fieldminWidthmin-widthsds-fieldperPageper-pagesds-nav-paginationpreviousHref, previousLabel, nextHref, nextLabelprevious-href, previous-label, next-href, next-labelsds-nav-pager| Property | Attribute | On |
|---|---|---|
iconOnly |
icon-only |
sds-button |
lang |
code-lang |
sds-code |
boxStyle |
box-style |
sds-surface |
fieldId |
field-id |
sds-field |
minWidth |
min-width |
sds-field |
perPage |
per-page |
sds-nav-pagination |
previousHref, previousLabel, nextHref, nextLabel |
previous-href, previous-label, next-href, next-label |
sds-nav-pager |
box-style exists because every host in this system is
display: contents and therefore not in the box tree: a width or a
flex set on the tag would land on nothing. What the property carries is
given to the element that is actually laid out.
box-style exists because every host in this system is
display: contents and therefore not in the box tree: a width or a
flex set on the tag would land on nothing. What the property carries is
given to the element that is actually laid out.
Names that had to differ#
Each of these is a global HTML or ARIA attribute that a component would otherwise have quietly overridden.
headingtitletitle is the global attribute, and would put a tooltip on the whole
componentasrolerole is the ARIA attribute, so role="maintainer" claims a role
that does not exist — and axe says socode-langlanglang names the human language, so lang="json" sends every
screen reader to a language tag that does not exist| Written | Instead of | Because |
|---|---|---|
heading |
title |
title is the global attribute, and would put a tooltip on the whole
component |
as |
role |
role is the ARIA attribute, so role="maintainer" claims a role
that does not exist — and axe says so |
code-lang |
lang |
lang names the human language, so lang="json" sends every
screen reader to a language tag that does not exist |
What an element announces#
Every event below bubbles and is composed, so a page listens on the element rather than on whatever is inside it.
detailsds-changesds-nav-pills, sds-nav-main, sds-nav-rail, sds-tabs{ index, label } — the item that became currentsds-changesds-nav-pagination{ page }, one-based. Cancelable: call preventDefault() to
page in place instead of following the linksds-changesds-checkbox, sds-radiosds-inputsds-fieldsds-commandsds-button with for{ command, source } — dispatched on the element named by
for, the way the platform's own invokers do itsds-theme-changesds-theme{ theme } — "light", "dark", or null for the machine's| Event | From | detail |
|---|---|---|
sds-change |
sds-nav-pills, sds-nav-main, sds-nav-rail, sds-tabs |
{ index, label } — the item that became current |
sds-change |
sds-nav-pagination |
{ page }, one-based. Cancelable: call preventDefault() to
page in place instead of following the link |
sds-change |
sds-checkbox, sds-radio |
the new state, or the chosen value |
sds-input |
sds-field |
what is in the field now |
sds-command |
sds-button with for |
{ command, source } — dispatched on the element named by
for, the way the platform's own invokers do it |
sds-theme-change |
sds-theme |
{ theme } — "light", "dark", or null for the machine's |
Wiring one control to another is markup:
<sds-button for="the-drawing">Open the drawing</sds-button>
<sds-lightbox id="the-drawing" src="/art/pipeline.svg" alt="…"></sds-lightbox><sds-button for="the-drawing">Open the drawing</sds-button>
<sds-lightbox id="the-drawing" src="/art/pipeline.svg" alt="…"></sds-lightbox>
An id and an event, so neither end holds the other. command says what is
being asked — show unless something else is written, and close or
toggle where that is what the press means.
Before the script, and without one#
These elements are written to survive both. A page rendered ahead of the browser holds its markup already, the element upgrades it in place rather than drawing it a second time, and a reader who runs no script keeps everything but the behaviour.
Two things follow for anything rendering in Node — the specimen cards, the Guides site, a static export:
- Content between the tags is lifted on connect, which never happens outside a
browser. The same content arrives as the
contentproperty instead, and every element reads whichever it was given. - A card carries no JavaScript at all, so
renderStaticflattens each element to the markup it renders. An element that was handed children cannot be flattened — the body goes in as a property there.
Page layout for the page these components stand in, and Screens for finished pages built out of them.
Page layout for the page these components stand in, and Screens for finished pages built out of them.