Skip to content
fandhe-frontendcore v0.4.3
GitHub

Message

AI チャット UI の「会話 1 発言」を表現する shadcn/ui Message 相当の部品です(参照軸はイシュー #2001、shadcn/ui 追加はイシュー #2004)。fandhe-frontend-headless-ui の message mod が構造・アクセシビリティ(WAI-ARIA)・表示状態(data-*)のみを提供する unstyled 部品で、root / avatar / header / content / footer / group の 6 anatomy パーツを持ちます。状態機械を持たない静的部品であり、応答待ち・送信失敗の判定や再送、ストリーミング更新はアプリ側の責務です。

root は role(user / assistant / system)・align(start / end)・loading(bool)・error(bool)の props を受け取り、それぞれ data-role / data-align / data-loading / data-error として出力します。data-align は data-role から自動導出されない独立した軸で、既定は start です。data-loading / data-error は存在属性(値が真のときのみ出力)で、応答待ち・送信失敗の表示のみを担います。この 4 語彙は会話系部品(message / bubble / attachment / marker)が共有する共通語彙として message mod が最初に確定したものです。

avatar はスロットで、既存の avatar mod を内部で呼び出しません。呼び出し側が中に avatar::root / avatar::image / avatar::fallback を自由に組み込めます。content も同様にスロットで、Markdown レンダリング結果等の中身は利用者側で用意します。同じ発言者の連続発言は group でまとめられます(先頭以外の avatar を省略する見た目は CSS 側の責務です)。

アクセシビリティ

  • root は role="listitem" を固定付与します。
  • group は role="list" を固定付与します。WAI-ARIA の listitem は list(または同等のコンテナ)を required context として要求するため、会話全体は「発言者ターンごとの group(list)の並び」として読み上げられる想定です。label を渡すと aria-label を出力します(空文字列のときは省略します)。group を介さず root 単体で使う場合は、呼び出し側が ul / role="list" コンテナへ置いてください。
  • aria-live / aria-busy は付与しません。ストリーミング応答の通知や応答待ちの読み上げはアプリケーション固有の UX 判断であり、本部品の責務外です。

fandhe-frontend-pre-styled-ui に対応するスタイル済み部品があります。Themes 版は Message を参照してください。

自前 CSS の最小例:

CSS
[data-scope="message"][data-part="root"] {
  display: flex;
  flex-direction: column;
  max-width: 32rem;
}
[data-scope="message"][data-part="root"][data-align="end"] {
  margin-left: auto;
}
[data-scope="message"][data-part="content"] {
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
}

関連 API: fandhe-frontend-headless-ui API

Demo

枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。

You
You
How do I center a div?
09:41
AI
Thinking...
Failed to send message.

Features

  • AI チャット UI の「会話 1 発言」を表現する 6 anatomy パーツ(root/avatar/header/content/footer/group)を提供する(message.rs)。状態機械を持たない静的部品であり wasm-full 側の配線は不要。
  • 会話系 4 部品(message/bubble/attachment/marker)が共有する data-role(user/assistant/system)・data-align(start/end、data-role から独立した軸)・data-loading/data-error(存在属性)を本モジュールが最初に確定する(message.rs「会話系 4 部品の共通語彙」節)。
  • root は role="listitem" を固定付与し、group は required context を満たす role="list" + 任意 aria-label を固定付与する(message.rs「role="listitem"/role="list"」節)。
  • aria-live/aria-busy は付けない(ストリーミング通知・応答待ちの読み上げはアプリ責務、message.rs「aria-live/aria-busy を付けない理由」節)。参照実体は shadcn/ui の Message のみ(ark-ui・chakra-ui・Radix に対応部品なし、docs/design/component-coverage-map.md §12.1、参照軸 #2001)。

Anatomy

group
  root
    avatar
    header
    content
    footer

API Reference

Arguments

NameTypeDefaultDescription
root: props.roleMessageRoleMessageRole::User発言者の役割(user/assistant/system)。data-role へ出力する(message.rs)。
root: props.alignMessageAlignMessageAlign::Startroot の水平整列(start/end)。data-role から独立した軸。data-align へ出力する(message.rs)。
root: props.loadingboolfalsetrue のとき data-loading 存在属性を付与する(応答待ちの表示のみ、message.rs)。
root: props.errorboolfalsetrue のとき data-error 存在属性を付与する(送信失敗の表示のみ、message.rs)。
group: label&str""空でなければ aria-label へ出力する(message.rs)。

Data Attributes

PartAttributeObserved Values
rootdata-alignend, start
rootdata-error(値なし)
rootdata-loading(値なし)
rootdata-roleassistant, system, user

Examples

Basic user/assistant pair

user(右寄せ)と assistant(左寄せ)の 1 往復を group でまとめる基本例です。

How do I center a div?
Use display: flex + place-items: center.

Consecutive messages in one group

同じ発言者(assistant)の連続発言を 1 つの group へまとめる例です。

First, install the crate.
Then call render().

自前 CSS の最小例

data-scope/data-part/data-role/data-align 属性セレクタでスタイルを当てる例です。

data-scope / data-part / data-role / data-align 属性セレクタで吹き出しの位置・余白を当てる最小例です。headless-ui 自体はスタイルを持ちません。root(role="listitem")は message::group(role="list")でラップし required context を満たします。

Styled with plain CSS.
CSS
[data-scope="message"][data-part="root"] {
  display: flex;
  flex-direction: column;
  max-width: 32rem;
}
[data-scope="message"][data-part="root"][data-align="end"] {
  margin-left: auto;
}
[data-scope="message"][data-part="content"] {
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
}

Accessibility

Keyboard Interactions

KeyDescription
(なし)root/avatar/header/content/footer/group はいずれもキー操作を提供しない静的コンテナである(message.rs。子要素として置くインタラクティブ要素のキー操作はその要素自体に委ねる)。

WAI-ARIA

AttributeDescription
role="listitem"root パーツに固定付与する(message.rs「role="listitem"/role="list"」節)。
role="list" / aria-labelgroup パーツに固定付与する。label が空でなければ aria-label を出力する(message.rs)。
(aria-live / aria-busy は付与しない)ストリーミング通知・応答待ちの読み上げはアプリ責務のため本モジュールは付与しない(message.rs「aria-live/aria-busy を付けない理由」節)。