Detent web components
By Shane Logsdon

Feedback & status

Shape Loader

Implemented

Changing SVG shape loader

detent-shape-loader

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

4.4 KB gzip for the class module

Variants

Stroke and filled variants, three sizes and a custom shape list. With prefers-reduced-motion: reduce each loader paints one static shape and schedules no frame.

Recorded states

  • loading recorded state; no setter
  • reduced motion recorded state; no setter

Usage

Import

import '/components/shape-loader/define.js';

// or register it yourself
import { DetentShapeLoader } from '/components/shape-loader/shape-loader.js';

Attributes

  • color
  • duration
  • filled
  • hold-duration
  • label
  • loop
  • size
  • stroke-width

Properties

  • shapes

Slots

No slots are recorded for this component.

Events

No events are recorded for this component.

Example

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

<detent-shape-loader
  color="#FAFAFA"
  duration="1.6"
  filled
  hold-duration="0.4"
  label
  loop
  size="96"
  stroke-width
></detent-shape-loader>

Property-only values

const element = document.querySelector('detent-shape-loader');
if (element !== null) {
  // shapes: ShapeKind[]
  element.shapes = [];
}

Source

The pinned upstream source for this row:

  • src/components/ui/MorphingShapeLoader.tsx sha256 9c06f1e2ef4e…

Native files

The native module and its artifacts:

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

API

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

Attributes

Attributes
AttributePropertyTypeDefaultNotes
colorcolorstring'#FAFAFA'Kebab-case attribute; camelCase property.
durationdurationnumber1.6Kebab-case attribute; camelCase property.
filledfilledbooleanfalsePresence semantics: present means true, absent means false.
hold-durationholdDurationnumber0.4Kebab-case attribute; camelCase property.
label———Recorded in the catalog as an attribute.
looploopbooleantruePresence semantics: present means true, absent means false.
sizesizenumber96Kebab-case attribute; camelCase property.
stroke-width———Recorded in the catalog as an attribute.

Properties

Properties
PropertyTypeDefaultNotes
shapesShapeKind[]['circle','square','triangle','circle']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.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • `color` no longer defaults to #FAFAFA (dark)/#0A0A0A (light) via a React theme hook; an absent `color` renders `currentColor` so the token sheet drives both schemes (the catalog default is dark-only and cannot be the native default).
  • className replaced by parts svg/shape and `--detent-morphing-loader-color`.
  • Morph is a scripted rAF timeline (PC-10.1) because SVG `d` is not interpolable via WAAPI/CSS transitions in Firefox/WebKit; upstream Framer Motion `motion.path` replaced, eased with the upstream cubic-bezier(0.45,0.05,0.2,1).
  • `loop` keeps the upstream true default with presence semantics + reflection; opt-out is the property `loop = false`.
  • Upstream duplicate aria-label + sr-only span reduced to one host aria-label (PC-12.5).

What it does

One SVG path whose eight anchor points are interpolated between configured shapes, so the morph is a genuine geometric interpolation of matched points rather than a cross-fade.

Upstream behaviour
  • Continuous morph between matched-control-point shapes
  • Configurable shape list, duration, hold time, and loop behavior
  • Stroke and filled variants with optional gradient
  • Respects prefers-reduced-motion (renders a single static shape)
Differences from upstream
  • 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.
  • `color` no longer defaults to #FAFAFA (dark)/#0A0A0A (light) via a React theme hook; an absent `color` renders `currentColor` so the token sheet drives both schemes (the catalog default is dark-only and cannot be the native default).
  • className replaced by parts svg/shape and `--detent-morphing-loader-color`.
  • Morph is a scripted rAF timeline (PC-10.1) because SVG `d` is not interpolable via WAAPI/CSS transitions in Firefox/WebKit; upstream Framer Motion `motion.path` replaced, eased with the upstream cubic-bezier(0.45,0.05,0.2,1).
  • `loop` keeps the upstream true default with presence semantics + reflection; opt-out is the property `loop = false`.
  • Upstream duplicate aria-label + sr-only span reduced to one host aria-label (PC-12.5).
Previous: Morphing Mega Menu Next: Neon Edge Button

Docs

Components

Project