Realtime SDK

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:

PropertyTypeDescription
idstringUser ID
namestring | undefinedUser's display name
colorstringUser'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

  1. Use CSS transforms instead of left/top for smooth animation
  2. Add pointer-events: none to cursor elements
  3. Consider hiding cursors outside the visible viewport
  4. Use will-change: transform for 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);

On this page