Pointer Highlight
Draws a rectangle around its children while a cursor travels to the far corner, as though someone were drag-selecting the text. Fires once, the first time it scrolls into view. Used on the service card titles.
Default
Websites & Web Apps
<PointerHighlight>Websites & Web Apps</PointerHighlight>On a light ground, with a swept colour
Case Studies
The fill is --accent-deep on every ground (it is one of the two tokens the surface classes deliberately never re-point), so a dark heading on cream would sit at roughly 3:1 on it. swept flips each letter to white as the edge crosses it — 5.83:1 — rather than cross-fading the whole string out of step with the fill. Give it a plain span rather than repeating the heading, so the document keeps one heading and its text isn’t doubled.
<PointerHighlight
swept={<span className="heading-h2 text-white">Case Studies</span>}
>
<h2 className="heading-h2 text-foreground">Case Studies</h2>
</PointerHighlight>Inline, around part of a sentence
The best way to grow is to collaborate
The best way to grow is to{' '}
<PointerHighlight>
<span className="text-foreground">collaborate</span>
</PointerHighlight>Why the fill is accent-deep, not accent
The upstream component fills the box with the primary colour and leaves the text on top. On this page that would be white on #5ba3ff, which fails contrast. The fill uses --accent-deep instead — white on that measures 5.83:1, clearing AA for normal text — while the border and cursor stay bright --accent so the outline still reads as accent.
<PointerHighlight rectangleClassName="border-accent bg-accent-deep" />Behaviour
Animates clip-path on a box that is already at full size, rather than measuring the child and animating pixel width and height. It therefore tracks text that rewraps at a breakpoint or reflows when the webfont swaps in, keeps the border a crisp 1px where scaling would smear it, and never flashes empty on first paint. Under reduced motion the box renders fully drawn with the cursor already parked at the corner.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | The content to draw around. Keeps its own layout — the box sits on a negative inset rather than padding the content, so a shared baseline is preserved. |
rectangleClassName | string | — | Overrides the box. Defaults to a solid accent-deep fill, no border. |
pointerClassName | string | — | Overrides the cursor icon. Defaults to a 20px accent pointer. |
containerClassName | string | — | Overrides the wrapping span. |
swept | React.ReactNode | — | The same content in the colour it should take where the fill has already swept over it. Rendered aria-hidden under the same clip animation as the fill, so each letter changes colour exactly as the edge crosses it. Pass a plain span carrying the same type token rather than repeating a heading, so the document does not gain a second heading with the same text. |
Import
import { PointerHighlight } from '@/components/ui/PointerHighlight'