Status
Screens for when a page can't do its job: sign in, no access, not found, errors, maintenance, loading, a launch, tracking, a public status page and a pre-launch waitlist, most beside a miniature that plays the page's state.
Installation & usage
npx @youj/cli add app-status-screenAlso installs async-button, button, icon-external-link, icon-home, icon-key, icon-log-in, icon-refresh, progress, reveal, stagger, use-now, youj-core, youj-presets, youj-ui-core.
The CLI copies the block to blocks/app/status-screen.tsx with every component it uses, so it’s yours to edit.
Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:
'use client'
import Link from 'next/link'
import { StatusScreen, type StatusScreenProps } from '@/blocks/app/status-screen'
export function StatusScreenView({ status, retryDelays }: Pick<StatusScreenProps, 'status' | 'retryDelays'>) {
return (
<StatusScreen
status={status}
retryDelays={retryDelays}
copy={{ home: 'Back to home' }}
linkComponent={Link}
onSignIn={() => {
// your code
}}
onRequestAccess={async () => {
// await your API here; the block shows progress until it settles
}}
onRetry={async () => {
// await your API here; the block shows progress until it settles
}}
/>
)
}Description
Say the service is temporarily down and nothing was lost. The page tries again on its own, waiting longer each time, with the countdown under Try now, while the server cabinet beside it runs with two nodes down; they recover when a retry gets through.
Ask for a sign-in, beside a parcel locker whose keypad waits for its code. Sign in goes to your sign-in page, and the line under the buttons says where the visitor comes back to.
The same page without the miniature (media={null}): the code set large over the headline.
Explain that the visitor is signed in but not allowed, beside a firewall in lockdown. The page names the permission they lack and the account they're signed in with (Switch account beside it), asks an admin for access and says what happens next.
The 403 without the miniature.
Give visitors a way forward when a page has moved or never existed: a lighthouse sweeps the fog beside a search field, the way home and a few likely destinations.
The 404 without the miniature: its digits rise out of their masks.
Apologize plainly when the server fails. The mainframe stands in machine check; Try again resets it and feeds its cards, and it runs again once the retry works. The status page, each service's state and the incident ID to copy for support sit under it.
The 500 without the miniature: the code set large.
The 503 without the miniature.
Announce a planned window: the time left, how far along it is and each step, a field to be emailed when it's back, and a repair bench whose checklist lights up as the window passes. Its beacon turns green when the window ends.
Maintenance without the miniature.
Hold the page while it loads. The hourglass's sand is the progress (it turns over on its own while that's unknown), a polite live region says what is happening, and past slowAfter the page offers a reload.
Loading without the miniature: the headline over a progress bar that sweeps until you pass progress.
The page before a launch: the time left in rolling digits and a field for early-access codes, beside a drone charging on its pad that takes off when the countdown reaches zero. The demo accepts EARLY.
The launch countdown without the miniature.
Let people look up an order, request or incident by its reference and see where it stands, step by step, with when each step happened and what comes next. The packaging line beside it fills its pallet as the order moves through its steps and wraps it once it's delivered.
Tracking without the miniature.
Keep your customers informed with a public status page for the same services, their uptime and incident updates. It has no miniature: people scan it for one answer, so the answer leads.
Build interest before launch with a waitlist page, a countdown and a referral link. The demo shows your place in line after you join.
Code
Status Screen, the Service unavailable (503) story: the files youj add writes.
Reference
Props20 props
Props
| Prop | Type | |
|---|---|---|
status | StatusScreenStatus'401''403''503''loading'Which page: default '401' | '401' |
media | ReactNodeThe picture beside the text: your own node, or | – |
actions | ReactNodeReplaces the page's buttons with your own. Default: the status's own actions. | – |
signInHref | string401: where the sign-in page lives; 403: where Switch account goes. default '#sign-in' | '#sign-in' |
onSignIn | MouseEventHandler<HTMLAnchorElement>401: runs when Sign in is pressed, before the link is followed. | – |
returnTo | string401: the page they return to, shown under the buttons. Empty hides it. default '/settings/billing' | '/settings/billing' |
permission | string403: the permission they lack, shown on the page. Empty hides it. default 'billing:read' | 'billing:read' |
account | string403: the account that's signed in, with Switch account beside it. Empty hides it. default 'ana@northwind.io' | 'ana@northwind.io' |
onRequestAccess | () => Promise<unknown> | unknown403: ask for access; resolve when sent, reject with an Error whose message says why not. default a short demo wait | a short demo wait |
onRetry | () => Promise<unknown> | unknown503: try the request again; resolve when it worked, reject when it didn't. default a short demo wait that fails | a short demo wait that fails |
retryDelays | number[]503: seconds before each automatic retry, the last one repeating; default `[5, 15, 30, 60]` | `[5, 15, 30, 60]` |
statusHref | string503: where the status page lives. default '#status' | '#status' |
homeHref | stringWhere Back to home goes. default '#home' | '#home' |
progress | numberLoading: how far along, 0 to 100. Default: unknown, so the bar sweeps. | – |
slowAfter | numberLoading: after this many ms, say it's slow and offer Reload; 0 never does. default 10000 | 10000 |
onReload | () => Promise<unknown> | unknownLoading: what Reload does once it's slow. default a short demo wait | a short demo wait |
headingLevel | 1 | 2 | 3The headline's level. default 1 | 1 |
linkComponent | ElementTypeThe element every link renders as, e.g. Next.js default 'a' | 'a' |
copy | Partial<StatusScreenCopy>Any of the page's strings, to rewrite or translate. | – |
theme | ThemeInputDefault: the host's theme. | – |
Strings30 keys for copy
Strings
copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.
homeerrorCodeunauthorizedTitleunauthorizedDescriptionsignInreturnHintforbiddenTitleforbiddenDescriptionpermissionLabelrequestAccessrequestingrequestedrequestFailedrequestedHintsignedInAsswitchAccountunavailableTitleunavailableDescriptionretryretryingbackOnlinestillDownstatusPageretryInretryHintloadingTitleloadingDescriptionloadingLabelloadingSlowreloadAccessibilitylandmarks, decorative miniatures, status, live regions
Accessibility
Every screen is a main with one heading (an h1 by default; set headingLevel where the page around it needs another). The miniatures are decoration: each is a still, unfocusable picture (interactive={false}) inside an aria-hidden stage, so the headline, the text and the live regions carry the meaning, and each follows reduced motion, showing its states at once. The status code is read as plain text: a small line over the headline beside a miniature, set large on the plain page.
Status screen's loading state sets aria-busy on the page and announces its headline through a status region; its progress bar is a labelled progressbar, with no value while the wait is unknown, and the line that offers a reload is a status as well. The 503's automatic retries run through its Try now button, so each attempt and its outcome are announced (Retrying…, Still down, Back online); the countdown to the next one is plain text, never read out every second. After a 403 request, the line saying what happens next is a status. The 404's search is a search landmark with a labelled field. Request tracking announces a found request politely, lists the steps as an ordered list with the current one marked aria-current="step" and each step's state spelled out for screen readers, and shows lookup errors under the field (aria-describedby).
Actions that wait on a server (Try again, Try now, Request access, Notify me, Track) are Buttons with onAction or a status: they show progress and the result in text as well as motion. Links and buttons are real a and button elements with the kit's focus ring. Everything animated stands still under reduced motion.