メインコンテンツまでスキップ

チャット会話ブロック

ChatConversation は、MUI StackTextField 入力に基づく、レスポンシブで高度にカスタマイズ可能なメッセージングインターフェースです。日付ごとにグループ化されたメッセージストリーム、モバイル向けに最適化されたオーバーフローメニュー、無限スクロールのページネーションフック、レイアウト構成をサポートします。

インストール

npm install @nodeblocks/frontend-chat-conversation-block

必要なもの

項目理由
messages表示するメッセージバブルの配列。ブロックは createdAt でグループ化し、並べ替えます
chatView見出し、アバター、モバイル用オーバーフローメニュー、ローダー表示を制御するチャットパネル設定
labels見出しタイトル、任意のサブ見出し、デスクトップのアクションボタン用テキストラベル
placeholdersメッセージコメント入力などの入力プレースホルダー
onNavigateナビゲーション見出しをクリックしたり、アバターをリンクしたりしたときに呼び出されるコールバックフック
制御コンポーネント

ChatConversation は表示専用で、アクティブな状態リストは管理しません。アプリケーション内でローカルの messages 状態を維持し、onMessageSubmit 内で配列を更新し、chatView.isLoading でページ読み込みスピナーを切り替えてください。

コード例

ライブエディター
function Example() {
  const [messages, setMessages] = React.useState([
    {
      id: 'msg-1',
      title: 'John Doe',
      content: 'Hey! Are we still on for the project review today?',
      createdAt: new Date(Date.now() - 3600000).toISOString(),
      isOwnMessage: false,
    },
    {
      id: 'msg-2',
      title: 'You',
      content: 'Yes! I have the slides ready.',
      createdAt: new Date(Date.now() - 1800000).toISOString(),
      isOwnMessage: true,
    },
  ]);

  const [isLoading, setIsLoading] = React.useState(false);
  const [lastEvent, setLastEvent] = React.useState('Ready');

  const handleMessageSubmit = text => {
    setLastEvent(`Sent: ${text}`);
    // Add user message
    const userMsg = {
      id: `msg-${Date.now()}`,
      title: 'You',
      content: text,
      createdAt: new Date().toISOString(),
      isOwnMessage: true,
    };
    setMessages(prev => [...prev, userMsg]);

    // Simulate reply
    setIsLoading(true);
    setTimeout(() => {
      setMessages(prev => [
        ...prev,
        {
          id: `reply-${Date.now()}`,
          title: 'John Doe',
          content: 'Awesome, see you in the meeting room!',
          createdAt: new Date().toISOString(),
          isOwnMessage: false,
          avatar: {children: 'JD'},
        },
      ]);
      setIsLoading(false);
    }, 1500);
  };

  return (
    <div style={{height: 500, border: '1px solid #e0e0e0', borderRadius: 8, overflow: 'hidden'}}>
      <ChatConversation
        chatView={{
          heading: {
            avatar: {children: 'JD'},
            buttonHref: '#home',
          },
          isLoading: isLoading,
        }}
        labels={{
          chatViewHeadingButtonText: 'Home',
          chatViewHeadingText: 'Project Chat',
          chatViewHeadingSubText: 'Review team',
        }}
        placeholders={{
          commentInput: 'Type your message...',
        }}
        messages={messages}
        onMessageSubmit={handleMessageSubmit}
        onNavigate={url => setLastEvent(`Navigating to: ${url}`)}
      />
      <div style={{marginTop: 8, fontSize: 12, color: '#666'}}>{lastEvent}</div>
    </div>
  );
}
結果
Loading...

重要なプロパティ

コアプロパティ

プロパティ必須デフォルト説明
messagesArray<{ id: string; content: string; createdAt: string; title?: string; isOwnMessage?: boolean; avatar?: object }>はい-createdAt でグループ化・並べ替えされたチャットメッセージレコードの配列
onMessageSubmit(text: string) => voidいいえundefinedテキストフィールドから入力を送信したときに呼び出されるコールバック
onInputChange(text: string) => voidいいえundefinedコメント入力テキストが編集されたときに呼び出されるコールバック

メッセージオブジェクト

messages 配列内のプロパティを設定します:

プロパティ必須デフォルト説明
idstringはい-一意のメッセージレコード識別子
contentstringはい-チャットバブル内に表示される主要なコンテンツテキスト
createdAtstringはい-日区切りのグループ化に使う日時タイムスタンプ(ISO文字列形式)
isOwnMessagebooleanいいえfalsetrue のとき、自分のコメントを強調し、バブルを右端に配置します
titlestringいいえundefinedチャットバブルの上に表示する作成者ヘッダータイトル
avatarobjectいいえundefined個別コメントの Avatar 設定。MUI Avatar の props に加え、任意の hrefisLoading、リンク/クリック動作(component="a" 対応)を含みます

