Collaborative Cursor

Shows another user's current cursor.

Jordan Blake

html

<div class="cursor-field">
  <div class="cursor-field__cursor" data-state="idle" style="left:140px; top:60px;">
    <svg class="cursor-field__arrow" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1 L16 8 L9 10 L7 17 Z" fill="#BFD9F2" stroke="#FAF7F2" stroke-width="1"></path></svg>
    <span class="cursor-field__tag" style="background:#BFD9F2;">Jordan Blake</span>
  </div>
</div>
<style>
.cursor-field { position: relative; width: 400px; max-width: 100%; height: 220px; background: #FAF7F2; border: 1px solid #24143020; border-radius: 12px; overflow: hidden; font: 13px system-ui, sans-serif; color: #241430; box-sizing: border-box; }
.cursor-field__cursor { position: absolute; display: flex; align-items: center; gap: 6px; }
.cursor-field__tag { color: #FAF7F2; padding: 3px 8px; border-radius: 6px; font-weight: 600; white-space: nowrap; position: relative; }
.cursor-field__cursor[data-state="typing"] .cursor-field__tag::after { content: " · typing"; font-weight: 400; }
.cursor-field__cursor[data-state="selecting"] .cursor-field__tag::after { content: " · selecting"; font-weight: 400; }
</style>

tailwind

<div class="relative w-[400px] max-w-full h-[220px] bg-[#FAF7F2] border border-[#24143020] rounded-xl overflow-hidden font-sans text-[13px] text-[#241430] box-border">
  <div class="cursor-field-tw__cursor absolute flex items-center gap-1.5" data-state="idle" style="left:140px; top:60px">
    <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1 L16 8 L9 10 L7 17 Z" fill="#BFD9F2" stroke="#FAF7F2" stroke-width="1"></path></svg>
    <span class="cursor-field-tw__tag text-[#FAF7F2] px-2 py-0.5 rounded-md font-semibold whitespace-nowrap relative" style="background:#BFD9F2">Jordan Blake</span>
  </div>
</div>
<style>
.cursor-field-tw__cursor[data-state="typing"] .cursor-field-tw__tag::after { content: " · typing"; font-weight: 400; }
.cursor-field-tw__cursor[data-state="selecting"] .cursor-field-tw__tag::after { content: " · selecting"; font-weight: 400; }
</style>

react

export function CollaborativeCursor({
  name = "Jordan Blake",
  color = "#BFD9F2",
  x = 140,
  y = 60,
  state = "idle",
}) {
  const suffix = { idle: "", typing: " · typing", selecting: " · selecting" }[state] ?? "";
  return (
    <div style={{ position: "relative", width: 400, maxWidth: "100%", height: 220, background: "#FAF7F2", border: "1px solid #24143020", borderRadius: 12, overflow: "hidden", fontFamily: "system-ui, sans-serif", fontSize: 13, color: "#241430", boxSizing: "border-box" }}>
      <div style={{ position: "absolute", left: x, top: y, display: "flex", alignItems: "center", gap: 6 }}>
        <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1 L16 8 L9 10 L7 17 Z" fill={color} stroke="#FAF7F2" strokeWidth="1" /></svg>
        <span style={{ background: color, color: "#FAF7F2", padding: "3px 8px", borderRadius: 6, fontWeight: 600, whiteSpace: "nowrap" }}>{name}{suffix}</span>
      </div>
    </div>
  );
}