Vanilla Breeze

comment-thread

Persistent threaded-discussion container. Decorates author-rendered

children with header, action row, and threaded indentation. Composes (reply form) and bubbles events naturally.

Overview

<comment-thread> is the container primitive for a persistent, threaded discussion. Authors render comments as <article data-comment> children with metadata attributes; the component decorates each one with an author header, relative timestamp, action toolbar (Reply / Edit / Delete), and threaded indentation via data-parent.

The component is presentational with respect to persistence: action clicks emit events, and authors call addComment / updateComment / removeComment after the server confirms.

When to use which primitive

Use thisWhen
<comment-thread>Threaded, persistent discussion attached to an item. Comments have authors + timestamps + replies + reactions + edit/delete.
<comment-wc>Single inline action button used by <selection-menu> for adding a comment to selected text. Different role — we keep both.
<comment-box>The reply / new-comment form. <comment-thread> consumes it as the reply-form template.
<chat-thread>Real-time chat (sender-grouped, ephemeral). Different interaction model from threaded comments.

Author surface

Render comments as direct <article data-comment> children. Put the rendered body in <div data-comment-body>. Provide a <template data-reply-form> that wraps a <comment-box> — the component clones it under whichever comment is being replied to.

Comment attributes

AttributeDescription
idStable comment id (used in events + parent refs).
data-authorDisplay name.
data-author-hrefOptional link to the author's profile.
data-author-avatarOptional avatar URL (renders <user-avatar>).
data-timeISO-8601 timestamp; rendered as relative ("2 hours ago") with absolute on hover.
data-mineCurrent user authored this — enables Edit / Delete actions and accent styling.
data-parentId of the parent comment for nested replies (drives indent depth).
data-editedOptional ISO timestamp; renders an "(edited)" badge with the absolute time on hover.

Wiring the backend

Hook the events; call back via the imperative API.

Per-comment reactions bubble up as reaction-bar:toggle events — the thread doesn't intercept them. Wire them once at the thread level.

Read-only mode

Set data-disabled on the thread to hide all action toolbars (no Reply / Edit / Delete). Reactions still render but stay clickable unless the inner <reaction-bar> elements also carry data-disabled.

Accessibility

  • Thread: role="region" with the host's aria-label ("Comments" by default).
  • Comments: native <article> role; nested replies get aria-level matching their depth.
  • Action buttons: labelled per target ("Reply to Ada Lovelace", "Edit your comment", "Delete your comment").
  • Times: <time datetime> with the absolute timestamp in title; component refreshes the relative text every 60s.
  • Reply form: focus moves into the editor when shown; Cancel removes the form. (<comment-box> handles its own keyboard.)

Attributes

AttributeTypeDefaultDescription
aria-labelstringCommentsRegion label.
data-disabledbooleanfalseRead-only mode — hides the action toolbar on every comment.

Events

EventBubblesDetail
comment-thread:replyyes{ parentId, value }
comment-thread:edit-requestyes{ commentId, value }
comment-thread:delete-requestyes{ commentId }

Reactions bubble naturally via reaction-bar:toggle from each per-comment <reaction-bar>.

JavaScript API

MethodDescription
addComment(data)Insert a new comment. data: { id, author, time, body, parentId?, mine?, authorHref?, authorAvatar?, edited? }.
updateComment(id, patch)Patch a comment. patch: { body?, author?, edited? }.
removeComment(id)Remove a comment from the thread.

See also

  • <comment-box> — the reply form (composed via the <template data-reply-form>).
  • <comment-wc> — single inline action used by <selection-menu>. Different role; both ship.
  • <reaction-bar> — per-comment emoji reactions.
  • <markdown-viewer> — for rendering the comment body server-side or client-side.