Skip to content

Commit 1f7beeb

Browse files
[RTE] Storybook update for rich text edit box (#4441)
1 parent 68dfd12 commit 1f7beeb

13 files changed

+99
-280
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "none",
3+
"area": "improvement",
4+
"workstream": "RTE",
5+
"comment": "Add rich text editor examples for MessageThread",
6+
"packageName": "@azure/communication-react",
7+
"email": "[email protected]",
8+
"dependentChangeType": "none"
9+
}

packages/storybook/stories/INTERNAL/RTE/RichTextEditBox.stories.tsx

Lines changed: 0 additions & 82 deletions
This file was deleted.

packages/storybook/stories/INTERNAL/RTE/snippets/RichTextEditBoxAttachmentUploads.snippet.tsx

Lines changed: 0 additions & 46 deletions
This file was deleted.

packages/storybook/stories/MessageThread/MessageThread.stories.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { MessageWithCustomMentionRenderer } from './snippets/MessageWithCustomMe
5959
import { MessageThreadWithSystemMessagesExample } from './snippets/SystemMessages.snippet';
6060
import { MessageThreadWithInlineImageExample } from './snippets/WithInlineImageMessage.snippet';
6161
import { MessageThreadWithMessageDateExample } from './snippets/WithMessageDate.snippet';
62+
import { MessageThreadWithRichTextEditorExample } from './snippets/WithRichTextEditor.snippet';
6263

6364
const MessageThreadWithBlockedMessagesExampleText =
6465
require('!!raw-loader!./snippets/BlockedMessages.snippet.tsx').default;
@@ -89,6 +90,7 @@ const MessageThreadWithSystemMessagesExampleText =
8990
const MessageThreadWithInlineImageExampleText =
9091
require('!!raw-loader!./snippets/WithInlineImageMessage.snippet.tsx').default;
9192
const MessageThreadWithMessageDateExampleText = require('!!raw-loader!./snippets/WithMessageDate.snippet.tsx').default;
93+
const MessageThreadWithRichTextEditorText = require('!!raw-loader!./snippets/WithRichTextEditor.snippet.tsx').default;
9294

