# AI lights

One body that becomes four agent UI components in turn, each announced by a pulse of light around its rim. Live at https://design.how/vault#ai-lights.

Install the skill, which carries the template, the brief and a check script:

```sh
npx skills add https://design.how/vault/ai-lights
```

## What it is

A single white component sits in the middle of a pale tinted card. Every 2.6 seconds a pulse of light runs round its rim, a tight comet of five hues that fades up, swings back and blooms open as it dies, and then the component becomes something else: a three-step workflow chain with the middle step running, a one-line progress row with a spinner, an inverted terminal, a prompt bar with a send button. It is one element the whole time. Its width, height and corner radius animate to the measured size of the next component.

The glow is a conic gradient, seen through a mask. The gradient packs its five colours into about 84 degrees of the circle, so it reads as a travelling comet, not a spinning disc, and its start angle and stops animate through registered custom properties over 1.6 seconds. The masks are drawn on a canvas: the body's rounded rect, stroked with a conic of opacity that is clear across two thirds of the circle, then blurred. Five layers at rising stroke width and blur build the falloff, the first a crisp 1 px ring carved out of a fill, and every layer is drawn twice, the second mirrored, because the lit arc sits on one side.

The timeline is three beats that never overlap: the light runs once; 120 ms after it has gone the contents fade out over 160 ms; then the empty body morphs for 380 ms and the new contents rise in letter by letter. Morphing in the dark is what makes it cheap. A mask is a PNG for one box, so a glow chasing a moving edge would need it redrawn every frame; here the glow layers leave the render tree during the morph and the mask is rebuilt once, 90 ms after the box stops. Each pulse rolls a new palette: one random anchor hue walking an arc of 90 to 190 degrees, with fixed saturation and lightness, and the card's background takes three pale tints of the same arc.

## How it works

- Measure every variant off screen once, and animate one body's width, height and radius to the current variant's box.
- Draw each glow layer's mask on a canvas: a rounded rect stroked with an opacity conic, blurred, exported as a data URL, cached by geometry.
- Paint each layer with a conic gradient whose start angle and stops are registered custom properties, animated by one keyframe rule; draw it twice, mirrored.
- Replay the pulse by setting data-playing false and back to true two frames apart, after rolling a palette from one anchor hue along an arc.
- Hand over in three beats with no overlap, and take the glow layers out of the tree while the body morphs.
- Under reduced motion, show the first component with the rim held lit as a quarter of the way into a pulse.

## What you can change

- `VARIANTS` (chain, progress, terminal, prompt): The components, each its contents, a corner radius and a padding.
- `PULSE_MS` (1600): One pulse of light. Keep the CSS animation in step.
- `MORPH_MS, FADE_OUT_MS, SETTLED_MS` (380, 160, 260): The handover's beats; the gap between pulses is derived from them.
- `RIM_LAYERS` (a 1 px ring and four blurred strokes): The glow's falloff.
- `RIM_STOPS` (lit from 347 round to 54 degrees): How much of the rim can light.
- `ARC_MIN, ARC_MAX` (90, 190): How far round the wheel each pulse's palette walks.

Last updated: 2026-11-02
