1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

この記事では、React / TypeScript 環境で chat-ui-kit-react を使ったチャット UI の実装方法を記載します。

chat-ui-kit-react とは

chat-ui-kit-react は、チャットアプリケーションの UI を構築するための React コンポーネントライブラリです。

事前にデザインされた豊富なコンポーネントを提供しており、メッセージリスト、入力エリア、会話リスト、アバターなど、チャット UI に必要な要素をすぐに利用できます。以下のような特徴があります。

  • 豊富なプリビルドコンポーネント(30種類以上)
  • レスポンシブデザイン対応
  • カスタマイズ可能なスタイリング
  • TypeScript サポート
  • アクセシビリティ対応
  • 軽量で依存関係が少ない

開発環境

開発環境は以下の通りです。

  • Windows 11
  • React 19.2.0
  • TypeScript 5.9.3
  • bun 1.3.6
  • @chatscope/chat-ui-kit-react 2.0.3
  • @chatscope/chat-ui-kit-styles 1.4.0

インストール

まずは以下のコマンドでインストールします。

bun install @chatscope/chat-ui-kit-react @chatscope/chat-ui-kit-styles

基本的な利用方法

スタイルのインポート

chat-ui-kit-react を使用するには、まずスタイルシートをインポートする必要があります。

src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

基本的なチャット画面の構築

chat-ui-kit-react の基本的な構成は、MainContainerChatContainerMessageListMessageInput を組み合わせて作成します。

src/App.tsx
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
} from "@chatscope/chat-ui-kit-react";

export function App() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <MessageList>
            <Message
              model={{
                message: "こんにちは!",
                sender: "田中",
                direction: "incoming",
                position: "single",
              }}
            />
            <Message
              model={{
                message: "こんにちは!元気ですか?",
                sender: "自分",
                direction: "outgoing",
                position: "single",
              }}
            />
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

export default App;

image.png

Message コンポーネントの詳細

Message コンポーネントの model プロパティには以下のプロパティを指定できます。

プロパティ 説明
message string メッセージの内容
sender string 送信者名
direction "incoming" | "outgoing" メッセージの方向(受信/送信)
sentTime string 送信時刻
position "single" | "first" | "normal" | "last" 連続メッセージ内での位置
type "html" | "text" | "image" | "custom" メッセージタイプ(デフォルト: "text")
payload string | object | allowedChildren([MessageCustomContent]) カスタムデータやメタ情報

position プロパティは、同じ送信者からの連続したメッセージを表示する際に使用します。
値によってメッセージの吹き出しの形が変わります。

src/components/ContinuousChat.tsx
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
} from "@chatscope/chat-ui-kit-react";

export function ContinuousChat() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <MessageList>
            <Message
              model={{
                message: "こんにちは",
                sender: "田中",
                direction: "incoming",
                position: "first",
              }}
            />
            <Message
              model={{
                message: "今日の会議は15時からです",
                sender: "田中",
                direction: "incoming",
                position: "normal",
              }}
            />
            <Message
              model={{
                message: "よろしくお願いします",
                sender: "田中",
                direction: "incoming",
                position: "last",
              }}
            />
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

image.png

アバターの追加

Avatar コンポーネントを使用して、メッセージにアバター画像を追加できます。

src/components/ChatWithAvatar.tsx
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  Avatar,
} from "@chatscope/chat-ui-kit-react";

export function ChatWithAvatar() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <MessageList>
            <Message
              model={{
                message: "こんにちは!",
                sender: "田中",
                direction: "incoming",
                position: "single",
              }}
            >
              <Avatar
                src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
                name="田中"
              />
            </Message>
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

image.png

AvatarMessage コンポーネントの子要素として配置します。複数の連続メッセージでは、最後のメッセージ(position: "last" または position: "single")にのみアバターを表示するのが一般的です。

会話ヘッダーの追加

ConversationHeader を使用して、チャット画面の上部にヘッダーを追加できます。

src/components/ChatWithHeader.tsx
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  ConversationHeader,
  Avatar,
} from "@chatscope/chat-ui-kit-react";

export function ChatWithHeader() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <ConversationHeader>
            <ConversationHeader.Back />
            <Avatar
              src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
              name="田中太郎"
            />
            <ConversationHeader.Content userName="田中太郎" info="オンライン" />
            <ConversationHeader.Actions>
              {/* アクションボタンを配置 */}
            </ConversationHeader.Actions>
          </ConversationHeader>
          <MessageList>
            <Message
              model={{
                message: "こんにちは!",
                sender: "田中",
                direction: "incoming",
                position: "single",
              }}
            />
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

image.png

会話リストの実装

SidebarConversationList を使用して、複数の会話を一覧表示できます。

src/components/ChatList.tsx
import {
  MainContainer,
  Sidebar,
  Search,
  ConversationList,
  Conversation,
  Avatar,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  ConversationHeader,
} from "@chatscope/chat-ui-kit-react";

export function ChatList() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <Sidebar position="left">
          <Search placeholder="検索..." />
          <ConversationList>
            <Conversation
              name="田中太郎"
              lastSenderName="田中"
              info="こんにちは!"
              active
            >
              <Avatar
                src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
                name="田中太郎"
              />
            </Conversation>
            <Conversation
              name="佐藤花子"
              lastSenderName="佐藤"
              info="明日の予定は?"
            >
              <Avatar
                src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
                name="佐藤花子"
              />
            </Conversation>
            <Conversation
              name="鈴木一郎"
              lastSenderName="鈴木"
              info="了解しました"
              unreadCnt={3}
            >
              <Avatar
                src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
                name="鈴木一郎"
              />
            </Conversation>
          </ConversationList>
        </Sidebar>

        <ChatContainer>
          <ConversationHeader>
            <Avatar
              src="https://chatscope.io/storybook/react/assets/zoe-E7ZdmXF0.svg"
              name="田中太郎"
            />
            <ConversationHeader.Content userName="田中太郎" info="オンライン" />
          </ConversationHeader>
          <MessageList>
            <Message
              model={{
                message: "こんにちは!",
                sender: "田中",
                direction: "incoming",
                position: "single",
              }}
            />
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

image.png

Conversation コンポーネントの主なプロパティは以下の通りです。

プロパティ 説明
name string 会話相手の名前
lastSenderName string 最後のメッセージの送信者名
info string 最後のメッセージの内容
active boolean アクティブ状態
unreadCnt number 未読メッセージ数

タイピングインジケーター

相手が入力中であることを示す TypingIndicator を追加できます。

src/components/ChatWithTyping.tsx
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  TypingIndicator,
} from "@chatscope/chat-ui-kit-react";

export function ChatWithTyping() {
  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <MessageList typingIndicator={<TypingIndicator content="田中が入力中..." />}>
            <Message
              model={{
                message: "こんにちは!",
                sender: "田中",
                direction: "incoming",
                position: "single",
              }}
            />
          </MessageList>
          <MessageInput placeholder="メッセージを入力..." />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

Bun-React-Google-Chrome-2026-01-21-10-39-04.gif

状態管理と組み合わせた実装

Jotai などの状態管理ライブラリと組み合わせて、動的なチャット機能を実装できます。

atom の定義

src/atoms/chatAtom.ts
import { atom } from "jotai";

export interface ChatMessage {
  id: string;
  message: string;
  sender: string;
  direction: "incoming" | "outgoing";
  sentTime: string;
}

export const messagesAtom = atom<ChatMessage[]>([
  {
    id: "1",
    message: "こんにちは!何かお手伝いできることはありますか?",
    sender: "AI アシスタント",
    direction: "incoming",
    sentTime: new Date().toLocaleTimeString(),
  },
]);

export const addMessageAtom = atom(
  null,
  (get, set, newMessage: Omit<ChatMessage, "id" | "sentTime">) => {
    const messages = get(messagesAtom);
    const message: ChatMessage = {
      ...newMessage,
      id: Date.now().toString(),
      sentTime: new Date().toLocaleTimeString(),
    };
    set(messagesAtom, [...messages, message]);
  }
);

export const isTypingAtom = atom(false);

チャットコンポーネント

src/components/DynamicChat.tsx
import { useAtomValue, useSetAtom } from "jotai";
import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  TypingIndicator,
} from "@chatscope/chat-ui-kit-react";
import { messagesAtom, addMessageAtom, isTypingAtom } from "../atoms/chatAtom";

