Border Glow

Lights the border of its child where the pointer is, following it. A single element, no wrapper added to the DOM.

API

Props

proptypedefault
children?ReactElementthe element to light up; cloned, not wrapped
position?BorderGlowPosition"all"which edge glows: up, down, left, right, or the whole ring
tolerance?number1radius of the glow as a fraction of the element's longest side

Examples

Usage

tsx
<BorderGlow>
  <Card>
    <p>the whole ring lights up</p>
  </Card>
</BorderGlow>
previewhover the cards

position="all"

position="down"

Details

It clones, it does not wrap

The child is cloned with an extra class and a pointer handler, so nothing is inserted into the DOM and the element keeps its place in the layout — inside a grid it still owns its own cell. The price is that the child must be a single element that accepts className and onPointerMove; an existing handler of yours is called too, not replaced.

How the light is drawn

The glow is a radial gradient on a pseudo-element, and the border is only the part of it you see: for the full ring, the gradient is clipped to the border box minus the padding box, which leaves exactly the border width lit. For a single edge, the pseudo-element is that edge and nothing more.

tsx
<BorderGlow position="down" tolerance={0.2}>
  <header className="border-b-2 border-border"></header>
</BorderGlow>

On an edge, the coordinate perpendicular to it is mirrored, so the light tracks the pointer along the edge and fades as it moves away — which is why the fixed header of this site lights from below as you sweep across it.

Tolerance

The radius is a fraction of the element's longest side rather than a length in pixels, so the same value reads the same on a chip and on a full-width header. Lower it when the element is large and the light would otherwise cover all of it at once.

tsx
tolerance = 1     // radius = the longest side: a wide, soft light
tolerance = 0.2   // radius = a fifth of it: a tight, fast highlight

Values are clamped between 0 and 1. The glow appears on hover and on focus-within, so a card reached with the keyboard lights up as well.