Detent web components
By Shane Logsdon

Feedback & status

Alert

Implemented

Smooth height collapse on dismissal with tone styling

detent-alert

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

Neutral notice

Nothing needs your attention right now.

4.0 KB gzip for the class module

Variants

Scheduled maintenance

The workspace is read-only on Sunday from 02:00 to 04:00 UTC.

Deployment finished

Version 2.4.0 is live in every region.

Sync paused

Reconnect to continue syncing this workspace.

Reconnect

Payment failed

We could not charge the card on file. Update it to keep the workspace open.

Update card

Custom icon

The icon slot replaces the tone icon.

No icon

An empty icon slot suppresses the tone icon.

Recorded states

  • focus-visible recorded state; no setter
  • closed recorded state; no setter
  • collapsed recorded state; no setter

Usage

Import

import '/components/alert/define.js';

// or register it yourself
import { DetentAlert } from '/components/alert/alert.js';

Attributes

  • dismissible
  • tone

Properties

  • tone
  • dismissible
  • collapsed
  • closed
  • dismiss
  • onDismiss

Slots

  • action
  • icon

Events

  • detent-dismiss — {}

Example

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

<detent-alert
  dismissible
  tone="neutral"
></detent-alert>

Property-only values

const element = document.querySelector('detent-alert');
if (element !== null) {
  // onDismiss: () => void
  element.onDismiss = () => {};
}

Source

The pinned upstream source for this row:

  • src/components/ui/alert.tsx sha256 a77cd155d44d…

Native files

The native module and its artifacts:

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

API

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

Attributes

Attributes
AttributePropertyTypeDefaultNotes
dismissibledismissiblebooleanfalsePresence semantics: present means true, absent means false.
tonetone'neutral' | 'info' | 'success' | 'warning' | 'danger''neutral'Kebab-case attribute; camelCase property.

Properties

Properties
PropertyTypeDefaultNotes
tone'neutral' | 'info' | 'success' | 'warning' | 'danger''neutral'Property-only: assign from script; not accepted as an attribute.
dismissiblebooleanfalseProperty-only: assign from script; not accepted as an attribute.
collapsed——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
closed——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
dismiss——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
onDismiss() => voidundefinedProperty-only: assign from script; not accepted as an attribute.

Events

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

Slots

Slots
SlotNotes
actionConsumer content; rendered through a slot, never re-created.
iconConsumer content; rendered through a slot, never re-created.

CSS customisation

  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `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.
  • `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • `icon={false}` has no attribute form; an empty `icon` slot suppresses the tone icon (the catalog records `icon` as a slot, so no attribute was added).
  • Upstream `AlertTitle`/`AlertDescription` helper exports map to slotted paragraphs: the first `<p>` is the title, later `<p>` elements are the muted description.
  • The dismiss control is a native `<button aria-label="Dismiss">` with a `:focus-visible` outline from `--detent-color-accent`; upstream relied on Tailwind ring utilities.
  • Dismissal moves focus out of the removed button to the next focusable element in document order (accessibility correction, PC-12.6).
  • Collapse is a Web Animations API height/opacity animation (upstream 0.25s, cubic-bezier(0.32,0.72,0,1)) and is skipped under reduced motion.
  • `detent-dismiss` detail is `{}` (upstream `onDismiss: () => void` carries no arguments) and is emitted once, after the collapse finishes.

What it does

A toned, optionally dismissible message with an icon, an action area and a smooth height collapse on dismissal.

Upstream behaviour
  • Dismissing collapses height and fades out smoothly without sudden content jumps
  • Supports 5 semantic tones: neutral, info, success, warning, and danger
  • Automatic matching Lucide icons with custom icon or icon={false} override
  • Action slot on the right for buttons, retry triggers, or secondary actions
  • Proper accessibility: role="alert" for danger/warning and role="status" for neutral/info/success
Differences from upstream
  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `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.
  • `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • `icon={false}` has no attribute form; an empty `icon` slot suppresses the tone icon (the catalog records `icon` as a slot, so no attribute was added).
  • Upstream `AlertTitle`/`AlertDescription` helper exports map to slotted paragraphs: the first `<p>` is the title, later `<p>` elements are the muted description.
  • The dismiss control is a native `<button aria-label="Dismiss">` with a `:focus-visible` outline from `--detent-color-accent`; upstream relied on Tailwind ring utilities.
  • Dismissal moves focus out of the removed button to the next focusable element in document order (accessibility correction, PC-12.6).
  • Collapse is a Web Animations API height/opacity animation (upstream 0.25s, cubic-bezier(0.32,0.72,0,1)) and is skipped under reduced motion.
  • `detent-dismiss` detail is `{}` (upstream `onDismiss: () => void` carries no arguments) and is emitted once, after the collapse finishes.
Previous: Matrix Clock Next: Animated File Upload

Docs

Components

Project