Ably Chat UI React Components

Components

This page documents the components available in the Ably Chat React UI Components library. These components provide a comprehensive UI for building chat applications with Ably.

Styling and Theming

The Ably Chat React UI Components use Tailwind CSS for styling. Here's how styling works and how you can customize the appearance of the components:

CSS Import

The components come with pre-compiled CSS that you can import directly into your application:

React

1

2

// Import the pre-compiled CSS
import '@ably/chat-react-ui-components/dist/style.css';

This CSS file contains all the necessary styles for the components, compiled from the Tailwind utility classes used in the component code. You don't need to install Tailwind CSS in your project to use these components.

Light and Dark Mode

The components support both light and dark modes through the ThemeProvider:

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import { ThemeProvider } from '@ably/chat-react-ui-components';

// Basic usage with default options
<ThemeProvider>
  <YourApp />
</ThemeProvider>

// With custom configuration
<ThemeProvider
  options={{
    persist: true, // Save preference to localStorage
    detectSystemTheme: true, // Use system preference
    defaultTheme: 'light' // Initial theme if no preference found
  }}
>
  <YourApp />
</ThemeProvider>

The ThemeProvider manages theme state and automatically applies the appropriate CSS classes to enable light or dark mode styling. It also provides a useTheme hook that you can use to access and change the current theme:

React

1

2

3

4

5

6

7

8

9

10

11

import { useTheme } from '@ably/chat-react-ui-components';

function ThemeToggle() {
  const { theme, toggleTheme } = useTheme();

  return (
    <button onClick={toggleTheme}>
      Current theme: {theme}
    </button>
  );
}

Customizing Component Styles

Currently, there are two main ways to customize the appearance of components:

  1. Using the className prop: Most components accept a className prop that allows you to add custom CSS classes:
React

1

2

3

4

<ChatWindow
  roomName="general"
  className="my-custom-chat-window border-red-500"
/>
  1. Component-specific style props: Some components have specific props for styling, such as the Avatar component's color prop:
React

1

2

3

4

5

<Avatar
  alt="User Name"
  color="bg-blue-500"
  size="lg"
/>

Future Styling Improvements

We are planning to enhance the theming and customization capabilities in future releases:

  • Full theming support with customizable color palettes
  • Component-level style overrides through a theme context
  • Additional theme variants beyond light/dark (e.g., high contrast)
  • Custom user/brand theming options

These improvements will provide more flexibility for integrating the chat components into your application's design system.

App

The App component is a complete, ready-to-use chat application that combines all the components above with sensible defaults. It's ideal for quickly prototyping a chat interface or seeing how everything fits together.

Features

  • Manages room state (adding, leaving, selecting rooms)
  • Shows loading state when not connected
  • Renders layout with Sidebar and ChatWindow
  • Includes RoomInfo in header and RoomReaction in footer
  • Handles connection status and error states
  • Provides customizable width and height
  • Shows empty state when no room is selected

Props

PropDescription
initialRoomNamesAn optional array of room names to populate the sidebar initially
widthWidth of the app container
heightHeight of the app container

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

import { App } from '@ably/chat-react-ui-components';
import * as Ably from 'ably';
import { ChatClient } from '@ably/chat';
import { ChatClientProvider } from '@ably/chat/react';
import { ThemeProvider, AvatarProvider, ChatSettingsProvider } from '@ably/chat-react-ui-components';
import '@ably/chat-react-ui-components/dist/styles.css';

// Create Ably Realtime client
const ablyClient = new Ably.Realtime({
  key: '{{API_KEY}}',
  clientId: 'user-' + Math.random().toString(36).substring(2, 15),
});

const chatClient = new ChatClient(ablyClient);

// Basic usage
function QuickChatPrototype() {
  return (
    <ThemeProvider>
      <AvatarProvider>
        <ChatSettingsProvider>
          <ChatClientProvider client={chatClient}>
            <App initialRoomNames={['my-first-room']} />
          </ChatClientProvider>
        </ChatSettingsProvider>
      </AvatarProvider>
    </ThemeProvider>
  );
}

// With custom dimensions
function CustomSizedChat() {
  return (
    <ChatClientProvider client={chatClient}>
      <App
        initialRoomNames={['my-first-room']}
        width="100%"
        height="600px"
      />
    </ChatClientProvider>
  );
}

ChatWindow

The ChatWindow component provides the main chat interface for a room. This includes message display, input, and custom header/footer content. It also enters presence automatically when mounted.

Features

  • Message display with history loading
  • Message editing, deletion, and reactions
  • Typing indicators and presence awareness
  • Custom header and footer content
  • Discontinuity recovery on reconnection
  • Active chat window management to control which messages are rendered in the UI

