·Playground

The “Ask AI” button.

I saw Octant’s iridescent Ask AI button and wanted to know exactly how it was made, so I rebuilt it. The glowing rim isn’t a CSS gradient at all; it’s a tiny WebGL shader. Here’s the recreation, made interactive, and a short writeup.

Original by Octant ↗

How it works

01 The glow is layered drop-shadows

The soft colored halo around the pill is three stacked drop-shadow() filters (amber, fuchsia, teal) at increasing blur. drop-shadow (not box-shadow) so the aura follows the painted shape, not the box.

.glow {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden;
  filter:
    drop-shadow(0 0 5px  rgba(255,150,2,.22))    /* amber   */
    drop-shadow(0 0 8px  rgba(217,70,239,.22))   /* fuchsia */
    drop-shadow(0 0 12px rgba(120,240,226,.22)); /* teal    */
}

02 The rim is a shader, not a gradient

This is the part that surprised me. The moving, “liquid” rim is a WebGL fragment shader. It measures the signed distance to a rounded rectangle (an SDF), draws a bright meniscus just inside that edge, and tints it with iridescence that cycles around the rim by angle + time. A little fbm noise warps the edge so the colors blob and drift instead of forming a perfect ring. That’s what makes it feel alive rather than mechanical.

// iridescence cycles around the rim by angle + time + noise
float t = fract(angle / 6.283 + 0.5 + u_time * u_speed
                + (noise - 0.5) * u_wobble * 0.043);
vec3 hue = t < 0.333 ? mix(orange,  magenta, smoothstep(0., 1., t * 3.))
         : t < 0.667 ? mix(magenta, teal,    smoothstep(0., 1., (t-.333)*3.))
                     : mix(teal,    orange,  smoothstep(0., 1., (t-.667)*3.));

03 Made interactive

Octant’s version lights from a fixed upper-left. I added two things, both eased per frame so they feel physical: the light direction follows the pointer around the rim, and hovering ramps an “energy” value that brightens the rim, speeds the drift, and blooms the inner color.

// light eases toward the pointer; hover ramps an "energy" 0 → 1
lx     += (targetX - lx) * 0.08;          // eased light direction
energy += (energyTarget - energy) * 0.08; // 0 idle · 1 hovered
const intensity = base.intensity * (1 + energy * 0.5);  // brighter
const speed     = base.speed     * (1 + energy * 1.1);  // faster drift
const fill      = base.fill      * (1 + energy * 4);    // inner bloom

04 The sparkle & recoloring

A single gradient-filled SVG star: static, by choice (no spin, no pulse). The whole thing is palette-driven: the three iridescence stops are shader uniforms, and the glow and the star read from the same trio, so the toggle above swaps rim, glow, and sparkle in one move. Try Clay or Ocean.

Rebuilt as a self-contained Svelte action: drop a <canvas use:aiRing> inside any rounded element. Honors prefers-reduced-motion; pauses off-screen. Open to borrow.