A2UIのコンポーネントとレンダリング規則
基本カタログの各コンポーネントのレンダリング方法に加え、バインディング、検証、テンプレート、テーマ設定、カタログの拡張方法を説明します。
@language-lit/material3-expressive-a2uiはA2UI v0.9.1 basic catalog全体を実装しています。カタログの各コンポーネントはMaterial 3 Expressiveのコンポーネントとしてレンダリングされます。また、すべての色、タイプスタイル、角、モーションの値はデザインシステムのトークンに解決されるため、サーフェスはライトモードとダークモードでテーマに従います。
最初にセットアップガイドでパッケージをインストールし、両方のスタイルシートを読み込んで、サーフェスをレンダリングしてください。
どのようにレンダリングされるか
| A2UIコンポーネント | Material 3 Expressive | 備考 |
|---|---|---|
Text | Text | h1からh5はheadlineとtitleのロールに対応し、captionは小さく控えめに、bodyは読みやすいサイズで表示します。Markdownの対応範囲は、太字、斜体、コード、リンク、見出し、リストです。 |
Image | バリアントに応じたサイズの画像 | icon、avatar(円形)、smallFeature、mediumFeature、largeFeature、header(全幅)に対応します。fitはobject-fitに対応します。 |
Icon | Icon | カタログ名はフォントなしで埋め込みグリフとして表示されます。svgPathはインラインで表示されます。 |
Video | ネイティブの動画プレーヤー | コントロールを有効にします。 |
AudioPlayer | ネイティブの音声プレーヤー | コントロールを有効にします。 |
Row | Flex行 | justify、align、子要素のweightを使います。 |
Column | Flex列 | justify、align、子要素のweightを使います。 |
List | リスト | 縦向きまたは横向きです。 |
Card | アウトライン付きCard | 受動的なコンテナーです。 |
Tabs | Tabs | 項目ごとにタブを1つ表示し、キーボードで操作できます。 |
Modal | Dialog | トリガーでダイアログを開き、トリガー自身のアクションも送信します。 |
Divider | Divider | 水平または垂直です。 |
Button | Button | primaryはfilled、defaultはtonal、borderlessはtextです。checksが失敗すると無効になります。 |
TextField | TextFieldまたはTextArea | shortText、longText、obscured、numberのバリアントがあります。 |
CheckBox | Checkbox | ラベル付きです。 |
ChoicePicker | Radio、Checkbox、またはフィルター用Chip | mutuallyExclusiveまたはmultipleChoiceに対応し、任意でフィルターフィールドも使えます。 |
Slider | Slider | 小数点以下の精度は範囲に従います。 |
DateTimeInput | DatePicker、TimePicker、またはDateTimePicker | 1.3.0-rc.1のMaterial picker機能を使います。宣言済みの1.2 peer系列でも、ネイティブ入力にフォールバックする互換性機能を通じて読み込み可能です。明示的にタイムゾーンを指定した日時はローカルの暦時刻で表示され、UTCの瞬間として書き戻されます。 |
ストリーミングとプレースホルダー
エージェントは、子要素のデータを送る前にその名前を指定できます。childrenにまだ届いていないIDが含まれるColumnは、それぞれにプレースホルダーを表示し、一致するupdateComponentsメッセージが届くとすぐに置き換えます。デモの最初のシナリオでは、内容が届く前のカードの形を確認できます。
各コンポーネントは自身のモデルを購読するため、あるコンポーネントへの更新で再レンダリングされるのはそのコンポーネントだけです。
データバインディング
プロパティにはリテラル、{ "path": "/some/value" }形式のバインディング、formatCurrencyやformatDateのような関数呼び出しを指定できます。バインディングは、updateDataModelメッセージで更新されるサーフェスのデータモデルを読み取ります。
入力値は同じモデルに書き戻されます。/nameにバインドしたTextFieldは入力に合わせて/nameを更新し、同じパスにバインドしたTextも一緒に更新されます。sendDataModelを指定して作成したサーフェスでは、getClientDataModel()でモデルをエージェントに送信します。
テンプレートを使うと、リストの各項目についてコンポーネントを繰り返し表示できます。
{
"id": "flights",
"component": "Column",
"children": { "path": "/flights", "componentId": "flight-row" }
}flight-rowの内側では、{ "path": "airline" }などの相対パスは各項目を基準に解決されます。後続のupdateDataModelで/flightsに項目を追加すると、行も追加されます。
検証とアクション
checksを使って、入力またはボタンに条件とメッセージを関連付けます。チェックに失敗したフィールドは、ユーザーが操作した後にメッセージを表示します。チェックに失敗したボタンは無効になり、有効なデータの場合だけアクションを送信できます。条件ではrequired、email、regex、and、or、notなど、カタログの関数を使います。
Buttonを押すとaction.eventが送信されます。イベントのcontextにあるすべての{ "path" }は、アクションがonActionコールバックに届く前に解決されます。エージェントに送信するアクションオブジェクトは次のとおりです。
| フィールド | 意味 |
|---|---|
name | ボタンのイベント名です。 |
surfaceId | ボタンが属するサーフェスです。 |
sourceComponentId | ボタンのコンポーネントIDです。 |
timestamp | ユーザーが押した時刻を示すISO 8601文字列です。 |
context | 解決済みのコンテキストオブジェクトです。 |
テーマと表示元の明示
サーフェスは、最も近いMaterial3Providerのテーマを継承します。ライト、ダーク、システムのカラーモード、カスタムのソースカラー、ネストしたテーマスコープは、設定なしで適用されます。
createSurfaceのthemeフィールドにはagentDisplayName、iconUrl、primaryColorを指定できます。どちらかが設定されている場合、A2uiSurfaceはサーフェスの内容の上に名前とアイコンを表示します。非表示にするにはattribution={false}を渡します。primaryColorはサーフェス要素の--m3e-a2ui-agent-colorカスタムプロパティとして公開され、表示元の明示に使われます。エージェントが選んだ色はMaterialテーマではないため、サーフェスのテーマ全体は変更しません。
インスタンスごとのスタイルを変更するには、所有する祖先要素にデザインシステムの公開コンポーネントエイリアスを設定します。非公開の.m3e-クラス名を対象にしないでください。
カタログを拡張する
createMaterial3ComponentとcreateMaterial3Catalogを使うと、独自のコンポーネントを追加したり既存のコンポーネントを置き換えたりできます。実装は解決済みのpropsとbuildChild関数を受け取る表示専用コンポーネントです。
import { Text } from '@language-lit/material3-expressive'
import { TextApi } from '@a2ui/web_core/v0_9/basic_catalog'
import {
createMaterial3Catalog,
createMaterial3Component,
useA2ui,
} from '@language-lit/material3-expressive-a2ui'
const ShoutingText = createMaterial3Component(TextApi, ({ props }) => (
<Text as="p" variant="bodyLarge">{String(props.text).toUpperCase()}</Text>
))
const catalog = createMaterial3Catalog({
components: [ShoutingText],
locale: 'pt-BR',
})
// Inside a component:
const a2ui = useA2ui({ catalogs: [catalog] })後から登録した同名の項目が優先されるため、1つの上書きでデフォルト実装を置き換えられます。localeはformatCurrency、formatDateなどの書式関数にロケールを設定します。独自のカタログIDで公開する場合はidを、関数セットを置き換える場合はfunctionsを渡してください。
GoogleのReactサーフェスでカタログを使う
material3Catalogは@a2ui/web_coreのカタログで、Googleの@a2ui/reactサーフェスが利用する表示専用の形式で実装されています。すでにそのサーフェスで表示しているホストは、Materialカタログを登録したうえで、独自のサーフェス、トランスポート、フォールバック方針を維持できます。この場合に必要なのは、このパッケージのスタイルシートだけです。
import { A2uiSurface } from '@a2ui/react/v0_9'
import { MessageProcessor } from '@a2ui/web_core/v0_9'
import { material3Catalog } from '@language-lit/material3-expressive-a2ui'
const processor = new MessageProcessor([material3Catalog], onAction)
// processor.processMessages(messages)
// <A2uiSurface surface={processor.model.surfacesMap.get(surfaceId)!} />連携パッケージのテストスイートでは、@a2ui/react 0.11.0上でカタログをレンダリングしています。このパッケージは連携パッケージの依存関係ではなく、それ自体がReact 19を必要とします。
制限事項
- デフォルトで使えるのはbasic catalogのみです。その他のカタログには、
createMaterial3Catalogを通じて実装を登録する必要があります。 - カタログ一覧にないアイコン名はMaterial Symbolsのリガチャにフォールバックします。アプリでそのフォントを読み込んでいる場合のみ表示されます。
- Markdownの対応範囲にテーブル、画像、生HTML、入れ子のリストは含まれません。リンクで開けるのは
http、https、mailto、telのみです。 DateTimeInputは1.3.0-rc.1のMaterial pickerエクスポートを使い、互換性のある1.2 peer系列がインストールされている場合はプラットフォームの入力にフォールバックします。- トランスポート、認証、永続化、エージェントのオーケストレーションはアプリケーション側の責任です。
パッケージのソースには、公開されているTypeScript定義とテストの全体が含まれています。