コンテンツプロパティ

プロパティ必須デフォルト説明
chatView{ heading?: { avatar?: object; buttonHref: string; onBack?: () => void; menuItems?: Array<{ label: string; href?: string; icon?: ReactNode; onClick?: (e: MouseEvent<HTMLElement>) => void }> }; isLoading?: boolean; onScrollTop?: (earliestId: string) => void }はい-見出し、モバイルメニュー、戻る操作、無限スクロールを設定するパネルレイアウト。見出しアバターは component="a" + href によるリンク付きアバターを含む標準の MUI Avatar props を受け付けます
labels{ chatViewHeadingButtonText?: string; chatViewHeadingText?: string; chatViewHeadingSubText?: string }はい-メイン見出しラベルと終了ボタンのテキスト
placeholders{ commentInput: string }はい-入力欄の文言設定
onNavigate(url: string) => voidはい-クリックされた要素や設定をマッピングする標準のリダイレクトフック
commentInput{ isDisabled?: boolean; errorText?: string }いいえundefined下部コメント入力の設定
commentSubmitButton{ isDisabled?: boolean }いいえundefined送信ボタンの有効状態

chatView の構造

chatView 内でレイアウト見出しインジケーターを設定します:

プロパティ必須デフォルト説明
heading{ avatar?: object; buttonHref: string; onBack?: () => void; menuItems?: ChatConversationHeadingMenuItem[] }いいえundefined見出しアクションの設定。heading がある場合は buttonHref が必須です。
isLoadingbooleanいいえfalseデータ取得時に上部のページネーションローダーや全画面スピナーを表示します
onScrollTop(earliestId: string) => voidいいえundefined先頭までスクロールしたときに呼び出されるコールバック(過去履歴の読み込みに使用)

メニュー項目オブジェクト

見出しのオーバーフロードロップダウンメニューリスト(menuItems)のオプション設定:

プロパティ必須デフォルト説明
labelstringはい-メニュー項目に表示されるラベルテキスト
hrefstringいいえundefinedonNavigate によってマッピングされる遷移先
iconReactNodeいいえundefinedメニュー項目ラベルの先頭に表示されるアイコン要素
onClick(e: MouseEvent<HTMLElement>) => voidいいえundefined項目をクリックしたときに呼び出されるハンドラ

レイアウトと構成のプロパティ

プロパティ必須デフォルト説明
childrenBlocksOverride | ReactNodeいいえundefinedコンパウンド子要素またはオーバーライド関数の子
classNamestringいいえundefined外側コンテナに適用されるスタイルクラス
sxSxPropsいいえundefined外側の Stack に渡される MUI SX スタイル上書き

ChatConversationStackPropschildren を除く)をすべて継承します。デフォルトのブロック順は ['heading', 'body'] (defaultBlockOrder) です。

デフォルト UI ブロック

ブロック基盤備考
ChatConversation (root)Stack見出しと本文のパネルを縦に積み重ねます
ChatConversation.HeadingStack戻るボタン、アバター詳細、結合タイトル、終了ボタンを表示します
ChatConversation.BodyStackメッセージを日ごとにグループ化し、createdAt で並べ替え、onScrollTop 境界を発火し、入力欄をマウントします

TypeScript

import {ChatConversation} from '@nodeblocks/frontend-chat-conversation-block';
import type {MouseEvent, ReactNode} from 'react';

type ChatMessage = {
id: string;
content: string;
createdAt: string;
title?: string;
isOwnMessage?: boolean;
avatar?: {
component?: 'a';
onClick?: (event: MouseEvent<HTMLElement>) => void;
children?: ReactNode;
src?: string;
srcSet?: string;
href?: string;
isLoading?: boolean;
sx?: object;
};
};

type MenuItem = {
label: string;
href?: string;
icon?: ReactNode;
onClick?: (event: MouseEvent<HTMLElement>) => void;
};

const messages: ChatMessage[] = [
{
id: 'msg_001',
title: 'Customer support',
content: 'We are processing your request. Please hold on.',
createdAt: '2026-05-27T02:00:00Z',
isOwnMessage: false,
avatar: {children: 'CS', sx: {bgcolor: 'primary.main'}},
},
];

const menuItems: MenuItem[] = [{label: 'View Profile', onClick: () => void 0}];

<ChatConversation
chatView={{
heading: {
buttonHref: '/support',
menuItems,
},
isLoading: false,
}}
labels={{
chatViewHeadingButtonText: 'Exit',
chatViewHeadingText: 'Customer Care',
}}
placeholders={{
commentInput: 'Describe your issue...',
}}
messages={messages}
onMessageSubmit={text => void text}
onNavigate={url => void url}
/>;