Skip to content

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-screen

Also 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:

statusScreen-view.tsx
'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
      }}
    />
  )
}

Reference

Props20 props

Props

StatusScreen props
PropType
statusStatusScreenStatus
'401''403''503''loading'

Which page: 401 sign in, 403 no access, 503 temporarily unavailable, loading still on its way.

default '401'

'401'
mediaReactNode

The picture beside the text: your own node, or null for the plain page. Default: the status's miniature, playing the page's state.

–
actionsReactNode

Replaces the page's buttons with your own. Default: the status's own actions.

–
signInHrefstring

401: where the sign-in page lives; 403: where Switch account goes.

default '#sign-in'

'#sign-in'
onSignInMouseEventHandler<HTMLAnchorElement>

401: runs when Sign in is pressed, before the link is followed.

–
returnTostring

401: the page they return to, shown under the buttons. Empty hides it.

default '/settings/billing'

'/settings/billing'
permissionstring

403: the permission they lack, shown on the page. Empty hides it.

default 'billing:read'

'billing:read'
accountstring

403: the account that's signed in, with Switch account beside it. Empty hides it.

default 'ana@northwind.io'

'ana@northwind.io'
onRequestAccess() => Promise<unknown> | unknown

403: 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> | unknown

503: 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
retryDelaysnumber[]

503: seconds before each automatic retry, the last one repeating; [] retries only when asked.

default `[5, 15, 30, 60]`

`[5, 15, 30, 60]`
statusHrefstring

503: where the status page lives.

default '#status'

'#status'
homeHrefstring

Where Back to home goes.

default '#home'

'#home'
progressnumber

Loading: how far along, 0 to 100. Default: unknown, so the bar sweeps.

–
slowAfternumber

Loading: after this many ms, say it's slow and offer Reload; 0 never does.

default 10000

10000
onReload() => Promise<unknown> | unknown

Loading: what Reload does once it's slow.

default a short demo wait

a short demo wait
headingLevel1 | 2 | 3

The headline's level.

default 1

1
linkComponentElementType

The element every link renders as, e.g. Next.js Link.

default 'a'

'a'
copyPartial<StatusScreenCopy>

Any of the page's strings, to rewrite or translate.

–
themeThemeInput

Default: 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.

homeerrorCodeunauthorizedTitleunauthorizedDescriptionsignInreturnHintforbiddenTitleforbiddenDescriptionpermissionLabelrequestAccessrequestingrequestedrequestFailedrequestedHintsignedInAsswitchAccountunavailableTitleunavailableDescriptionretryretryingbackOnlinestillDownstatusPageretryInretryHintloadingTitleloadingDescriptionloadingLabelloadingSlowreload
Built from4 components

Built from

Accessibilitylandmarks, 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.