Guides
Usage rules
The short list. Every rule here exists because something shipped broken without it.
Color
- Use semantic tokens, never ladder steps, and never a raw hex.
- Text on a fill uses its "on" token. Labels on
action.primaryuseaction.onPrimary. In dark mode the fills are light, so typed white text drops to about 1.8:1. - Code blocks use
text.onCode, nottext.inverse. Both flip in dark mode, and together they fall to about 1.1:1. - Muted text is for secondary information, never anything someone must read to finish a task.
- Decorative borders are decorative.
border.defaultandborder.strongnever form the only edge of a control. Controls useborder.control. - Feedback families stay together. An error uses the error surface, border and text, never a mix.
- Never color alone. Status, selection and errors pair color with text, an icon, weight or a shape.
Show a selected nav item with the selected surface, selected text and a 3px bar.
Show it with a tinted background only. Some people can't see the difference.
Type
- Open Sans for everything. Use the type styles, never a hand-set size.
- Nothing below 12px. Running text stays under about 80 characters a line.
- Headings follow document order. Never pick a heading level for its size.
Space and size
- Spacing stays on the scale: 0, 2, 4, 8, 12, 16, 24, 32, 40, 48, 64.
- Targets are at least 24px (44pt on iOS). Aim for 40px on anything used often.
- Density changes inset and gap only.
Components
- One primary button per view. Everything else is secondary or text.
- Destructive actions use the danger button and a confirm step.
- Fields always have a visible label. Errors replace the helper text, and focus moves to the first field with an error.
- Dialogs and drawers trap focus, close on Esc and return focus to what opened them.
- Every interactive thing has every state: default, hover, focus, disabled, and selected or error where they apply.