Props

PropDescription
roomNameUnique identifier for the chat room
customHeaderContentOptional custom content for the header area of the chat window
customFooterContentOptional custom content for the footer area of the chat window
enableTypingIndicatorsWhether to show typing indicators in the chat window
'autoEnterPresence'Whether to automatically enter presence when the component mounts
windowSizeControls the window size for rendering messages in UI
classNameAdditional CSS class names to apply to the root container
onErrorList of callbacks triggered when an error occurs in the chat window

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

import { ChatWindow, RoomInfo, RoomReaction } from '@ably/chat-react-ui-components';
import { ChatRoomProvider } from '@ably/chat/react';

// Basic usage
<ChatRoomProvider name="general">
  <ChatWindow roomName="general" />
</ChatRoomProvider>

// With custom header and footer
<ChatRoomProvider name="general">
  <ChatWindow
    roomName="general"
    customHeaderContent={<RoomInfo />}
    customFooterContent={<RoomReaction />}
  />
</ChatRoomProvider>

// With typing indicators disabled
<ChatRoomProvider name="general">
  <ChatWindow
    roomName="general"
    enableTypingIndicators={false}
  />
</ChatRoomProvider>

// Setting a custom window size
<ChatRoomProvider name="general">
  <ChatWindow
    roomName="general"
    windowSize={300} // Custom size for message rendering in the UI
  />
</ChatRoomProvider>

Integration with Other Components

The ChatWindow component integrates several other components:

  • ChatMessageList: Displays the messages with infinite scrolling
  • MessageInput: Allows users to compose and send messages
  • ChatWindowHeader: Contains room information and controls
  • ChatWindowFooter: Contains additional controls and features

MessageInput

The MessageInput component provides a comprehensive text input interface for composing and sending chat messages. This component supports multi-line input, emoji selection, and typing indicators.

Features

  • Multi-line text input with automatic height adjustment (max 150px)
  • Enter key to send (Shift+Enter for new line)
  • Integrated emoji picker with cursor position insertion
  • Typing indicators to alert others when composing messages
  • Automatic input cleanup and focus management
  • Accessible form controls with proper ARIA attributes

Props

PropDescription
onSentCallback function triggered when a message is sent
placeholderPlaceholder text displayed in the input field when empty
classNameAdditional CSS class names to apply to the input container
enableTypingWhether to enable typing indicators on user input
onSendErrorCallback triggered when an error occurs while sending a message

Typing Indicators

The MessageInput component automatically triggers typing indicators when the user is typing. This is handled through the Ably Chat SDK's typing indicators feature:

  • Triggered on each keystroke when content is present
  • Automatically stopped when input is cleared or message is sent
  • Integrated with the useTyping hook from @ably/chat/react

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

import { MessageInput } from '@ably/chat-react-ui-components';
import { useMessages } from '@ably/chat/react';

// Basic usage
const { send } = useMessages();

const handleSendMessage = (text: string) => {
  console.log(`Sending message: ${text}`);
  send({ text });
};

<MessageInput
  onSend={handleSendMessage}
  placeholder="Type your message here..."
/>

The Sidebar component provides room navigation and management.

Features

  • Collapsible interface with avatar-only mode
  • Room creation and management
  • Theme toggle integration
  • Active room highlighting
  • Room count display
  • Automatic room attachment/detachment

Props

PropDescription
roomNamesRooms to display
activeRoomNameCurrently-active room (optional)
defaultRoomOptionsAbly options passed to each ChatRoomProvider
addRoomAdds (or joins) a room
setActiveRoomSets the active room
leaveRoomLeaves a room
classNameOptional CSS class names for additional styling
isCollapsedWhether the sidebar is in collapsed mode (avatar-only)
onToggleCollapseCallback to toggle the collapsed state

Room Management

The Sidebar component handles room management through the following functions:

  • addRoom: Adds a new room to the list or joins an existing room
  • setActiveRoom: Sets the active room for display in the main content area
  • leaveRoom: Removes a room from the list and handles cleanup

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

import { Sidebar } from '@ably/chat-react-ui-components';
import { RoomOptions } from '@ably/chat';
import { useState } from 'react';

const [rooms, setRooms] = useState<string[]>(['general', 'random']);
const [activeRoom, setActiveRoom] = useState<string | undefined>('general');
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
const [roomOptions] = useState<RoomOptions>({ occupancy: { enableEvents: true } });

const addRoom = (name: string) => {
  console.log(`Adding room: ${name}`);
  setRooms(prev => prev.includes(name) ? prev : [...prev, name]);
};

const leaveRoom = (name: string) => {
  console.log(`Leaving room: ${name}`);
  setRooms(prev => prev.filter(n => n !== name));
  if (activeRoom === name) {
    setActiveRoom(rooms.length > 0 ? rooms[0] : undefined);
  }
};

