Standards
Rules for naming things in Moments, and for writing component guidelines.
Rules for naming things in Moments, and for writing component guidelines. A component, property, value, or token has one name. Use that name in Figma, in code, and in these docs.
Usage and copy
For usage guidance and the wording in component guidelines, look at Mews, Primer, and Nordhealth.
Write the wording with the clear-writing skill in this repo, at .claude/skills/clear-writing/SKILL.md.
Principles
- One name, everywhere. Use the same name in Figma, code, and docs. If a component has another common name, list that alias on its guidelines page. Do not use the alias as a second name.
- Name by role, not by appearance. Write
tone="critical", nottone="red". Writecolour-text-accent-default, notcolour-text-purple. Only core tokens, such ascore-colour-primary-500, describe a raw value. - Use the same word for the same concept. If two components have a size, they use the same size words. If a word already means something in Moments, do not reuse it for something else.
baseis a colour role, so it is not also a size. A component and a token may use different words for the same idea: writetone="neutral"on a component, andbaseon the colour token, as incolour-text-base-default. - Singular by default. Write
Button, notButtons. Use a plural only when multiplicity is the point, as inTabsandBreadcrumbs. - Spell words out in component APIs. People read
size="small". Abbreviations belong on dense token scales, such asspacing-padding-sm. - Add a segment only when it adds meaning.
colour-text-errordoes not need-defaultwhen there is no other variant. State always goes last. - Spell it
colour. Usecolourin tokens, component names, properties, and docs. The CSS property stayscolor, as incolor:andborder-color. - Review a name before it ships. Renaming something already in production takes a deprecation cycle: add the new name, keep the old name as an alias, then remove the old name in a later version.
Casing
| What | Convention | Example |
|---|---|---|
| Component name (Figma, docs, sidebar) | Title case, singular, spelled out | Text Field, Icon Button |
| Custom element tag | moments- plus kebab-case | <moments-text-field> |
| Class name | PascalCase, Moments prefix | MomentsTextField |
| Attribute | kebab-case. Use the native HTML name where one exists | details, validation-guidance, full-width, maxlength |
| JavaScript property | camelCase | validationGuidance, fullWidth |
| Attribute value | lowercase, kebab-case when it has more than one word | size="small", variant="primary" |
| Boolean attribute | the plain adjective, with no is- or has- prefix. Match native HTML where a name exists | disabled, readonly, loading |
| Slot | kebab-case, named by role | prefix, suffix, icon, primary-action |
| CSS part | kebab-case, named by what it is | label, field, icon, footer |
| Event | one lowercase word, like a native event. Join extra words with no hyphen. Use the native name where one exists | change, input, droprejected, aftershow |
| CSS variable (token) | --moments- plus kebab-case segments | --moments-semantic-colour-text-accent-default |
| Figma variable | the same segments, grouped with / | colour/text/accent/default |
| Figma component property | the same name and values as the code attribute | size with values small, default, large |
| Figma layer | what it is, not where it sits | Icon, Label |
| Docs page | the component name | Forms / Text Field |
Sizing
Name a size option with a full word. Use small, default, and large.
When one option is the usual size, name that option default. Leave default out when no option is the usual one.
Write the Figma label in sentence case, such as Default. Use the same word in lowercase in code, such as size="default". The word stays the same. Only the capital letter changes.
Other values
Use these words. The Avoid column lists synonyms that mean the same thing. Bold marks the value you get when you leave the attribute off, where the component has a default.
| Concept | Where | Use | Avoid |
|---|---|---|---|
| Hierarchy | variant | primary, secondary, tertiary | main, ghost, outline, link, filled |
| Tone | tone | accent, neutral, critical, inverse | brand, danger, destructive, red |
| Feedback status | status, or tone on a feedback component | info, success, warning, error | alert, danger, positive, negative |
| Density | padding | none, compact, default | base, tight, comfortable |
| Contrast | colour modifiers | lightest, lighter, light, default, strong, stronger, strongest | dark, subtle, bold, numbers in semantic tokens |
| Resting state | state segment, Figma variant | default | rest, resting, base, normal, enabled, idle |
| Interaction states | state segment, Figma variants | hover, pressed, focus, disabled | active for pressed, focused, inactive |
| Component states | boolean attributes, Figma variants | selected, checked, indeterminate, error, readonly, loading, open | is-selected, invalid, read-only, busy, expanded |
| Orientation | orientation | horizontal, vertical | row, column |
| Width | layout, for example on Tabs | hug, fill | auto, stretch, full |
| Text on a field | attributes | label, details, validation-guidance, placeholder | hint, description, helper-text, help-text, error-text, message |
| Actions | slot names | primary-action, secondary-action, actions | cta, buttons, main-action |
critical is a tone for an action that is destructive or irreversible, such as a Delete button. error is a status: something went wrong or is invalid, such as a field's validation message.
pressed is the state while a pointer is down. selected is a persistent choice in a set, such as a tab or a list item. checked is the form value of a checkbox, radio, or switch.
Tokens
Name a token in Token framework. That page defines each segment. Token workflow covers adding, renaming, and deprecating a token.
In Figma, separate the segments with /, as in colour/text/accent/default. In CSS, join them with - and start with --moments-. State goes last. Components use semantic tokens. A component token exists only when no semantic token is precise enough. Core tokens are the only place for literal names such as neutral-100.
Exceptions
These names do not follow the rules above yet.
- Section Header and Page Header
sizeusemediumrather thandefault. - Avatar, Object, and Thumbnail
sizeuse abbreviations, from2xstoxl. - Divider
toneusesbase. - Banner
type, Listtype, and Tableformatusebase.
Component guidelines
Ready-component guidelines live on docs.easol.com. Storybook for a ready component is Playground plus a Variants group. While a component is still in progress, write guidelines in Storybook with this structure and <ArgTypes of={S} />. The table comes from the argTypes in the stories file, so the docs and the Controls panel stay in sync.
Component
One short sentence. Say what the component is and what it is for.
Show the default story here, directly under that sentence, in a <Canvas>.
A Canvas uses the page-background token. Playground is unstyled. See Storybook previews.
Usage
When to use
Simple bullet points. Each one gives a reason to use this component.
When not to use
Simple bullet points. Each one gives a reason not to use this component, and names what to use instead. Link to that component when one exists.
Variants
Give each property its own section.
Property
A <Canvas> that shows an example of the component for each value. Label the value in the example.
Explain the values this property can take, and when to use each one.
Recommendations
The description continues the title, so Don't and the description read as one sentence. Write "Put a full-width image inside the default inset", not a second "Do not".
Props
<ArgTypes of={S} />. Give every property an argTypes entry with a description, a table.type.summary and, when it has one, a table.defaultValue.summary. Add properties that have no control, such as name or autocomplete, with control: false.
Add properties that appear in Figma but not in code to the same argTypes, with control: false and table: { category: 'In Figma only' }. The table groups them under an "In Figma only" heading. Use the Figma property name as name, and say in description how code covers it. Leave them out when there are none.
figmaState: {
name: 'State',
control: false,
description: 'Hover and focus come from CSS.',
table: { category: 'In Figma only', type: { summary: 'default | hover | focus' } },
},List the properties in parameters.controls.include so the Figma-only rows stay out of the Controls panel.
Slots and events
If the component has slots or events, document them after Props. Leave this section out when it has none.
Name a slot by its role, in kebab-case, such as prefix, suffix, or primary-action. Name an event with the native name where one exists, such as change or input. Otherwise use one lowercase verb, such as dismiss or remove.