Live Cursor
Remote user's cursor rendered at canvas coordinates with name + status chip. Install Live Cursor from the VLLNT UI registry with the shadcn CLI.
What it is and when to use
Live Cursor renders a remote user's pointer on a shared canvas or document, positioned by x and y pixel coordinates, with an optional name-and-status chip beside it. It is pure presentation: your app owns the realtime stream and maps each user to a color, then feeds coordinates in. The wrapper is pointer-events none, so it never blocks the interactions underneath. Use it to build multiplayer cursors for collaborative editors, whiteboards, and design tools.
UtilityRemote user's cursor rendered at canvas coordinates with name + status chip. Part of the utility family in VLLNT UI, it ships as a machine-readable registry entry — copy the source directly into your app with the shadcn CLI and own it, no runtime dependency on a component library.
Preview
Switch between light and dark to inspect the embedded Storybook preview.
Installation
Add Live Cursor to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:
pnpm dlx shadcn@latest add https://ui.vllnt.com/r/live-cursor.jsonSource
"use client";
import type { ComponentPropsWithoutRef, ReactNode } from "react";
import { cn } from "../../lib/utils";
/**
* Localizable strings.
*
* @public
*/
export type LiveCursorLabels = {
/** Aria-label override. Defaults to `"Live cursor"`. */
region?: string;
};
const DEFAULT_LABELS = {
region: "Live cursor",
} as const satisfies Required<LiveCursorLabels>;
/**
* Props for {@link LiveCursor}.
*
* @public
*/
export type LiveCursorProps = {
/** Tailwind / arbitrary CSS color used for the pointer + name chip. Defaults to `var(--foreground)`. */
color?: string;
/** Localizable strings. */
labels?: LiveCursorLabels;
/** Display name shown in the chip. Pass `null` to hide the chip. */
name?: ReactNode;
/** Optional secondary line in the chip (e.g. status, role). */
status?: ReactNode;
/** Cursor X in canvas pixels. */
x: number;
/** Cursor Y in canvas pixels. */
y: number;
} & ComponentPropsWithoutRef<"div">;
/**
* Remote user's cursor rendered at canvas coordinates with an optional
* name + status chip. Pure presentation; the host owns the websocket
* stream + maps user ids to colors.
*
* The wrapper is `pointer-events: none` so host gestures pass through.
*
* @example
* ```tsx
* <div className="relative h-screen w-screen">
* <Canvas />
* <LiveCursor x={420} y={180} name="Bea" color="#5b8def" />
* </div>
* ```
*
* @public
*/
export const LiveCursor = ({
ref,
...props
}: LiveCursorProps & { ref?: React.Ref<HTMLDivElement> }) => {
const { className, color, labels, name, status, x, y, ...rest } = props;
const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
const resolvedColor = color ?? "var(--foreground)";
return (
<div
aria-label={
typeof name === "string"
? `${resolvedLabels.region}: ${name}`
: resolvedLabels.region
}
className={cn(
"pointer-events-none absolute z-30 flex items-start gap-1",
className,
)}
data-live-cursor
ref={ref}
role="img"
style={{ left: x, top: y }}
{...rest}
>
<svg
aria-hidden="true"
className="-ml-1 -mt-1 drop-shadow-sm"
data-live-cursor-pointer
fill={resolvedColor}
height={18}
viewBox="0 0 16 18"
width={16}
>
<path d="M0 0 L0 14 L4 11 L7 17 L10 16 L7 10 L13 10 Z" />
</svg>
{name === null || name === undefined ? null : (
<span
className="ml-2 mt-2 inline-flex flex-col rounded-md px-1.5 py-0.5 text-[10px] font-medium text-white shadow-sm"
data-live-cursor-chip
style={{ backgroundColor: resolvedColor }}
>
<span>{name}</span>
{status ? (
<span className="text-[9px] opacity-80" data-live-cursor-status>
{status}
</span>
) : null}
</span>
)}
</div>
);
};
LiveCursor.displayName = "LiveCursor";
Stories
Explore every variant and state in the interactive Storybook:
Preview
Switch between light and dark to inspect the embedded Storybook preview.
FAQ
- What is Live Cursor?
- Live Cursor is a React component that draws another user's cursor at given canvas coordinates, with an optional name and status chip. It is presentation-only — you supply the position, color, and name from your realtime layer.
- How do I add Live Cursor to my app?
- Run `pnpm dlx shadcn@latest add https://ui.vllnt.com/r/live-cursor.json`, then render `<LiveCursor x={x} y={y} name="Bea" color="#5b8def" />` inside a positioned container.
- Does Live Cursor block clicks on the canvas underneath?
- No. The cursor wrapper uses pointer-events none, so gestures pass through to the canvas. It also sets `role="img"` with an aria-label derived from the user's name for screen readers.