Presentational comment leaf with host-owned author, timestamp, body, decision marker, and edit/delete events.
Install @wyrd-company/react or the Flutter package and use it directly —
your DESIGN.md does the styling.
catalog/contracts/comment.ymlsource of truth · verbatim
$schema: https://thewyrdingway.dev/schemas/component-contract.schema.ymlcontractVersion: 0.1.0identity:name: Commenttag: wyrd-commentpackage: wyrd.component.commenttitle: Commentsummary: Presentational comment leaf with host-owned author, timestamp, body, decision marker, and edit/delete events.relationships:related-to: - quality-parity-and-gatesclassification:category: collaborationcomposition: leafinteractive: truetarget-strategy:react: requiredflutter: requiredsurface:properties: - name: comment-idtype:kind: stringrequired: trueserializable: truesummary: Opaque host-supplied comment identifier. - name: author-idtype:kind: stringrequired: trueserializable: truesummary: Opaque host-supplied author identifier with no authentication semantics. - name: author-nametype:kind: stringrequired: trueserializable: truesummary: Host-supplied display name for the author. - name: timestamptype:kind: stringrequired: trueserializable: truesummary: Host-supplied ISO timestamp or already-portable timestamp string. - name: timestamp-labeltype:kind: stringrequired: falseserializable: truesummary: Optional host-formatted timestamp display string. - name: body-formattype:kind: enumvalues: - plain-textrequired: falsedefault: plain-textserializable: truesummary: Body format discriminator; v1 renders plain text only. - name: bodytype:kind: stringrequired: trueserializable: truesummary: Plain text comment body. - name: decisiontype:kind: enumvalues: - none - approve - request-changes - comment - suggestionrequired: falsedefault: noneserializable: truesummary: Optional review disposition marker. - name: editedtype:kind: booleanrequired: falsedefault: falseserializable: truesummary: Host-supplied edited marker. - name: can-edittype:kind: booleanrequired: falsedefault: falseserializable: truesummary: Shows an edit affordance when true. - name: can-deletetype:kind: booleanrequired: falsedefault: falseserializable: truesummary: Shows a delete affordance when true.slots: []events: - name: editpayload:comment-id:kind: stringbubbles: truecomposed: truecancelable: truesummary: Emitted when the user activates the edit affordance. - name: deletepayload:comment-id:kind: stringbubbles: truecomposed: truecancelable: truesummary: Emitted when the user activates the delete affordance.states: - name: defaultsource: platformsummary: Comment is visible. - name: actionablesource: propertysummary: Edit or delete affordances are visible.parts: - name: rootsummary: Comment article. - name: headersummary: Author, timestamp, edited marker, and decision metadata. - name: authorsummary: Author display name. - name: timestampsummary: Timestamp display. - name: decisionsummary: Optional decision badge. - name: bodysummary: Plain text comment body. - name: actionssummary: Edit/delete action container. - name: editsummary: Edit button. - name: deletesummary: Delete button.tokens:background: color.surfaceforeground: color.on-surfacemuted: color.on-surface-variantborder-color: color.outlineaction-background: color.surface-containerdecision-background: color.secondarydecision-foreground: color.on-secondaryradius: rounded.mdpadding-x: spacing.mdpadding-y: spacing.smgap: spacing.xsmessages: - key: comment.editdescription: Accessible label for the comment edit affordance. - key: comment.deletedescription: Accessible label for the comment delete affordance. - key: comment.editeddescription: Marker text shown when a comment has been edited. - key: comment.decision.approvedescription: Label for an approving decision marker. - key: comment.decision.request-changesdescription: Label for a request-changes decision marker. - key: comment.decision.commentdescription: Label for a neutral comment decision marker. - key: comment.decision.suggestiondescription: Label for a suggestion decision marker.obligations:accessibility:role: articlename: Author name and timestamp identify the comment; the body provides comment content.keyboard: - Tab moves to edit/delete affordances when present. - Enter or Space activates focused edit/delete affordances.semantics: - The comment root exposes article semantics. - Timestamp renders with a dateTime value when the host supplies an ISO timestamp. - Edit/delete affordances are buttons named by component-owned localized messages. - Decision and edited markers render as text so assistive technology receives the same information as sighted users.behavior:model: statelessinteractions: - Comment renders only host-supplied author, timestamp, body, edited marker, and decision marker. - Activating edit emits edit with comment-id. - Activating delete emits delete with comment-id.hostEffects: - Dispatch edit event. - Dispatch delete event. - Hosts own editing, deletion, persistence, identity, and permissions.conditions: - rtl - reduced-motion - cvd-deuteranopia - density-compact - text-expansionsdui:status: serializableserializableProperties: - comment-id - author-id - author-name - timestamp - timestamp-label - body-format - body - decision - edited - can-edit - can-deleteserializableSlots: []eventBindings: - edit - deletenotes: Comment serializes host-owned comment data and edit/delete bindings. Hosts own permission decisions and persistence.examples: - name: defaultstate: defaultproperties:comment-id: comment-1author-id: author-caseyauthor-name: Caseytimestamp: "2026-07-04T16:00:00.000Z"timestamp-label: Today at 4:00 PMbody: Primary action is in the right place.decision: noneslots: {} - name: decisionstate: defaultproperties:comment-id: comment-2author-id: author-rinauthor-name: Rintimestamp: "2026-07-04T16:15:00.000Z"body: Delay copy should identify the affected service window.decision: request-changesedited: trueslots: {} - name: actionablestate: actionableproperties:comment-id: comment-3author-id: author-maraauthor-name: Maratimestamp: "2026-07-04T16:20:00.000Z"body: Locked coordinator field matches this scenario.can-edit: truecan-delete: trueslots: {}overrides:react:properties:comment-id: commentIdauthor-id: authorIdauthor-name: authorNametimestamp-label: timestampLabelbody-format: bodyFormatcan-edit: canEditcan-delete: canDeleteflutter:properties:comment-id: commentIdauthor-id: authorIdauthor-name: authorNametimestamp-label: timestampLabelbody-format: bodyFormatcan-edit: canEditcan-delete: canDelete
01
Examples
Generated from the contract's examples block.
Previews are the published @wyrd-company/react component, themed by the
brand's role tokens — flip the site's light/dark toggle and they follow.
defaultstate: default
Usage
import { WyrdComment } from"@wyrd-company/react";
<WyrdComment commentId="comment-1" authorId="author-casey" authorName="Casey" timestamp="2026-07-04T16:00:00.000Z" timestampLabel="Today at 4:00 PM" body="Primary action is in the right place." decision="none" />
// events: onEdit, onDelete
import'package:wyrd_flutter/wyrd_flutter.dart';
WyrdComment(
commentId: 'comment-1',
authorId: 'author-casey',
authorName: 'Casey',
timestamp: '2026-07-04T16:00:00.000Z',
timestampLabel: 'Today at 4:00 PM',
body: 'Primary action is in the right place.',
decision: 'none',
)
// events: onEdit, onDelete
decisionstate: default
Usage
import { WyrdComment } from"@wyrd-company/react";
<WyrdComment commentId="comment-2" authorId="author-rin" authorName="Rin" timestamp="2026-07-04T16:15:00.000Z" body="Delay copy should identify the affected service window." decision="request-changes" edited />
// events: onEdit, onDelete
import'package:wyrd_flutter/wyrd_flutter.dart';
WyrdComment(
commentId: 'comment-2',
authorId: 'author-rin',
authorName: 'Rin',
timestamp: '2026-07-04T16:15:00.000Z',
body: 'Delay copy should identify the affected service window.',
decision: 'request-changes',
edited: true,
)
// events: onEdit, onDelete
Emitted when the user activates the edit affordance.
delete
comment-id
Emitted when the user activates the delete affordance.
04
Tokens
The contract's token bindings. Open the shared contextual sidebar from any example;
primary swatches reflect the color you pick there. Error swatches show the active
preset's values; editing any knob switches to custom and resets error to TWW · Ink.
Binding
Token
background
color.surface
foreground
color.on-surface
muted
color.on-surface-variant
border-color
color.outline
action-background
color.surface-container
decision-background
color.secondary
decision-foreground
color.on-secondary
radius
rounded.md
padding-x
spacing.md
padding-y
spacing.sm
gap
spacing.xs
05
States
State
Source
Summary
default
platform
Comment is visible.
actionable
property
Edit or delete affordances are visible.
06
Accessibility
From the contract's accessibility obligations. Role article; Author name and timestamp identify the comment; the body provides comment content.
Tab moves to edit/delete affordances when present.
Enter or Space activates focused edit/delete affordances.
The comment root exposes article semantics.
Timestamp renders with a dateTime value when the host supplies an ISO timestamp.
Edit/delete affordances are buttons named by component-owned localized messages.
Decision and edited markers render as text so assistive technology receives the same information as sighted users.