New to wireframes? Start with UI Customization Concepts and the Template Variables overview.
Overview
The Comment Bubble wireframe exposes the variables below. Use them inside any<velt-comment-bubble-...-wireframe> tag via three forms:
| You want to… | Use | Example |
|---|---|---|
| Display a value as text | <velt-data field="var" /> | <velt-data field="annotation.from.name" /> |
| Hide / show conditionally | velt-if="{var}" | velt-if="{annotation.unread}" |
| Toggle a CSS class | velt-class="'cls': {var}" | velt-class="'is-unread': {annotation.unread}" |
componentConfig. prefix.
Naming conflicts — use full path. A few names collide with mappings used elsewhere. Inside a Comment Bubble wireframe, prefer the explicit path on the right when reading these values:
| Conflicting name | Use this in Comment Bubble |
|---|---|
customStatusesShown | globalConfigSignal.featureState.customStatusesShown |
resolvedCommentsOnDom | globalConfigSignal.featureState.resolvedCommentsOnDom |
readOnly | globalConfigSignal.featureState.readOnly (workspace) or {readOnly} (per-render local) |
App State
App-wide values resolved from the shared global signal.| Variable | Type | Description | Example |
|---|---|---|---|
globalConfigSignal.appState.user | User | null | Currently identified end-user. | <velt-data field="globalConfigSignal.appState.user.name" /> |
Data State
Per-bubble data: the annotation this bubble previews, the surrounding annotation list, and unread / unresolved counts.| Variable | Type | Description | Example |
|---|---|---|---|
annotation | CommentAnnotation | null | Annotation this bubble represents. | velt-if="{annotation}" |
annotation.from | User | Author of the annotation’s first comment. | <velt-data field="annotation.from.name" /> |
annotation.comments | Comment[] | Comments in the thread. | <velt-data field="annotation.comments.length" /> |
annotation.status.id | string | Current status id (e.g. "open", "resolved"). | velt-class="'status-{annotation.status.id}': true" |
annotation.unread | boolean | Annotation has unread comments for the current user. | velt-class="'is-unread': {annotation.unread}" |
annotation.iam.accessMode | 'public' | 'private' | Visibility mode. | velt-if="{annotation.iam.accessMode} === 'private'" |
annotations | CommentAnnotation[] | All annotations currently in scope. | <velt-data field="annotations.length" /> |
unresolvedAnnotationsCount | number | Number of unresolved annotations across the document. | <velt-data field="unresolvedAnnotationsCount" /> |
unreadCount | number | Unread-comment count for this bubble’s annotation. | <velt-data field="unreadCount" /> |
data.folderId | string | Folder id this bubble’s annotation belongs to. | <velt-data field="data.folderId" /> |
data.context | Record<string, any> | Free-form annotation context. | <velt-data field="data.context.key" /> |
UI State
Per-bubble UI flags driven by the bubble itself.| Variable | Type | Description | Example |
|---|---|---|---|
uiState.commentPinSelected | boolean | Pin associated with this bubble is currently selected. | velt-class="'pin-selected': {uiState.commentPinSelected}" |
selectedAnnotationsMap | SelectedAnnotationsMap | Map keyed by annotationId → boolean; true if that annotation is selected. | velt-class="'selected': {selectedAnnotationsMap[annotation.annotationId]}" |
selectedAnnotationsLocationMap | SelectedAnnotationsLocationMap | Internal selection bookkeeping by location. | Internal — read individual entries via bracket notation if needed. |
darkMode | boolean | Dark mode is active for this bubble. | velt-class="'dark': {darkMode}" |
variant | string | Per-instance variant tag set on the host element. | <velt-data field="variant" /> |
parentLocalUIState.shadowDom | boolean | Shadow-DOM rendering is enabled for this instance. | Host config — set via element attribute. |
commentBubbleTargetPinHover | boolean | The bubble’s anchor pin is currently hovered. | velt-class="'hover': {commentBubbleTargetPinHover}" |
openDialog | boolean | A comment dialog is open for this bubble’s annotation. | velt-if="{openDialog}" |
readOnly | boolean | Per-render read-only flag. | velt-class="'readonly': {readOnly}" |
showAvatar | boolean | Avatar should be rendered. | velt-if="{showAvatar}" |
commentCountType | 'total' | 'unread' | Which count drives the badge. | velt-class="'count-{commentCountType}': true" |
Feature State
Capability flags toggled at the workspace level. These are documented under the explicitglobalConfigSignal.featureState.<name> path because the bare names collide with other mappings.
| Variable | Type | Description | Example |
|---|---|---|---|
globalConfigSignal.featureState.customStatusesShown | boolean | Custom-status decoration enabled on bubbles. | velt-class="'show-status': {globalConfigSignal.featureState.customStatusesShown}" |
globalConfigSignal.featureState.groupMatchedComments | boolean | Matched comments are grouped together on the page. | velt-class="'grouped': {globalConfigSignal.featureState.groupMatchedComments}" |
globalConfigSignal.featureState.resolvedCommentsOnDom | boolean | Resolved annotations still render bubbles. | velt-if="{globalConfigSignal.featureState.resolvedCommentsOnDom}" |
globalConfigSignal.featureState.readOnly | boolean | Workspace read-only mode is active. | velt-class="'readonly': {globalConfigSignal.featureState.readOnly}" |
Common Props
Every Comment Bubble primitive accepts:| React Prop | HTML Attribute | Type | Default | Description |
|---|---|---|---|---|
defaultCondition | default-condition | boolean | "true" | "false" | true | When false, the component always renders regardless of internal state. |
[componentConfigSignal]— shared config signal (annotation, selected-annotations map, unread count).[parentLocalUIState]— per-instance UI state signal (darkMode, variant, shadowDom, readOnly, showAvatar, commentCountType).
<velt-comment-bubble> element additionally accepts attributes that map onto config and local UI state values: dark-mode, variant, show-avatar, comment-count-type, etc.
Type Reference
Types referenced by the variables above are documented in Data Models:| Type | Description |
|---|---|
CommentAnnotation | The annotation thread (id, status, comments, from, unread, iam, etc.). |
Comment | A single message inside an annotation thread. |
User | Identified end-user object. |
CommentVisibilityOptionType | Annotation visibility mode ('public', 'private', 'organization', 'selected_people'). |
Subcomponents
Each subcomponent below has its own wireframe tag. The annotation root supports nested access — seeCommentAnnotation for the full shape.
comment-bubble (root)
The bubble pin that previews an annotation when the user is not focused on it.
- Public element:
<velt-comment-bubble> - Wireframe tag:
<velt-comment-bubble-wireframe> - Children:
*-avatar,*-comments-count,*-unread-icon
| Property | Value |
|---|---|
| Extra variables | None — root only sees common variables. |
shouldShow | One bubble renders per non-resolved annotation on the current document. Resolved bubbles render only when globalConfigSignal.featureState.resolvedCommentsOnDom === true. |
- React / Next.js
- Other Frameworks
comment-bubble-avatar
The avatar of the annotation’s author.
- Public element:
<velt-comment-bubble-avatar> - Wireframe tag:
<velt-comment-bubble-avatar-wireframe>
| Property | Value |
|---|---|
| Extra variables | None beyond common variables. Read annotation.from.photoUrl / annotation.from.name from the parent annotation. |
- React / Next.js
- Other Frameworks
comment-bubble-comments-count
The “N” badge showing how many comments are in the thread.
- Public element:
<velt-comment-bubble-comments-count> - Wireframe tag:
<velt-comment-bubble-comments-count-wireframe>
| Property | Value |
|---|---|
| Extra variables | None beyond common variables. |
shouldShow | Renders only when the thread has more than one comment. |
- React / Next.js
- Other Frameworks
comment-bubble-unread-icon
The unread-indicator dot on the bubble.
- Public element:
<velt-comment-bubble-unread-icon> - Wireframe tag:
<velt-comment-bubble-unread-icon-wireframe>
| Property | Value |
|---|---|
| Extra variables | None beyond common variables. |
shouldShow | unreadCount > 0 (or annotation.unread === true, depending on commentCountType). |
Deeply-Nested Wireframe Tags
A separate-but-related set of primitives renders the comment pin (the small marker on the page) — distinct from the bubble (which previews the comment). Each tag below has its own<velt-comment-pin-...-wireframe> registration and reads from the same annotation context.
Comment Pin tags
| Tag | Notes | Example |
|---|---|---|
<velt-comment-pin-wireframe> | Root pin element. | velt-class="'pin-status-{annotation.status.id}': true" |
<velt-comment-pin-triangle-wireframe> | The pointing-arrow triangle below the pin. | Visual only — no data binding. |
<velt-comment-pin-index-wireframe> | Pin index number (e.g. “3” — order it was placed). | <velt-data field="annotation.annotationIndex" /> |
<velt-comment-pin-number-wireframe> | Auto-generated annotation number. | <velt-data field="annotation.annotationNumber" /> |
<velt-comment-pin-unread-comment-indicator-wireframe> | Unread dot indicator on the pin. | velt-if="{annotation.unread}" |
<velt-comment-pin-private-comment-indicator-wireframe> | Private-mode lock icon on the pin. | velt-if="{annotation.iam.accessMode} === 'private'" |
<velt-comment-pin-ghost-comment-indicator-wireframe> | Indicator shown when the pin has lost its DOM target (ghost-comment state). | velt-if="{annotation.ghostComment}" |
Related
- Comment Bubble Wireframes — composition reference for the wireframe tags themselves.
- Comment Bubble Primitives — granular components if you don’t need a full wireframe.
- Template Variables — overview of the
velt-data/velt-if/velt-classsystem.