const handleSetActiveRoom = (name?: string) => {
  console.log(`Setting active room to: ${name}`);
  setActiveRoom(name);
};

<Sidebar
  roomNames={rooms}
  activeRoomName={activeRoom}
  defaultRoomOptions={roomOptions}
  addRoom={addRoom}
  setActiveRoom={handleSetActiveRoom}
  leaveRoom={leaveRoom}
  isCollapsed={isSidebarCollapsed}
  onToggleCollapse={() => setIsSidebarCollapsed(prev => !prev)}
/>

Rooms are automatically attached when the Sidebar is mounted, and detached when the component unmounts.

ChatMessageList

The ChatMessageList component displays a list of chat messages with advanced scrolling functionality. It supports infinite scrolling, message history loading, and automatic scrolling to new messages.

Features

  • Message display with history loading and infinite scroll
  • Automatic scrolling to new messages
  • Loading indicators for history fetching
  • Typing indicators integration
  • Scroll position preservation when loading history
  • Virtualized rendering for performance with large message lists
  • Accessibility support with proper ARIA roles

Props

PropDescription
messagesArray of Ably Chat Message objects to render
onLoadMoreHistoryCallback triggered when user scrolls near the top of the message list
isLoadingWhether a history loading operation is currently in progress
hasMoreHistoryWhether there are more historical messages available to load
onMessageInViewCallback triggered when the user scrolls to view a specific message
onViewLatestCallback triggered when the user scrolls to the bottom of the message list
onEditCallback triggered when a user saves an edited message
onDeleteCallback triggered when a user confirms deletion of their message
onReactionAddCallback triggered when a user adds an emoji reaction to any message
onReactionRemoveCallback triggered when a user removes their emoji reaction from a message
childrenOptional React elements to render after all messages (e.g., TypingIndicators)
autoScrollWhether to automatically scroll to bottom when new messages arrive
loadMoreThresholdDistance in pixels from the top edge that triggers onLoadMoreHistory callback
enableTypingIndicatorsWhether to enable built-in typing indicators in the chat window

Scrolling Behavior

The ChatMessageList component implements sophisticated scrolling logic:

  1. Auto-scrolling: When new messages arrive, the list automatically scrolls to the bottom if the user is already near the bottom. This prevents interrupting the reading experience when viewing older messages.

  2. Infinite scrolling: When the user scrolls near the top of the list, the onLoadMoreHistory callback is triggered to load older messages.

  3. Scroll position preservation: When older messages are loaded, the scroll position is preserved so the user doesn't lose their place.

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

import { ChatMessageList } from '@ably/chat-react-ui-components';
import { Message } from '@ably/chat';
import { useState } from 'react';

// Example with useState for messages
const [messages, setMessages] = useState<Message[]>([]);
const [isLoadingHistory, setIsLoadingHistory] = useState(false);
const [hasMoreMessages, setHasMoreMessages] = useState(true);

const fetchPreviousMessages = () => {
  console.log('Loading more message history');
  setIsLoadingHistory(true);
  // Fetch logic would go here
  setIsLoadingHistory(false);
};

const handleEditMessage = (message: Message, newText: string) => {
  console.log(`Editing message with serial: ${message.serial}, setting text to: ${newText}`);
};

const handleDeleteMessage = (message: Message) => {
  console.log(`Deleting message with serial: ${message.serial}`);
};

const handleAddReaction = (message: Message, emoji: string) => {
  console.log(`Adding reaction ${emoji} to message with serial: ${message.serial}`);
};

const handleRemoveReaction = (message: Message, emoji: string) => {
  console.log(`Removing reaction ${emoji} from message with serial: ${message.serial}`);
};

<ChatMessageList
  messages={messages}
  onLoadMoreHistory={fetchPreviousMessages}
  isLoading={isLoadingHistory}
  hasMoreHistory={hasMoreMessages}
  enableTypingIndicators={true}
  onEdit={handleEditMessage}
  onDelete={handleDeleteMessage}
  onReactionAdd={handleAddReaction}
  onReactionRemove={handleRemoveReaction}
  autoScroll={true}
  loadMoreThreshold={150}
>
</ChatMessageList>

ChatMessage

The ChatMessage component displays an individual chat message with interactive capabilities. It allows users to view, edit, delete, and react to messages.

Features

  • Message content display with sender avatar
  • Edit/delete functionality for own messages with confirmation dialogs
  • Emoji reactions system with picker and toggle functionality
  • Status indicators (edited, deleted)
  • Basic ARIA support (role, aria-label)
  • Hover tooltips showing sender information

