Skip to content

No.70 · Buttons· New

Field Button

A pill with a living background inside it — storm smoke, neon veins, strands of light, velvet grain, a blade of light or fire plumes, taken from the backgrounds library — drifting slowly at rest. Point at it and the field wakes: it quickens, brightens and turns towards your pointer, under a thin rim of glass and a soft glow in its own colour.

The prompt

Copy this text

Automatic copying is unavailable. Copy the selected text using your device’s copy command.

Written for the variant you picked above: Smoke

Build a pill button whose fill is a live WebGL background. Props: children, field (which shader), zoom (3.2), onClick, type and motion. The shader runs on a canvas filling the button, through a small harness: DPR capped at 2, paused offscreen and in hidden tabs, one still frame under reduced motion, a smoothed pointer (uMouse, uPress), context-lost handling and a CSS gradient fallback. Two additions make a full-screen background work inside a 56px pill: a zoom, so the shader sees a canvas that many times bigger (uRes is multiplied, and the shader reads its fragment coordinate through a macro FC = gl_FragCoord.xy × uZoom), which makes the pill a slice of the field rather than one giant blob; and a rate, a multiplier on the speed of time read every frame, eased towards 0.6 at rest and 3 while the button is hovered or focused, so the field drifts quietly and wakes up smoothly. Each field is one of the library's full-screen backgrounds with its first palette, and reacts to the pointer just as it does at full size. Over the canvas: a soft radial dark bed under the label (42% at the centre fading out), a top sheen, a hairline glass rim and a top highlight; the label is white with a small shadow, so it reads on any frame. Hover lifts the pill 1px, brightens and saturates the field over 420ms, and adds a glow in the field's colour; press dips it. The focus ring is a 2px white outline 4px out. Selected variant — Smoke (smoke): Storm smoke: navy #323e62 smoke with #a3b4dd light on #010209, cover 0.29. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Point at the button or focus it and the field wakes and turns towards the pointer; press it as usual. Motion: The field drifts at 0.6× and eases up to 3× on hover; brightness and glow ease over 420ms. Reduced motion draws one still frame. Accessibility: A real button with its text label; the canvas is decorative and hidden. A dark bed and text shadow keep the white label readable on every frame. One WebGL context per button, paused offscreen. Responsive behavior: At least 200px wide and 56px tall; the field fills whatever size the label needs. Touch: The field drifts on its own; tapping works as usual. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.

Notes

Interaction
Point at the button or focus it and the field wakes and turns towards the pointer; press it as usual.
Motion
The field drifts at 0.6× and eases up to 3× on hover; brightness and glow ease over 420ms. Reduced motion draws one still frame.
Accessibility
A real button with its text label; the canvas is decorative and hidden. A dark bed and text shadow keep the white label readable on every frame. One WebGL context per button, paused offscreen.
Responsive
At least 200px wide and 56px tall; the field fills whatever size the label needs.
On touch
The field drifts on its own; tapping works as usual.

Loading components…