Writing rules
Sentence case in two languages, never ALL CAPS, labels that start with a verb, numbers with a true minus — and the words the system uses for itself.
Case — sentence case, never ALL CAPS
Section titled “Case — sentence case, never ALL CAPS”Do
| Example | Why |
|---|---|
| sentence case: the first letter, then only names | |
| a button says what happens | |
| Where the money goes | a heading is a sentence, not a title |
Don’t
| Example | Why |
|---|---|
| shouting — the deck tool re-cases a caps heading at parse time | |
| Title Case — every word capitalised reads as a name | |
| WHERE THE MONEY GOES | no ALL CAPS, anywhere |
| Where The Money Goes | Title Case on a heading |
Exceptions — what keeps its caps
Section titled “Exceptions — what keeps its caps”Keep caps
| Example | Why |
|---|---|
| KYC | an acronym |
| DSP | an acronym |
| TL;DR | an abbreviation with punctuation |
| B2B | a digit token |
| Q3 | a digit token |
| MAFO | a house product — brand-style name |
| iRTB | a product’s own casing, kept as typed |
Caps by component
| Example | Why |
|---|---|
| About us | the Heading pair’s web eyebrow — typed ‘About us’, the component sets UPPER and +6% tracking |
| Workspace | the rail’s Nav section — typed ‘Workspace’, the component sets UPPER and +8% |
Only these two show caps, and only because their component sets textCase — the text underneath stays sentence case, searchable and re-usable. Never type caps into a label. Unknown tokens keep their caps when re-cased: the brand-safe default — so a heading typed in caps with a brand in it comes out right.
Labels — short, a verb first
Section titled “Labels — short, a verb first”Do
| Example | Why |
|---|---|
| verb + object: the outcome | |
| two words carry it | |
| the danger button names what it destroys | |
| an error offers the next step |
Don’t
| Example | Why |
|---|---|
| the sentence belongs in the description, not the button | |
| says nothing about what happens (Alert dialog: name the action) | |
| a form word, not an outcome | |
| a yes/no pair forces the reader back to the question |
Numbers — one style, a true minus
Section titled “Numbers — one style, a true minus”Do
| Example | Why |
|---|---|
| −12.5% | the true minus U+2212 — Poppins has the glyph; a hyphen is shorter and sits lower |
| 1,240 | thousands grouped with a comma |
| $1.2K | one style per chart (Auto · 1,000 · 1,000.00 · 1.2K); the unit is a verbatim prefix or suffix, never a conversion |
Don’t
| Example | Why |
|---|---|
| -12.5% | a hyphen-minus |
| 1240 | no grouping past three digits |
| $1.2K and $900 | two styles in one chart — 1.2K beside 900 reads as two units |
Vocabulary — how the system names itself
Section titled “Vocabulary — how the system names itself”| Term | The rule |
|---|---|
| Component names | Sentence case, the style after a spaced hyphen: Button - secondary, Icon button - ghost, Alert dialog, Data table. One name in Figma, the registry and the docs. |
| Properties and values | Property=value, the property Capitalised and the value lowercase: Size=small, State=hover, Tone=neutral, Style=connected, Orientation=vertical. |
| States | default · hover · focus · disabled, plus the state a component’s job needs — pressed on Button, on on Toggle, error on Input; a Switch has four and a Nav link two; selected where a thing is chosen (Table row, Nav item active). |
| Sizes | small · medium · large. Controls stand 28 / 36 / 44 tall — a scale that has no name yet. |
| Tones | blue · red · yellow · neutral on the KPI tile; the same with green and dark on Badge and Chip; accent · success · danger · neutral on the Icon list; neutral · info · success · warning · danger on Alert. |
| The contract | Every description ends the same way: Use when · Do not use when · Relates to · Anti-patterns · Keywords — one text in Figma and in the registry item’s meta. |
| Icons | Lucide names as Lucide spells them — chevron-down, circle-check, layout-dashboard — as Icon/<name>; a custom icon needs a documented Lucide gap. |
| Marks | A logo is an asset placed from assets/logo or Brand/ — Logo/Pepper mark, Logo/MAFO — never re-drawn, never an emoji, a product’s mark where that product is the subject — its rail, its page on the site — and the corporate mark never inside a product. |
| Tokens | Slash paths in Figma, var(--pui-…) on the web, the same words in both: surface/card is --pui-surface-card. Never a hex in a component, never a value the source lacks — ask, then add it to tokens/*.json. |
Generated content — marked where it appears
Section titled “Generated content — marked where it appears”Do
| Example | Why |
|---|---|
| “Q3 revenue rose 12 % on iRTB volume; MAFO margins held at 41 %.” | the answer carries Echo’s own avatar — the brand’s mark, which is what says a machine wrote it — and the feedback row; the mark is said once, so no name and no second glyph sit beside it, and the reader knows before reading |
| a control that invokes the model carries the sparkles glyph — the one glyph reserved for AI |
Don’t
| Example | Why |
|---|---|
| “Q3 revenue rose 12 % on iRTB volume; MAFO margins held at 41 %.” | the same answer as a bare bubble — a machine’s text passing as a person’s; a Bubble is never used outside Message |
| an emoji as the mark — an emoji is never a glyph (Icons & logos); the sparkles Lucide glyph is the mark |
The rule: text a model generated is labelled ‘AI’ where it appears — Echo’s own avatar in a chat, which carries the brand’s mark and is said once, a neutral ‘AI’ Badge on a Card or an Insight the model wrote — and a control that sends something to the model carries the sparkles glyph; nothing else uses that glyph. The label is neutral, never a colour team: the mark states provenance, not status. Feedback controls (copy · helpful · not helpful) sit under every generated answer; the mark and the feedback are what a design system can do.
On the Figma page
Section titled “On the Figma page”Each section is a Do row and a Don’t row of real components, the reason under each specimen. The mark and the sparkles glyph are the Chat page’s (Message, Composer).
The same page in the Figma library: Writing rules.
Pepper UI v1.5.0
The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.