Skip to content

Pointer

A named pointer that follows the mouse inside a container, like a collaborator cursor: an arrow drawn in CSS with a name tag. It hides when the mouse leaves.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

Optional, and kept apart.

Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.

Move the mouse here to see a named pointer.

import { Pointer } from "@rdloom/react";

export default function PointerBasicExample() {
  return (
    <div className="flex w-full justify-center">
      <Pointer name="Maya" className="flex h-48 w-full max-w-md items-center justify-center rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-subtle)]">
        <p className="text-sm text-[var(--rd-color-text-muted)]">Move the mouse here to see a named pointer.</p>
      </Pointer>
    </div>
  );
}

Installation

npx rdloom add pointer

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.

It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/pointer.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { Pointer } from "@rdloom/react";

<div className="flex w-full justify-center">
  <Pointer name="Maya" className="flex h-48 w-full max-w-md items-center justify-center rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-subtle)]">
    <p className="text-sm text-[var(--rd-color-text-muted)]">Move the mouse here to see a named pointer.</p>
  </Pointer>
</div>

Custom color

A teal pointer labelled Jordan.

import { Pointer } from "@rdloom/react";

export default function PointerCustomColorExample() {
  return (
    <div className="flex w-full justify-center">
      <Pointer
        name="Jordan"
        color="#0f766e"
        className="flex h-48 w-full max-w-md items-center justify-center rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)]"
      >
        <p className="text-sm text-[var(--rd-color-text-muted)]">A teal pointer labelled Jordan.</p>
      </Pointer>
    </div>
  );
}

On a canvas

Ideas
Draft
Done
import { Pointer } from "@rdloom/react";

export default function PointerOnACanvasExample() {
  return (
    <div className="flex w-full justify-center">
      <Pointer name="Sam" color="#7c3aed" className="h-56 w-full max-w-md rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-subtle)] p-4">
        <div className="grid h-full grid-cols-3 gap-3">
          {["Ideas", "Draft", "Done"].map((title) => (
            <div key={title} className="rounded-[var(--rd-radius-control)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)] p-2 text-xs font-medium">
              {title}
            </div>
          ))}
        </div>
      </Pointer>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
children

Content of the container the pointer lives in.

nodenone
namerequired

The text on the name tag.

stringnone
color

Colour of the arrow and the tag, any CSS colour. Defaults to the primary action colour.

stringnone
isStill

Switches the pointer off.

booleanfalse

Accessibility

Role presentation, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

Not interactive.

Screen readers announce

  • Not announced: the pointer is purely visual

What your code must do

  • Decoration for mouse users: the pointer is aria-hidden, ignores the pointer (pointer-events none) and never takes focus
  • It never replaces keyboard focus and no information may depend on it
  • Not shown for touch or pen input, for prefers-reduced-motion, with isStill, or inside rdm-still
  • Hidden as soon as the mouse leaves the container; listeners are removed on unmount
  • Forced-colors: the arrow keeps its own colour (forced-color-adjust none) so it stays visible, and the tag keeps a border

Guidelines

Use it when

  • Showing how a shared canvas could look with several people on it
  • Product tours and landing page demos

Avoid it when

  • Real presence information: send that as text a screen reader can read

Don't

  • Long names that cover the content
  • Relying on the pointer to show who is doing something

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-action-primary
  • --rd-color-action-on-primary