Detent web components
By Shane Logsdon

Content & disclosure

Accordion

Implemented

Panels that unfold with a chevron

detent-accordion

Port status
Catalog status
implemented
Origin
upstream
Phase
1
Wave
phase-1-pilot
Group
Content & disclosure

3.6 KB gzip for the class module

Recorded states

open
  • expanded recorded state; no setter
  • dark theme recorded state; no setter

Usage

Import

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

// or register it yourself
import { DetentAccordion } from '/components/accordion/accordion.js';

Attributes

  • allow-multiple

Properties

  • defaultOpen
  • items

Slots

No slots are recorded for this component.

Events

No events are recorded for this component.

Example

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

<detent-accordion
  allow-multiple
></detent-accordion>

Property-only values

const element = document.querySelector('detent-accordion');
if (element !== null) {
  // items: UnfoldAccordionItem[]
  element.items = [];
  // defaultOpen: string[]
  element.defaultOpen = [];
}

Source

The pinned upstream source for this row:

  • src/components/ui/UnfoldAccordion.tsx sha256 e174326057ff…

Native files

The native module and its artifacts:

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

API

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

Attributes

Attributes
AttributePropertyTypeDefaultNotes
allow-multipleallowMultiplebooleanfalsePresence semantics: present means true, absent means false.

Properties

Properties
PropertyTypeDefaultNotes
defaultOpenstring[][]Property-only: assign from script; not accepted as an attribute.
itemsUnfoldAccordionItem[][]Property-only: assign from script; not accepted as an attribute.

Events

No custom events are recorded for this component.

Slots

No slots are recorded for this component.

CSS customisation

  • 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.
  • item.content is text (string) rendered with textContent; upstream accepted React.ReactNode. The row records no slots and PC-11.1 forbids parsing consumer strings as HTML.
  • Trigger/panel are not wrapped in a heading/region landmark; upstream semantics (button + following content) are preserved exactly.
  • Content block uses symmetric 1rem block padding; upstream pt-0 left the content text 2px below the trigger's hover surface while the item border sat 16px below it, so the block read as top-cropped.

What it does

An accordion whose panel height and chevron unfold together; single-open by default, allowMultiple for multi-open.

Upstream behaviour
  • Chevron rotation, content height, and inner content slide are tuned to overlap
  • Inner content uses a slightly faster ease so it "leads" the chevron by a hair
  • Spring-based height expansion (springGentle) for a calm, continuous feel
  • Single-open by default; allowMultiple for multi-open mode
  • Light/dark theme aware — works in both palettes
Differences from upstream
  • 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.
  • item.content is text (string) rendered with textContent; upstream accepted React.ReactNode. The row records no slots and PC-11.1 forbids parsing consumer strings as HTML.
  • Trigger/panel are not wrapped in a heading/region landmark; upstream semantics (button + following content) are preserved exactly.
  • Content block uses symmetric 1rem block padding; upstream pt-0 left the content text 2px below the trigger's hover surface while the item border sat 16px below it, so the block read as top-cropped.
Previous: Undo Toast Next: Notice Toast

Docs

Components

Project