Live cursorsPro
Teammates' and agents' cursors over a shared canvas or document, with selections, messages and edge pins.
On this page
Installation
Usage
import { LiveCursors } from "@/components/ui/chatcn/pro/live-cursors"
<LiveCursors
cursors={[
{ ...noor, x: 0.72, y: 0.3 },
{ ...ledger, x: 0.1, y: 0.5, activity: "selecting 3 rows", selection: { x: 0, y: 0.45, width: 1, height: 0.3 } },
]}
onCursorMove={(pos) => room.broadcast(pos)}
>
<RefundsSheet />
</LiveCursors>Positions are fractions of the surface, so every screen size agrees, and each cursor glides between updates with a short linear transition on transform alone. People get the arrow; agents get a squircle pointer and a mono label that says what they are doing. Selections draw as a tint with an edge in the member's color. The label hangs below and after the tip, off the arrow's line of sight, and moves to the other side only near the far edges so it never clips. A message typed at the cursor joins the label in one bubble, its tight corner toward the tip, and a cursor outside the surface pins to the nearest edge with an arrow toward it. Idle cursors fold their label. Colors default to the chart palette in order; pass color to match your own. onCursorMove reports the viewer's position once per frame, mirrored for right to left.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
cursors | (CollabMember & { x, y, activity?, message?, selection?, color?, idle? })[] | x, y from 0 to 1 |
children | ReactNode | The shared surface |
onCursorMove | (pos | null) => void | The viewer's own position |
showLabels | boolean | Default true |
labels | Partial<LiveCursorsLabels> | Every string, for translation |
Labels
labels covers the agent tag, describe(name, activity) for the screen reader list and offscreen(name).
Accessibility
- Cursors are decorative; a visually hidden list names everyone, what they are doing and any message they typed.
- The surface stays fully usable: the overlay never takes the pointer.
Motion
Cursors move with a 140 ms linear transition on transform, labels fold in from 0.95 over 150 ms and a new message fades in over 150 ms. Reduced motion jumps to each position and keeps the fades.