<!-- GENERATED by scripts/build-llms.mjs from llms/conversation.md — do not edit this file. -->

# `lr-message-feedback`

- **Import** `import '@aceshooting/lyra-ui/components/lr-message-feedback.js';` (stable tag alias; registers the tag)
- **Class** `LyraMessageFeedback`, also available unregistered from `@aceshooting/lyra-ui/components/conversation/message-feedback/message-feedback.class.js`
- **Family** `components/conversation/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
- **Deprecations** none
- **Optional peers** none
- **Themeable via** 8 parts, 6 custom properties — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-message-feedback`

Thumbs up/down for one assistant message, with an optional inline detail step (categorical reason
chips + a free-text comment) that opens as a disclosure directly below the thumbs. Emits; never
persists — a host reflects a previously-recorded rating back via `rating` (+ `disabled` for a
read-only display). Activating the pressed thumb while its detail panel is open toggles it off to
`null`. If an applicable panel was closed without changing the rating (for example with Escape),
activating the still-pressed thumb reopens it with the surviving draft. A thumbs-only control always
uses the ordinary re-activate-to-clear toggle.

Asynchronous finalization or reversion preserves focus on an outside control. Settlement retains the
existing thumb/submit fallback when focus remains within the feedback or was lost as its pending
controls became disabled.

**Properties:** `rating: MessageFeedbackValue = null` (`'up' | 'down' | null`, reflected),
`detail?: MessageFeedbackDetailConfiguration` (attribute: false) — one configuration with optional
`reasons?: readonly { id, label }[]` and `commentable?: boolean`; omit it for thumbs-only feedback.
The record and nested reasons are a bounded clone-owned frozen snapshot; malformed, empty, blank,
and later duplicate reason ids are omitted first-wins before selection and submission. Create and
reassign a new detail record after changes.
`detailFor: 'none' | 'up' | 'down' | 'both' = 'down'` (attribute `detail-for`) selects which rating
owns that one detail panel. `disabled: boolean = false` (reflected) makes a recorded rating read-only, and
`pending: boolean = false` (reflected) — set automatically when a submit listener prevents the
submission while host persistence is unresolved; all feedback controls are disabled and the panel
reports busy until that state is resolved.

When the optional comment textarea renders, `spellcheck: boolean = true`,
`autocapitalize: string = ''`, `autocorrect: boolean = true`, and
`wrap: MessageFeedbackWrap = 'soft'` forward to it; they have no effect without that textarea.
`MessageFeedbackWrap` is `'soft' | 'hard' | 'off'`, the native textarea wrap vocabulary.

**Methods:** `focus()` focuses the thumb matching the current `rating` (the up thumb when `null`);
`blur()` blurs both thumbs; `click()` activates that same thumb when enabled.
`getToolbarActions()` returns the ordered logical thumb actions used by an enclosing toolbar.
`finalizePendingSubmit(submissionId?: string): boolean` completes a prevented submit after persistence succeeds, closing the
panel, announcing success, and returning focus to the active thumb.
`revertPendingSubmit(submissionId?: string): boolean` releases
the pending state after failure without clearing the draft or announcing success, restoring the
prior rating and panel state. A detail-panel submit remains open for retry, while a thumbs-only
submit remains panel-free; it likewise accepts an optional `submissionId` and returns `boolean`. The event
supplies a nonblank, never-reused id; a later/current settlement must use that exact id. Legacy
no-argument settlement remains available only for the first transaction that has never been
invalidated; stale or mismatched settlements return `false`.

**Events:** `lr-feedback-change` — `detail: { rating: 'up' | 'down' | null }`, fired when a thumb's
provisional rating changes or clears. `lr-feedback-submit` — cancelable
`detail: { rating: 'up' | 'down' | null; reasonIds: string[]; comment: string; submissionId: string }`, fired for every
terminal thumbs-only choice/clear and by the detail panel's submit button. The pending transaction
is installed before dispatch, so even a synchronous listener may finalize/revert it safely. The
event detail is frozen.
`preventDefault()` holds the panel/control in `pending` and delays
success announcement/focus until `finalizePendingSubmit(detail.submissionId)`; call
`revertPendingSubmit(detail.submissionId)` on failure. The no-argument form is only the documented
legacy first-transaction path.
When uncanceled it retains the synchronous close/announce/focus behavior. The optional comment
`<textarea>`'s native `focus` and `blur` are re-dispatched as bubbling, composed host events.
`lr-toolbar-actions-change` is the no-detail coordination event emitted when the provider's logical
toolbar actions change availability or order.

**CSS parts:** `base` (the root), `thumbs` (wrapper around both thumb buttons), `up-button`,
`down-button`, `panel` (the inline detail disclosure, only rendered when `reasons` is non-empty or
`commentable` is set), `reasons` (the reason-chip group), `comment` (the comment `<textarea>`), and
`submit-button`.

**Themeable custom properties:** six pressed-state hooks, three per thumb —
`--lr-message-feedback-up-active-color` (default `var(--lr-color-success)`),
`--lr-message-feedback-up-active-bg` (default `var(--lr-color-success-quiet)`),
`--lr-message-feedback-up-active-border` (default `var(--lr-color-success)`), and the thumbs-down
trio `--lr-message-feedback-down-active-color`, `--lr-message-feedback-down-active-bg`,
`--lr-message-feedback-down-active-border` (defaulting to `var(--lr-color-danger)`,
`var(--lr-color-danger-quiet)`, `var(--lr-color-danger)`). Each styles the glyph, background, and
border of its thumb only while that thumb is pressed. All six are declared as inline `var()`
fallbacks at the point of use and never on `:host`, so each can be set on the element _or on any
ancestor_ — a whole transcript's feedback controls retint from one declaration. That shape is
required because `::part(up-button)[aria-pressed='true']` is invalid CSS (Shadow Parts forbids an
attribute selector after `::part()`), which previously left overriding the library-wide
`--lr-color-success`/`--lr-color-danger` tokens as the only lever, repainting every other element
reading them. Unset, each falls back to exactly the token its rule used before.
