Skip to main content
Real-time “who’s here” avatars (presence) and live remote cursors. Both are wireframed at the per-item level and use flat-config variables ({componentConfig.<x>}).

Components

Presence

VeltPresence (primitive) · VeltPresenceWireframe + VeltPresenceTooltipWireframe. The tooltip has no standalone mount: customize it only via VeltPresenceTooltipWireframe.

Live Cursors

VeltCursor (primitive) · VeltCursorPointerWireframe. Only the per-user pointer is wireframable: the root <velt-cursor> just spawns one pointer per remote user and isn’t wireframable.

Config props

Presence

maxUsers (default 5: caps avatars before the “+N” overflow), self (include local user), inactivityTime (→ away, default 5 min), offlineInactivityTime (default 10 min), variant, shadowDom, flockMode / defaultFlockNavigation, location/locationId.

Live Cursors

avatarMode (avatar bubbles vs arrows), inactivityTime (default 5), allowedElementIds (restrict cursors to elements), variant, darkMode.

CSS: stateful classes

(Override with !important, R9b.)

Presence

velt-presence-avatar--away (and .away) when onlineStatus === 'away'; velt-presence-avatar-outline is tinted by presenceUser.color.

Live Cursors

no-transition (self pointer); …default-container-comment-border when cursorUser.comment; flip on the huddle <video> for the self pointer.

Wireframes: slot trees + tokens

Presence

VeltPresenceWireframe → .AvatarList → .AvatarList.Item   ·   .AvatarRemainingCount
VeltPresenceTooltipWireframe → .Avatar · .UserName · .UserActive · .UserInactive · .StatusContainer
Tooltip slots are status-gated: .UserActive renders only for online, .UserInactive only for away (neither for offline). Key tokens ({componentConfig.<x>}): filteredPresenceUsers (list hidden when length === 0), user (hidden if user.isAnonymous), maxUsers; per-item presenceUser (.name/.email/.onlineStatus/.color), index (renders when index < maxUsers); remaining-count renders when filteredPresenceUsers.length > maxUsers.

Live Cursors

VeltCursorPointerWireframe
├── .Arrow                         (the cursor glyph; fill bound to cursorUser.color)
├── .Default → .Name / .Comment
├── .Avatar
├── .AudioHuddle → .Avatar / .Audio
└── .VideoHuddle
Key tokens (per-user, flat): cursorUser (.name/.color/.photoUrl/.comment/.position), selfCursorPointer, showDefault/showAvatar/showAudio/showVideo (derived from stream + avatarMode), variant.

Headless hooks

Presence

usePresenceData(query?){ data: PresenceUser[] | null } (current); usePresenceUtils() (imperative). (usePresenceUsers() is deprecated.)

Live Cursors

useCursorUsers()CursorUser[] | null; useCursorUtils() (imperative: setInactivityTime, allowedElementIds).

Limitations

Presence

Anonymous local users never see presence; maxUsers both caps avatars and gates the overflow badge; a custom template needs explicit shadowDom="true" to use shadow DOM.

Live Cursors

  • There is no live-cursor pin/image prop. (pin-cursor-image is a VeltComments prop for the comment-placement cursor, not live cursors.) To change the live cursor glyph, use the <slot name="cursor"> or the .Arrow wireframe.
  • The root <velt-cursor> isn’t wireframable: only the per-user pointer is.
  • Your own cursor is hidden in normal use (selfCursorPointer shows only in huddle-on-cursor mode).
  • Requires an identified (non-anonymous) user.