Page state
ProWhat a page shows instead of its content: nothing here yet (empty), nothing matches the filters (no-match), something broke (error), or it can't be shown to you (unavailable). The words are the caller's, since they are the product's. An error carries the request id to quote; "unavailable" is for both "doesn't exist" and "not yours", so it never reveals which.
Preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/page-state
Brings in: button, copy-field, locale, skeleton, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { PageSkeleton, PageState } from "@/components/page-state"
export default function Example() {
return (
<div className="grid max-w-3xl gap-4 sm:grid-cols-2">
<div className="flex rounded-lg border">
<PageState
kind="no-match"
title="No migrations match these filters"
detail="Nothing on Staging was rolled back in the last 30 days."
secondary={{ label: "Clear filters", onClick: () => {} }}
/>
</div>
<div className="flex rounded-lg border">
<PageState
kind="error"
title="The flags couldn’t load"
detail="Keel couldn’t reach the flag service. Try again, or quote this id to support."
requestId="req_7f3a91c2"
action={{ label: "Try again", onClick: () => {} }}
/>
</div>
<div className="flex h-72 overflow-hidden rounded-lg border sm:col-span-2">
<PageSkeleton label="Loading repositories" />
</div>
</div>
)
}<PageState>
| Prop | Type | Default | Description |
|---|---|---|---|
| kindrequired | PageStateKind | — | empty, no-match, error or unavailable; sets the icon, and an error is announced. |
| titlerequired | string | — | What's going on, in the product's words. |
| detail | React.ReactNode | undefined | — | More on why, or what to do, under the title. |
| action | { label: string; onClick: () => void } | undefined | — | The one thing to do next. |
| secondary | { label: string; onClick: () => void } | undefined | — | A quieter second option, e.g. clear filters. |
| requestId | string | undefined | — | For errors: the id support needs. |
| Icon | LucideIcon | undefined | — | Replaces the kind's icon. |
| className | string | undefined | — | Extra classes for the outer element. |
<PageSkeleton>
A page that's loading: the shape of what's coming, announced once.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "list" | "detail" | undefined | "list" | The shape to sketch: rows of a list (the default) or one item's detail. |
| label | string | undefined | — | What's loading, announced to screen readers. Defaults to "Loading". |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under pageState in <LocaleProvider strings={{ … }}>; the table is exported as pageStateStrings.
| Key | English |
|---|---|
| requestId | Request id |
| loading | Loading |
Types
- PageStateKind
"empty" | "no-match" | "error" | "unavailable"