Cursors
Cursors
Display live cursor positions for all users in a room, with automatic color coding and name labels.
Basic Usage
import { useCursors } from '@realtime-sdk/react';
function CursorLayer({ room }) {
const { cursors, updateCursor } = useCursors(room);
return (
<div
className="relative w-full h-full"
onMouseMove={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
updateCursor({
x: e.clientX - rect.left,
y: e.clientY - rect.top,
});
}}
onMouseLeave={() => updateCursor(null)}
>
{cursors.map(cursor => (
<Cursor key={cursor.id} {...cursor} />
))}
</div>
);
}
Cursor Data
Each cursor includes:
| Property | Type | Description |
|---|---|---|
id | string | User ID |
name | string | undefined | User's display name |
color | string | User's assigned color |
position | { x, y } | Cursor coordinates |
Cursor Component
A simple cursor implementation:
function Cursor({ color, name, position }) {
return (
<div
className="absolute pointer-events-none transition-transform duration-50"
style={{
transform: `translate(${position.x}px, ${position.y}px)`,
}}
>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill={color}
className="drop-shadow"
>
<path d="M0 0L16 6L8 8L6 16L0 0Z" />
</svg>
{name && (
<div
className="absolute left-4 top-4 px-2 py-0.5 rounded text-xs text-white whitespace-nowrap"
style={{ backgroundColor: color }}
>
{name}
</div>
)}
</div>
);
}
Throttling
By default, cursor updates are throttled to 50ms (20 updates/second). Customize this:
const { cursors, updateCursor } = useCursors(room, {
throttle: 33, // ~30fps
});
Selection Awareness
Track text selection along with cursors:
updateCursor({
x: cursorX,
y: cursorY,
selectionStart: editor.selectionStart,
selectionEnd: editor.selectionEnd,
});
Performance Tips
- Use CSS transforms instead of
left/topfor smooth animation - Add
pointer-events: noneto cursor elements - Consider hiding cursors outside the visible viewport
- Use
will-change: transformfor GPU acceleration
<div
style={{
transform: `translate(${x}px, ${y}px)`,
willChange: 'transform',
pointerEvents: 'none',
}}
/>
Hiding Your Own Cursor
Show only other users' cursors:
const { cursors } = useCursors(room);
const { self } = usePresence(room);
const otherCursors = cursors.filter(c => c.id !== self?.id);