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.
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.
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 pointerCopies 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.jsonWorks, 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
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
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.
| Prop | Type | Default |
|---|---|---|
childrenContent of the container the pointer lives in. | node | none |
namerequiredThe text on the name tag. | string | none |
colorColour of the arrow and the tag, any CSS colour. Defaults to the primary action colour. | string | none |
isStillSwitches the pointer off. | boolean | false |
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