Product designer
Starting points to open, tokens to draw against, and a specimen for every rule — so a decision is looked up rather than remembered.
Tokens, a class layer and the elements over it — one vocabulary, whether a surface runs JavaScript or is rendered by PHP. Every rule it holds is shown on a card generated from the component that holds it.
Starting points to open, tokens to draw against, and a specimen for every rule — so a decision is looked up rather than remembered.
Custom elements that need no build step and no framework. Light DOM, so the page around them styles them like anything else.
The same class names a template writes by hand. Neither layer is a fallback for the other, and both are checked against the same file.
Four layers, and each of them is worth having on its own. A surface that takes only the tokens still cannot invent a colour; one that takes only the classes still gets both modes.
| Layer | Ships as | Read by |
|---|---|---|
| tokens | tokens.css — custom properties | every layer above it, and a design tool |
| classes | styles.css | a Twig or Fluid template, by hand |
| elements | soul.js — light DOM, no build | a surface that runs JavaScript |
| specimens | generated cards | the guidelines, and the pane a design opens in |
One per plane: a block the machine writes, the navigation beside a page, and the navigation above it. Each is documented from the element that renders it.
A fenced block, its head and its copy button. It highlights what it is given rather than leaving that to the page — fourteen grammars, one of them TYPO3’s own, and a caption where a renderer has one to place.
| Property | Required | Meaning |
|---|---|---|
| lang | no | The fence’s language. Sets the head and picks the grammar. |
| caption | no | What the block is, in a sentence, above the frame. |
| copy | no | The copy button. It copies what the block says, never its chrome. |
| source | no | The block as text, where the caller holds the source rather than markup. |
<sds-code code-lang="bash" caption="Install" copy>
<code>composer require typo3/soul-design-system</code>
</sds-code>
The tool rail: a flat list, or one long enough to need sections. A section is a `details`, so it folds before any script has run and a closed rail is a few lines rather than a screen of them.
| Property | Required | Meaning |
|---|---|---|
| items | yes | Labels, or entries with an href, an icon, or a group of their own. |
| active | no | Which item is current. Pressing one moves it and says so. |
| open | no | Per group. A group holding the current item opens regardless. |
<sds-nav-rail active="1" items='[
"overview",
{ "label": "tools", "items": ["typo3_icon_lookup"] }
]'></sds-nav-rail>
The bar at the top of a page, and what it does as the page runs out. A row while there is room; one button and one drawer holding the field, the sections and the page rail when there is not — and which of the two is measured, not declared at a breakpoint somebody picked for one page.
| Property | Required | Meaning |
|---|---|---|
| product | yes | The name in the lockup, with brand and signet where there are two halves. |
| items | no | The sections of the site, or the links a server wrote between the tags. |
| rail | no | The id of the page rail, which hangs under its own section in the drawer once it has no column. |
<sds-nav-main product="Soul" signet="signet.svg" search items='[
{ "label": "overview", "href": "#overview" }
]'></sds-nav-main>
Four places, and every one of them is a file rather than a habit.
The documentation is generated from the components, in four steps that run on every change.
The component, with the properties it is being shown at. Nothing is hand-built beside it — a specimen that rebuilds the markup documents the rebuild.
Server-side, to flat HTML at the size it declares, with every element replaced by what it produced.
With styles.css and no JavaScript at all, which is the state that proves the class layer stands on its own.
A card that moved is a picture that changed, and it is reviewed as one.
Three of them, folded: a page that argues has to answer these, and a reader who has none of them is already at the install step.
Two files, and nothing to configure. The elements register themselves and the classes are already in the stylesheet — there is no build step to add and no framework to be on.
# one command, and the client finds it $ composer require typo3/soul-design-system ✓ linked two files into public/assets
Pin a version where you depend on it. The class layer is the contract; the elements are how a page that runs JavaScript gets it without writing the markup out.