Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 125 additions & 108 deletions src/pages/docs/chat/react-ui-kit/components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ The `MessageInput` component provides a comprehensive text input interface for c
|------|-------------|
| `onSent` | Callback function triggered when a message is sent |
| `placeholder` | Placeholder text displayed in the input field when empty |
| `className` | Additional CSS class names to apply to the input container |
| `enableTyping` | Whether to enable typing indicators on user input |
| `onSendError` | Callback triggered when an error occurs while sending a message |

Expand All @@ -300,18 +299,15 @@ The MessageInput component automatically triggers typing indicators when the use
<Code>
```react
import { MessageInput } from '@ably/chat-react-ui-kit';
import { useMessages } from '@ably/chat/react';

// Basic usage
const { sendMessage } = useMessages();
import { Message } from '@ably/chat';

const handleSendMessage = (text: string) => {
console.log(`Sending message: ${text}`);
sendMessage({ text });
// Basic usage - onSent receives the sent Message object
const handleMessageSent = (message: Message) => {
console.log(`Message sent with serial: ${message.serial}`);
};

<MessageInput
onSend={handleSendMessage}
onSent={handleMessageSent}
placeholder="Type your message here..."
/>
```
Expand Down Expand Up @@ -362,40 +358,44 @@ import { Sidebar } from '@ably/chat-react-ui-kit';
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);
};
function SidebarExample() {
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)}
/>
```
return (
<Sidebar
roomNames={rooms}
activeRoomName={activeRoom}
defaultRoomOptions={roomOptions}
addRoom={addRoom}
setActiveRoom={handleSetActiveRoom}
leaveRoom={leaveRoom}
isCollapsed={isSidebarCollapsed}
onToggleCollapse={() => setIsSidebarCollapsed(prev => !prev)}
/>
);
}
```
</Code>

Rooms are automatically attached when the Sidebar is mounted, and detached when the component unmounts.
Expand Down Expand Up @@ -453,48 +453,50 @@ import { ChatMessageList } from '@ably/chat-react-ui-kit';
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);
function ChatMessageListExample() {
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 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 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 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 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}`);
};
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>
return (
<ChatMessageList
messages={messages}
onLoadMoreHistory={fetchPreviousMessages}
isLoading={isLoadingHistory}
hasMoreHistory={hasMoreMessages}
enableTypingIndicators={true}
onEdit={handleEditMessage}
onDelete={handleDeleteMessage}
onReactionAdd={handleAddReaction}
onReactionRemove={handleRemoveReaction}
autoScroll={true}
loadMoreThreshold={150}
/>
);
}
```
</Code>

Expand Down Expand Up @@ -529,7 +531,7 @@ The `ChatMessage` component displays an individual chat message with interactive
<Code>
```react
import { ChatMessage } from '@ably/chat-react-ui-kit';
import { Message } from '@ably/chat';
import { Message, MessageReactionType } from '@ably/chat';
import { useMessages } from '@ably/chat/react';

const { updateMessage, deleteMessage, sendReaction, deleteReaction } = useMessages();
Expand All @@ -538,19 +540,24 @@ const { updateMessage, deleteMessage, sendReaction, deleteReaction } = useMessag
message={message}
onEdit={(message: Message, newText: string) => {
console.log(`Editing message with serial: ${message.serial}, setting text to: ${newText}`);
updateMessage(message.serial, { text: newText });
// Use message.copy() to create an updated message with the new text
const updated = message.copy({ text: newText, metadata: message.metadata, headers: message.headers });
updateMessage(message.serial, updated);
}}
onDelete={(message: Message) => {
console.log(`Deleting message with serial: ${message.serial}`);
deleteMessage(message.serial);
// Pass an optional description for the deletion
deleteMessage(message.serial, { description: 'deleted by user' });
}}
onReactionAdd={(message: Message, emoji: string) => {
console.log(`Adding reaction ${emoji} to message with serial: ${message.serial}`);
sendReaction(message.serial, { name: emoji });
// Include the reaction type (e.g., MessageReactionType.Distinct)
sendReaction(message.serial, { type: MessageReactionType.Distinct, name: emoji });
}}
onReactionRemove={(message: Message, emoji: string) => {
console.log(`Removing reaction ${emoji} from message with serial: ${message.serial}`);
deleteReaction(message.serial, { name: emoji });
// Include the reaction type when removing
deleteReaction(message.serial, { type: MessageReactionType.Distinct, name: emoji });
}}
/>
```
Expand Down Expand Up @@ -624,17 +631,22 @@ The Avatar component is designed to integrate with the `AvatarProvider` to displ
<Code>
```react
import { Avatar, useUserAvatar } from '@ably/chat-react-ui-kit';
const { userAvatar } = useUserAvatar({

function UserAvatarExample() {
const { userAvatar } = useUserAvatar({
clientId: 'user-123',
displayName: 'John Doe',
});

<Avatar
src={userAvatar?.src}
alt={userAvatar?.displayName}
color={userAvatar?.color}
initials={userAvatar?.initials}
/>
return (
<Avatar
src={userAvatar?.src}
alt={userAvatar?.displayName}
color={userAvatar?.color}
initials={userAvatar?.initials}
/>
);
}
```
</Code>

Expand Down Expand Up @@ -680,25 +692,30 @@ import { ParticipantList } from '@ably/chat-react-ui-kit';
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);
function ParticipantListExample() {
const { presenceData } = usePresence();
const { currentlyTyping } = useTyping();
const { clientId } = useChatClient();
const [participantListOpen, setParticipantListOpen] = useState(false);

const toggleParticipantList = () => {
console.log('Toggling participant list');
setParticipantListOpen(prev => !prev);
};
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 }}
/>
)}
return (
<>
{participantListOpen && (
<ParticipantList
presenceData={presenceData}
currentClientId={clientId}
currentlyTyping={currentlyTyping}
onToggle={toggleParticipantList}
position={{ top: 100, left: 200 }}
/>
)}
</>
);
}
```
</Code>
Loading