How to Implement a Chat Component for Messaging UIs in Astryx

Astryx provides a complete set of ready-made building blocks under the @astryxdesign/lab package that enables you to assemble production-ready chat interfaces with support for message bubbles, unread separators, typing indicators, and emoji reactions.

The facebook/astryx repository offers a robust design system for building modern messaging interfaces. By leveraging the specialized components in the @astryxdesign/lab package, you can implement a fully functional Chat component for messaging UIs in Astryx that handles complex interactions like mentions, reactions, and real-time typing status.

Core Architecture of the Chat System

The Astryx chat implementation follows a clear separation of concerns across three distinct layers, each handling specific responsibilities within the messaging interface.

Message List and Layout Layer

The foundation rests on ChatLayout and ChatMessageList components. As implemented in ChatLayoutShowcase.tsx and ChatMessageListShowcase.tsx, these containers manage the scrollable message area, header placement, and overall scaffold. The layout component provides the structural wrapper while the message list handles virtualization and scroll positioning for large conversation histories.

Message Bubble and Metadata Layer

Individual messages render through ChatMessageBubble, with dedicated variants handling different densities and grouping styles. The ChatMessageBubbleGrouping.tsx showcase demonstrates how consecutive messages from the same sender collapse visually to reduce clutter. Each bubble supports metadata display including avatars, timestamps, and delivery status indicators.

Interaction and Input Layer

User interactions are handled by specialized components: ChatReactionBar for emoji responses, ChatTypingIndicator for real-time status, and ChatComposerInput for message entry with support for mentions and dictation. These components coordinate to create a responsive messaging experience without managing complex state manually.

Step-by-Step Implementation Guide

Import the Component Library

Begin by importing the necessary components from the @astryxdesign/lab package. The library exports all chat primitives required for a complete implementation.

import {
  ChatLayout,
  ChatMessageList,
  ChatMessageBubble,
  ChatUnreadDivider,
  ChatTypingIndicator,
  ChatReactionBar,
  ChatComposerInput,
} from '@astryxdesign/lab';

Create the Layout Container

Wrap your chat interface with ChatLayout to establish the header, message area, and composer structure. This component provides consistent spacing and responsive behavior across screen sizes.

<ChatLayout>
  <ChatMessageList>
    {/* Messages will render here */}
  </ChatMessageList>
  
  <ChatComposerInput placeholder="Type a message…" />
</ChatLayout>

Render Messages with Bubbles

Map your message data to ChatMessageBubble components, utilizing ChatMessageBubbleGrouping for visual continuity between consecutive messages from the same sender. Pass required props including sender, timestamp, and status to control the bubble appearance.

<ChatMessageBubble sender="assistant" timestamp="10:32 AM">
  Hello! How can I help you today?
</ChatMessageBubble>

Add Unread Message Separators

Insert ChatUnreadDivider at the position where the first unread message appears in the conversation history. According to the source code in ChatUnreadDivider.tsx, this component renders an error-colored separator with a customizable label prop that defaults to "New".

<ChatUnreadDivider label="Unread Messages" />

Display Typing Indicators

When your backend reports active typers, render ChatTypingIndicator with an array of participant names. As implemented in ChatTypingIndicator.tsx, this component handles both single and multiple participants with appropriate grammar adjustments.

<ChatTypingIndicator names={['Ana', 'Ben']} />

Enable Emoji Reactions

Attach ChatReactionBar to each message bubble to allow users to add reactions. This component, defined in ChatReactionBar.tsx, displays existing reaction counts and triggers ChatEmojiPicker when users click the add-reaction button.

<ChatReactionBar
  reactions={[{emoji: '👍', count: 2}, {emoji: '❤️', count: 1}]}
  onAdd={(emoji) => addReaction(messageId, emoji)}
/>

Configure the Message Composer

Implement ChatComposerInput with optional triggers for mentions and dictation. The ChatComposerInputMultipleTriggers.tsx showcase provides a reference for handling complex input scenarios including the ChatComposerInputMentionTrigger component for @user style mentions.

<ChatComposerInputMultipleTriggers
  onSubmit={handleSend}
  mentionTrigger={<ChatComposerInputMentionTrigger />}
/>

Complete Working Example

Here is a fully functional implementation combining all layers:

import React from 'react';
import {
  ChatLayout,
  ChatMessageList,
  ChatMessageBubble,
  ChatUnreadDivider,
  ChatTypingIndicator,
  ChatReactionBar,
  ChatComposerInput,
} from '@astryxdesign/lab';

export default function ChatDemo() {
  const [messages, setMessages] = React.useState([
    {id: 1, sender: 'assistant', text: 'Welcome!', unread: false},
    {id: 2, sender: 'user', text: 'Hi there', unread: true},
  ]);
  const typing = ['Ana'];

  return (
    <ChatLayout>
      <ChatMessageList>
        {messages.map((msg) => (
          <React.Fragment key={msg.id}>
            {msg.unread && <ChatUnreadDivider label="Unread" />}
            <ChatMessageBubble sender={msg.sender} timestamp="Now">
              {msg.text}
            </ChatMessageBubble>
            <ChatReactionBar
              reactions={[]}
              onAdd={(emoji) => console.log('add', emoji, msg.id)}
            />
          </React.Fragment>
        ))}

        {typing.length > 0 && <ChatTypingIndicator names={typing} />}
      </ChatMessageList>

      <ChatComposerInput placeholder="Type a message…" />
    </ChatLayout>
  );
}

Customization and Theming

All components are built with StyleX, respecting design tokens such as colorVars and spacingVars. To customize the appearance, extend the component's xstyle prop with additional StyleX rules or supply a custom theme token set via themeProps. This approach ensures type-safe styling while maintaining consistency with the broader Astryx design system.

Key Source Files and References

Understanding the underlying implementation helps when debugging or extending functionality:

Summary

  • Astryx provides comprehensive chat primitives in the @astryxdesign/lab package, eliminating the need to build messaging UI from scratch.
  • The architecture separates concerns into Layout, Message, and Interaction layers for maintainable code organization.
  • Key components include ChatLayout, ChatMessageList, ChatMessageBubble, ChatUnreadDivider, ChatTypingIndicator, ChatReactionBar, and ChatComposerInput.
  • All components leverage StyleX for performance and theming, with extensive showcase files available in the facebook/astryx repository for reference implementations.

Frequently Asked Questions

What package contains the Chat components in Astryx?

The chat components are exported from @astryxdesign/lab, which is the experimental design system package within the facebook/astryx repository. This package contains all messaging primitives including message lists, bubbles, and composer inputs.

How do I handle mentions in the chat composer?

Use the ChatComposerInputMultipleTriggers component with ChatComposerInputMentionTrigger as demonstrated in ChatComposerInputMultipleTriggers.tsx. The trigger system detects @ symbols and provides autocomplete functionality for selecting users.

Can I customize the unread divider label?

Yes. The ChatUnreadDivider component accepts a label prop that allows you to override the default "New" text. Pass any string to customize the separator text for different languages or contexts.

Does Astryx support grouping consecutive messages?

Yes. The ChatMessageBubbleGrouping utility component, showcased in ChatMessageBubbleGrouping.tsx, handles visual grouping of consecutive messages from the same sender. This reduces avatar repetition and creates a cleaner conversation flow.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →