Skip to content

Components · Status and feedback

ErrorPage

A whole page failed: not found, forbidden, server error, offline or maintenance.

@rookcom/monarch-reactComponent

Not found, inside the shell

Page not found

The link may be broken, or the page may have moved.

Usage examples

Server error with support

Offline and maintenance, without the shell

Purpose

The page shown when a route cannot render: a 404, a 403, a server error, no connection or planned maintenance. It works on its own, without the app shell, so it can back root not-found and error routes.

Use when

  • A route does not exist or a record behind it is gone (not-found).
  • The person may not open the page (forbidden).
  • The page crashed or the server failed (server, the default).
  • The app cannot reach the network (offline).
  • The service is down on purpose (maintenance).

Avoid when

  • Only one region of the page failed: use ErrorState or InlineErrorRetry.
  • The page loaded and is simply empty: use EmptyState.

Design principles

  • The product supplies every word: title, description, actions and the support contact. The component supplies the layout, icon and numeral.
  • Never show a raw error message, stack, vendor or technology name; offer the next step instead.
  • A large, faint numeral (404, 403, 500) stands in for an illustration, so no artwork is needed; connectivity and maintenance have none.
  • One primary action (retry, or the product’s way home) and at most one secondary.

API reference

import { ErrorPage } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
ErrorPagecomponentclient.mn-error-page

The ref is forwarded to the root element (main, section or div). Native attributes pass through.

Actions are the product’s own elements: pass Buttons, or Button asChild around your router’s link.

Use errorKindFromStatus (exported with ErrorState) to pick a kind from an HTTP status; maintenance is always the product’s decision.

Generated from the TypeScript declarations of packages/react/src/components/feedback/error-page.

Properties

ErrorPage

A whole page that failed: not found, forbidden, server error, offline or maintenance. Works with or without the app shell. The product supplies every word, link and support contact.

PropTypeDescription
title requiredReactNodeWhat happened, in plain words. Supplied by the product.
actionsReactNodeThe product's links and buttons, e.g. "Go to dashboard" (Button `asChild` around a router link).
as"div" | "main" | "section"The root element. Default `main` when `fullScreen` (the page has no other main landmark) and `section` otherwise (the shell already has one).
brandReactNodeThe product's logo or wordmark, shown at the top when there is no app shell.
childrenReactNode
classNamestring
descriptionReactNodeWhat the person can do next. Supplied by the product; never a raw error message.
focusOnMountbooleanMoves focus to the title on mount, so a screen reader starts reading the error after a client-side navigation. Default false.
fullScreenboolean`true` (default) fills the viewport with its own background, for a root not-found or error route that renders without the app shell. `false` sits inside the shell's content area.
headingLevel"h2" | "h1"Title element. Default `h1`.
iconReactNodeReplaces the kind's default icon. Pass `null` for none. Decorative.
idstring
kindErrorPageKindWhich failure this page reports. Sets the default icon and numeral. Default `server`.
numeralstring | falseThe large faint numeral behind the icon. Defaults to 404, 403 or 500 for those kinds and none for `offline` and `maintenance`. Pass `false` to hide it. Decorative: drawn by CSS and hidden from assistive technology, so say the same thing in the title.
onRetry(() => void)Renders a primary retry button before `actions`. Use for `server`, `offline` and `maintenance`.
requestIdstringThe request id of the failed request, shown with a copy button.
requestIdLabelstringLabel before the request id. Default "Request ID".
retryingbooleanShows the retry button as busy while a retry is in flight.
retryLabelstringRetry button text. Default "Try again".
retryWhenOnlinebooleanWith `kind="offline"` and `onRetry`, calls `onRetry` once when the browser reports it is back online. Default true.
supportReactNodeHow to reach help, supplied by the product (a sentence with a link or email).

Variants

PropValuesDescription
kind'not-found''forbidden''server''offline''maintenance'Default icon, icon tint and numeral (404, 403 and 500; none for offline and maintenance). Exposed as data-kind.
fullScreen'true''false'true (default) fills the viewport with the canvas background and its own font, for pages without the app shell; false sits inside the shell’s content area. true is exposed as data-full-screen.
as'main''section''div'Root element. Default main when full screen, section otherwise, so it never nests a second main landmark.
numeral'string''false'Overrides the kind’s numeral (e.g. "502"), or false to hide it.

States

StateExposed asBehaviour
Retryingaria-busy="true" on the retry buttonretrying shows the Button loading state and blocks repeat clicks.
Waiting for connectiondata-kind="offline"With onRetry and retryWhenOnline (default), the page retries once when the browser fires online.

Interaction behaviour

  • The retry button (when onRetry is set) comes first and calls onRetry.
  • Offline pages retry automatically once when the connection returns; set retryWhenOnline={false} to opt out.
  • focusOnMount moves focus to the title after a client-side navigation, so screen readers start at the error.
  • The request-id copy button copies the id and announces the result.

Keyboard support

KeysAction
Tab / Shift+TabMoves through retry, the product’s actions, the copy button and support links.
Enter / SpaceActivates the focused action.

The title is focusable only by script (tabIndex=-1), for focusOnMount.

Accessibility

Role
main (full screen) or region, labelled by the title
Accessible name
From the title, through aria-labelledby with a generated id, so two pages never share an id.
  • The title is an h1 by default (headingLevel="h2" inside a shell that already has an h1).
  • The numeral is drawn by CSS (::before from data-numeral) and, like the icon, aria-hidden; say the same thing in the title ("Page not found", not "404").
  • No live region: the page is the content. Use focusOnMount after client-side navigation.
  • Verified with axe in jsdom and in Chromium, Firefox and WebKit on /components/error-page.

Responsive behaviour

  • Content is centred in a 30rem column; the numeral scales with the viewport (clamp).
  • Below 30rem the title steps down a size and actions stack full width.
  • Full screen uses 100dvh, so mobile browser toolbars do not cut it off.

Theme support

  • not-found uses the accent tile; server danger; offline warning; forbidden and maintenance the muted surface.
  • Full screen sets --mn-color-bg-canvas, --mn-color-text-default and --mn-font-sans itself, so it looks right without the app shell.
  • Colours are Monarch semantic tokens only, so light, dark and more-contrast themes apply automatically.

Do and don't

Do

  • Write a title that says what happened without the code ("Page not found").
  • Give a way forward: retry, home, or back.
  • Pass your support contact through support and the request id when you have one.
  • Use fullScreen={false} when the shell can still render around the error.

Don't

  • Do not show raw error messages, stack traces or vendor names.
  • Do not offer retry on a 404 or 403.
  • Do not render a full-screen ErrorPage inside another main; set as="section" or fullScreen={false}.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsButton, CopyButton, ErrorState

Testing coverage

  • Full screen renders a main landmark labelled by its h1, with an aria-hidden numeral.
  • Numerals default by kind and can be overridden or hidden.
  • Inside a shell it renders a labelled section, never a second main; each instance has its own title id.
  • Retry comes first, is keyboard operable and shows a busy state.
  • Offline retries once on the online event, and not when retryWhenOnline is false.
  • focusOnMount focuses the title; brand, support and request id render; the ref is forwarded.
  • as="div" drops aria-labelledby (not allowed on a generic element).
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery; Cross-browser axe: /components/error-page

Tests: packages/react/src/components/feedback/error-page