Skip to content
Template Empire
Browse components

Contour Magnet

One outline glides between native links and buttons while their hit areas stay put.

Field notes · 2026

Ideas in motion

Three recent dispatches from the studio archive.

Open studio · Saturday

Workshop schedule

Small-group sessions with the people who make the work.

09:30 · Print and paper

Press room · 8 places

13:00 · Type in space

Letter room · 5 places

Customise

Code

<CursorContourMagnet>
  {/* native links and buttons marked data-contour-target */}
</CursorContourMagnet>

Contour Magnet draws one lightweight outline around the native link or button beneath a fine pointer. Mark eligible controls with data-contour-target; the contour moves between their measured boxes while labels, layout and hit areas remain fixed.

The effect is decorative and pointer-only. The operating-system cursor, link and button semantics, keyboard focus rings and actions stay in the consumer's hands. Touch, reduced motion, print, offscreen and no-JavaScript use leave the native controls complete without the contour.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/cursor-contour-magnet

Usage

import { CursorContourMagnet } from "@/components/ui/cursor-contour-magnet";

export default function Page() {
  return (
    <CursorContourMagnet className="grid gap-4">
      <a href="/journal" data-contour-target className="text-base underline">
        Read the field notes
      </a>
      <button type="button" data-contour-target>
        Reserve a workshop seat
      </button>
    </CursorContourMagnet>
  );
}

Props

PropTypeDefaultDescription
childrenReactNoderequiredConsumer-owned content. Only marked native links and buttons can attract the contour.
classNamestringundefinedAdditional classes merged onto the root region.

Customisation

Mark only the links and buttons that should attract the contour. Set --contour-magnet-ink to a semantic theme colour and --contour-magnet-duration to a duration such as 240ms on this region or an ancestor. The root's className controls its layout; control labels, focus styling and actions remain consumer-owned.

<CursorContourMagnet
  className="grid gap-4 [--contour-magnet-ink:var(--ring)] [--contour-magnet-duration:240ms]"
>
  <a href="/journal" data-contour-target>Read the field notes</a>
  <button type="button" data-contour-target>Reserve a seat</button>
</CursorContourMagnet>

Frequently asked questions

Which elements can attract the contour?
Only native anchor links with an href and native buttons that carry data-contour-target. Marked non-native elements and nested marked targets are ignored.
Does it move or replace my controls?
No. The component measures each target and moves one aria-hidden outline. It never changes target styles or hit areas, and it never hides or replaces the operating-system pointer.
What happens with touch, keyboard focus or reduced motion?
Touch and coarse pointers, keyboard focus, reduced motion and print use the native links and buttons without the optional contour. Keep a visible focus style on every control.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates