annotation.context.*), it survives round-trips, and your wireframes can read it. It’s the bridge between your app’s domain (a form question, an invoice line, an email block) and Velt’s comment UI, and it’s how you scope a comment to a specific element on the page.
This is a core customization concept: if your design shows app-specific info in the comment UI (a question title in the dialog header, a “jump to this row” button, a per-element comment), context is how you get that data in.
1. Attach context (two ways)
A. Declarative props (simplest): on VeltCommentTool / VeltCommentBubble
context: your object (any keys). Lands onannotation.context.targetElementId: ties the comment/bubble to a DOM element with thatid(so the bubble renders on that row).contextInPageModeComposer: routes this context into the page-mode composer flow.
context={{ title: step.label, scope: "step", stepId: step.id }}, context={{ device, mode }}, etc.)
B. Imperative (page-mode composer flow): via useCommentUtils()
When a comment tool is clicked, Velt fires a commentToolClick event carrying that tool’s context + targetElementId; push it into the shared page-mode composer, then focus it:
useCommentUtils()): setContextInPageModeComposer({ context, targetElementId }), focusPageModeComposer(), clearPageModeComposerContext(). (Under the hood this is the context argument of addComment(...).)
2. Read context in the wireframe
Context is readable via{…} tokens: display with <VeltData field="…">, branch with <VeltIf condition="…">. The path prefix depends on the surface:
| Where you’re reading it | Path prefix |
|---|---|
| Comment dialog | annotation.context.<key> (also commentAnnotation.context.<key>) |
| Page-mode composer (live, not yet saved) | context.<key> |
| Sidebar focused thread | focusedAnnotation.context.<key> |
| Notification list item | notification.notificationSourceData.context.<key> (or notification.metadata.<key>) |
The customid="navigate-to-question-button"button is wired to app behavior via theveltButtonClickbridge (Patterns and tips): e.g. scroll to the question.
3. What context enables
- Scope a comment to a specific element:
targetElementId+ a matching DOMid(e.g.question-${id}); a<VeltCommentBubble targetElementId=…>then renders that element’s bubble in place. - Show app metadata in the comment UI: question title/number in the header, an invoice line label, an email device/mode badge: straight off
annotation.context.*. - Conditional UI by domain type: branch the wireframe on context, e.g.
velt-class="'is-action': {annotation.context.commentType} === 'action'"orvelt-if="{annotation.context.type} === 'ApproverComment'". - Deep-linking / navigation: a “jump to” button that exists only when a context key is present, handled via
veltButtonClick.
Checklist
- Attach
context(+targetElementIdfor element scoping) on the comment trigger, or viasetContextInPageModeComposerfor the page-mode flow. - Read it with the correct path prefix for the surface (
annotation.context.*in the dialog,context.*in the page-mode composer,focusedAnnotation.context.*in the sidebar). - Gate context-dependent UI with
velt-if="{…context.key}"so it only shows when present. - Clear page-mode context after submit/cancel (
clearPageModeComposerContext()).

