Skip to main content
Props tells you a prop’s name, type, and default. This page tells you what it actually does: how Velt behaves with no props at all, which props fight each other, and what you take over when you leave wireframes.
Generated from the Velt SDK. A name that isn’t listed here doesn’t exist: don’t guess.

Per-component behavior: every prop (exhaustive)

Every prop’s runtime effect, per component. These pages are source-derived, so they win on any conflict with other docs. Events are in Events; data fields in Data models.

Default behaviors (no prop needed)

What Velt does out of the box. These are the baseline a prop modifies.

Prop-interaction matrix

collapsedComments × collapsedRepliesPreview

The most misunderstood pair. Which comment cards render depends on three things: whether the dialog is selected, showAllComments (default true), and collapsedRepliesPreview.
First + second + last is not achievable with props. The collapsed view is strictly index === 0 || index === length - 1. There’s no prop for “first three” or “first + newest two”. For any other pattern, use a thread-card wireframe or primitives. maxReplyAvatars (default 3) caps avatars, not comment cards.

sortBy × sortOrder

sortBy picks the field ('createdAt' | 'lastUpdated'), sortOrder the direction ('asc' | 'desc'). They apply together to the comment list in the dialog and inline section. With neither set, comments render in creation order. They only reorder; they don’t hide cards. On the inline section, the older sortData is deprecated: pass sortBy + sortOrder instead.

visibilityOptions (requires isPrivateCommentsEnabled)

visibilityOptions (default false) shows the per-comment visibility picker. It’s gated: the banner renders only when the SDK’s private-comments capability is also on. Turning it on without that shows nothing. privateCommentMode makes comments private by default.

shadowDom vs dialogShadowDom

shadowDom is the master wrap for VeltComments. The per-surface flags (dialogShadowDom, pinShadowDom, textCommentToolShadowDom, …) default true and isolate each surface independently. To style a surface with your own CSS, turn off the shadow DOM that wraps it: dialogShadowDom={false} reaches dialog internals, pinShadowDom={false} reaches the pin. Master shadowDom={false} drops isolation everywhere. A per-surface true keeps that surface isolated even when others are off. See CSS classes for what becomes selectable.

defaultMinimalFilter (overridden by saved state)

Sets the sidebar’s initial quick-filter ('all' | 'unread' | 'resolved' | 'open' | 'assignedToMe' | …). Saved session state wins, so this is a first-run default, not a forced value. To force a filter on every open, set it programmatically with setCommentSidebarFilters (Layout config).

embedMode / pageMode (sidebar)

  • embedMode renders the sidebar inline in your layout instead of docked. The type differs by version: boolean on V1, string on V2. It makes position and floatingMode moot, since you own placement.
  • pageMode switches to page-level comments: no pins on the DOM, and the composer lives at the sidebar level (pageModePlaceholder, pageModeComposerVariant). Mutually exclusive with pin-based commenting.

fullExpanded vs default

fullExpanded (default false) forces threads fully expanded, with message text untruncated. It’s the opposite of collapsedComments: don’t set both. messageTruncation (+ messageTruncationLines, default 4) is a separate axis that truncates long single messages, independent of how many cards show.

commentPlaceholder vs replyPlaceholder priority

The composer’s placeholder resolves in this order:
  1. Generic placeholder overrides everything.
  2. Otherwise the thread’s comment count decides: no comments → commentPlaceholder, has comments → replyPlaceholder.
  3. Otherwise a built-in default that varies with userMentions.
So the two never both apply at once. Edit mode has its own chain: editPlaceholdereditCommentPlaceholder / editReplyPlaceholder, again with generic placeholder on top.

Dialog state machine

Selection state and composer state are tracked per dialog instance, so the sidebar list, a focused thread, and a floating pin dialog for the same annotation don’t leak state into each other. Dialog selection:
  • unselected → selected: clicking the pin, or via dialogOnHover / dialogOnTargetElementClick.
  • selected → expanded: automatic when expandOnSelection is true. Set it false and selection won’t expand: the dialog stays a preview and the composer stays hidden.
  • any → unselected: deselect, close, or forceCloseAllOnEsc.
Composer state (independent, per instance):
  • collapsed → open: focusing the composer. With composerMode: 'expanded' it starts open and never collapses.
  • open → recording: a recorder config is active. Recording takes precedence over open.
  • open → collapsed: on submit or clear (text, attachments, recordings, and tagged users all reset).

Variant → context scoping

The same dialog renders in several contexts, and each has its own variant prop. This is how you make the sidebar-opened dialog look different from the floating pin dialog. Register a named wireframe variant and point only the relevant prop at it. Setting the base variant on VeltComments changes the floating pin dialog only; the other contexts keep their defaults.
“The dialog changed in the sidebar but not on pins” (or the reverse) is almost always the wrong variant prop for the context.

Positioning ownership (anchored surfaces)

VeltComments owns pin placement and dialog anchoring. The dialog component takes no position or coordinate prop and doesn’t place itself: it asks the host to re-anchor when its size changes (composer expands, recording starts), and the host does the placement. targetElementId names an anchor element, not a coordinate. What each approach forfeits:
The public API doesn’t expose a pin’s resolved screen coordinates, so a custom primitive or headless dialog cannot be anchored to a Velt pin’s position.
Which surfaces Velt positions: