Feedback & status
Loader
Calm continuous loading feedback
detent-loader
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 2
- Wave
- phase-2-feedback
- Group
- Feedback & status
3.2 KB gzip for the class module
Variants
Recorded states
loadingrecorded state; no setterdark themerecorded state; no setterreduced motionrecorded state; no setter
Usage
Import
import '/components/loader/define.js';
// or register it yourself
import { DetentLoader } from '/components/loader/loader.js';
Attributes
colorlabelreduce-motionsizevariant
Properties
variantsizelabelcolorreduceMotion
Slots
No slots are recorded for this component.
Events
No events are recorded for this component.
Example
Runnable example: site/examples/loader.ts. The snippet below is generated from the catalogued attributes.
<detent-loader
color="currentColor"
label="Loading..."
reduce-motion
size="32"
variant="arc"
></detent-loader>
Source
The pinned upstream source for this row:
src/components/ui/Loader.tsxsha256 cf1330cc88e9…
Native files
The native module and its artifacts:
src/components/loader/loader.tssrc/components/loader/styles.csssrc/components/loader/define.tsdocs/components/loader.mdsite/examples/loader.tstests/browser/loader.spec.tsevidence/components/loader.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 |
|---|---|---|---|---|
color | color | string | 'currentColor' | Kebab-case attribute; camelCase property. |
label | label | string | 'Loading...' | Kebab-case attribute; camelCase property. |
reduce-motion | reduceMotion | boolean | false | Presence semantics: present means true, absent means false. |
size | size | number | 32 | Kebab-case attribute; camelCase property. |
variant | variant | 'arc' | 'dots' | 'line' | 'rings' | 'arc' | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
variant | 'arc' | 'dots' | 'line' | 'rings' | 'arc' | Property-only: assign from script; not accepted as an attribute. |
size | number | 32 | Property-only: assign from script; not accepted as an attribute. |
label | string | 'Loading...' | Property-only: assign from script; not accepted as an attribute. |
color | string | 'currentColor' | Property-only: assign from script; not accepted as an attribute. |
reduceMotion | boolean | false | 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
- `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
- 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.
- Colours are theme-token driven (`--detent-color-text`, `color-mix` track) instead of the upstream dark-only literals `text-[#FAFAFA]`, `#1F1F1F`, `#141414` (PC-9.5/PC-12.6); measured 16.47-17.93:1 against the page background in both schemes.
- `size` and `color` are applied through documented custom properties (`--detent-loader-size`, `--detent-loader-color`) written as inline styles, because CSS cannot read an attribute value as a length.
- The label is a single visually hidden text node inside `role="status"`; upstream rendered both `aria-label` and an sr-only span (duplicate announcement).
- Framer Motion timelines are CSS keyframes with the upstream durations/delays/easings (2.5s spin, 1.4s dots with 0.22s stagger, 1.8s slide, 2.2s rings with 0.9s stagger); reduced motion keeps the upstream opacity pulse.
- Invalid `size`/`variant` values fall back or clamp with a development warning instead of being passed through to inline styles.
What it does
Four animated loading indicators — a rotating arc, breathing dots, a sliding line and expanding rings — with a configurable size, paint colour and accessible label.
Upstream behaviour
- 4 refined motion variants: rotating arc, breathing dots, sliding line, and expanding concentric rings
- Configurable dimensions and stroke colors with seamless dark mode support
- Accessible role="status" and aria-busy telemetry without screen reader interruption
- Automatic reduced-motion adaptation for sensitive viewers
Differences from upstream
- `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
- 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.
- Colours are theme-token driven (`--detent-color-text`, `color-mix` track) instead of the upstream dark-only literals `text-[#FAFAFA]`, `#1F1F1F`, `#141414` (PC-9.5/PC-12.6); measured 16.47-17.93:1 against the page background in both schemes.
- `size` and `color` are applied through documented custom properties (`--detent-loader-size`, `--detent-loader-color`) written as inline styles, because CSS cannot read an attribute value as a length.
- The label is a single visually hidden text node inside `role="status"`; upstream rendered both `aria-label` and an sr-only span (duplicate announcement).
- Framer Motion timelines are CSS keyframes with the upstream durations/delays/easings (2.5s spin, 1.4s dots with 0.22s stagger, 1.8s slide, 2.2s rings with 0.9s stagger); reduced motion keeps the upstream opacity pulse.
- Invalid `size`/`variant` values fall back or clamp with a development warning instead of being passed through to inline styles.