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 の最小例:
[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 自体はスタイルを持ちません。
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
footerAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root: props.role | MessageRole | MessageRole::User | 発言者の役割(user/assistant/system)。data-role へ出力する(message.rs)。 |
root: props.align | MessageAlign | MessageAlign::Start | root の水平整列(start/end)。data-role から独立した軸。data-align へ出力する(message.rs)。 |
root: props.loading | bool | false | true のとき data-loading 存在属性を付与する(応答待ちの表示のみ、message.rs)。 |
root: props.error | bool | false | true のとき data-error 存在属性を付与する(送信失敗の表示のみ、message.rs)。 |
group: label | &str | "" | 空でなければ aria-label へ出力する(message.rs)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
root | data-align | end, start |
root | data-error | (値なし) |
root | data-loading | (値なし) |
root | data-role | assistant, system, user |
Examples
Basic user/assistant pair
user(右寄せ)と assistant(左寄せ)の 1 往復を group でまとめる基本例です。
Consecutive messages in one group
同じ発言者(assistant)の連続発言を 1 つの group へまとめる例です。
自前 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 を満たします。
[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
| Key | Description |
|---|---|
| (なし) | root/avatar/header/content/footer/group はいずれもキー操作を提供しない静的コンテナである(message.rs。子要素として置くインタラクティブ要素のキー操作はその要素自体に委ねる)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| role="listitem" | root パーツに固定付与する(message.rs「role="listitem"/role="list"」節)。 |
| role="list" / aria-label | group パーツに固定付与する。label が空でなければ aria-label を出力する(message.rs)。 |
| (aria-live / aria-busy は付与しない) | ストリーミング通知・応答待ちの読み上げはアプリ責務のため本モジュールは付与しない(message.rs「aria-live/aria-busy を付けない理由」節)。 |