<!-- https://getkonjo.com/design/components/empty-state · source: docs/design/components/empty-state.md -->

# Empty state

What a screen or section shows when there is genuinely nothing in it: what goes here, why, and
one way to start.

```kata-specimen
empty-left
```

> Source: [`EmptyState.tsx`](../../../src/components/ui/EmptyState.tsx). When a screen should be
> empty at all, and the loading and error states beside it: [states](../patterns/states.md).

## When to use it

- After asking whether the screen should be empty. Real data elsewhere that belongs here? Show
  it. Something you can suggest from a real source? Suggest it.
- Only then: an empty collection. An empty *search* is different — keep the field and filters
  and say what matched nothing.

Use `align="left"` for anything new. The centred shape is frozen for its existing call sites.

## Anatomy

`align="left"` — the Kata anatomy, in flow on the page's own gutter:

| Part | Token |
|---|---|
| Block | `spacing.section` 24 above and below, no horizontal padding, `spacing.s8` between parts |
| Eyebrow | `typography.eyebrow`, `text.secondary` |
| Title | `typography.title` 22/700, `text.primary` |
| Body | `typography.body`, `text.secondary` — what goes here and why |
| Primary | the red pill: `brand.red`, 48 floor, `typography.rowTitle`, `brand.onRed`, `spacing.s8` extra above |
| Link | `typography.label` 13/700 in `accent.red`, 32 drawn plus `hitSlop` to 44 |

`align="center"` — the legacy shape:

```kata-specimen
empty-center
```

| Part | Token |
|---|---|
| Block | centred, `spacing.s64` vertical, `spacing.detailHorizontal` 24 horizontal |
| Glyph | 36pt in `text.quaternary` — off the icon ramp and frozen; do not copy it |
| Title | `typography.rowTitle`, centred |
| Action | red pill, `typography.buttonMedium`, `spacing.s16` above, `hitSlop` to 44 |

## States

- An empty state is itself a state. Its actions press at `opacity.pressed` 0.85.
- While it shows, **demote the screen's other primary**: one filled primary per screen.
- Loading is never an empty state. Show nothing under a second, then a spinner or skeleton.
- An error uses the same left anatomy with "Couldn't load …" and a retry.

## Content

- Title says what is missing, plainly: "Nothing graded yet".
- Body says what goes here and how it gets there: "Add what you're teaching to start grading."
- No exclamation marks, no "let's", no apology. The ninja may appear in an empty state; a
  cheerful line about nothing may not.

## Accessibility

- The primary and the link are role `button`, labelled with their visible text, each 44pt or more.
- Left-aligned and in flow, so it is read in the order it is seen, right after the screen title.

## Do and don't

```kata-specimen
empty-void
```

## Code

```tsx
import { EmptyState } from '../../components/ui';

<EmptyState
  align="left"
  eyebrow="Grading"
  title="Nothing graded yet"
  subtitle="Add what you're teaching to start grading."
  action={{ label: 'Add a technique', onPress: addTechnique, testID: 'grading-empty-add' }}
  link={{ label: "See last month's list", onPress: openLastMonth, testID: 'grading-empty-last-month' }}
  testID="grading-empty"
/>
```
