Skip to content

Components / Sections

404

A 404 page: the code scrambles into place from random digits, rings spread slowly behind it, and the headline, copy and one link home arrive in three beats.

Live demo

404

Nothing here.

The page moved, or never was.

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density
align

Measured

JavaScript of its own

0 B

Uses TextScramble and the shared runtime (1.9 kB raw, once per site) and Reveal. With those included: 3.9 kB raw.

CSS 9.9 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

every browser.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/not-found-section
src/pages/index.astro
---
// src/pages/404.astro
import NotFoundSection from '@/components/moonarc/pro/NotFoundSection.astro';
---
<NotFoundSection headline="Page not found." copy="This page has moved or never existed." home={{ href: '/', label: 'Back home' }} />

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: text-scramble, ripple, reveal.

Props

PropTypeDefaultDescription
level1 | 21Heading level of the headline: 1 on a page's own hero, 2 under another h1 (a demo, or a block further down).
codestring'404'The code; scrambles from digits.
headlinestring'Page not found.'Headline.
copystringnoneA sentence.
home{ href, label }{ href: '/', label: 'Back home' }The one link.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so cards and fields follow the ground. Decoration is strongest on brand.
density'compact' | 'cozy' | 'roomy''cozy'Block padding ×0.8 / ×1 / ×1.25 through --ma-density.
align'start' | 'center''center'Text alignment.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-404.ma-404__actions.ma-404__code.ma-404__copy.ma-404__headline.ma-404__home.ma-404__inner

Slots

slot="eyebrow"slot="headline"slot="copy"slot="actions"

Reduced motion

The code is shown; rings are static; text fades.

With ClientRouter

Inherits every part; nothing to wire.

Why it is built this way

Replaces: 404 pages (Tailwind Plus). See the migration table.

Ripple

Backgrounds

Rings expand from a point and fade, one after another, like a pulse.

every browseralways

Entrance on scroll that plays once and stays, staggers its children, scrubs with the scroll position when asked, honours reduced motion, and keeps working after every ClientRouter navigation.

every browserscroll

Random characters resolve into the real text from left to right when it scrolls into view, on load, or on hover.

every browserscrollhoverload

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown