Zostel
Brand Empty State

Empty State

Nothing here yet, said the brand's way: one drawing from the brand library, picked by key so it follows every redraw, a title, a line and the way on. Ready presets for an empty list, a search with no results and no network. No state of its own, so it renders on the server.

Preview

A section with nothing in it yet

No trips yet

Every trip starts with an empty backpack. Pick a place, then pack.

The three presets

Nothing here yet

Every trip starts with an empty backpack. Add the first thing.

No results

No place called “Atlantis” yet. Try Jaipur, Bir or Leh.

You’re offline

No signal up here. Enjoy the view — we’ll reconnect when you’re back.

Any drawing from the library, by key — a place’s own pattern, or none

No sightings yet

Quiet in the forest today.

No kites up

Come back for Makar Sankranti.

No quests yet

Start one, and the crew will follow.

Usage

tsx
import { EmptyState } from "zostel-ui";

// a ready state, with its drawing and words
<EmptyState preset="no-results" action={{ label: "See every place", href: "/destinations" }} />

// any drawing from the brand library, by key, and your own words
<EmptyState
  drawing={{ set: "fauna", key: "red-panda" }}
  title="No sightings yet"
  body="Quiet in the forest today."
  action={{ label: "Try again", onClick: retry }}
/>

// in a product app on another host: the drawings come from the brand site
<EmptyState preset="empty" base="https://brand.zostel.com" />

Props

preset
Type: "empty" | "no-results" | "offline"
Default: —

A ready state, with its drawing and words (the table below). Any prop overrides its part.

drawing
Type: { set: "kit" | "fauna" | "city" | "culture"; key: string; version?; variant? }
Default: —

A drawing from the brand library, by key: kit = the detailed icons; fauna and city take version "colour" | "grey"; culture takes a variant (colour, tile, roundel, keycap, sticker, symbol).

src
Type: string
Default: —

Any picture instead (a URL). Wins over drawing.

drawingLabel
Type: string
Default: —

Names the drawing for screen readers. Without it the drawing is decorative (alt="" and hidden).

pattern
Type: PatternKey | false
Default: "khovar"

The brand pattern on the round plate behind the drawing, tone on tone and never behind the words. A place’s screen wears its own (jaipur → "leheriya"); false = no plate.

eyebrow
Type: ReactNode
Default: —

A small line above the title, e.g. "404".

title
Type: ReactNode
Default: —

The headline, in Futura: short, sentence case.

body
Type: ReactNode
Default: —

One or two short lines in the brand voice, in muted grey.

action
Type: { label; href } | { label; onClick } | ReactElement
Default: —

The way on: an orange-ink button, a link (href) or a button (onClick), never both (the kit’s ActionButton; the href passes through safeHref). A ready element is shown as it is.

secondaryAction
Type: { label; href } | { label; onClick } | ReactElement
Default: —

A second, quieter way on: a Beige button.

size
Type: "sm" | "md" | "lg"
Default: "md"

sm in a card or a list, md in a section, lg for a whole page.

titleAs
Type: "h1" | "h2" | "h3" | "h4" | "p"
Default: "h2"

The title’s element, so it sits in the page’s outline.

base
Type: string
Default: ""

Where the brand files live: "" is the same origin; a product app passes the brand site.

className
Type: string
Default: —

More classes, merged with the component’s own (tailwind-merge).

The presets

"empty"
Type: kit · backpack
Default: —

Nothing here yet — Every trip starts with an empty backpack. Add the first thing.

"no-results"
Type: kit · one-zobu-binoculars
Default: —

No results — Nothing matches that yet. Try another word, or a place nearby.

"offline"
Type: kit · mountain
Default: —

You’re offline — No signal up here. Enjoy the view — we’ll reconnect when you’re back.

Where the drawings come from

Every key is a file the brand tools generate, so a redrawn drawing reaches every empty state by itself. kit — the detailed icons on /icons. fauna — the animals on /illustrations. city — the city symbols, named place-symbol (e.g. jaipur-kites), on /illustrations and each place’s page. culture — the culture symbols on /zo-keyboard.

Pick a drawing that says the moment: a backpack for an empty list, Zobu with binoculars for a search, a mountain for no signal. The words say what to do next, in a verb.

The drawing sits on a round plate that wears a brand pattern at a whisper, tone on tone and never behind the words (brand/README.md §8, one pattern per surface): EmptyState wears khovar, NotFound jaali (the symbol’s own lattice), ZobuLoader gond scales. On a place’s screen, pass the place’s own (Jaipur wears leheriya); pattern={false} drops the plate.