# Front-End State Recipes

A compact reference for designing and implementing resilient UI states without turning every state into a one-off component.

## Recipe: Optimistic Action

Use when the action is fast, reversible, and low risk.

```ts
const previous = state;
setState(applyLocalChange(state, change));

try {
  await saveChange(change);
} catch {
  setState(previous);
  notify("Could not save. Your previous state was restored.");
}
```

Checklist:

- [ ] Previous state is stored before the optimistic update.
- [ ] Pending state remains visible.
- [ ] Failure restores or reconciles state.
- [ ] The user knows which action failed.
- [ ] High-risk actions still require explicit confirmation.

## Recipe: Loading State

Use when data is not ready yet.

- Preserve the final layout shape.
- Keep labels or skeletons close to the eventual content.
- Avoid spinners as the only signal in dense interfaces.
- Show which surface is loading, not only that something is loading.
- Keep retry behavior nearby when loading fails.

## Recipe: Empty State

Use when the product has no records, no matching filters, or no permission.

- Name the reason for emptiness.
- Separate true empty from filtered empty.
- Give one useful next action.
- Avoid decorative illustrations when the user needs instruction.
- Keep links to docs or setup steps specific.

## Recipe: Error State

Use when the product failed to complete a request.

- Say what failed.
- Say what happened to the user's work.
- Say what they can do next.
- Keep the failed object visible when possible.
- Avoid global banners for local row/action failures.

## Recipe: Data Transition

Use when a metric, chart, or list changes.

- Animate the value that carries meaning.
- Keep the duration short.
- Respect reduced-motion settings.
- Avoid animation that hides causality.
- Reconcile with server truth after the transition.

## Recipe: Disabled Control

Use only when the user cannot act yet.

- Put the reason next to the control.
- Make missing requirements visible.
- Prefer an enabled explanatory action when the next step is not obvious.
- Do not use disabled as a substitute for permission education.
