Vesyl UI

Empty

A centered empty-state layout for when there’s nothing to show — a list with no rows, a search with no matches, or a screen the user has fully cleared. Reach for it instead of leaving a blank panel: a glyph, a one-line title, and a sentence of guidance turn dead space into a next step.

Compose the parts: Empty (the centered, dashed-border container), EmptyHeader (groups the media + text, capped at max-w-sm), EmptyMedia (the icon tile), EmptyTitle, EmptyDescription, and EmptyContent (where actions live). Every part is a vertical Stack under the hood, so gap, align, and justify are props — no className wrestling.

Basic

The full pattern: an icon media tile, a title, a description, and a call-to-action in EmptyContent. This is the “no shipments yet” first-run screen.

No shipments yet
Once you buy a label or hand off an order to a carrier, it'll show up here.

Without an action

Drop EmptyContent when there’s nothing for the user to do — an error or informational state. Just the EmptyHeader (media + title + description) stands on its own.

Couldn't load your account
We hit an error fetching your profile. Refresh the page or try again in a moment.

No results

A search or filter that returned nothing. EmptyMedia variant="icon-muted" reads quieter than a first-run prompt, and the action resets the query rather than starting something new.

No results
No orders match "1Z999AA10123456784". Check the tracking number or clear your filters.

Resolved state

EmptyMedia variant="icon-success" tints the tile green for an “all caught up” outcome — a queue the user has emptied on purpose, not a screen that’s empty because nothing exists yet.

All caught up
Every order in this batch has been picked, packed, and shipped. Nothing left to do.

Media variants

EmptyMedia ships four variants. default is a bare, unstyled wrapper; the three icon-* variants render a 48px tile that auto-sizes an unsized leading svg. Pick by tone: icon for neutral, icon-muted for low-emphasis (no-results), icon-success for resolved.

icon
Solid muted tile, rounded corners.
icon-muted
Muted circle, lower-contrast glyph.
icon-success
Green tile for resolved states.

Reference

Empty

The centered container. Extends VStack props (minus direction); defaults to gap={4}, centered on both axes, with a dashed border, p-12, and balanced center text.

PropTypeDefaultDescription
gapnumber4Vertical gap between children
align"start" | "center" | "end" | "stretch""center"Cross-axis alignment
justify"start" | "center" | "end" | "between""center"Main-axis alignment
classNamestringMerged onto the container

EmptyHeader

Groups the media, title, and description. Extends VStack props (minus direction); capped at max-w-sm, gap={2}, centered.

PropTypeDefaultDescription
gapnumber2Vertical gap between children
alignstring"center"Cross-axis alignment
classNamestringMerged onto the header

EmptyMedia

The icon tile. Extends <div> props.

PropTypeDefaultDescription
variant"default" | "icon" | "icon-muted" | "icon-success""default"default is an unstyled wrapper; icon-* render a 48px tile and auto-size an unsized leading svg
classNamestringMerged onto the tile

EmptyTitle

The heading line (text-lg font-medium). Extends <div> props.

PropTypeDefaultDescription
classNamestringMerged onto the title

EmptyDescription

The supporting copy (text-sm muted). Nested <a> elements get underline + hover styling for free. Extends <p> props.

PropTypeDefaultDescription
classNamestringMerged onto the description

EmptyContent

Holds the action(s) below the header. Extends VStack props (minus direction); gap={4}, centered, capped at max-w-sm. Wrap multiple buttons in an HStack to lay them out in a row.

PropTypeDefaultDescription
gapnumber4Vertical gap between children
alignstring"center"Cross-axis alignment
classNamestringMerged onto the content