Props

PropDescription
messageThe Ably Chat message object used to display the message content
onEditCallback triggered when the user saves an edited message
onDeleteCallback triggered when the user confirms message deletion
onReactionAddCallback triggered when a user adds an emoji reaction to the message
onReactionRemoveCallback triggered when a user removes their emoji reaction from the message
classNameAdditional CSS class names to apply to the message container

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import { ChatMessage } from '@ably/chat-react-ui-components';
import { Message } from '@ably/chat';
import { useMessages } from '@ably/chat/react';

const { update, deleteMessage, addReaction, removeReaction } = useMessages();

<ChatMessage
  message={message}
  onEdit={(message: Message, newText: string) => {
    console.log(`Editing message with serial: ${message.serial}, setting text to: ${newText}`);
    update(message.serial, { text: newText });
  }}
  onDelete={(message: Message) => {
    console.log(`Deleting message with serial: ${message.serial}`);
    deleteMessage(message.serial);
  }}
  onReactionAdd={(message: Message, emoji: string) => {
    console.log(`Adding reaction ${emoji} to message with serial: ${message.serial}`);
    addReaction(message.serial, emoji);
  }}
  onReactionRemove={(message: Message, emoji: string) => {
    console.log(`Removing reaction ${emoji} from message with serial: ${message.serial}`);
    removeReaction(message.serial, emoji);
  }}
/>

Avatar

The Avatar component displays a user or room avatar with fallback to initials when no image is available.

Props

PropDescription
srcURL to the avatar image
altAlternative text for the avatar image, also used for generating initials if needed
colorBackground color for the avatar when no image is provided (uses Tailwind CSS color classes)
sizeSize of the avatar
initialsCustom initials to display when no image is available
onClickClick handler for the avatar

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import { Avatar } from '@ably/chat-react-ui-components';

// Basic usage
<Avatar
  src="https://example.com/avatar.jpg"
  alt="John Doe"
  size="md"
/>

// With fallback to initials
<Avatar
  alt="John Doe"
  color="bg-blue-500"
  size="lg"
/>

// With custom initials
<Avatar
  alt="John Doe"
  initials="JD"
  color="bg-green-500"
  size="xl"
/>

// With click handler
<Avatar
  alt="John Doe"
  onClick={() => console.log('Avatar clicked')}
/>

Integration with AvatarProvider

The Avatar component is designed to integrate with the AvatarProvider to display consistent avatars across your application, but it also works independently. The AvatarProvider can be used to manage avatar generation and caching for users and rooms.:

React

1

2

3

4

5

6

7

8

9

10

11

12

import { Avatar, useUserAvatar } from '@ably/chat-react-ui-components';
const { userAvatar } = useUserAvatar({
    clientId: 'user-123',
    displayName: 'John Doe',
  });

<Avatar
  src={userAvatar?.src}
  alt={userAvatar?.displayName}
  color={userAvatar?.color}
  initials={userAvatar?.initials}
/>

ParticipantList

The ParticipantList component displays a positioned modal showing all room participants.

Features

  • Modal overlay with absolute positioning based on provided coordinates
  • Participant list with avatars, names, and status indicators
  • Smart sorting: current user appears first, followed by alphabetical order
  • Typing indicators for active participants
  • Participant count display in header
  • Scrollable list with fixed maximum height for large participant counts
  • Accessible modal dialog with proper ARIA attributes and focus management

Props

PropDescription
presenceDataArray of Ably Chat presence members currently in the room
currentClientIdClient ID of the current Ably Connection for the room
currentlyTypingSet of client IDs for users who are currently typing
onToggleCallback function to toggle the list open/closed state
positionAbsolute positioning coordinates for rendering the modal

Live Participant Tracking

The ParticipantList component can be used to show currently active participants in the room.

  • Only shows users who are currently present in the room based on presence data
  • Displays typing indicators for users who are currently typing
  • Sorts the current user to the top of the list for easy identification

Usage

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

import { ParticipantList } from '@ably/chat-react-ui-components';
import { useChatClient, usePresence, useTyping } from '@ably/chat/react';
import { useState } from 'react';

// Integration with presence and typing hooks
const { presenceData } = usePresence();
const { currentlyTyping } = useTyping();
const { clientId } = useChatClient();
const [participantListOpen, setParticipantListOpen] = useState(false);

const toggleParticipantList = () => {
  console.log('Toggling participant list');
  setParticipantListOpen(prev => !prev);
};

{participantListOpen && (
  <ParticipantList
    presenceData={presenceData}
    currentClientId={clientId}
    currentlyTyping={currentlyTyping}
    onToggle={toggleParticipantList}
    position={{ top: 100, left: 200 }}
  />
)}
Select...