About
A live cursor/collaboration name-label that pushes overlapping labels apart with a magnet-like physics simulation so the currently typing collaborator's label stays readable while others yield.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Pole Shy to your project and fits it to your theme.
Code
How Pole Shy is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
"use client";
import PoleShy, { type PoleShyUser } from "@/components/ui/pole-shy";
import * as React from "react";
const baseUsers: PoleShyUser[] = [
{ id: "you", name: "You", x: 0.14, row: 0, typing: false },
{ id: "priya", name: "Priya Nair", x: 0.3, row: 0, typing: false },
{ id: "theo", name: "Theo Voss", x: 0.46, row: 0, typing: false },
{ id: "sam", name: "Sam Ochieng", x: 0.62, row: 0, typing: false },
{ id: "wren", name: "Wren Delacroix", x: 0.22, row: 1, typing: false },
{ id: "kai", name: "Kai Fujimori", x: 0.68, row: 1, typing: false },
];
export default function PoleShyDemo() {
const [users, setUsers] = React.useState<PoleShyUser[]>(baseUsers);
React.useEffect(() => {
let i = 0;
const interval = setInterval(() => {
setUsers((prev) =>
prev.map((u, idx) => ({ ...u, typing: idx === i % prev.length })),
);
i++;
}, 1800);
return () => clearInterval(interval);
}, []);
return (
<div className="w-full max-w-2xl space-y-6 rounded-lg border border-border bg-card p-6">
<div className="space-y-1">
<h3 className="text-sm font-medium text-foreground">
Section 2 — release notes
</h3>
<p className="text-xs text-muted-foreground">
Several cursors crowd one line below. Type in the box — your label
carries a stronger field while you're actively typing, and the
others yield to make room.
</p>
</div>
<PoleShy users={users} />
<textarea
placeholder="Type here — your caret label pushes the others aside"
className="w-full resize-none rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground outline-none"
rows={2}
onChange={() =>
setUsers((prev) =>
prev.map((u) => (u.id === "you" ? { ...u, typing: true } : u)),
)
}
onBlur={() =>
setUsers((prev) =>
prev.map((u) => (u.id === "you" ? { ...u, typing: false } : u)),
)
}
/>
</div>
);
}








