Patterns
Empty, loading & error
Any surface that can hold data has four states, not one. This was the largest undocumented gap in the system: table.ts already reserves a stateAction slot and nothing said what goes in it.
Empty · first run
No events yet
Publish an event and athletes can start rating it the same day.
Nothing exists yet. Explain what would appear here, and give the action that creates it. Never an illustration, never "Nothing to see here".
Empty · filtered
No trail events in the last 30 days
Four events match if the range goes to 90 days.
Data exists but the filter excludes it. A filtered empty is a different state from a first-run empty — name the filter, and offer the way back.
Loading uses a skeleton in the shape of the content, not a spinner — the layout must not jump when the data lands. A spinner is only for an action in progress, inside a button.
Reviews didn't load
The connection dropped partway through. Nothing was lost.
Say what happened, not that something happened. Say what to do next. Never "you" — the system failed, not the person. An error without a recovery action is incomplete.
The contract
| Slot | Required | Rule |
|---|---|---|
stateTitle | Yes | Sentence case, no period. States the situation, not the feeling. |
stateBody | Optional | One sentence. What would be here, or what went wrong. |
stateAction | Yes on error | Primary on a first-run empty; secondary on a filtered empty and on error. |
tone | Optional | Only destructive, and only on error. Empty states are not a problem. |
Sporting Scouter Design System
Every token on this site is generated from
theme.css.