Empty state
Empty states are the moment between nothing and something. Settld treats them as warm invitations — never cold error pages. The tone is always specific, contextual, and forward-pointing. The art uses ASCII in monospace to stay on-brand without importing illustration libraries.
Variants
Default is the standard empty state — warm ASCII art, a specific headline, a human description, and an optional CTA button. Used for "no expenses", "no groups", "no search results".
Settled is the celebration variant — same structure, but the headline turns teal and the CTA becomes teal too. Used exclusively for the "all settled up" state. It should feel like a small win, not just an absence of data.
Both variants accept any combination of art + title + description + CTA. The CTA is optional — some empty states (search results, filters) don't need one.
Context sizing
Empty states scale to their container. Full-screen empties (when a whole view is empty) use 80px vertical padding and full prose. Inline empties (inside a card or panel) use 24px padding and abbreviated text — no CTA.
States
| State | When to use | Has CTA? |
|---|---|---|
| Default (no content) | No items exist yet — first use | Yes — add/create action |
| Settled | All balances are zero | Yes — start next group/expense |
| No search results | Filter/search returned nothing | No — user should modify their query |
| Inline empty | A card/panel has no data | Usually no |
On dark surfaces
On dark surfaces, the art block uses --dark-elevated background with a --dark-border dashed border. Text shifts to the dark text tokens. The settled variant's title uses a lighter teal tint (#5fc7a8) instead of the full --teal to maintain contrast on dark.
Anatomy
| Part | Element | Notes |
|---|---|---|
| Illustration | .empty-state-art | Monospace ASCII art in a dashed border box. Max 5 lines × 16 chars. Warm background --s-warm. |
| Headline | .empty-state-title | Display font, 20px/600. Specific — names the thing that's missing. Sentence case. |
| Description | .empty-state-desc | Body font, 14px, --ink-mute. Max 28ch. One sentence. Forward-pointing — tells the user what to do, not what failed. |
| CTA | .empty-state-action | Optional. Pill button, ink fill. Verb-led. One CTA maximum per empty state. |
Usage
.settled variant exclusively for the "all settled up" state. This is a celebrated outcome — the teal headline and CTA signal it positively. It's the app's signature happy path.
Accessibility
aria-hidden="true" to .empty-state-art. The headline and description carry the full meaning — the art is purely visual mood.
.empty-state-action should be a <button> for actions or <a> for navigation. The label must be specific: "Add expense" not just "Add". Avoid generic "Get started" — it fails for users who navigate by button list.
aria-live="polite" so screen readers announce the change without interrupting the user.
Code
HTML
<!-- Default empty state --> <div class="empty-state"> <div class="empty-state-art" aria-hidden="true"> ₹ · · · · [ ] · · · · · ₹ · </div> <div class="empty-state-title">No expenses yet</div> <div class="empty-state-desc">Split your first one. Even the ₹40 chai counts.</div> <button class="empty-state-action">Add expense →</button> </div> <!-- Settled variant --> <div class="empty-state settled"> <div class="empty-state-art" aria-hidden="true"> · · ✓ · · · · · · · · ✓ · · </div> <div class="empty-state-title">All settled up ✓</div> <div class="empty-state-desc">No one owes anyone. Enjoy that guilt-free chai.</div> <button class="empty-state-action">New group →</button> </div>
CSS classes
| Class | Purpose |
|---|---|
.empty-state | Centered column flex container |
.empty-state.settled | Celebration variant — teal headline and CTA |
.empty-state-art | Mono ASCII art block with dashed border |
.empty-state-title | Display headline — 20px/600 |
.empty-state-desc | Body description — 14px, muted, max 28ch |
.empty-state-action | Optional CTA — pill button, ink fill |
Design tokens used
| Token | Value | Role |
|---|---|---|
--font-mono | JetBrains Mono | ASCII art typeface |
--s-warm | #F1E9D5 | Art block background |
--ink-line | #DDD2B8 | Art block dashed border |
--ink-mute | #8A8276 | Art text and description color |
--teal | #0E7C66 | Settled title and CTA |
--r-lg | 24px | Art block border-radius |
--r-pill | 999px | CTA border-radius |