Detent web components
By Shane Logsdon

Feedback & status

Not Found

Implemented

Minimal spring-displaced 404 error experience with tactile proximity physics

detent-not-found

Port status
Catalog status
implemented
Origin
upstream
Phase
2
Wave
phase-2-feedback
Group
Feedback & status

7.1 KB gzip for the class module

Variants

Two configurations: the primary 404 above the Variants heading with a path chip and a secondary action, and this 410 with the chip hidden and the secondary control in detent-back mode. Both link sets are real <a href> elements; the pointer parallax and the entrance rise stop under prefers-reduced-motion: reduce.

Recorded states

  • focus-visible recorded state; no setter
  • reduced motion recorded state; no setter
  • active recorded state; no setter

Usage

Import

import '/components/not-found/define.js';

// or register it yourself
import { DetentNotFound } from '/components/not-found/not-found.js';

Attributes

  • action-label
  • back-label
  • badge-label
  • description
  • document-title
  • error-code
  • home-href
  • home-label
  • parallax
  • path
  • secondary-action-label
  • show-back
  • title

Properties

  • suggestions
  • onAction
  • onSecondaryAction

Slots

  • default
  • description
  • footer

Events

  • detent-action — {}
  • detent-secondary-action — {}
  • detent-back — {}

Example

Runnable example: site/examples/not-found.ts. The snippet below is generated from the catalogued attributes.

<detent-not-found
  action-label="Go back home"
  back-label
  badge-label
  description="The requested page doesn\\'t exist or may have moved."
  document-title
  error-code="404"
  home-href
  home-label
  parallax
  path
  secondary-action-label
  show-back
  title="This page took a wrong turn."
></detent-not-found>

Property-only values

const element = document.querySelector('detent-not-found');
if (element !== null) {
  // onAction: () => void
  element.onAction = () => {};
  // onSecondaryAction: () => void
  element.onSecondaryAction = () => {};
}

Source

The pinned upstream source for this row:

  • src/components/ui/NotFound.tsx sha256 d18b49cfe8db…

Native files

The native module and its artifacts:

  • src/components/not-found/not-found.ts
  • src/components/not-found/styles.css
  • src/components/not-found/define.ts
  • docs/components/not-found.md
  • site/examples/not-found.ts
  • tests/browser/not-found.spec.ts
  • evidence/components/not-found.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
action-labelactionLabelstring'Go back home'Kebab-case attribute; camelCase property.
back-label———Recorded in the catalog as an attribute.
badge-labelbadgeLabelstringundefinedKebab-case attribute; camelCase property.
descriptiondescriptionstring'The requested page doesn\\'t exist or may have moved.'Kebab-case attribute; camelCase property.
document-title———Recorded in the catalog as an attribute.
error-codeerrorCodestring'404'Kebab-case attribute; camelCase property.
home-href———Recorded in the catalog as an attribute.
home-label———Recorded in the catalog as an attribute.
parallax———Recorded in the catalog as an attribute.
path———Recorded in the catalog as an attribute.
secondary-action-labelsecondaryActionLabelstringundefinedKebab-case attribute; camelCase property.
show-back———Recorded in the catalog as an attribute.
titletitlestring'This page took a wrong turn.'Kebab-case attribute; camelCase property.

Properties

Properties
PropertyTypeDefaultNotes
suggestions——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
onAction() => voidundefinedProperty-only: assign from script; not accepted as an attribute.
onSecondaryAction() => voidundefinedProperty-only: assign from script; not accepted as an attribute.

Events

Events
EventUpstream propPayload typeNotes
detent-actiononAction() => voidComposed, bubbles; fires only for a user action.
detent-secondary-actiononSecondaryAction() => voidComposed, bubbles; fires only for a user action.
detent-backonBack() => voidComposed, bubbles; fires only for a user action.

Slots

Slots
SlotNotes
defaultConsumer content; rendered through a slot, never re-created.
descriptionConsumer content; rendered through a slot, never re-created.
footerConsumer content; rendered through a slot, never re-created.

CSS customisation

  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • No `LinkComponent` property (a React component reference cannot be an attribute or plain-data property, PC-3.1); links are real `<a href>` (PC-12.1) and the callbacks become cancelable composed events.
  • `onAction`/`onBack`/`onSecondaryAction` become `detent-action`, `detent-back` and `detent-secondary-action` (detail `{}`, bubbles + composed, cancelable): `detent-action` on primary activation, and the secondary control emits `detent-secondary-action` when `secondary-action-label` is set, otherwise `detent-back` - exactly one event per activation.
  • `className` replaced by 16 parts and 2 custom properties.
  • Token palette instead of the dark-only hex set; solid heading instead of gradient-clipped text (contrast).
  • `document-title` attribute instead of React 19 head hoisting, and no `<meta name="robots">` write.
  • `--detent-not-found-min-height` (22rem) instead of `min-h-screen`.
  • CSS keyframes/transitions and a throttled transform instead of Framer Motion springs (no spring smoothing on the parallax).
  • `suggestions` is property-only with a URL-scheme allow-list (`javascript:`/`data:` never become hrefs).
  • Illustration re-created as local SVG/CSS (glass panel + SVG-text 404 glyphs) - an L5 visual gap until compared against the reference.
  • `show-back`/`parallax` keep the upstream true default with presence semantics + property opt-out.

What it does

A recovery page for a missing route: an illustration (orange panel, big 404, frosted-glass folder, cross badge), a badge, a heading, a description, an optional "missing path" chip, one primary recovery control, an optional secondary/back control, up to three suggestion links and a footer.

Upstream behaviour
  • Pure floating spring-physics entities for each character with custom mass and damping
  • Continuous pointer proximity repulsion without React state re-renders (zero-jank 60fps)
  • Mobile-first tactile tap impulse feedback for touch screens
  • Strictly adheres to EasyUI dark neutral palette and Sky-400 focus ring
  • Full accessibility support with screen reader announcements and semantic heading hierarchy
  • Seamless prefers-reduced-motion fallback disabling continuous movement
Differences from upstream
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • No `LinkComponent` property (a React component reference cannot be an attribute or plain-data property, PC-3.1); links are real `<a href>` (PC-12.1) and the callbacks become cancelable composed events.
  • `onAction`/`onBack`/`onSecondaryAction` become `detent-action`, `detent-back` and `detent-secondary-action` (detail `{}`, bubbles + composed, cancelable): `detent-action` on primary activation, and the secondary control emits `detent-secondary-action` when `secondary-action-label` is set, otherwise `detent-back` - exactly one event per activation.
  • `className` replaced by 16 parts and 2 custom properties.
  • Token palette instead of the dark-only hex set; solid heading instead of gradient-clipped text (contrast).
  • `document-title` attribute instead of React 19 head hoisting, and no `<meta name="robots">` write.
  • `--detent-not-found-min-height` (22rem) instead of `min-h-screen`.
  • CSS keyframes/transitions and a throttled transform instead of Framer Motion springs (no spring smoothing on the parallax).
  • `suggestions` is property-only with a URL-scheme allow-list (`javascript:`/`data:` never become hrefs).
  • Illustration re-created as local SVG/CSS (glass panel + SVG-text 404 glyphs) - an L5 visual gap until compared against the reference.
  • `show-back`/`parallax` keep the upstream true default with presence semantics + property opt-out.
Previous: Hanging Charm Next: Notification Bell

Docs

Components

Project