VeltPresence, VeltCursor, and VeltReactionTool are the three real-time-collaboration surfaces. This file owns the layer above Props for them: what every prop does at runtime, its default, the state it drives, and how props combine: plus the default behaviors you get with no prop at all (presence avatar list + self, live cursor follow, reaction-tool emoji set).
Read this alongside Component definitions (anchored-vs-static classification) and Data models (the PresenceUser / CursorUser entities these surfaces read).
- Who positions them (the key gotcha):
VeltPresenceis statically placed: it renders an avatar row exactly where you mount it, like any normal React element; you control its position with your own CSS.VeltCursoris anchored / Velt-positioned: mount it once (typically near the app root) and Velt paints every remote user’s cursor as a fixed-position overlay following each user’s real pointer in viewport coordinates. You do not position individual cursors.VeltReactionToolis a statically-placed trigger button (you place it), but the reactions it can produce on a video timeline are themselves anchored to media position.- See
Behaviors→ Positioning ownership andComponent definitionsfor the anchored-vs-static axis.
- One mount each:
VeltCursorguards against duplicate subscriptions: only the firstvelt-cursorelement in the DOM actually subscribes to the live-cursor stream and renders; additional instances are inert. Mount it once.
Per-prop behavior (exhaustive)
The exhaustive per-prop behavior for the three real-time surfaces is organized per component below: each## Velt… subsection carries that component’s full prop table (default + runtime behavior + interactions) and its own ### Default behaviors (no prop needed) block. Every prop in Props for these components is covered (plus the source-only props noted inline); see Provable coverage.
VeltPresence
A statically-placed avatar row showing who is currently online on the same document/location. It subscribes to online users for the current document, filters them by location (if scoped), and renders avatars with a hover tooltip. Confirmed against the presence component.
Default behaviors (no prop needed)
- Avatar row of online users. Out of the box
VeltPresencerenders a horizontal list of avatars for everyone online on the current document, capped at 5 (maxUsers), with a “+N” overflow count beyond that. Each avatar has a hover tooltip showing the user’s name and active/away status. - You are included.
selfdefaults totrue, so your own avatar is in the row by default. - All users, unless scoped. With no
location/locationId, every online user on the document shows; set either to scope to a sub-region. - Idle then offline. Users transition online → inactive (after
inactivityTime) → offline (afterofflineInactivityTime), driving the tooltip’s away-time. The component literals are5/10; the presence service’s real baselines are minute-scale, and the prop values you pass are interpreted as milliseconds. - No flock by default.
flockModeis off; clicking an avatar only emitsonPresenceUserClickand shows the tooltip: it does not start following anyone until you enable flock mode. - Style-isolated.
shadowDomdefaultstrue.
VeltCursor
An anchored / Velt-positioned surface: mount it once and Velt overlays every other online user’s live cursor on the page, tracking each user’s real pointer position. The local user’s own pointer position is read from window pointer-move events (offset by 2px). Confirmed against the cursor component.
Default behaviors (no prop needed)
- Live remote cursors follow real pointers. With just
<VeltCursor />mounted, every other online user’s cursor appears as a named pointer that moves in real time, positioned in viewport coordinates (Velt owns placement: you don’t set per-cursor positions). The local user’s position is sampled from window pointer-move (offset −2px / −2px). - Name labels, not avatars.
avatarModeisfalseby default → cursors show the user’s name, not their avatar. - Mount-once / first-instance-wins. Only the first
velt-cursorelement subscribes and renders; duplicate mounts are inert (prevents double subscriptions). Mount one near the app root. - Idle cursors flush. A cursor that stops updating past
inactivityTimeis hidden (service baseline 2 minutes). - Whole-page by default.
allowedElementIdsempty → cursors render anywhere; set it to confine them. - Always shadow-DOM isolated. The cursor component renders with shadow-DOM encapsulation always on (it is not a toggleable prop here, unlike presence): style it via the cursor CSS variables, not deep selectors. There is no
shadowDomprop onVeltCursor; this reference documents no master flag that affects it.
VeltReactionTool
A statically-placed trigger button that opens an emoji/reaction picker panel. Documented props in Props are videoPlayerId and onReactionToolClick; the component also accepts several additional inputs/outputs present in source (noted below and marked where not listed in Props). Confirmed against the reaction-tool component.
Default behaviors (no prop needed)
- A button that opens an emoji panel. Out of the box the tool renders an “Add reaction” trigger (role=
button,aria-haspopup); clicking it opens a positioned overlay panel of emojis. - The default emoji set. With no customization the picker shows Velt’s built-in SVG emoji set: confirmed keys:
RAISED_HANDS,THUMBS_DOWN,THUMBS_UP,HEART_FACE,TEARS_OF_JOY,EYES,FIRE. The rendered ordering follows the emoji-map iteration order; this reference does not guarantee it as a stable display order. - Emit-only unless bound to video. With no
videoPlayerId, selecting an emoji just firesemojiSelectedand closes the panel: nothing is persisted; the host wires up the effect. BindvideoPlayerIdto make selection write a reaction at the current media position (and pause playback). - Custom emoji set is an SDK-level concern. The picker’s contents come from the emoji service, which is overridden via the app-level
customReactions/ReactionMapconfiguration (seeComponent config), not via a prop on this component.excludeReactionIdsonly subtracts from whatever set is active. - Style-isolated.
shadowDomdefaultstrue.
Default behaviors (no prop needed)
Each component’s zero-prop baseline is documented in its### Default behaviors (no prop needed) block above. In brief:
VeltPresence: renders a horizontal avatar row of everyone online on the document (capmaxUsers5, “+N” overflow, hover tooltips), includes the current user (selftrue), shows all users unless scoped bylocation/locationId, transitions online → inactive → offline, no flock by default, shadow-DOM isolated.VeltCursor: paints every other online user’s live cursor as a name-labeled pointer in viewport coordinates (Velt owns placement); only the first mounted instance subscribes; idle cursors flush after the inactivity window; always shadow-DOM isolated.VeltReactionTool: renders an “Add reaction” button that opens Velt’s default emoji set, emitsemojiSelectedonly (no persistence) unless bound to avideoPlayerId, shadow-DOM isolated.
Prop-interaction matrix
No separate multi-prop matrix for this group: pairwise effects live in each prop’s Interactions & gotchas column above. The interactions worth restating:VeltPresence:offlineInactivityTimemust be ≥inactivityTime(a smaller value is rejected);locationIdtakes precedence overlocation;flockModegatesonNavigate/defaultFlockNavigationand pairs withonPresenceUserClick(a click sets the flock leader only when flock mode is on); the current user counts towardmaxUserswhenselfis on.- Deprecated callbacks fire/write alongside their replacements:
onUsersChanged→onPresenceUserChange,onCursorUsersChanged→onCursorUserChange,disableFlockNavigation→defaultFlockNavigation. VeltReactionTool:videoPlayerIdswitches selection from emit-only to writing a media-anchored reaction;excludeReactionIdsonly subtracts from the active set (customReactionsis the SDK-level way to add).
Positioning & composition
Mixed:VeltPresence and VeltReactionTool are statically placed: they render where you mount them and you control position with your own CSS (the video reactions a reaction tool can produce are themselves anchored to media-timeline position). VeltCursor is anchored / Velt-positioned: mount it once near the app root and Velt paints each remote cursor as a fixed-position overlay tracking that user’s real pointer; you do not position individual cursors. See Behaviors → Positioning ownership and the anchored-vs-static classification in Component definitions.
Provable coverage
Coverage notes:
documentParams is not documented as a live presence input; no master shadowDom flag is documented for VeltCursor; the default emoji display order is not guaranteed as stable. Everything else is stated as covered behavior.
