Product designer
Starting points to open, tokens to draw against, and a specimen for every rule. A decision is a lookup, not a memory.
Tokens, a class layer and the elements over it — one vocabulary, on a surface that runs JavaScript and on one PHP renders. Every rule it holds shows on a card generated from the component that holds it.
Starting points to open, tokens to draw against, and a specimen for every rule. A decision is a lookup, not a memory.
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 one file checks both.
Four layers, and each of them stands 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 documents itself from the element that renders it.
A fenced block, its head and its copy button. It colours its own content rather than leaves that to the page. Fourteen grammars, one of them TYPO3’s own, and a caption where a renderer has one.
| 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 runs. 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. A press on 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 comes out of the components, in four steps that run on every change.
The component, with the properties it shows at. Nothing hand-built stands 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 a review reads it 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.