Skip to content
weftGitHub

Cursors

Other people's pointers, with their names, over a shared document.

SourcePackage @weft-js/warp

Preview

tsx
import { onCleanup, onMount, state } from '@weft-js/core'import { Cursors, Heading, Stack, Text } from '@weft-js/warp'import type { CursorPeer, Peer } from '@weft-js/warp'export function Document() {  const peers = state<CursorPeer[]>(CURSOR_PEERS)  onMount(() => {    let tick = 0    const timer = setInterval(() => {      tick++      peers.value = CURSOR_PEERS.map((p, i) => ({ ...p, cursor: { ...p.cursor!, x: 0.2 + 0.6 * Math.abs(Math.sin(tick / 2 + i)) } }))    }, 1400)    onCleanup(() => clearInterval(timer))  })  return (    <Stack gap="related" style="position:relative">      <div data-anchor="title"><Heading level={3}>Rollback runbook</Heading></div>      <div data-anchor="body"><Text subtle>When a deploy fails its health check, roll back first and read the logs second. A failed deploy never blocks the next one, and the person on call owns the call.</Text></div>      <Cursors peers={peers} idle={3600000} />    </Stack>  )}const PEOPLE = [  { id: 'mara', name: 'Mara Lindqvist', email: 'mara@weft.dev', role: 'Owner', team: 'Platform', initials: 'ML' },  { id: 'jun', name: 'Jun Tanaka', email: 'jun@weft.dev', role: 'Admin', team: 'Platform', initials: 'JT' },  { id: 'priya', name: 'Priya Raman', email: 'priya@weft.dev', role: 'Member', team: 'Web', initials: 'PR' },  { id: 'tomas', name: 'Tomás Oliveira', email: 'tomas@weft.dev', role: 'Member', team: 'Web', initials: 'TO' },  { id: 'lena', name: 'Lena Fischer', email: 'lena@weft.dev', role: 'Member', team: 'Data', initials: 'LF' },  { id: 'noor', name: 'Noor Haddad', email: 'noor@weft.dev', role: 'Viewer', team: 'Data', initials: 'NH' },  { id: 'sam', name: 'Sam Okafor', email: 'sam@weft.dev', role: 'Member', team: 'Mobile', initials: 'SO' },  { id: 'ines', name: 'Inés Vidal', email: 'ines@weft.dev', role: 'Viewer', team: 'Mobile', initials: 'IV' },]const PEERS: Peer[] = PEOPLE.map((p, i) => ({ id: p.id, name: p.name, color: i + 1 }))const [MARA, JUN, PRIYA, TOMAS, LENA, NOOR, SAM, INES] = PEERS as [Peer, Peer, Peer, Peer, Peer, Peer, Peer, Peer]const CURSOR_PEERS: CursorPeer[] = [{ ...JUN, cursor: { anchor: 'title', x: 0.42, y: 0.8 } }, { ...LENA, cursor: { anchor: 'body', x: 0.7, y: 0.35 } }, { ...SAM, cursor: { anchor: 'body', x: 0.22, y: 0.85 } }]

Installation

npm install @weft-js/warp

Usage

tsx
import { Cursors } from '@weft-js/warp'

Accessibility

  • The layer is hidden from assistive tech. PresenceStack says who is here.

API Reference

PropTypeDefaultDescription
peersLive<CursorPeer[]>—People and where their cursors are.
anchorstring—Limits the cursors to one anchor.
idlenumber5000Milliseconds before a still cursor fades.

RelatedPeer markPeer selectionPresence stack