Data & tables
Expandable Data Row
Table row that unfolds into account details
detent-expandable-data-row
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-data
- Group
- Data & tables
8.1 KB gzip for the class module
Variants
A local sample table of three accounts. Opening a row unfolds its account metadata, recent activity and quick actions
directly beneath the row — no modal. The first row has no metadata, so the documented
Standard/Unknown/Card/Recently fallbacks appear. Resize the window
below 48em to see the same DOM laid out as labelled cards. Copy Email writes to your clipboard; nothing is fetched and
nothing is charged.
No row action has run yet.
Recorded states
loadingrecorded state; no setterexpandedrecorded state; no setterreduced motionrecorded state; no setter
Usage
Import
import '/components/expandable-data-row/define.js';
// or register it yourself
import { DetentExpandableDataRow } from '/components/expandable-data-row/expandable-data-row.js';
Attributes
allow-multipleis-loading
Properties
defaultExpandedIdsitemsonRowAction
Slots
No slots are recorded for this component.
Events
detent-row-action— {}
Example
Runnable example: site/examples/expandable-data-row.ts. The snippet below is generated from the catalogued attributes.
<detent-expandable-data-row
allow-multiple
is-loading
></detent-expandable-data-row>
Property-only values
const element = document.querySelector('detent-expandable-data-row');
if (element !== null) {
// items: DataRowItem[]
element.items = [];
// defaultExpandedIds: string[]
element.defaultExpandedIds = [];
// onRowAction: (action: string, row: DataRowItem) => void
element.onRowAction = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/ExpandableDataRow.tsxsha256 465ae93bd12d…
Native files
The native module and its artifacts:
src/components/expandable-data-row/expandable-data-row.tssrc/components/expandable-data-row/styles.csssrc/components/expandable-data-row/define.tsdocs/components/expandable-data-row.mdsite/examples/expandable-data-row.tstests/browser/expandable-data-row.spec.tsevidence/components/expandable-data-row.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
allow-multiple | allowMultiple | boolean | false | Presence semantics: present means true, absent means false. |
is-loading | isLoading | boolean | false | Presence semantics: present means true, absent means false. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
defaultExpandedIds | string[] | ['usr_01'] | Property-only: assign from script; not accepted as an attribute. |
items | DataRowItem[] | [...] | Property-only: assign from script; not accepted as an attribute. |
onRowAction | (action: string, row: DataRowItem) => void | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-row-action | onRowAction | (action: string, row: DataRowItem) => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- 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.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- items defaults to [] and defaultExpandedIds to []. Upstream defaults to a four-row demo dataset and ['usr_01']; baking demo data into the element would fabricate consumer records, so an empty items renders the documented empty state instead.
- onRowAction becomes the composed detent-row-action event carrying a plain row snapshot; property writes emit none (PC-6.5). It is not available as a property.
- Copy Email keeps upstream's clipboard write and 2 s Copied feedback but is best-effort: the clipboard API needs a permission grant, so the state is optimistic and the failure is swallowed rather than thrown.
- Upstream used animate-pulse on hard-coded #0E0E0E/#141414/#1F1F1F surfaces; the port uses theme tokens so both colour schemes exist and meet AA.
- The mobile layout is a CSS-only conversion of the same table DOM rather than a second, parallel card tree. The visible result (stacked card with label/value pairs) matches; the accessible structure is a table at every width.
- lucide-react icons (ChevronRight, Copy, Check, CreditCard, ArrowUpRight) become local aria-hidden text glyphs and the Check/Copy swap becomes the Copied label.
- The springGentle (170/26/0.9) height/opacity presence runs on the shared spring helper: a folding row is aria-expanded=false and inert at once and hidden when the spring settles; defaultExpandedIds seeds paint with no motion. The chevron turns 90 degrees on springSnappy through the shared spring helper.
What it does
All rows in this documentation are local sample data. Nothing is fetched, no billing is performed and the copy action only writes to the clipboard.
Upstream behaviour
- Soft accordion expansion unfolding details directly beneath rows without modals
- Single or multi-row simultaneous expansion modes
- Full metadata breakdown with account metrics and historical activity timeline
- Adaptive layout engine transforming desktop table into touch cards on mobile devices
- Integrated quick actions with one-click email copying and callback hooks
Differences from upstream
- 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.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- items defaults to [] and defaultExpandedIds to []. Upstream defaults to a four-row demo dataset and ['usr_01']; baking demo data into the element would fabricate consumer records, so an empty items renders the documented empty state instead.
- onRowAction becomes the composed detent-row-action event carrying a plain row snapshot; property writes emit none (PC-6.5). It is not available as a property.
- Copy Email keeps upstream's clipboard write and 2 s Copied feedback but is best-effort: the clipboard API needs a permission grant, so the state is optimistic and the failure is swallowed rather than thrown.
- Upstream used animate-pulse on hard-coded #0E0E0E/#141414/#1F1F1F surfaces; the port uses theme tokens so both colour schemes exist and meet AA.
- The mobile layout is a CSS-only conversion of the same table DOM rather than a second, parallel card tree. The visible result (stacked card with label/value pairs) matches; the accessible structure is a table at every width.
- lucide-react icons (ChevronRight, Copy, Check, CreditCard, ArrowUpRight) become local aria-hidden text glyphs and the Check/Copy swap becomes the Copied label.
- The springGentle (170/26/0.9) height/opacity presence runs on the shared spring helper: a folding row is aria-expanded=false and inert at once and hidden when the spring settles; defaultExpandedIds seeds paint with no motion. The chevron turns 90 degrees on springSnappy through the shared spring helper.