Border Glow | Pointer-following Border Feedback
Border Glow uses pointer position to drive a border highlight, combining attention, clickable area, and committed state in one lightweight panel.
Effect Showcase
Design Notes
Scenario
Border glow can easily become decoration. Its useful role is showing where the current actionable area is. When users move across a card, setting row, release gate, or confirmation panel, a border-following glow helps them understand focus and intent.
Border Glow works well as a tiny Lab case: the border lights up near the pointer, and clicking the panel commits a state. It does not replace card or button components. It adds attention feedback that component libraries usually do not model.
Interaction Design
The case keeps only three actions:
- Approach
The pointer enters the panel boundary and the glow appears on the border wrapper.
- Track
The glow center follows local pointer coordinates without reflowing the content layer.
- Commit
Clicking the panel toggles a visible state, so the user can distinguish Idle from Armed.
Implementation Model
The smallest implementation uses an outer p-px wrapper and an inner semantic button. The wrapper owns the border glow. The button owns content and accessible interaction. onPointerMove calculates the pointer position relative to the wrapper and writes it into an inline radial-gradient().
This does not require an animation library or a Tailwind plugin. The glow is only a background layer; the button still uses native focus, click, and aria-pressed.
SEO and Content Positioning
Useful search intent includes "pointer glow", "micro interaction", and "attention feedback". The difference from a normal component library is that most libraries expose static borders, hover colors, or focus rings, while this case explains how boundary feedback can follow user attention.
Testing Notes
Check five boundaries: the glow does not change panel size, pointer leave returns to a quiet border, click toggles state, keyboard focus remains visible, and mobile users do not need hover to understand the essential state.
Copyable Source
Source is read from the case examples folder, so the displayed snippet and typechecked code stay aligned.
"use client"; import * as React from "react"; type GlowState = { x: number; y: number; active: boolean;}; const hoverGlowColor = "rgb(var(--lab-hover-purple-rgb) / 0.9)";const hoverGlowFadeColor = "rgb(var(--lab-hover-purple-rgb) / 0.22)"; function pointerState(event: React.PointerEvent<HTMLElement>): GlowState { const rect = event.currentTarget.getBoundingClientRect(); return { active: true, x: event.clientX - rect.left, y: event.clientY - rect.top, };} export function BorderGlowPanel() { const [glow, setGlow] = React.useState<GlowState>({ x: 220, y: 120, active: false, }); const [armed, setArmed] = React.useState(false); const glowStyle: React.CSSProperties = { background: glow.active ? `radial-gradient(160px circle at ${glow.x}px ${glow.y}px, ${hoverGlowColor}, ${hoverGlowFadeColor} 44%, transparent 72%)` : "linear-gradient(135deg, hsl(var(--border)), transparent, hsl(var(--border)))", }; return ( <div className="rounded-card border border-border bg-background p-2 shadow-soft"> <div className="flex min-h-[340px] items-center justify-center rounded-card border border-border/70 bg-card/60 p-5"> <div className="relative w-full max-w-[420px] rounded-card p-px" onPointerEnter={(event) => setGlow(pointerState(event))} onPointerLeave={() => setGlow((current) => ({ ...current, active: false })) } onPointerMove={(event) => setGlow(pointerState(event))} > <div aria-hidden="true" className="pointer-events-none absolute inset-0 rounded-card opacity-80 transition-opacity duration-200" data-border-glow="" style={glowStyle} /> <button aria-pressed={armed} className="relative w-full rounded-card border border-border bg-card p-5 text-left outline-none transition-colors hover:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring" onClick={() => setArmed((value) => !value)} type="button" > <span className="flex items-start justify-between gap-4"> <span> <span className="text-sm font-semibold text-foreground"> Release gate </span> <span className="mt-2 block text-sm leading-6 text-muted-foreground"> The border glow follows attention before the user commits. </span> </span> <span className="rounded-full border border-border bg-background px-2.5 py-1 text-xs font-medium text-muted-foreground"> {armed ? "Armed" : "Idle"} </span> </span> <span className="mt-6 grid gap-2"> {["Diff reviewed", "Preview verified", "Fallback defined"].map( (item) => ( <span className="flex items-center gap-2 text-sm text-muted-foreground" key={item} > <span className="size-1.5 rounded-full bg-primary" /> {item} </span> ), )} </span> </button> </div> </div> </div> );} export default BorderGlowPanel;Agent Prompt
Agent Prompt
Build a Border Glow interaction inspired by https://reactbits.dev/components/border-glow, but implement the simplified Lab version with only React, pointer events, inline radial gradients, and existing Tailwind utility classes. Do not install animation libraries, do not add Tailwind plugins, and do not change Tailwind config. Deliver one self-contained React component, a small preview, and localized Markdown content. The interaction should show a panel whose border glow follows the pointer, while clicking the panel toggles a visible committed state. Use a semantic button, `aria-pressed`, theme tokens, and a fallback border when the pointer is not active. Acceptance: the glow stays on the border wrapper, pointer leave returns to a quiet border, clicking toggles state without layout shift, keyboard focus remains visible, and the example source is the same component used by the demo.