export function DynamicChat() {
  const messages = useAtomValue(messagesAtom);
  const addMessage = useSetAtom(addMessageAtom);
  const isTyping = useAtomValue(isTypingAtom);

  const handleSend = (text: string) => {
    addMessage({
      message: text,
      sender: "自分",
      direction: "outgoing",
    });
  };

  return (
    <div style={{ position: "relative", height: "500px" }}>
      <MainContainer>
        <ChatContainer>
          <MessageList
            typingIndicator={
              isTyping ? <TypingIndicator content="AI が入力中..." /> : null
            }
          >
            {messages.map((msg, index) => {
              const isLastFromSender =
                index === messages.length - 1 ||
                messages[index + 1]?.sender !== msg.sender;

              return (
                <Message
                  key={msg.id}
                  model={{
                    message: msg.message,
                    sender: msg.sender,
                    direction: msg.direction,
                    position: isLastFromSender ? "last" : "normal",
                  }}
                />
              );
            })}
          </MessageList>
          <MessageInput
            placeholder="メッセージを入力..."
            onSend={handleSend}
          />
        </ChatContainer>
      </MainContainer>
    </div>
  );
}

カスタムスタイリング

chat-ui-kit-react は CSS 変数を使用してスタイルをカスタマイズできます。

src/styles/chat-custom.css
/* メインコンテナのカスタマイズ */
.cs-main-container {
  --main-container-bg-color: #f5f5f5;
}

/* メッセージのカスタマイズ */
.cs-message__content {
  --message-content-bg-color: #e3f2fd;
}

.cs-message--outgoing .cs-message__content {
  --message-content-bg-color: #c8e6c9;
}

/* 入力エリアのカスタマイズ */
.cs-message-input {
  --message-input-bg-color: #ffffff;
  --message-input-border-color: #e0e0e0;
}

/* 会話リストのカスタマイズ */
.cs-conversation--active {
  --conversation-bg-color: #e3f2fd;
}
src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
import "./styles/chat-custom.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

TypeScript の型定義

chat-ui-kit-react は TypeScript をサポートしており、型定義が提供されています。

src/types/chat.ts
import type { MessageModel } from "@chatscope/chat-ui-kit-react";

export interface ChatUser {
  id: string;
  name: string;
  avatarUrl?: string;
  status: "online" | "offline" | "away";
}

export interface ChatConversation {
  id: string;
  participants: ChatUser[];
  lastMessage?: MessageModel;
  unreadCount: number;
}

export interface ChatState {
  currentUser: ChatUser;
  conversations: ChatConversation[];
  activeConversationId: string | null;
  messages: Record<string, MessageModel[]>;
}

主要コンポーネント一覧

chat-ui-kit-react が提供する主要なコンポーネントは以下の通りです。

コンポーネント 説明
MainContainer チャット UI のルートコンテナ
ChatContainer 個別のチャット画面のコンテナ
MessageList メッセージ一覧を表示
Message 個別のメッセージ
MessageInput メッセージ入力エリア
Avatar ユーザーアバター
ConversationHeader チャット画面のヘッダー
Sidebar サイドバー
ConversationList 会話一覧
Conversation 個別の会話項目
Search 検索入力
TypingIndicator 入力中インジケーター
MessageSeparator メッセージ間の区切り線(日付表示など)
ExpansionPanel 展開可能なパネル
InputToolbox 入力エリアのツールボックス

まとめ

chat-ui-kit-react を使うことで、React / TypeScript アプリケーションに洗練されたチャット UI を簡単に導入できます。

主なポイントは以下の通りです。

  • 豊富なプリビルドコンポーネントにより、迅速な開発が可能
  • MainContainer、ChatContainer、MessageList、MessageInput の組み合わせで基本的なチャット画面を構築
  • Avatar、ConversationHeader でリッチな UI を実現
  • Sidebar、ConversationList で複数会話の管理が可能
  • TypingIndicator でリアルタイム感のある UX を提供
  • CSS 変数によるカスタマイズが可能
  • TypeScript による型安全性

chat-ui-kit-react は、カスタマーサポートチャット、AI チャットボット、メッセージングアプリなど、様々なチャット機能の実装に活用できます。

参考

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?