RoadieRoadie
  • Home
  • Brand
  • Foundations
  • Content
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeBrandFoundations
Appearance

Components

  • Navigation

    • Breadcrumb
    • LinkBeta
    • NavigatorAlpha
    • Steps
    • Tabs
  • Layout

    • Accordion
    • CollapsibleBeta
    • PaneAlpha
    • ScrollArea
    • Separator
  • Actions

    • Button
    • IconButton
    • ToggleBeta
    • Toggle groupBeta
    • ToolbarBeta
  • Fields

    • EditorAlpha
    • Field
    • Fieldset
    • Input
    • Label
    • Number fieldBeta
    • OTP fieldBeta
    • Query fieldAlpha
    • Textarea
  • Choices

    • Autocomplete
    • CheckboxBeta
    • Combobox
    • Radio group
    • Select
    • SliderBeta
    • SwitchBeta
  • Date and time

    • CalendarBeta
    • CalendarTile
    • Countdown
    • Dashboard periodBeta
    • Date fieldBeta
    • Date pickerBeta
    • Date range pickerBeta
    • DateTime
    • Duration
    • Time fieldBeta
  • Collections

    • Card
    • Carousel
    • DataTableBeta
    • ListAlpha
    • Marquee
    • RecordGridAlpha
    • RecordTableAlpha
    • SortableAlpha
    • TableBeta
  • Overlays

    • Dialog
    • Drawer
    • MenuBeta
    • Popover
    • ToastBeta
    • Tooltip
  • Status

    • Badge
    • CalloutBeta
    • DeltaBeta
    • Empty state
    • MeterBeta
    • ProgressBeta
    • SkeletonBeta
    • SparklineBeta
    • StatTileBeta
  • Media & brand

    • AvatarBeta
    • Icon Tile
    • Image
    • Logo
    • PatternBeta
    • QR codeBeta
    • SpotIllustration
  • Text

    • Code
    • Highlight
    • KbdBeta
    • Mark
    • Prose

Empty state

Status
Stable
Added
Components 2.8.017 Jun 2026
Updated
Components 2.16.020 Oct 2026
Docs updated
19 Oct 2026

Communicates that a section or page has no content. A single size token scales it from a small empty section up to a whole-page empty or 404 screen.

Import

import { EmptyState } from '@oztix/roadie-components/empty-state'

Examples

Default

The standalone md empty state has an IconTile, a message, and one action.

<EmptyState>
<EmptyState.IconTile>
<TicketIcon weight='duotone' />
</EmptyState.IconTile>
<EmptyState.Title>No events yet</EmptyState.Title>
<EmptyState.Description>

In a section

Use size='sm' for an empty state inside a card or panel.

<Card>
<Card.Content>
<EmptyState size='sm'>
<EmptyState.IconTile>
<TicketIcon weight='duotone' />
</EmptyState.IconTile>

Whole page

Use size='lg' with a custom hero illustration for a full-page empty or 404 screen. Raise the heading to h1 with render.

<EmptyState size='lg'>
<EmptyState.Title render={<h1 />}>This page packed up early</EmptyState.Title>
<EmptyState.Description>
The link is broken. The event might be over. Let's find you another gig.
</EmptyState.Description>
<EmptyState.Actions>

Sizes

{['sm', 'md', 'lg'].map((size) => (
<EmptyState key={size} size={size}>
<EmptyState.IconTile>
<MagnifyingGlassIcon weight='duotone' />
</EmptyState.IconTile>
<EmptyState.Title>No events match your search</EmptyState.Title>

Media by size

The recommended pairing: sm → IconTile, md → SpotIllustration, lg → hero illustration. The pairing is a convention, not enforced.

<EmptyState size='sm'>
<EmptyState.IconTile>
<HeartIcon weight='duotone' />
</EmptyState.IconTile>
<EmptyState.Title>No favourites yet</EmptyState.Title>
<EmptyState.Description>

Intents

Set intent on the root to tint the IconTile and Button together. Omit it to inherit the palette from an ancestor instead.

<EmptyState intent='accent' size='sm'>
<EmptyState.IconTile>
<StarIcon weight='duotone' />
</EmptyState.IconTile>
<EmptyState.Title>You're all caught up</EmptyState.Title>
<EmptyState.Description>No new notifications right now.</EmptyState.Description>

Without actions

Title and description only.

<EmptyState size='sm'>
<EmptyState.IconTile>
<EnvelopeIcon weight='duotone' />
</EmptyState.IconTile>
<EmptyState.Title>Inbox zero</EmptyState.Title>
<EmptyState.Description>You're all caught up.</EmptyState.Description>

Guidelines

Write the title, description, and actions with Interface copy.

Match the size to its context

No tickets

Tickets you buy will appear here.

Do

Use size='sm' inside a card or panel, md for a standalone state, and lg only for a whole-page empty or 404 screen.

No tickets

Tickets you buy will appear here.

Don’t

Don't drop a whole-page lg state into a small section. It overwhelms the surrounding UI.

Set the intent once on the root

<EmptyState intent='danger'>
<EmptyState.IconTile>…</EmptyState.IconTile>
<EmptyState.Title>We couldn't load your events</EmptyState.Title>
<EmptyState.Actions>
<Button emphasis='strong'>Retry</Button>
</EmptyState.Actions>

Do

Pass intent on the root (or inherit it from an ancestor) so the tile and buttons share one palette.

<EmptyState>
<EmptyState.IconTile intent='danger'>…</EmptyState.IconTile>
<EmptyState.Actions>
<Button intent='danger'>Retry</Button>
</EmptyState.Actions>
</EmptyState>

Don’t

Don't hard-code the same intent on every child. It drifts out of sync.

Let EmptyState borrow a surface

<Card>
<Card.Content>
<EmptyState size='sm'>…</EmptyState>
</Card.Content>
</Card>

Do

Wrap the empty state in a Card when you need a background or border. EmptyState has no surface of its own.

<EmptyState className='rounded-xl border bg-raised p-6'>…</EmptyState>

Don’t

Don't bolt an ad-hoc surface onto the root with utility classes. Reach for the Card you already have.

Accessibility

  • EmptyState.Title renders an <h2> by default. Use render={<h1 />} (or another level) so the heading fits the surrounding document outline. A whole-page state usually wants h1.
  • Decorative media should be hidden from assistive tech: pass alt='' on <img> heroes. SpotIllustration sets aria-hidden automatically unless you give it an aria-label. IconTile is not hidden by default. Add aria-hidden to a purely decorative tile. The title and description carry the meaning.

API reference

EmptyState

size"sm" | "md" | "lg"

Scales typography, spacing, and media together.

intent"neutral" | "brand" | "brand-secondary" | "brand-blue" | "brand-orange" | "brand-purple" | "accent" | "danger" | "success" | "warning" | "info"

Palette for the empty state. Omit to inherit from an ancestor.

EmptyState.Actions

No additional props. It forwards all standard HTML attributes to the underlying element.

EmptyState.Description

No additional props. It forwards all standard HTML attributes to the underlying element.

EmptyState.IconTile

intent"neutral" | "brand" | "brand-secondary" | "brand-blue" | "brand-orange" | "brand-purple" | "accent" | "danger" | "success" | "warning" | "info" | null
emphasis"strong" | "normal" | "subtle" | "subtler" | null
size"xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | null
shape"circle" | "square" | null

Defaults to circle.

EmptyState.Illustration

No additional props. It forwards all standard HTML attributes to the underlying element.

EmptyState.Title

renderRoadieRenderProp

Change the heading level, e.g. `render={<h1 />}`. Defaults to `<h2>`.

Previous page← CalloutNext pageProgress →