9395
const importStatement = `
9496
import { FluentThemeProvider, MessageThread } from '@azure/communication-react';
@@ -115,6 +117,7 @@ const Docs: () => JSX.Element = () => {
115117
const refDisplayInlineImages = useRef(null);
116118
const refDisplayAttachments = useRef(null);
117119
const refMentionOfUsers = useRef(null);
120+
const refRichTextEditor = useRef(null);
118121
const refProps = useRef(null);
119122

120123
const scrollToRef = (ref): void => {
@@ -159,6 +162,8 @@ const Docs: () => JSX.Element = () => {
159162
scrollToRef(refDisplayAttachments);
160163
} else if (url.includes('mention-of-users-with-a-custom-renderer-within-messages') && refMentionOfUsers.current) {
161164
scrollToRef(refMentionOfUsers);
165+
} else if (url.includes('rich-text-editor-support-for-editing-messages') && refRichTextEditor.current) {
166+
scrollToRef(refRichTextEditor);
162167
} else if (url.includes('props') && refProps.current) {
163168
scrollToRef(refProps);
164169
}
@@ -192,6 +197,12 @@ const Docs: () => JSX.Element = () => {
192197
checkout the details about these components
193198
[here](https://microsoft.github.io/fluentui-contrib/react-chat/?path=/story/chat--default).
194199
</Description>
200+
<Description>
201+
The MessageThread component supports lazy loading for the rich text editor used for editing messages. This means
202+
that the rich text editor and its dependencies can be excluded from the bundle if they're not required,
203+
utilizing tree-shaking techniques such as [the sideEffects
204+
option](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) in webpack.
205+
</Description>
195206

196207
<Heading>Importing</Heading>
197208
<Source code={importStatement} />
@@ -368,6 +379,18 @@ const Docs: () => JSX.Element = () => {
368379
</Canvas>
369380
</div>
370381

382+
<div ref={refRichTextEditor}>
383+
<Heading>Rich Text Editor Support for Editing Messages</Heading>
384+
<DetailedBetaBanner />
385+
<Description>
386+
The following example shows how to enable rich text editor for message editing by providing the
387+
`richTextEditor`` property.
388+
</Description>
389+
<Canvas mdxSource={MessageThreadWithRichTextEditorText}>
390+
<MessageThreadWithRichTextEditorExample />
391+
</Canvas>
392+
</div>
393+
371394
<div ref={refProps}>
372395
<Heading>Props</Heading>
373396
<Props of={MessageThreadComponent} />
@@ -452,6 +475,9 @@ const MessageThreadStory = (args): JSX.Element => {
452475
if (message.messageType === 'chat') {
453476
message.content = content;
454477
message.editedOn = new Date(Date.now());
478+
if (args.richTextEditor === true) {
479+
message.contentType = 'html';
480+
}
455481
}
456482
updatedChatMessages[msgIdx] = message;
457483
setChatMessages(updatedChatMessages);
@@ -553,6 +579,7 @@ const MessageThreadStory = (args): JSX.Element => {
553579
onRenderMessage={onRenderMessage}
554580
inlineImageOptions={inlineImageOptions}
555581
onUpdateMessage={onUpdateMessageCallback}
582+
richTextEditor={args.richTextEditor}
556583
onRenderAvatar={(userId?: string) => {
557584
return (
558585
<Persona
@@ -608,6 +635,7 @@ export default {
608635
showMessageDate: controlsToAdd.showMessageDate,
609636
showMessageStatus: controlsToAdd.showMessageStatus,
610637
enableJumpToNewMessageButton: controlsToAdd.enableJumpToNewMessageButton,
638+
richTextEditor: controlsToAdd.richTextEditor,
611639
// Hiding auto-generated controls
612640
styles: hiddenControl,
613641
strings: hiddenControl,
@@ -623,8 +651,7 @@ export default {
623651
onRenderMessage: hiddenControl,
624652
onUpdateMessage: hiddenControl,
625653
onDeleteMessage: hiddenControl,
626-
disableEditing: hiddenControl,
627-
richTextEditor: hiddenControl
654+
disableEditing: hiddenControl
628655
},
629656
parameters: {
630657
docs: {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { FluentThemeProvider, MessageThread } from '@azure/communication-react';
2+
import React, { useCallback, useState } from 'react';
3+
import { GetHistoryHTMLChatMessages } from './placeholdermessages';
4+
5+
export const MessageThreadWithRichTextEditorExample: () => JSX.Element = () => {
6+
const [messages, setMessages] = useState(GetHistoryHTMLChatMessages());
7+
const onUpdateMessage = useCallback(
8+
(messageId: string, content: string): Promise<void> => {
9+
const updatedMessages = messages;
10+
const index = updatedMessages.findIndex((m) => m.messageId === messageId);
11+
if (index === -1) {
12+
return Promise.reject('Message not found');
13+
}
14+
const message = updatedMessages[index];
15+
message.content = content;
16+
message.editedOn = new Date(Date.now());
17+
updatedMessages[index] = message;
18+
setMessages(updatedMessages);
19+
20+
return Promise.resolve();
21+
},
22+
[messages]
23+
);
24+
25+
return (
26+
<FluentThemeProvider>
27+
<MessageThread userId={'1'} richTextEditor={true} messages={messages} onUpdateMessage={onUpdateMessage} />
28+
</FluentThemeProvider>
29+
);
30+
};

packages/storybook/stories/MessageThread/snippets/placeholdermessages.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ export const GetHistoryChatMessages = (): ChatMessage[] => {
5757
];
5858
};
5959

60+
export const GetHistoryHTMLChatMessages = (): ChatMessage[] => {
61+
return GetHistoryChatMessages().map((message) => {
62+
return {
63+
...message,
64+
contentType: 'html'
65+
};
66+
});
67+
};
68+
6069
export const GetHistoryWithSystemMessages = (): (SystemMessage | ChatMessage)[] => {
6170
return [
6271
...GetHistoryChatMessages(),

packages/storybook/stories/INTERNAL/RTE/RichTextSendBox.stories.tsx renamed to packages/storybook/stories/SendBox/RichTextSendBox.stories.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
import { RichTextSendBox as RichTextSendBoxComponent } from '@internal/react-components';
4+
import { RichTextSendBox as RichTextSendBoxComponent } from '@azure/communication-react';
55
import { Title, Description, Props, Heading, Canvas, Source } from '@storybook/addon-docs';
66
import { Meta } from '@storybook/react/types-6-0';
77
import React from 'react';
8-
import { DetailedBetaBanner } from '../../BetaBanners/DetailedBetaBanner';
9-
import { COMPONENT_FOLDER_PREFIX } from '../../constants';
10-
import { hiddenControl } from '../../controlsUtils';
8+
import { DetailedBetaBanner } from '../BetaBanners/DetailedBetaBanner';
9+
import { SingleLineBetaBanner } from '../BetaBanners/SingleLineBetaBanner';
10+
import { COMPONENT_FOLDER_PREFIX } from '../constants';
11+
import { hiddenControl, controlsToAdd } from '../controlsUtils';
1112
import { RichTextSendBoxExample } from './snippets/RichTextSendBox.snippet';
1213
import { RichTextSendBoxAttachmentUploadsExample } from './snippets/RichTextSendBoxAttachmentUploads.snippet';
1314
import { RichTextSendBoxWithSystemMessageExample } from './snippets/RichTextSendBoxWithSystemMessage.snippet';
@@ -23,8 +24,12 @@ const importStatement = `import { RichTextSendBox } from '@azure/communication-r
2324
const getDocs: () => JSX.Element = () => {
2425
return (
2526
<>
27+
<SingleLineBetaBanner topOfPage={true} />
2628
<Title>RichTextSendBox</Title>
27-
<Description>Component for composing messages with rich text formatting.</Description>
29+
<Description>
30+
Component for composing messages with rich text formatting. RichTextSendBox has a callback for sending typing
31+
notification when user starts entering text. It also supports an optional message above the rich text editor.
32+
</Description>
2833

2934
<Heading>Importing</Heading>
3035
<Source code={importStatement} />
@@ -65,12 +70,16 @@ const RichTextSendBoxStory = (args): JSX.Element => {
6570
<div style={{ width: '31.25rem', maxWidth: '90%' }}>
6671
<RichTextSendBoxComponent
6772
disabled={args.disabled}
68-
systemMessage={args.isSendBoxWithWarning ? args.systemMessage : undefined}
73+
systemMessage={args.hasWarning ? args.warningMessage : undefined}
6974
onSendMessage={async (message) => {
7075
timeoutRef.current = setTimeout(() => {
7176
alert(`sent message: ${message} `);
7277
}, delayForSendButton);
7378
}}
79+
onTyping={(): Promise<void> => {
80+
console.log(`sending typing notifications`);
81+
return Promise.resolve();
82+
}}
7483
/>
7584
</div>
7685
);
@@ -81,13 +90,13 @@ const RichTextSendBoxStory = (args): JSX.Element => {
8190
export const RichTextSendBox = RichTextSendBoxStory.bind({});
8291

8392
export default {
84-
id: `${COMPONENT_FOLDER_PREFIX}-internal-richtextsendbox`,
85-
title: `${COMPONENT_FOLDER_PREFIX}/Internal/RichTextSendBox`,
93+
id: `${COMPONENT_FOLDER_PREFIX}-richtextsendbox`,
94+
title: `${COMPONENT_FOLDER_PREFIX}/Send Box/Rich Text Send Box`,
8695
component: RichTextSendBoxComponent,
8796
argTypes: {
88-
disabled: { control: 'boolean', defaultValue: false },
89-
systemMessage: { control: 'text', defaultValue: undefined },
90-
isSendBoxWithWarning: { control: 'boolean', defaultValue: false, name: 'Has warning/information message' },
97+
disabled: controlsToAdd.disabled,
98+
hasWarning: controlsToAdd.isSendBoxWithWarning,
99+
warningMessage: controlsToAdd.sendBoxWarningMessage,
91100
strings: hiddenControl,
92101
onRenderAttachmentUploads: hiddenControl,
93102
attachmentsWithProgress: hiddenControl,

packages/storybook/stories/SendBox/SendBox.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export const SendBox = SendBoxStory.bind({});
132132

133133
export default {
134134
id: `${COMPONENT_FOLDER_PREFIX}-sendbox`,
135-
title: `${COMPONENT_FOLDER_PREFIX}/Send Box`,
135+
title: `${COMPONENT_FOLDER_PREFIX}/Send Box/Send Box`,
136136
component: SendBoxComponent,
137137
argTypes: {
138138
disabled: controlsToAdd.disabled,

0 commit comments

Comments
 (0)