A custom cursor, and a label that follows it, inside an area or across the page.
Move your pointer over this area
Installation
Usage
import {
Cursor,
CursorContainer,
CursorFollow,
CursorProvider,
} from '@animate-ui/react/primitives/cursor';
export function Canvas() {
return (
<div className="relative h-72">
<CursorProvider>
<CursorContainer>
<Cursor>
<ArrowIcon />
</Cursor>
<CursorFollow side="bottom" align="end">
<span>Designer</span>
</CursorFollow>
</CursorContainer>
</CursorProvider>
</div>
);
}By default, the cursor lives in the parent of CursorContainer. With global, it replaces the pointer on the whole page.
Animation
- Entering the area hides the native pointer and pops the cursor and the follower in: they scale up from 0 on a spring with a little overshoot (stiffness 550, damping 30) while fading in (300ms). Leaving scales them back to 0 without overshoot and fades them out, then restores the pointer.
Cursorsticks to the pointer, its top-left corner on it (where an arrow's tip goes).CursorFollowtrails it on a spring without bounce (stiffness 500, damping 50), so it feels attached without being rigid. It springs from where it last was: the first time, it flies in from near the area's top-left corner.- The position is driven by motion values with a hardware-accelerated transform (
x/y): moving the pointer never re-renders React. - Touch pointers are ignored: a custom cursor only makes sense for pointers that hover.
<AnimateUIProvider tempo>paces the pop and the follow spring.- Under reduced motion, the cursors only fade in and out, and
CursorFollowsticks to the pointer too.
API Reference
CursorProvider
| Prop | Type | Default |
|---|---|---|
global? | boolean | false |
children | React.ReactNode | - |
CursorContainer
Marks the area: the cursor shows inside its parent element.
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | false |
...props? | HTMLMotionProps<'div'> | - |
Cursor
Its top-left corner sits on the pointer.
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | false |
children | React.ReactNode | - |
...props? | HTMLMotionProps<'div'> | - |
CursorFollow
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | false |
side? | 'top' | 'right' | 'bottom' | 'left' | 'bottom' |
sideOffset? | number | 0 |
align? | 'start' | 'center' | 'end' | 'end' |
alignOffset? | number | 0 |
transition? | SpringOptions | { stiffness: 500, damping: 50, bounce: 0 } |
children | React.ReactNode | - |
...props? | Omit<HTMLMotionProps<'div'>, 'transition'> | - |
useCursor
Returns the cursor state: cursorX and cursorY motion values, active, global, containerRef, cursorRef, and cursorPos (a snapshot of the position when read).