> ## Documentation Index
> Fetch the complete documentation index at: https://velt.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Comment Dialog Wireframe Variables

> Template variables the Velt Comment Dialog wireframe exposes, used with velt-data, velt-if, and velt-class for dynamic content and styling.

> [!NOTE]
>
> New to wireframes? Start with the [Comment Dialog Customization overview](https://velt.dev/docs/ui-customization/features/async/comments/comment-dialog/overview.md) and the general [Template Variables](https://velt.dev/docs/ui-customization/template-variables.md) concept.

## Overview

The **Comment Dialog** wireframe exposes the variables below. Use them inside any `<velt-comment-dialog-...-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="{enableResolve} && {canResolveAnnotation}"` |
| Toggle a CSS class | `velt-class="'cls': {var}"` | `velt-class="'is-private': {isPrivateComment}"` |

All variables are mapped — reference them by their short name. You do not need the `componentConfig.` prefix unless explicitly noted (see [Root-Level Properties](#root-level-properties-use-full-path)).

## App State

App-wide values resolved from the shared per-annotation signal.

| Variable | Type | Description | Example |
| - | - | - | - |
| `user` | [`User`](https://velt.dev/docs/api-reference/sdk/models/data-models#user) | Currently identified end-user. | `<velt-data field="user.name" />` |
| `isUserAdmin` | `boolean` | True when `user.isAdmin === true`. | `velt-if="{isUserAdmin}"` |
| `isKnownUser` | `boolean` | True when the user has been identified (vs. anonymous). | `velt-class="'is-known': {isKnownUser}"` |
| `repliesUniqueUsers` | [`User`](https://velt.dev/docs/api-reference/sdk/models/data-models#user)`[]` | Distinct authors of replies on the current annotation. | `<velt-data field="repliesUniqueUsers.length" />` |

## Data State

Per-annotation data: the live annotation, comment list, edit / draft state, attachments, and recordings.

| Variable | Type | Description | Example |
| - | - | - | - |
| `annotation` | [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation) | Annotation this dialog represents. | `<velt-data field="annotation.from.name" />` |
| `annotations` | [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation)`[]` | All annotations in scope (for sidebar usage). | `<velt-data field="annotations.length" />` |
| `allAnnotations` | [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation)`[]` | Unfiltered annotation list. | `<velt-data field="allAnnotations.length" />` |
| `ghostComment` | `GhostComment` \| `null` | Set when the annotation has lost its DOM target. | `velt-if="{ghostComment}"` |
| `assignTo` | [`UserContact`](https://velt.dev/docs/api-reference/sdk/models/data-models#usercontact) | Currently selected assignee. | `<velt-data field="assignTo.name" />` |
| `selectedUserContacts` | [`UserContact`](https://velt.dev/docs/api-reference/sdk/models/data-models#usercontact)`[]` | Selected user contacts (for assign / mention). | `<velt-data field="selectedUserContacts.length" />` |
| `customList` | `any[]` | Autocomplete reference list (when registered). | `<velt-data field="customList.length" />` |
| `toOrganizationUserGroup` | `any[]` | Organization user-group contacts. | `<velt-data field="toOrganizationUserGroup.length" />` |
| `taggedUserContacts` | [`AutocompleteUserContactReplaceData`](https://velt.dev/docs/api-reference/sdk/models/data-models#autocompleteusercontactreplacedata)`[]` | Users tagged via @mention in the active composer. | `<velt-data field="taggedUserContacts.length" />` |
| `taggedGroups` | `any[]` | Groups tagged via @mention in the active composer. | `<velt-data field="taggedGroups.length" />` |
| `customChipData` | [`CustomAnnotationDropdownData`](https://velt.dev/docs/api-reference/sdk/models/data-models#customannotationdropdowndata) \| `null` | Custom-chip dropdown config for this annotation. | `velt-if="{customChipData}"` |
| `selectedCustomChipSet` | `Set<string>` | IDs currently selected in the custom-chip dropdown. | `<velt-data field="selectedCustomChipSet.size" />` |
| `currentDialogView` | `Record<string, any>` | Seen-by aggregation keyed by `commentId`. | `<velt-data field="currentDialogView[annotation.annotationId].count" />` |
| `selectedFiles` | `FileData[]` | Files staged in the composer. | `velt-if="{selectedFiles.length} > 0"` |
| `invalidSelectedFiles` | `InvalidFileData[]` | Files rejected by validation. | `velt-if="{invalidSelectedFiles.length} > 0"` |
| `selectedAttachments` | `any[]` | Attachments staged for the new comment. | `<velt-data field="selectedAttachments.length" />` |
| `editComment` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) \| `null` | Comment currently being edited in this dialog. | `velt-if="{editComment}"` |
| `editCommentIndex` | `number` \| `null` | Index of the comment being edited. | `<velt-data field="editCommentIndex" />` |
| `localRecordedData` | [`RecordedData`](https://velt.dev/docs/api-reference/sdk/models/data-models#recordeddata)`[]` | Recordings staged in the composer. | `<velt-data field="localRecordedData.length" />` |
| `attachmentsToDelete` | `any[]` | Attachments queued for deletion on save. | `<velt-data field="attachmentsToDelete.length" />` |

## UI State

Per-instance UI flags driven by the dialog itself. Grouped by area for readability — the underlying shape is flat.

**Layout modes** — which rendering mode the dialog is in.

| Variable | Type | Description | Example |
| - | - | - | - |
| `sidebarMode` | `boolean` | Dialog is rendered inside the comments sidebar. | `velt-class="'is-sidebar': {sidebarMode}"` |
| `inboxMode` | `boolean` | Dialog is rendered inside the inbox layout. | `velt-class="'is-inbox': {inboxMode}"` |
| `dialogMode` | `boolean` | Default popup-dialog layout. | `velt-class="'is-dialog': {dialogMode}"` |
| `inlineCommentMode` | `boolean` | Inline-comment-pin styling. | `velt-class="'is-inline': {inlineCommentMode}"` |
| `inlineCommentSectionMode` | `boolean` | Inline comments section layout. | `velt-class="'is-inline-section': {inlineCommentSectionMode}"` |
| `focusedThreadMode` | `boolean` | Focused-thread layout is active. | `velt-class="'is-focused': {focusedThreadMode}"` |
| `isFocusedThreadEnabled` | `boolean` | Focused-thread navigation is allowed. | `velt-if="{isFocusedThreadEnabled}"` |
| `pageModeComposer` | `boolean` | Page-level composer mode (sidebar). | `velt-class="'page-composer': {pageModeComposer}"` |
| `bottomSheetMode` | `boolean` | Bottom-sheet layout is active. | `velt-class="'bottom-sheet': {bottomSheetMode}"` |
| `commentComposerMode` | `boolean` | Composer-only layout (no thread). | `velt-class="'composer-only': {commentComposerMode}"` |
| `multiThreadAnnotationId` | `string` \| `null` | Multi-thread context id (when in multi-thread mode). | `velt-if="{multiThreadAnnotationId}"` |
| `dialogOpenedInSidebar` | `boolean` | Dialog opened in sidebar context. | `velt-class="'in-sidebar': {dialogOpenedInSidebar}"` |
| `dialogShadowDOM` | `boolean` | Shadow-DOM rendering is enabled. | `velt-if="{dialogShadowDOM}"` |
| `containerComponentId` | `string` | Owning container id (scoping). | `<velt-data field="containerComponentId" />` |
| `commentDialogUniqueId` | `string` | Unique id for this dialog instance. | `<velt-data field="commentDialogUniqueId" />` |
| `deviceType` | `string` | Device-type modifier (`'desktop'`, `'mobile'`, etc.). | `velt-class="'device-{deviceType}': true"` |
| `darkMode` | `boolean` | Dark mode is active. | `velt-class="'theme-dark': {darkMode}"` |
| `variant` | `string` | Per-instance variant tag set on the host element. | `<velt-data field="variant" />` |
| `disabled` | `boolean` | Dialog is disabled. | `velt-class="'is-disabled': {disabled}"` |
| `readOnly` | `boolean` | Per-instance read-only mode. | `velt-class="'readonly': {readOnly}"` |
| `commentPinSelected` | `boolean` | Pin associated with this dialog is selected. | `velt-class="'pin-selected': {commentPinSelected}"` |
| `commentDialogSelected` | `boolean` | This dialog is the currently selected one. | `velt-class="'selected': {commentDialogSelected}"` |
| `fullExpanded` | `boolean` | Dialog is fully expanded (sidebar). | `velt-class="'expanded': {fullExpanded}"` |
| `expandOnSelection` | `boolean` | Sidebar expands on click vs. just visually selecting. | `velt-if="{expandOnSelection}"` |
| `composerPosition` | `string` | Composer position (`'top'` or `'bottom'`). | `velt-class="'composer-{composerPosition}': true"` |
| `selectedVisibility` | [`CommentVisibilityOptionType`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentvisibilityoptiontype) | Currently selected visibility option. | `velt-class="'visibility-{selectedVisibility}': true"` |
| `selectedVisibilityUsers` | `any[]` | Users selected when `selectedVisibility === 'selected_people'`. | `<velt-data field="selectedVisibilityUsers.length" />` |
| `locationVersion` | `string` | Annotation location version. | `<velt-data field="locationVersion" />` |

**Composer state** — input, draft, and submission state.

| Variable | Type | Description | Example |
| - | - | - | - |
| `composerContent` | `string` | Plain-text composer draft. | `<velt-data field="composerContent" />` |
| `composerContentHTML` | `string` | Rich-text composer draft. | `<velt-data field="composerContentHTML" />` |
| `newComment` | `string` | Alias for `composerContent`. | `<velt-data field="newComment" />` |
| `newCommentHTML` | `string` | Alias for `composerContentHTML`. | `<velt-data field="newCommentHTML" />` |
| `composerInOpenState` | `boolean` | Composer is currently expanded. | `velt-class="'composer-open': {composerInOpenState}"` |
| `composerMode` | `'default'` \| `'expanded'` | Current composer mode. | `velt-class="'composer-{composerMode}': true"` |
| `isInputFocused` | `boolean` | Composer input has keyboard focus. | `velt-class="'input-focused': {isInputFocused}"` |
| `showCommentButtons` | `boolean` | Composer's action-button row should render. | `velt-if="{showCommentButtons}"` |
| `isAutocompleteDropdownOpen` | `boolean` | @-mention autocomplete dropdown is open. | `velt-class="'autocomplete-open': {isAutocompleteDropdownOpen}"` |
| `uploadingAttachments` | `boolean` | One or more attachments are uploading. | `velt-class="'uploading': {uploadingAttachments}"` |
| `recorderInitConfig` | `any` | Active recorder configuration (or `null`). | `velt-class="'recording-{recorderInitConfig.type}': true"` |

**Reactions, replies, and dropdowns.**

| Variable | Type | Description | Example |
| - | - | - | - |
| `showReplies` | `boolean` | Reply list is currently shown. | `velt-class="'show-replies': {showReplies}"` |
| `collapsedComments` | `boolean` | Comments are collapsed (only first comment visible). | `velt-class="'collapsed': {collapsedComments}"` |
| `showAllComments` | `boolean` | "Show all" mode is active. | `velt-if="{showAllComments}"` |
| `showReplyComposer` | `boolean` | Reply composer is currently visible. | `velt-if="{showReplyComposer}"` |
| `maxReplyAvatars` | `number` | Maximum reply avatars to show before "+N". | `<velt-data field="maxReplyAvatars" />` |
| `showSuggestionModeActions` | `boolean` | Suggestion-mode accept/reject actions visible. | `velt-if="{showSuggestionModeActions}"` |
| `reactionToolOpenIndex` | `number` | Comment index whose reaction picker is open (`-1` if none). | `velt-class="'reaction-open': '{reactionToolOpenIndex} === {commentIndex}'"` |
| `openDropdownIndexValue` | `number` | Comment index whose options dropdown is open (`-1` if none). | `velt-class="'dropdown-open': '{openDropdownIndexValue} === {commentIndex}'"` |
| `hasReactionsByCommentId` | `Record<string, boolean>` | Map keyed by `commentId` → has-reactions flag. | `velt-if="{hasReactionsByCommentId[comment.commentId]}"` |
| `assignToMenuOpened` | `boolean` | Assign-to menu is open. | `velt-class="'assign-open': {assignToMenuOpened}"` |
| `isPrivateComment` | `boolean` | Annotation is in private mode. | `velt-class="'private': {isPrivateComment}"` |
| `showGhostCommentMessage` | `boolean` | Ghost-comment banner should show. | `velt-if="{showGhostCommentMessage}"` |
| `playVideoInFullScreen` | `boolean` | Recordings play full-screen. | `velt-class="'fullscreen-video': {playVideoInFullScreen}"` |
| `shouldScrollToBottom` | `boolean` | *Internal transient signal* — triggers auto-scroll to latest comment. | *Internal — not typically used in wireframes.* |
| `showScreenSizeInfo` | `boolean` | Screen-size information overlay is visible. | `velt-if="{showScreenSizeInfo}"` |
| `sidebarButtonOnCommentDialogVisible` | `boolean` | "View all comments" sidebar button is visible on the dialog. | `velt-if="{sidebarButtonOnCommentDialogVisible}"` |

## Feature State

Capability flags toggled via SDK config. All `Shared` — the same value applies to every dialog instance for the same annotation.

| Variable | Type | Description | Example | | |
| - | - | - | - | - | - |
| `canResolveAnnotation` | `boolean` | Current user is allowed to resolve this annotation. | `velt-if="{canResolveAnnotation}"` | | |
| `canUnresolveAnnotation` | `boolean` | Current user is allowed to unresolve this annotation. | `velt-if="{canUnresolveAnnotation}"` | | |
| `dialogSelectedByKnownUser` | `boolean` | Selected dialog belongs to an identified user. | `velt-class="'known-user-selected': {dialogSelectedByKnownUser}"` | | |
| `enableResolve` | `boolean` | Resolve action enabled by config. | `velt-if="{enableResolve}"` | | |
| `resolveStatusAccessAdminOnly` | `boolean` | Only admins can change resolve status. | \`velt-if="!{resolveStatusAccessAdminOnly} | | {isUserAdmin}"\` |
| `enableSignInButton` | `boolean` | Sign-in button is rendered for anonymous users. | `velt-if="{enableSignInButton}"` | | |
| `enableUpgradeButton` | `boolean` | Upgrade button is rendered when plan is expired. | `velt-if="{enableUpgradeButton}"` | | |
| `enableGhostCommentsMessage` | `boolean` | Ghost-comment banner is enabled. | `velt-if="{enableGhostCommentsMessage}"` | | |
| `replyAvatars` | `boolean` | Reply-avatars strip is enabled. | `velt-if="{replyAvatars}"` | | |
| `collapsedRepliesPreview` | `boolean` | Surface the collapsed teaser (first comment + "Show N replies…" divider + last comment) even while the dialog is non-selected/preview. Default `false`. | `velt-if="{collapsedRepliesPreview}"` | | |
| `userMentions` | `boolean` | @-mention autocomplete is enabled. | `velt-if="{userMentions}"` | | |
| `recordingSummaryEnabled` | `boolean` | Recording AI-summary feature enabled. | `velt-if="{recordingSummaryEnabled}"` | | |
| `enableAttachment` | `boolean` | File attachments enabled. | `velt-if="{enableAttachment}"` | | |
| `allowedFileTypes` | `string[]` | File-type allow-list. | `<velt-data field="allowedFileTypes.length" />` | | |
| `allowedRecordings` | `string[]` | Recording types enabled (`'audio'` / `'video'` / `'screen'`). | `<velt-data field="allowedRecordings.0" />` | | |
| `screenSharingSupported` | `boolean` | Browser supports screen-sharing. | `velt-if="{screenSharingSupported}"` | | |
| `enterKeyToSubmit` | `boolean` | Enter key submits (vs. inserts a newline). | `velt-class="'enter-submit': {enterKeyToSubmit}"` | | |
| `deleteOnBackspace` | `boolean` | Backspace on empty composer deletes the comment. | `velt-class="'backspace-delete': {deleteOnBackspace}"` | | |
| `enableReactions` | `boolean` | Emoji reactions enabled. | `velt-if="{enableReactions}"` | | |
| `isInsidePdfViewer` | `boolean` | Dialog is inside a PDF viewer. | `velt-class="'in-pdf': {isInsidePdfViewer}"` | | |
| `enableStatus` | `boolean` | Status dropdown enabled. | `velt-if="{enableStatus}"` | | |
| `customStatusesShown` | `boolean` | Custom-status decoration enabled. | `velt-class="'custom-statuses': {customStatusesShown}"` | | |
| `statusOptions` | [`CustomStatus`](https://velt.dev/docs/api-reference/sdk/models/data-models#customstatus)`[]` | Available status options. | `<velt-data field="statusOptions.length" />` | | |
| `enablePriority` | `boolean` | Priority dropdown enabled. | `velt-if="{enablePriority}"` | | |
| `priorityOptions` | [`CustomPriority`](https://velt.dev/docs/api-reference/sdk/models/data-models#custompriority)`[]` | Available priority options. | `<velt-data field="priorityOptions.length" />` | | |
| `visibilityOptions` | `boolean` | Visibility dropdown enabled. | `velt-if="{visibilityOptions}"` | | |
| `enableAssignment` | `boolean` | Assign-to dropdown enabled. | `velt-if="{enableAssignment}"` | | |
| `enableNotifications` | `boolean` | Notification toggle enabled. | `velt-if="{enableNotifications}"` | | |
| `enableEdit` | `boolean` | Edit action enabled. | `velt-if="{enableEdit}"` | | |
| `enableDelete` | `boolean` | Delete action enabled. | `velt-if="{enableDelete}"` | | |
| `enablePrivateMode` | `boolean` | Private-mode toggle enabled. | `velt-if="{enablePrivateMode}"` | | |
| `deleteThreadWithFirstComment` | `boolean` | Deleting the first comment deletes the entire thread. | `velt-class="'delete-cascade': {deleteThreadWithFirstComment}"` | | |
| `seenByUsers` | `boolean` | "Seen by" feature enabled. | `velt-if="{seenByUsers}"` | | |
| `commentAcceptedStatus` | [`CustomStatus`](https://velt.dev/docs/api-reference/sdk/models/data-models#customstatus) | Accepted-suggestion status object. | `<velt-data field="commentAcceptedStatus.name" />` | | |
| `commentRejectedStatus` | [`CustomStatus`](https://velt.dev/docs/api-reference/sdk/models/data-models#customstatus) | Rejected-suggestion status object. | `<velt-data field="commentRejectedStatus.name" />` | | |
| `enableAutoCategorize` | `boolean` | Auto-categorize feature enabled. | `velt-if="{enableAutoCategorize}"` | | |
| `suggestionMode` | `boolean` | Suggestion mode is active. | `velt-class="'suggestion-mode': {suggestionMode}"` | | |
| `moderatorMode` | `boolean` | Moderator mode is active. | `velt-class="'moderator': {moderatorMode}"` | | |
| `isPlanExpired` | `boolean` | Workspace plan is expired. | `velt-class="'plan-expired': {isPlanExpired}"` | | |

### Collapsed replies preview

The `collapsedRepliesPreview` variable mirrors the `collapsed-replies-preview` host attribute (and the `collapsedRepliesPreview` React prop). When `true`, the collapsed teaser — first comment + "Show N replies…" divider + last comment — is surfaced even while the dialog is non-selected/preview. It widens the `comment-dialog-more-reply` `shouldShow` from `isDialogSelected` to (`isDialogSelected` **or** `collapsedRepliesPreview`). Default `false`.

```html theme={null}
<ng-container velt-if="{collapsedRepliesPreview}">
  <!-- preview-only content -->
</ng-container>
```

## Common Props

Every Comment Dialog primitive accepts a small shared set of attributes. The most useful ones inside wireframes:

| React Prop | HTML Attribute | Type | Default | Description |
| - | - | - | - | - |
| `annotationId` | `annotation-id` | `string` | — | Standalone mode — pin this primitive to an annotation id. |
| `inlineCommentSectionMode` | `inline-comment-section-mode` | `boolean` \| `"true"` \| `"false"` | `false` | Switch to inline-section behavior. |
| `defaultCondition` | `default-condition` | `boolean` \| `"true"` \| `"false"` | `true` | When `false`, bypasses `shouldShow` so the primitive always renders. |

Signal inputs (auto-wired in parent-child component composition):

* `[componentConfigSignal]` — shared per-annotation config signal.
* `[parentLocalUIState]` — per-instance UI state signal.

For the full per-subcomponent prop list, see [Comment Dialog Primitives](https://velt.dev/docs/ui-customization/features/async/comments/comment-dialog/primitives.md).

## Context-Specific Variables

These are only resolvable inside the nested wireframe tags noted in the **Available in** column. Each is injected by the iteration primitive that owns the tag.

| Variable | Type | Available in | Example |
| - | - | - | - |
| `commentObj` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) | `<velt-comment-dialog-thread-card-wireframe>` and descendants | `<velt-data field="commentObj.commentText" />` |
| `comment` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) | Same as above (alias of `commentObj`) | `<velt-data field="comment.from.name" />` |
| `commentIndex` | `number` | Same as above. `0` on the parent comment. | `velt-class="'is-first': '{commentIndex} === 0'"` |
| `commentAnnotation` | [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation) | Available everywhere (alias of `annotation`) | `<velt-data field="commentAnnotation.from.userId" />` |
| `commentAnnotations` | [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation)`[]` | Available everywhere (alias of `annotations`) | `<velt-data field="commentAnnotations.length" />` |
| `userContact` | [`UserContact`](https://velt.dev/docs/api-reference/sdk/models/data-models#usercontact) | User-selector items | `<velt-data field="userContact.email" />` |
| `context` | `Record<string, any>` | Inline-comment-section context | `<velt-data field="context.foo" />` |

> [!NOTE]
>
> **Aliases:** `commentObj` ↔ `comment`, `annotation` ↔ `commentAnnotation`, `annotations` ↔ `commentAnnotations`. Either name resolves; the friendly short form is preferred.

## Version 1 Backward-Compatibility Aliases

Inherited from v4 SDK config signals. They are mapped so wireframes written for v4 keep working — the **Maps to** column tells you the v5 equivalent.

| Version 1 Alias | Maps to | Description |
| - | - | - |
| `allowAssignment` | `enableAssignment` | Was in `CommentDialogOptionsDropdownConfig`. |
| `allowToggleNotification` | `enableNotifications` | Was the per-comment notification toggle flag. |
| `allowEdit` | `enableEdit` | Was the per-comment edit-permission flag. |
| `allowChangeCommentAccessMode` | `enablePrivateMode` | Was the access-mode toggle flag. |
| `notificationEnabled` | `notificationEnabled` (passthrough) | Pass-through; the data context must provide it. |
| `mainCommentId` | `annotation.comments.0.commentId` | Convenience alias for the first comment's id. |

The resolver also unwraps two legacy signal-name prefixes — `commentDialogOptionsDropdownConfigSignal.*` and `commentDialogStatusDropdownConfigSignal.*` — so an old wireframe written as `{commentDialogOptionsDropdownConfigSignal.allowAssignment}` keeps working.

## Root-Level Properties (Use Full Path)

These properties live at the root of `componentConfigSignal` and **are not** entries in the variable map. To use them, write the full `componentConfigSignal.<name>` path.

| Variable | Type | Description |
| - | - | - |
| `componentConfigSignal.unreadCommentsMap` | `Record<string, number>` \| `null` | Map keyed by `annotationId` to unread count. Combine with bracket notation: `{componentConfigSignal.unreadCommentsMap[annotation.annotationId]}`. |
| `componentConfigSignal.unreadIndicatorMode` | `'minimal'` \| `'detailed'` | Unread-indicator display mode. |
| `componentConfigSignal.commentplaceholder` | `string` | Placeholder for the new-comment composer. |
| `componentConfigSignal.replyplaceholder` | `string` | Placeholder for the reply composer. |
| `componentConfigSignal.editplaceholder` | `string` | Placeholder for the generic edit composer. |
| `componentConfigSignal.editcommentplaceholder` | `string` | Placeholder for the edit-comment composer. |
| `componentConfigSignal.editreplyplaceholder` | `string` | Placeholder for the edit-reply composer. |
| `componentConfigSignal.placeholder` | `string` | Generic placeholder; takes priority over the others. |

One root-level helper **is** mapped:

| Variable | Type | Description |
| - | - | - |
| `unreadCommentAnnotationCount` | `number` | Mapped explicitly. Populated for the unread counter on the dialog/sidebar entry-points. Read as `{unreadCommentAnnotationCount}`. |

## Type Reference

Types referenced by the variables above are documented in [Data Models](https://velt.dev/docs/api-reference/sdk/models/data-models.md):

| Type | Description |
| - | - |
| [`User`](https://velt.dev/docs/api-reference/sdk/models/data-models#user) | Identified end-user object (userId, name, email, photoUrl, isAdmin). |
| [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) | A single message inside an annotation thread. |
| [`CommentAnnotation`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotation) | The annotation thread (id, status, comments, from, etc.). |
| [`UserContact`](https://velt.dev/docs/api-reference/sdk/models/data-models#usercontact) | Selectable user contact (assign-to, mention). |
| [`Attachment`](https://velt.dev/docs/api-reference/sdk/models/data-models#attachment) | Saved attachment record on a comment. |
| [`RecordedData`](https://velt.dev/docs/api-reference/sdk/models/data-models#recordeddata) | Audio / video / screen recording metadata. |
| [`CustomStatus`](https://velt.dev/docs/api-reference/sdk/models/data-models#customstatus) | Status definition (id, name, color, icon). |
| [`CustomPriority`](https://velt.dev/docs/api-reference/sdk/models/data-models#custompriority) | Priority definition (id, name, color, icon). |
| [`CustomAnnotationDropdownData`](https://velt.dev/docs/api-reference/sdk/models/data-models#customannotationdropdowndata) | Custom-chip dropdown configuration. |
| [`CustomAnnotationDropdownItem`](https://velt.dev/docs/api-reference/sdk/models/data-models#customannotationdropdownitem) | A single chip option in the custom-annotation dropdown. |
| [`CommentVisibilityOptionType`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentvisibilityoptiontype) | Visibility mode (`'public'`, `'organization'`, `'selected_people'`, `'private'`). |
| [`AutocompleteUserContactReplaceData`](https://velt.dev/docs/api-reference/sdk/models/data-models#autocompleteusercontactreplacedata) | Tagged-mention replacement payload. |
| [`CommentAnnotationContext`](https://velt.dev/docs/api-reference/sdk/models/data-models#commentannotationcontext) | Free-form annotation context. |
| [`GhostComment`](https://velt.dev/docs/api-reference/sdk/models/data-models#ghostcomment) | Placeholder set when the annotation has lost its DOM target. |
| [`FileData`](https://velt.dev/docs/api-reference/sdk/models/data-models#filedata) | Pending file selection (composer-staged file). |
| [`InvalidFileData`](https://velt.dev/docs/api-reference/sdk/models/data-models#invalidfiledata) | Rejected file selection (composer-staged file with a validation error). |

## Subcomponents

Each subcomponent below has its own wireframe tag. The tables show extra variables beyond the common set, the `shouldShow` condition, and host CSS classes.

### `comment-dialog` (root)

The root primitive — the `<velt-comment-dialog>` element customers place in their app.

* **Public element:** `<velt-comment-dialog>`
* **Wireframe tag:** `<velt-comment-dialog-wireframe>`
* **Children:** `*-header`, `*-body`, `*-composer`, `*-close-button`

| Property | Value |
| - | - |
| Extra variables | None — root only sees common variables. |
| `shouldShow` | Renders when `defaultCondition === false` **or** `componentConfig` exists with a non-null `annotation`. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltWireframe>
>   <VeltCommentDialogWireframe veltClass="'my-dialog--dark': {darkMode}, 'my-dialog--readonly': {readOnly}">
>     <div className="my-dialog">
>       <VeltCommentDialogWireframe.Header />
>       <VeltCommentDialogWireframe.Body />
>       <VeltCommentDialogWireframe.Composer />
>     </div>
>   </VeltCommentDialogWireframe>
> </VeltWireframe>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-wireframe>
>   <velt-comment-dialog-wireframe>
>     <div class="my-dialog" velt-class="'my-dialog--dark': {darkMode}, 'my-dialog--readonly': {readOnly}">
>       <velt-comment-dialog-header-wireframe></velt-comment-dialog-header-wireframe>
>       <velt-comment-dialog-body-wireframe></velt-comment-dialog-body-wireframe>
>       <velt-comment-dialog-composer-wireframe></velt-comment-dialog-composer-wireframe>
>     </div>
>   </velt-comment-dialog-wireframe>
> </velt-wireframe>
> ```

***

### `comment-dialog-header`

The header strip across the top of the dialog: status, priority, custom-chip, options dropdown, copy-link, resolve / unresolve buttons.

* **Public element:** `<velt-comment-dialog-header>`
* **Wireframe tag:** `<velt-comment-dialog-header-wireframe>`
* **Children:** `*-status-dropdown`, `*-priority-dropdown`, `*-custom-annotation-dropdown`, `*-options-dropdown`, `*-resolve-button`, `*-unresolve-button`, `*-copy-link`

| Property | Value |
| - | - |
| Extra variables | None beyond common variables. |
| `shouldShow` | `defaultCondition === false` **or** `annotation.comments.length > 0`. Hidden on a brand-new annotation. |
| Host class | `velt-header` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Header veltIf="{enableStatus} || {enablePriority}">
>   <div className="my-header">
>     <velt-comment-dialog-status-dropdown-wireframe></velt-comment-dialog-status-dropdown-wireframe>
>     <velt-comment-dialog-priority-dropdown-wireframe></velt-comment-dialog-priority-dropdown-wireframe>
>     <span className="spacer"></span>
>     <velt-comment-dialog-options-dropdown-wireframe></velt-comment-dialog-options-dropdown-wireframe>
>     <VeltCommentDialogWireframe.ResolveButton />
>   </div>
> </VeltCommentDialogWireframe.Header>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-header-wireframe>
>   <div class="my-header" velt-if="{enableStatus} || {enablePriority}">
>     <velt-comment-dialog-status-dropdown-wireframe></velt-comment-dialog-status-dropdown-wireframe>
>     <velt-comment-dialog-priority-dropdown-wireframe></velt-comment-dialog-priority-dropdown-wireframe>
>     <span class="spacer"></span>
>     <velt-comment-dialog-options-dropdown-wireframe></velt-comment-dialog-options-dropdown-wireframe>
>     <velt-comment-dialog-resolve-button-wireframe></velt-comment-dialog-resolve-button-wireframe>
>   </div>
> </velt-comment-dialog-header-wireframe>
> ```

***

### `comment-dialog-body`

The middle section: threads list, reply avatars, toggle / hide-reply controls.

* **Public element:** `<velt-comment-dialog-body>`
* **Wireframe tag:** `<velt-comment-dialog-body-wireframe>`
* **Children:** `*-threads`, `*-reply-avatars`, `*-toggle-reply`, `*-hide-reply`, `*-more-reply`

| Property | Value |
| - | - |
| Extra variables | None at the body level. |
| `shouldShow` | `defaultCondition === false` **or** `annotation.comments.length > 0`. |
| Host class | `velt-body` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Body veltClass="'my-body--collapsed': '!{commentDialogSelected} && {annotation.comments.length}'">
>   <div className="my-body">
>     <VeltCommentDialogWireframe.Threads />
>     <VeltIf condition="{replyAvatars} && !{commentDialogSelected} && !{readOnly}">
>       <div className="reply-strip">
>         <VeltCommentDialogWireframe.ReplyAvatars />
>         <VeltCommentDialogWireframe.ToggleReply />
>       </div>
>     </VeltIf>
>   </div>
> </VeltCommentDialogWireframe.Body>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-body-wireframe>
>   <div class="my-body" velt-class="'my-body--collapsed': '!{commentDialogSelected} && {annotation.comments.length}'">
>     <velt-comment-dialog-threads-wireframe></velt-comment-dialog-threads-wireframe>
>     <div class="reply-strip" velt-if="{replyAvatars} && !{commentDialogSelected} && !{readOnly}">
>       <velt-comment-dialog-reply-avatars-wireframe></velt-comment-dialog-reply-avatars-wireframe>
>       <velt-comment-dialog-toggle-reply-wireframe></velt-comment-dialog-toggle-reply-wireframe>
>     </div>
>   </div>
> </velt-comment-dialog-body-wireframe>
> ```

***

### `comment-dialog-threads`

The list container. Iterates `annotation.comments` and renders one thread-card per comment.

* **Public element:** `<velt-comment-dialog-threads>`
* **Wireframe tag:** `<velt-comment-dialog-threads-wireframe>`
* **Children:** `*-thread-card`

The threads container injects per-iteration variables into each thread-card:

| Variable | Type | Example |
| - | - | - |
| `commentObj` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) | `<velt-data field="commentObj.commentText" />` |
| `comment` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) (alias) | `<velt-data field="comment.from.name" />` |
| `commentIndex` | `number` | `velt-class="'is-first': '{commentIndex} === 0'"` |

| Property | Value | | |
| - | - | - | - |
| `shouldShow` | Each thread-card renders only when \`!isDialogSelected() ? !i : (!collapsedComments | | !i)\` — i.e. only the first comment when collapsed, all comments when expanded. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Threads>
>   <VeltCommentDialogWireframe.ThreadCard>
>     <article className="my-thread">
>       <VeltCommentDialogWireframe.ThreadCard.Name />
>       <VeltCommentDialogWireframe.ThreadCard.Time />
>       <VeltCommentDialogWireframe.ThreadCard.Message />
>       {/* {comment.from.name}, {commentIndex} are in scope here */}
>     </article>
>   </VeltCommentDialogWireframe.ThreadCard>
>
>   <VeltCommentDialogWireframe.MoreReply>
>     <button>Show more replies</button>
>   </VeltCommentDialogWireframe.MoreReply>
> </VeltCommentDialogWireframe.Threads>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-threads-wireframe>
>   <velt-comment-dialog-thread-card-wireframe>
>     <article class="my-thread">
>       <velt-comment-dialog-thread-card-name-wireframe></velt-comment-dialog-thread-card-name-wireframe>
>       <velt-comment-dialog-thread-card-time-wireframe></velt-comment-dialog-thread-card-time-wireframe>
>       <velt-comment-dialog-thread-card-message-wireframe></velt-comment-dialog-thread-card-message-wireframe>
>       <!-- {comment.from.name}, {commentIndex} are in scope here -->
>     </article>
>   </velt-comment-dialog-thread-card-wireframe>
>
>   <velt-comment-dialog-more-reply-wireframe>
>     <button>Show more replies</button>
>   </velt-comment-dialog-more-reply-wireframe>
> </velt-comment-dialog-threads-wireframe>
> ```

***

### `comment-dialog-close-button`

Close button that dismisses the dialog.

* **Public element:** `<velt-comment-dialog-close-button>`
* **Wireframe tag:** `<velt-comment-dialog-close-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | Always renders when the dialog is shown. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.CloseButton>
>   <button aria-label="Close" className="my-close">×</button>
> </VeltCommentDialogWireframe.CloseButton>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-close-button-wireframe>
>   <button aria-label="Close" class="my-close">×</button>
> </velt-comment-dialog-close-button-wireframe>
> ```

***

### `comment-dialog-composer`

The composer assembly — owns the per-instance composer state machine and emits change events as the user types.

* **Public element:** `<velt-comment-dialog-composer>`
* **Wireframe tag:** `<velt-comment-dialog-composer-wireframe>`
* **Children:** `*-input`, `*-avatar`, `*-action-button`, `*-attachments`, `*-recordings`, `*-private-badge`, `*-format-toolbar`, `*-assign-user`

The composer injects extras for its child tags:

| Variable | Type | Example |
| - | - | - |
| `editMode` | `boolean` | `velt-class="'is-editing': {editMode}"` |
| `commentObj` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) (edit mode only) | `<velt-data field="commentObj.commentText" />` |
| `commentIndex` | `number` (edit mode only) | `<velt-data field="commentIndex" />` |

| Property | Value |
| - | - |
| `shouldShow` | Renders when `!disabled && isKnownUser && !isPlanExpired`, **and** edit-mode parity matches (`!!editComment === editMode`), **and** for new-comment mode one of `annotation.comments.length === 0`, `commentDialogSelected`, or `focusedThreadMode` is true. |
| Host class | `velt-composer` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer veltClass="'my-composer--editing': {editMode}">
>   <div className="my-composer">
>     <VeltCommentDialogWireframe.Composer.PrivateBadge />
>     <VeltCommentDialogWireframe.Composer.Attachments />
>     <VeltCommentDialogWireframe.Composer.Input />
>     <VeltIf condition="{composerInOpenState}">
>       <div className="my-composer__actions">
>         <VeltCommentDialogWireframe.Composer.ActionButton type="autocomplete" />
>         <VeltCommentDialogWireframe.Composer.ActionButton type="attachments" />
>         <VeltCommentDialogWireframe.Composer.ActionButton type="submit" />
>       </div>
>     </VeltIf>
>   </div>
> </VeltCommentDialogWireframe.Composer>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-wireframe>
>   <div class="my-composer" velt-class="'my-composer--editing': {editMode}">
>     <velt-comment-dialog-composer-private-badge-wireframe></velt-comment-dialog-composer-private-badge-wireframe>
>     <velt-comment-dialog-composer-attachments-wireframe></velt-comment-dialog-composer-attachments-wireframe>
>     <velt-comment-dialog-composer-input-wireframe></velt-comment-dialog-composer-input-wireframe>
>     <div class="my-composer__actions" velt-if="{composerInOpenState}">
>       <velt-comment-dialog-composer-action-button-wireframe type="autocomplete"></velt-comment-dialog-composer-action-button-wireframe>
>       <velt-comment-dialog-composer-action-button-wireframe type="attachments"></velt-comment-dialog-composer-action-button-wireframe>
>       <velt-comment-dialog-composer-action-button-wireframe type="submit"></velt-comment-dialog-composer-action-button-wireframe>
>     </div>
>   </div>
> </velt-comment-dialog-composer-wireframe>
> ```

***

### `comment-dialog-composer-action-button`

A polymorphic action button — the same primitive renders different controls depending on its `type` attribute.

* **Public element:** `<velt-comment-dialog-composer-action-button>`
* **Wireframe tag:** `<velt-comment-dialog-composer-action-button-wireframe>`

Supported `type` values: `userMentions`, `autocomplete`, `file`, `attachments`, `audio`, `video`, `screen`, `format`, `submit`.

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` (per type) | `userMentions` / `autocomplete`: `userMentions === true`. `file` / `attachments`: `enableAttachment === true`. `audio` / `video` / `screen`: corresponding entry in `allowedRecordings`. `format`: `enableFormatOptions === true`. `submit`: always renders. |
| Host class | `velt-comment-dialog-composer-action-button` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> {/* Register per-type wireframes */}
> <VeltCommentDialogWireframe.Composer.ActionButton type="audio">
>   <button className="my-mic">🎤</button>
> </VeltCommentDialogWireframe.Composer.ActionButton>
>
> <VeltCommentDialogWireframe.Composer.ActionButton type="submit">
>   <button className="my-submit">Send</button>
> </VeltCommentDialogWireframe.Composer.ActionButton>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <!-- Register per-type wireframes -->
> <velt-comment-dialog-composer-action-button-wireframe type="audio">
>   <button class="my-mic">🎤</button>
> </velt-comment-dialog-composer-action-button-wireframe>
>
> <velt-comment-dialog-composer-action-button-wireframe type="submit">
>   <button class="my-submit">Send</button>
> </velt-comment-dialog-composer-action-button-wireframe>
> ```

***

### `comment-dialog-composer-input`

The contenteditable input area with autocomplete (@mention) support.

* **Public element:** `<velt-comment-dialog-composer-input>`
* **Wireframe tag:** `<velt-comment-dialog-composer-input-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `!editMode && !isRecordingActive` for new-comment; `editMode && commentObj && !isRecordingActive` for edit-comment. |
| Host class | `velt-composer-input` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.Input>
>   <div className="my-input">
>     {/* The internal textarea is injected via the default template path; */}
>     {/* override only the surrounding chrome here */}
>   </div>
> </VeltCommentDialogWireframe.Composer.Input>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-input-wireframe>
>   <div class="my-input">
>     <!-- The internal textarea is injected via the default template path; -->
>     <!-- override only the surrounding chrome here -->
>   </div>
> </velt-comment-dialog-composer-input-wireframe>
> ```

***

### `comment-dialog-composer-avatar`

The current user's avatar shown next to the composer in inline-section mode.

* **Public element:** `<velt-comment-dialog-composer-avatar>`
* **Wireframe tag:** `<velt-comment-dialog-composer-avatar-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `inlineCommentSectionMode === true` and `annotation.comments.length === 0`. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.Avatar>
>   <img className="my-avatar" src="..." alt="" />
> </VeltCommentDialogWireframe.Composer.Avatar>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-avatar-wireframe>
>   <img class="my-avatar" [src]="..." alt="" />
> </velt-comment-dialog-composer-avatar-wireframe>
> ```

***

### `comment-dialog-composer-attachments`

The display row that lists files staged for upload and any rejected files.

* **Public element:** `<velt-comment-dialog-composer-attachments>`
* **Wireframe tag:** `<velt-comment-dialog-composer-attachments-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `editComment` is set, `selectedFiles.length > 0`, or `invalidSelectedFiles.length > 0`. |
| Host class | `velt-composer--attachments` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.Attachments>
>   <ul className="my-attachments">
>     {/* Default content delegates to selected/invalid sub-primitives */}
>   </ul>
> </VeltCommentDialogWireframe.Composer.Attachments>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-attachments-wireframe>
>   <ul class="my-attachments">
>     <!-- Default content delegates to selected/invalid sub-primitives -->
>   </ul>
> </velt-comment-dialog-composer-attachments-wireframe>
> ```

***

### `comment-dialog-composer-recordings`

The display row that lists active and pending recordings.

* **Public element:** `<velt-comment-dialog-composer-recordings>`
* **Wireframe tag:** `<velt-comment-dialog-composer-recordings-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | Renders when `localRecordedData.length > 0` or a recording session is active. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.Recordings>
>   {/* Wraps the default recordings list; default content remains */}
> </VeltCommentDialogWireframe.Composer.Recordings>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-recordings-wireframe>
>   <!-- Wraps the default recordings list; default content remains -->
> </velt-comment-dialog-composer-recordings-wireframe>
> ```

***

### `comment-dialog-composer-private-badge`

The "Only for your team" badge shown above the composer when private mode is active.

* **Public element:** `<velt-comment-dialog-composer-private-badge>`
* **Wireframe tag:** `<velt-comment-dialog-composer-private-badge-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `isPrivateComment === true` **and** `annotation.comments.length === 0`. |
| Host class | `velt-private-badge` |

> [!NOTE]
>
> When `featureState.visibilityOptions === true`, this legacy primitive auto-suppresses — the new visibility-options dropdown owns the privacy indicator. The `isPrivateComment` value also now correctly reflects `visibilityConfig.type === 'restricted' | 'organizationPrivate'` in addition to the legacy `iam.accessMode === 'private'`.

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.PrivateBadge>
>   <span className="my-badge">🔒 Private</span>
> </VeltCommentDialogWireframe.Composer.PrivateBadge>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-private-badge-wireframe>
>   <span class="my-badge">🔒 Private</span>
> </velt-comment-dialog-composer-private-badge-wireframe>
> ```

***

### `comment-dialog-composer-format-toolbar`

The bold / italic / underline / strikethrough toolbar.

* **Public element:** `<velt-comment-dialog-composer-format-toolbar>`
* **Wireframe tag:** `<velt-comment-dialog-composer-format-toolbar-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `formatToolbarOpen === true` **and** `enableFormatOptions === true`. |
| Host class | `velt-format-toolbar` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.FormatToolbar>
>   <div className="my-format-bar">
>     <VeltCommentDialogWireframe.Composer.FormatToolbar.Button type="bold">
>       <button>B</button>
>     </VeltCommentDialogWireframe.Composer.FormatToolbar.Button>
>     <VeltCommentDialogWireframe.Composer.FormatToolbar.Button type="italic">
>       <button>I</button>
>     </VeltCommentDialogWireframe.Composer.FormatToolbar.Button>
>   </div>
> </VeltCommentDialogWireframe.Composer.FormatToolbar>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-format-toolbar-wireframe>
>   <div class="my-format-bar">
>     <velt-comment-dialog-composer-format-toolbar-button-wireframe type="bold">
>       <button>B</button>
>     </velt-comment-dialog-composer-format-toolbar-button-wireframe>
>     <velt-comment-dialog-composer-format-toolbar-button-wireframe type="italic">
>       <button>I</button>
>     </velt-comment-dialog-composer-format-toolbar-button-wireframe>
>   </div>
> </velt-comment-dialog-composer-format-toolbar-wireframe>
> ```

***

### `comment-dialog-composer-assign-user`

The assign-to dropdown shown beneath the composer when the user opens the @-mention picker.

* **Public element:** `<velt-comment-dialog-composer-assign-user>`
* **Wireframe tag:** `<velt-comment-dialog-composer-assign-user-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `userMentions === true` and `composerInOpenState === true`. |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.Composer.AssignUser>
>   {/* Customize the dropdown chrome here */}
> </VeltCommentDialogWireframe.Composer.AssignUser>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-composer-assign-user-wireframe>
>   <!-- Customize the dropdown chrome here -->
> </velt-comment-dialog-composer-assign-user-wireframe>
> ```

***

### `comment-dialog-thread-card`

A single comment inside the thread list. Renders avatar, name, time, message, options, reactions, recordings, and edit-composer.

* **Public element:** `<velt-comment-dialog-thread-card>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-wireframe>`
* **Children:** `*-avatar`, `*-name`, `*-time`, `*-message`, `*-edited`, `*-options`, `*-reactions`, `*-reaction-tool`, `*-recordings`, `*-seen-dropdown`, `*-attachments`, `*-edit-composer`, `*-assign-button`, `*-unread`, `*-draft`, `*-device-type`

| Variable | Type | Example |
| - | - | - |
| `commentObj` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) | `<velt-data field="commentObj.commentText" />` |
| `comment` | [`Comment`](https://velt.dev/docs/api-reference/sdk/models/data-models#comment) (alias) | `<velt-data field="comment.from.name" />` |
| `commentIndex` | `number` | `velt-class="'is-first': '{commentIndex} === 0'"` |

| Property | Value |
| - | - |
| `shouldShow` | Renders when `comment` resolves to a truthy value (triple-input lookup found a comment). |
| Host class | `velt-thread-card--container` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.ThreadCard veltClass="'my-card--mine': '{comment.from.userId} === {user.userId}'">
>   <article className="my-card">
>     <header className="my-card__head">
>       <VeltCommentDialogWireframe.ThreadCard.Avatar />
>       <VeltCommentDialogWireframe.ThreadCard.Name />
>       <VeltCommentDialogWireframe.ThreadCard.Time />
>       <VeltCommentDialogWireframe.ThreadCard.Edited />
>       <VeltCommentDialogWireframe.ThreadCard.Options />
>     </header>
>     <VeltCommentDialogWireframe.ThreadCard.Message />
>     <VeltCommentDialogWireframe.ThreadCard.EditComposer />
>   </article>
> </VeltCommentDialogWireframe.ThreadCard>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-thread-card-wireframe>
>   <article class="my-card" velt-class="'my-card--mine': '{comment.from.userId} === {user.userId}'">
>     <header class="my-card__head">
>       <velt-comment-dialog-thread-card-avatar-wireframe></velt-comment-dialog-thread-card-avatar-wireframe>
>       <velt-comment-dialog-thread-card-name-wireframe></velt-comment-dialog-thread-card-name-wireframe>
>       <velt-comment-dialog-thread-card-time-wireframe></velt-comment-dialog-thread-card-time-wireframe>
>       <velt-comment-dialog-thread-card-edited-wireframe></velt-comment-dialog-thread-card-edited-wireframe>
>       <velt-comment-dialog-thread-card-options-wireframe></velt-comment-dialog-thread-card-options-wireframe>
>     </header>
>     <velt-comment-dialog-thread-card-message-wireframe></velt-comment-dialog-thread-card-message-wireframe>
>     <velt-comment-dialog-thread-card-edit-composer-wireframe></velt-comment-dialog-thread-card-edit-composer-wireframe>
>   </article>
> </velt-comment-dialog-thread-card-wireframe>
> ```

***

### `comment-dialog-thread-card-avatar`

The author's avatar.

* **Public element:** `<velt-comment-dialog-thread-card-avatar>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-avatar-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| Host class | `comment-dialog-user-avatar` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.ThreadCard.Avatar>
>   <img className="my-avatar" src="..." alt="" />
> </VeltCommentDialogWireframe.ThreadCard.Avatar>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-thread-card-avatar-wireframe>
>   <img class="my-avatar" [src]="..." alt="" />
> </velt-comment-dialog-thread-card-avatar-wireframe>
> ```

***

### `comment-dialog-thread-card-name`

The author's display name.

* **Public element:** `<velt-comment-dialog-thread-card-name>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-name-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| Host class | `velt-thread-card--name` |

> [tab] React / Next.js
>
> ```jsx theme={null}
> <VeltCommentDialogWireframe.ThreadCard.Name>
>   <strong><VeltData field="comment.from.name" /></strong>
> </VeltCommentDialogWireframe.ThreadCard.Name>
> ```

> [tab] Other Frameworks
>
> ```html theme={null}
> <velt-comment-dialog-thread-card-name-wireframe>
>   <strong>{{ '{comment.from.name}' }}</strong>
> </velt-comment-dialog-thread-card-name-wireframe>
> ```

***

### `comment-dialog-thread-card-time`

The comment's `lastUpdated` timestamp formatted as relative time.

* **Public element:** `<velt-comment-dialog-thread-card-time>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-time-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| Host class | `velt-thread-card--time` |

***

### `comment-dialog-thread-card-message`

The comment body. Renders text, HTML, or voice player. Supports message truncation.

* **Public element:** `<velt-comment-dialog-thread-card-message>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-message-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| Host class | `velt-thread-card--message` |

***

### `comment-dialog-thread-card-edited`

Small "Edited" badge shown when a comment has been modified.

* **Public element:** `<velt-comment-dialog-thread-card-edited>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-edited-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | `comment.isEdited === true` or a local edit draft exists. |

***

### `comment-dialog-thread-card-options`

The "..." options dropdown trigger on a comment.

* **Public element:** `<velt-comment-dialog-thread-card-options>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-options-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | Dialog is selected and the comment belongs to the current user or user is admin. |

***

### `comment-dialog-thread-card-reactions`

Emoji reaction badges displayed below a comment.

* **Public element:** `<velt-comment-dialog-thread-card-reactions>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-reactions-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | `enableReactions === true` and the comment has reactions. |

***

### `comment-dialog-thread-card-recordings`

Recordings attached to a comment (audio / video / screen).

* **Public element:** `<velt-comment-dialog-thread-card-recordings>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-recordings-wireframe>`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | `comment.recorders.length > 0`. |

***

### `comment-dialog-thread-card-seen-dropdown`

"Seen by" dropdown showing which users have viewed the comment.

* **Public element:** `<velt-comment-dialog-thread-card-seen-dropdown>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-seen-dropdown-wireframe>`
* **Children:** `*-trigger`, `*-content`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | `seenByUsers === true` and `commentIndex === 0`. |

***

### `comment-dialog-thread-card-attachments`

Attachments (images and other files) attached to a comment.

* **Public element:** `<velt-comment-dialog-thread-card-attachments>`
* **Wireframe tag:** `<velt-comment-dialog-thread-card-attachments-wireframe>`
* **Children:** `*-image`, `*-other`

| Property | Value |
| - | - |
| Extra variables | Inherits `commentObj`, `comment`, `commentIndex` from thread-card. |
| `shouldShow` | `comment.attachments.length > 0`. |

***

### `comment-dialog-status-dropdown`

The annotation status dropdown in the header.

* **Public element:** `<velt-comment-dialog-status-dropdown>`
* **Wireframe tag:** `<velt-comment-dialog-status-dropdown-wireframe>`
* **Children:** `*-trigger`, `*-content`

Per-iteration context inside content items:

| Variable | Type | Example |
| - | - | - |
| `statusObj` | [`CustomStatus`](https://velt.dev/docs/api-reference/sdk/models/data-models#customstatus) | `<velt-data field="statusObj.name" />` |

| Property | Value |
| - | - |
| `shouldShow` | `enableStatus === true`. |
| Host class | `velt-status-dropdown` |

***

### `comment-dialog-priority-dropdown`

The annotation priority dropdown in the header.

* **Public element:** `<velt-comment-dialog-priority-dropdown>`
* **Wireframe tag:** `<velt-comment-dialog-priority-dropdown-wireframe>`
* **Children:** `*-trigger`, `*-content`

Per-iteration context inside content items:

| Variable | Type | Example |
| - | - | - |
| `priorityObj` | [`CustomPriority`](https://velt.dev/docs/api-reference/sdk/models/data-models#custompriority) | `<velt-data field="priorityObj.name" />` |

| Property | Value |
| - | - |
| `shouldShow` | `enablePriority === true`. |
| Host class | `velt-priority-dropdown` |

***

### `comment-dialog-custom-annotation-dropdown`

The custom-chip dropdown in the header.

* **Public element:** `<velt-comment-dialog-custom-annotation-dropdown>`
* **Wireframe tag:** `<velt-comment-dialog-custom-annotation-dropdown-wireframe>`
* **Children:** `*-trigger`, `*-content`

Per-iteration context inside content items:

| Variable | Type | Example |
| - | - | - |
| `item` | [`CustomAnnotationDropdownItem`](https://velt.dev/docs/api-reference/sdk/models/data-models#customannotationdropdownitem) | `<velt-data field="item.label" />` |

| Property | Value |
| - | - |
| `shouldShow` | `customChipData` is set. |

***

### `comment-dialog-options-dropdown`

The per-comment "..." options dropdown. Contains assign, delete, edit, make-private, mark-as-read, and notification items.

* **Public element:** `<velt-comment-dialog-options-dropdown>`
* **Wireframe tag:** `<velt-comment-dialog-options-dropdown-wireframe>`
* **Children:** `*-trigger`, `*-content`

| Property | Value |
| - | - |
| Extra variables | None beyond common variables. |
| `shouldShow` | Dialog is selected and the current comment's options should be visible. |

***

### `comment-dialog-resolve-button`

The "Resolve" button. Sets the annotation status to a resolving status.

* **Public element:** `<velt-comment-dialog-resolve-button>`
* **Wireframe tag:** `<velt-comment-dialog-resolve-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `canResolveAnnotation === true` and annotation has no `assignedTo` and (`!resolveStatusAccessAdminOnly` or user is author or user is admin). |

***

### `comment-dialog-unresolve-button`

The "Reopen" / unresolve button.

* **Public element:** `<velt-comment-dialog-unresolve-button>`
* **Wireframe tag:** `<velt-comment-dialog-unresolve-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `canUnresolveAnnotation === true` and annotation has no `assignedTo`. |

***

### `comment-dialog-private-button`

The "Make private" button.

* **Public element:** `<velt-comment-dialog-private-button>`
* **Wireframe tag:** `<velt-comment-dialog-private-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `enablePrivateMode === true`. |

***

### `comment-dialog-delete-button`

The "Delete" button. Click triggers thread deletion.

* **Public element:** `<velt-comment-dialog-delete-button>`
* **Wireframe tag:** `<velt-comment-dialog-delete-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `annotation.from.userId === user.userId` (only the original author can delete). |

***

### `comment-dialog-approve`

Moderator-mode "Approve" button shown only when an admin is reviewing a not-yet-approved comment.

* **Public element:** `<velt-comment-dialog-approve>`
* **Wireframe tag:** `<velt-comment-dialog-approve-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | Dialog is selected, annotation has comments, `moderatorMode === true`, annotation is not approved, and `isUserAdmin === true`. |

***

### `comment-dialog-assignee-banner`

A horizontal banner shown above the dialog when the annotation has been assigned to a user.

* **Public element:** `<velt-comment-dialog-assignee-banner>`
* **Wireframe tag:** `<velt-comment-dialog-assignee-banner-wireframe>`
* **Children:** `*-resolve-button`, `*-unresolve-button`, `*-user-avatar`, `*-user-name`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `!inlineCommentMode` and `annotation.assignedTo` is set. |
| Host class | `velt-assignee-banner--heading` |

***

### `comment-dialog-private-banner`

Banner shown above the dialog when the comment thread is in private mode.

* **Public element:** `<velt-comment-dialog-private-banner>`
* **Wireframe tag:** `<velt-comment-dialog-private-banner-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `isPrivateComment === true` **and** `annotation.comments.length > 0`. |
| Host class | `velt-private-comment--heading` |

> [!NOTE]
>
> When `featureState.visibilityOptions === true`, this legacy primitive auto-suppresses — the new visibility-options dropdown owns the privacy indicator. The `isPrivateComment` value also now correctly reflects `visibilityConfig.type === 'restricted' | 'organizationPrivate'` in addition to the legacy `iam.accessMode === 'private'`.

***

### `comment-dialog-ghost-banner`

Banner shown when the annotation has lost its DOM target.

* **Public element:** `<velt-comment-dialog-ghost-banner>`
* **Wireframe tag:** `<velt-comment-dialog-ghost-banner-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `showGhostCommentMessage === true` **and** `!inlineCommentMode` **and** `annotation.comments.length > 0`. |
| Host class | `velt-ghost-banner` |

***

### `comment-dialog-visibility-banner`

The "Public / Private / Selected people" banner shown above the dialog when visibility-options are enabled.

* **Public element:** `<velt-comment-dialog-visibility-banner>`
* **Wireframe tag:** `<velt-comment-dialog-visibility-banner-wireframe>`
* **Children:** `*-dropdown`, `*-icon`, `*-text`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `visibilityOptions === true` **and** private comments feature is enabled. |
| Host class | `velt-visibility-banner` |

***

### `comment-dialog-metadata`

Renders an `annotation.metadata.metadataTemplate` strip above the comment list.

* **Public element:** `<velt-comment-dialog-metadata>`
* **Wireframe tag:** `<velt-comment-dialog-metadata-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `annotation.metadata.metadataTemplate.length > 0` **and** `annotation.comments.length > 0`. |
| Host class | `velt-comment-dialog--metadata-container` |

***

### `comment-dialog-comment-category`

Category chip(s) shown when auto-categorization is enabled.

* **Public element:** `<velt-comment-dialog-comment-category>`
* **Wireframe tag:** `<velt-comment-dialog-comment-category-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `enableAutoCategorize === true` **and** `annotation.commentCategories.length > 0`. |
| Host class | `velt-comment-category` |

***

### `comment-dialog-comment-index`

Numeric index label — the "1 of N" indicator (sidebar mode).

* **Public element:** `<velt-comment-dialog-comment-index>`
* **Wireframe tag:** `<velt-comment-dialog-comment-index-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `annotation.annotationIndex` is set. |
| Host class | `velt-comment-index` |

***

### `comment-dialog-comment-number`

The annotation's `annotationNumber` (the human-friendly "Comment #42" identifier).

* **Public element:** `<velt-comment-dialog-comment-number>`
* **Wireframe tag:** `<velt-comment-dialog-comment-number-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `annotation.annotationNumber` is set. |
| Host class | `velt-comment-number` |

***

### `comment-dialog-comment-suggestion-status`

The "Accepted" / "Rejected" badge shown in suggestion mode.

* **Public element:** `<velt-comment-dialog-comment-suggestion-status>`
* **Wireframe tag:** `<velt-comment-dialog-comment-suggestion-status-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `suggestionMode === true` and the annotation's status id matches the configured accepted or rejected status. |
| Host class | `velt-comment-suggestion-status` |

***

### `comment-dialog-reply-avatars`

The collapsed-state strip showing avatars of users who have replied.

* **Public element:** `<velt-comment-dialog-reply-avatars>`
* **Wireframe tag:** `<velt-comment-dialog-reply-avatars-wireframe>`
* **Children:** `*-list`, `*-remaining-count`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `repliesUniqueUsers.length > 0`. |
| Host class | `velt-comment-dialog-reply-avatars` |

***

### `comment-dialog-toggle-reply`

The "View replies (N)" / "Hide replies" toggle below a collapsed thread.

* **Public element:** `<velt-comment-dialog-toggle-reply>`
* **Wireframe tag:** `<velt-comment-dialog-toggle-reply-wireframe>`
* **Children:** `*-count`, `*-icon`, `*-text`

| Property | Value |
| - | - |
| Extra variables | `collapsedRepliesPreview` (`boolean`, `Shared`, default `false`). |
| `shouldShow` | `!isDialogSelected` **and** `!collapsedRepliesPreview` **and** `annotation.comments.length > 0`. |
| Host class | `velt-toggle-reply` |

***

### `comment-dialog-hide-reply`

The "Hide replies" link shown when the dialog is expanded.

* **Public element:** `<velt-comment-dialog-hide-reply>`
* **Wireframe tag:** `<velt-comment-dialog-hide-reply-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `!collapsedComments` **and** `isDialogSelected` **and** `annotation.comments.length > 1`. |
| Host class | `velt-comment-dialog-hide-reply-container` |

***

### `comment-dialog-more-reply`

The "Show N replies…" expander row between the first comment and the rest. The label is composed as `Show` + `Count` + `Text`.

* **Public element:** `<velt-comment-dialog-more-reply>`
* **Wireframe tag:** `<velt-comment-dialog-more-reply-wireframe>`
* **Children:** `*-count` (`<velt-comment-dialog-more-reply-count-wireframe>`), `*-text` (`<velt-comment-dialog-more-reply-text-wireframe>`)

| Property | Value |
| - | - |
| Extra variables | `collapsedRepliesPreview` (`boolean`, `Shared`, default `false`). |
| `shouldShow` | (`isDialogSelected` **or** `collapsedRepliesPreview`) **and** `!showAllComments` **and** `annotation.comments.length > 2`. |
| Host class | `velt-hidden-count` |

The `count` child renders the number of hidden replies (`annotation.comments.length - 2`, clamped to ≥ 0); the `text` child renders the pluralized noun (`reply` when exactly one reply is hidden, otherwise `replies`).

***

### `comment-dialog-navigation-button`

Sidebar-mode pin-navigation button that scrolls to the related annotation in the document.

* **Public element:** `<velt-comment-dialog-navigation-button>`
* **Wireframe tag:** `<velt-comment-dialog-navigation-button-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `!annotation.isPageAnnotation`. |

***

### `comment-dialog-all-comment`

The "View all comments" footer button that opens the comments sidebar.

* **Public element:** `<velt-comment-dialog-all-comment>`
* **Wireframe tag:** `<velt-comment-dialog-all-comment-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `isDialogSelected` **and** `annotation.comments.length > 0` **and** `dialogMode === true` **and** `sidebarButtonOnCommentDialogVisible === true`. |

***

### `comment-dialog-copy-link`

The "Copy link" button — copies a deep-link to this annotation to the clipboard.

* **Public element:** `<velt-comment-dialog-copy-link>`
* **Wireframe tag:** `<velt-comment-dialog-copy-link-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |

***

### `comment-dialog-sign-in`

"Sign in" button shown to anonymous users.

* **Public element:** `<velt-comment-dialog-sign-in>`
* **Wireframe tag:** `<velt-comment-dialog-sign-in-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `isDialogSelected` **and** `annotation.comments.length > 0` **and** user is anonymous **and** `enableSignInButton === true`. |

***

### `comment-dialog-upgrade`

"Upgrade" button shown when the workspace plan has expired.

* **Public element:** `<velt-comment-dialog-upgrade>`
* **Wireframe tag:** `<velt-comment-dialog-upgrade-wireframe>`

| Property | Value |
| - | - |
| Extra variables | None. |
| `shouldShow` | `isDialogSelected` **and** `annotation.comments.length > 0` **and** `isPlanExpired === true` **and** `enableUpgradeButton === true`. |

***

## Deeply-Nested Wireframe Tags

The primitives below decompose further into per-element wireframe tags. Each tag is registered separately and inherits the relevant parent's context variables.

### Composer attachments tags

The composer-attachments primitive renders three sub-trees: **selected** (valid pending uploads — image vs. other file), **invalid** (rejected files), and **other** non-image files.

| Tag | Notes | Example |
| - | - | - |
| `<velt-comment-dialog-composer-attachments-selected-wireframe>` | Valid-files row container. | `<velt-data field="selectedFiles.length" />` |
| `<velt-comment-dialog-composer-attachments-invalid-wireframe>` | Invalid-files row container. | `velt-if="{invalidSelectedFiles.length} > 0"` |
| `<velt-comment-dialog-composer-attachments-invalid-item-wireframe>` | A single invalid-file row. | `<velt-data field="invalidFile.errorMessage" />` |
| `<velt-comment-dialog-composer-attachments-invalid-item-message-wireframe>` | Error-message text. | `<velt-data field="invalidFile.errorMessage" />` |
| `<velt-comment-dialog-composer-attachments-invalid-item-preview-wireframe>` | Thumbnail preview of the rejected file. | (per-iteration) |
| `<velt-comment-dialog-composer-attachments-invalid-item-delete-wireframe>` | Delete (×) button. | (click handler) |
| `<velt-comment-dialog-composer-attachments-image-wireframe>` | Image-attachment row. | `<velt-data field="file.url" />` |
| `<velt-comment-dialog-composer-attachments-image-preview-wireframe>` | Image preview thumbnail. | `<velt-data field="file.url" />` |
| `<velt-comment-dialog-composer-attachments-image-loading-wireframe>` | Loading-state shimmer. | `velt-class="'is-uploading': {file.uploading}"` |
| `<velt-comment-dialog-composer-attachments-image-download-wireframe>` | Download button. | (click handler) |
| `<velt-comment-dialog-composer-attachments-image-delete-wireframe>` | Delete (×) button. | (click handler) |
| `<velt-comment-dialog-composer-attachments-other-wireframe>` | Non-image attachment row. | `<velt-data field="file.file.name" />` |
| `<velt-comment-dialog-composer-attachments-other-icon-wireframe>` | File-type icon. | `velt-class="'icon-{file.fileType}': true"` |
| `<velt-comment-dialog-composer-attachments-other-name-wireframe>` | File name. | `<velt-data field="file.file.name" />` |
| `<velt-comment-dialog-composer-attachments-other-size-wireframe>` | File-size label. | `<velt-data field="file.file.size" />` |
| `<velt-comment-dialog-composer-attachments-other-loading-wireframe>` | Loading shimmer. | `velt-class="'is-uploading': {file.uploading}"` |
| `<velt-comment-dialog-composer-attachments-other-download-wireframe>` | Download button. | (click handler) |
| `<velt-comment-dialog-composer-attachments-other-delete-wireframe>` | Delete button. | (click handler) |

### Status / Priority / Custom-annotation dropdown tags

| Tag | Notes | Example |
| - | - | - |
| `<velt-comment-dialog-status-dropdown-content-item-icon-wireframe>` | Icon inside a status-option row. | `<velt-data field="statusObj.svg" />` |
| `<velt-comment-dialog-status-dropdown-content-item-name-wireframe>` | Name inside a status-option row. | `<velt-data field="statusObj.name" />` |
| `<velt-comment-dialog-priority-dropdown-content-item-icon-wireframe>` | Icon inside a priority-option row. | `<velt-data field="priorityObj.svg" />` |
| `<velt-comment-dialog-priority-dropdown-content-item-name-wireframe>` | Name inside a priority-option row. | `<velt-data field="priorityObj.name" />` |
| `<velt-comment-dialog-priority-dropdown-content-item-tick-wireframe>` | Selected-tick inside a priority-option row. | `velt-class="'is-selected': '{priorityObj.id} === {annotation.priority.id}'"` |
| `<velt-comment-dialog-custom-annotation-dropdown-trigger-list-item-wireframe>` | A single selected-chip pill in the trigger. | `<velt-data field="item.label" />` |
| `<velt-comment-dialog-custom-annotation-dropdown-content-item-icon-wireframe>` | Icon inside a custom-chip option row. | `<velt-data field="item.icon" />` |
| `<velt-comment-dialog-custom-annotation-dropdown-content-item-label-wireframe>` | Label inside a custom-chip option row. | `<velt-data field="item.label" />` |

### Options dropdown content variants

The options-dropdown-content rows have variant-specific tags so customers can override "delete comment" vs "delete thread", "subscribe" vs "unsubscribe", etc.

| Tag | Notes | Example |
| - | - | - |
| `<velt-comment-dialog-options-dropdown-content-delete-comment-wireframe>` | "Delete comment" variant. | `velt-if="{commentIndex} !== 0"` |
| `<velt-comment-dialog-options-dropdown-content-delete-thread-wireframe>` | "Delete entire thread" variant. | `velt-if="{commentIndex} === 0"` |
| `<velt-comment-dialog-options-dropdown-content-make-private-enable-wireframe>` | "Make private" variant. | `velt-if="!{isPrivateComment}"` |
| `<velt-comment-dialog-options-dropdown-content-make-private-disable-wireframe>` | "Make public" variant. | `velt-if="{isPrivateComment}"` |
| `<velt-comment-dialog-options-dropdown-content-mark-as-read-mark-read-wireframe>` | "Mark as read" variant. | `velt-if="{annotation.unread}"` |
| `<velt-comment-dialog-options-dropdown-content-mark-as-read-mark-unread-wireframe>` | "Mark as unread" variant. | `velt-if="!{annotation.unread}"` |
| `<velt-comment-dialog-options-dropdown-content-notification-subscribe-wireframe>` | "Subscribe" variant. | `velt-if="!{notificationEnabled}"` |
| `<velt-comment-dialog-options-dropdown-content-notification-unsubscribe-wireframe>` | "Unsubscribe" variant. | `velt-if="{notificationEnabled}"` |

### Thread-card / seen-dropdown / reply-avatars tags

| Tag | Notes | Example |
| - | - | - |
| `<velt-comment-dialog-thread-card-message-show-more-wireframe>` | "Show more" link on a truncated message. | `velt-if="{isTruncated} && !{isExpanded}"` |
| `<velt-comment-dialog-thread-card-message-show-less-wireframe>` | "Show less" link on an expanded message. | `velt-if="{isExpanded}"` |
| `<velt-comment-dialog-thread-card-seen-dropdown-content-item-avatar-wireframe>` | Per-viewer avatar inside the seen-dropdown items. | `<velt-data field="user.photoUrl" />` |
| `<velt-comment-dialog-thread-card-seen-dropdown-content-item-name-wireframe>` | Per-viewer name. | `<velt-data field="user.name" />` |
| `<velt-comment-dialog-thread-card-seen-dropdown-content-item-time-wireframe>` | Per-viewer viewed-at timestamp. | `<velt-data field="viewedAt" />` |
| `<velt-comment-dialog-reply-avatars-list-item-wireframe>` | Single reply-avatars list item. | `<velt-data field="user.photoUrl" />` |

### Visibility banner tags

The visibility banner's dropdown decomposes into trigger (icon + label + selected-avatar list) + content (per-option rows).

| Tag | Notes | Example |
| - | - | - |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-wireframe>` | Trigger pill of the visibility-banner dropdown. | `velt-class="'mode-{selectedVisibility}': true"` |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-icon-wireframe>` | Icon inside the trigger. | `velt-class="'visibility-{selectedVisibility}': true"` |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-label-wireframe>` | Label inside the trigger. | `<velt-data field="selectedVisibility" />` |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-avatar-list-wireframe>` | Selected-people avatar list inside the trigger. | `<velt-data field="selectedVisibilityUsers.length" />` |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-avatar-list-item-wireframe>` | Per-user avatar inside the trigger list. | `<velt-data field="user.photoUrl" />` |
| `<velt-comment-dialog-visibility-banner-dropdown-trigger-avatar-list-remaining-count-wireframe>` | "+N" badge on the trigger list. | `<velt-data field="remainingCount" />` |
| `<velt-comment-dialog-visibility-banner-dropdown-content-wireframe>` | Open menu wrapper. | (visibility-options list) |
| `<velt-comment-dialog-visibility-banner-dropdown-content-item-wireframe>` | Per-option row. | `velt-class="'selected': '{option.value} === {selectedVisibility}'"` |
| `<velt-comment-dialog-visibility-banner-dropdown-content-item-icon-wireframe>` | Per-option icon. | `<velt-data field="option.icon" />` |
| `<velt-comment-dialog-visibility-banner-dropdown-content-item-label-wireframe>` | Per-option label. | `<velt-data field="option.label" />` |

## Related

* [Comment Dialog Wireframes](https://velt.dev/docs/ui-customization/features/async/comments/comment-dialog/wireframes.md) — composition reference for the wireframe tags themselves.
* [Comment Dialog Primitives](https://velt.dev/docs/ui-customization/features/async/comments/comment-dialog/primitives.md) — granular components if you don't need a full wireframe.
* [Template Variables](https://velt.dev/docs/ui-customization/template-variables.md) — overview of the `velt-data` / `velt-if` / `velt-class` system.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.