No.77 · Buttons· New
Field Rim
A dark pill whose rim is a window onto a living background from the backgrounds library — light strands, fire plumes, neon veins or a blade of light — running slowly round its edge. Point at it and the rim widens, the field quickens and its light spills out round the button.
The prompt
Written for the variant you picked above: Strands
Build a dark pill button whose border is a live WebGL background. Props: children, field (which shader), zoom (1.6), onClick, type and motion. The shader runs on a canvas filling the whole button, through a small harness: DPR capped at 2, paused offscreen and in hidden tabs, one still frame under reduced motion, a smoothed pointer, context-lost handling, a zoom (the shader sees a canvas that many times bigger and reads its fragment coordinate through a macro FC = gl_FragCoord.xy × uZoom, so the button shows a slice of the field) and a rate multiplier on time read every frame, eased towards 0.7 at rest and 2.6 while hovered or focused. A dark face (#0b0b10, with a faint glow of the field's colour rising from the bottom and an inner glow at its edge) covers the canvas inset by the rim width, so the field only shows as the rim. The rim is a registered CSS length property, 2.5px at rest, transitioning to 5px on hover and focus over 380ms. The canvas is brightened (2×), with a faint white hairline round the outside so the shape always reads, and saturated so the thin rim reads. Hover also lifts the pill 1px and adds an outer glow in the field's colour; press dips it. The label is near-white on the dark face. Without WebGL, the rim becomes a conic gradient in the field's colour. Each field is one of the library's full-screen backgrounds with its first palette, still reacting to the pointer. Selected variant — Strands (strands): Glow Strands: violet, blue and pale gold threads of light on black, glowing blue (#5aa8ff). 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: the rim widens, the field speeds up and glows out round it. Motion: The field drifts at 0.7× and eases up to 2.6× on hover; the rim widens from 2.5px to 5px over 380ms. Reduced motion draws one still frame. Accessibility: A real button with its text label on a solid dark face, so contrast never depends on the field; the canvas is decorative and hidden. One WebGL context per button, paused offscreen. Responsive behavior: At least 208px wide and 56px tall; the rim follows 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: the rim widens, the field speeds up and glows out round it.
- Motion
- The field drifts at 0.7× and eases up to 2.6× on hover; the rim widens from 2.5px to 5px over 380ms. Reduced motion draws one still frame.
- Accessibility
- A real button with its text label on a solid dark face, so contrast never depends on the field; the canvas is decorative and hidden. One WebGL context per button, paused offscreen.
- Responsive
- At least 208px wide and 56px tall; the rim follows whatever size the label needs.
- On touch
- The field drifts on its own; tapping works as usual.