Skip to content

Commit

Permalink
chore(docs/chat-composer): Update the documentation for the new Chat …
Browse files Browse the repository at this point in the history
…Composer elements (#3981)

* feat(composer): wip base elements

* feat(composer): addition of all attatchment components

* feat(composer): lint fix

* feat(composer): fix disabled styling

* feat(composer): responsive columns and JS doc

* feat(composer-docs): wip examples

* feat(composer): add new plugin to access state

* feat(composer): fix lint issues

* feat(docs-composer): added in stories for log types

* chore(docs): update AI Chat  Log page name

* chore(chat-composer): clenaup unused imports

* chore(chat-composer): remove duplicate story

* chore(docs/chat-composer): content changes for latest component updates

* chore(chat-composer): remove attachment

* chore(chat-composer): remove unused component

* chore(chat-composer): pr cleanup

* chore(docs/ai-chat-log): correct storybook link

* chore(docs/chat-composer): type fix

* chore(docs/chat-composer): formatting fix

* chore(docs/chat-composer): lint fix

* chore(docs/chat-composer): story update

* Update packages/paste-website/src/pages/components/chat-composer/index.mdx

Co-authored-by: Sarah <[email protected]>

* Apply suggestions from code review

Co-authored-by: Sarah <[email protected]>

* chore(docs/chat-composer): remove redundant changeset

* chore(docs/chat-composer): update docs AI story example

* chore(chat-composer): updated typedoc

* Update packages/paste-website/src/pages/components/chat-composer/index.mdx

Co-authored-by: Sarah <[email protected]>

* chore(docs/chat-composer): show default contained variant

* chore(docs/chat-composer): formatting fix

---------

Co-authored-by: Sarah <[email protected]>
  • Loading branch information
krisantrobus and serifluous authored Jul 11, 2024
1 parent 7779a24 commit 9e54abc
Show file tree
Hide file tree
Showing 10 changed files with 632 additions and 176 deletions.
6 changes: 6 additions & 0 deletions .changeset/cold-apes-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/chat-composer": patch
"@twilio-paste/core": patch
---

[ChatComposer] updated JS Doc used for tpye gen in docs website
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,7 @@ export const AIChatLogComposer = (): React.ReactNode => {
content: (
<AIChatMessage variant="user">
<AIChatMessageAuthor aria-label="you said at 2:36pm">Gibby Radki</AIChatMessageAuthor>
<AIChatMessageBody>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Deserunt delectus fuga, necessitatibus eligendi
iure adipisci facilis exercitationem officiis dolorem laborum, ex fugiat quisquam itaque, earum sit nesciunt
impedit repellat assumenda.
</AIChatMessageBody>
<AIChatMessageBody>Hi, I am getting errors codes when sending an SMS.</AIChatMessageBody>
</AIChatMessage>
),
},
Expand All @@ -144,9 +140,7 @@ export const AIChatLogComposer = (): React.ReactNode => {
<AIChatMessage variant="bot">
<AIChatMessageAuthor aria-label="AI said">Good Bot</AIChatMessageAuthor>
<AIChatMessageBody>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Deserunt delectus fuga, necessitatibus
eligendiiure adipisci facilis exercitationem officiis dolorem laborum, ex fugiat quisquam itaque, earum sit
nesciunt impedit repellat assumenda.
Error codes can be returned from various parts of the process. What error codes are you encountering?
<Box marginTop="space50">
<ButtonGroup>
<Button variant="secondary" onClick={() => {}} size="rounded_small">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface ChatComposerAttachmentGroupProps {
*/
element?: BoxProps["element"];
/**
* Sets the number of columns in the attachement grid
* Sets the number of columns in the attachment grid
* @default 2
* @type number
* @memberof ChatComposerAttachmentGroupProps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,38 +263,14 @@ const BotMessage = (props): JSX.Element => {
);
};

// eslint-disable-next-line storybook/prefer-pascal-case
const createNewAIMessage = (message: string): Omit<AIChat, "id"> => {
const messageDirection = getRandomInt(2) === 1 ? "user" : "bot";

return {
variant: messageDirection,
content:
messageDirection === "user" ? (
<AIChatMessage variant="user">
<AIChatMessageAuthor aria-label="You said at 2:39pm">Gibby Radki</AIChatMessageAuthor>
<AIChatMessageBody>{message}</AIChatMessageBody>
</AIChatMessage>
) : (
<AIChatMessage variant="bot">
<BotMessage message={message} />
</AIChatMessage>
),
};
};

export const AIChatLogComposer = (): React.ReactNode => {
const { aiChats, push } = useAIChatLogger(
{
variant: "user",
content: (
<AIChatMessage variant="user">
<AIChatMessageAuthor aria-label="you said at 2:36pm">Gibby Radki</AIChatMessageAuthor>
<AIChatMessageBody>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Deserunt delectus fuga, necessitatibus eligendi
iure adipisci facilis exercitationem officiis dolorem laborum, ex fugiat quisquam itaque, earum sit nesciunt
impedit repellat assumenda.
</AIChatMessageBody>
<AIChatMessageBody>Hi, I am getting errors codes when sending an SMS.</AIChatMessageBody>
</AIChatMessage>
),
},
Expand All @@ -304,9 +280,7 @@ export const AIChatLogComposer = (): React.ReactNode => {
<AIChatMessage variant="bot">
<AIChatMessageAuthor aria-label="AI said">Good Bot</AIChatMessageAuthor>
<AIChatMessageBody>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Deserunt delectus fuga, necessitatibus
eligendiiure adipisci facilis exercitationem officiis dolorem laborum, ex fugiat quisquam itaque, earum sit
nesciunt impedit repellat assumenda.
Error codes can be returned from various parts of the process. What error codes are you encountering?
<Box marginTop="space50">
<ButtonGroup>
<Button variant="secondary" onClick={() => {}} size="rounded_small">
Expand Down Expand Up @@ -362,7 +336,15 @@ export const AIChatLogComposer = (): React.ReactNode => {

const submitMessage = (): void => {
if (message === "") return;
push(createNewAIMessage(message));
push({
variant: "user",
content: (
<AIChatMessage variant="user">
<AIChatMessageAuthor aria-label="You said at 2:39pm">Gibby Radki</AIChatMessageAuthor>
<AIChatMessageBody>{message}</AIChatMessageBody>
</AIChatMessage>
),
});
};

const editorInstanceRef = React.useRef<LexicalEditor>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2324,7 +2324,7 @@
"defaultValue": "2",
"required": false,
"externalProp": false,
"description": "Sets the number of columns in the attachement grid"
"description": "Sets the number of columns in the attachment grid"
},
"element": {
"type": "string",
Expand Down
189 changes: 144 additions & 45 deletions packages/paste-website/src/component-examples/ChatComposerExamples.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { Box } from "@twilio-paste/box";
import { Button } from "@twilio-paste/button";
import { ChatBubble, ChatMessage, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log";
import type { Chat } from "@twilio-paste/chat-log";
import { SendIcon } from "@twilio-paste/icons/esm/SendIcon";
import {
CLEAR_EDITOR_COMMAND,
COMMAND_PRIORITY_HIGH,
Expand Down Expand Up @@ -94,23 +91,6 @@ export const createNewMessage = (message: string): Omit<Chat, "id"> => {
};
};

export const SendButtonPlugin = ({ onClick }: { onClick: () => void }): JSX.Element => {
const [editor] = useLexicalComposerContext();

const handleSend = (): void => {
onClick();
editor.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
};

return (
<Box position="absolute" top="space30" right="space30">
<Button variant="primary_icon" size="reset" onClick={handleSend}>
<SendIcon decorative={false} title="Send message" />
</Button>
</Box>
);
};

export const EnterKeySubmitPlugin = ({ onKeyDown }: { onKeyDown: () => void }): null => {
const [editor] = useLexicalComposerContext();

Expand All @@ -134,7 +114,7 @@ export const EnterKeySubmitPlugin = ({ onKeyDown }: { onKeyDown: () => void }):
};

export const ChatDialogExample = `const ChatDialog = () => {
const {chats, push} = useChatLogger(
const { chats, push } = useChatLogger(
{
content: (
<ChatBookend>
Expand All @@ -146,7 +126,7 @@ export const ChatDialogExample = `const ChatDialog = () => {
),
},
{
variant: 'inbound',
variant: "inbound",
content: (
<ChatMessage variant="inbound">
<ChatBubble>Quisque ullamcorper ipsum vitae lorem euismod sodales.</ChatBubble>
Expand All @@ -170,7 +150,7 @@ export const ChatDialogExample = `const ChatDialog = () => {
),
},
{
variant: 'inbound',
variant: "inbound",
content: (
<ChatMessage variant="inbound">
<ChatBubble>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</ChatBubble>
Expand All @@ -182,9 +162,9 @@ export const ChatDialogExample = `const ChatDialog = () => {
</ChatMessageMeta>
</ChatMessage>
),
}
},
);
const [message, setMessage] = React.useState('');
const [message, setMessage] = React.useState("");
const [mounted, setMounted] = React.useState(false);
const loggerRef = React.useRef(null);
Expand All @@ -196,7 +176,7 @@ export const ChatDialogExample = `const ChatDialog = () => {
React.useEffect(() => {
if (!mounted || !loggerRef.current) return;
scrollerRef.current?.scrollTo({top: loggerRef.current.scrollHeight, behavior: 'smooth'});
scrollerRef.current?.scrollTo({ top: loggerRef.current.scrollHeight, behavior: "smooth" });
}, [chats, mounted]);
const handleComposerChange = (editorState) => {
Expand All @@ -207,10 +187,12 @@ export const ChatDialogExample = `const ChatDialog = () => {
};
const submitMessage = () => {
if (message === '') return;
if (message === "") return;
push(createNewMessage(message));
};
const editorInstanceRef = React.useRef<LexicalEditor>(null);
return (
<Box>
<Box ref={scrollerRef} overflowX="hidden" overflowY="auto" maxHeight="size50" tabIndex={0}>
Expand All @@ -221,31 +203,148 @@ export const ChatDialogExample = `const ChatDialog = () => {
borderWidth="borderWidth0"
borderTopWidth="borderWidth10"
borderColor="colorBorderWeak"
display="flex"
flexDirection="row"
columnGap="space30"
paddingX="space70"
paddingTop="space50"
>
<ChatComposer
maxHeight="size10"
config={{
namespace: 'foo',
onError: (error) => {
throw error;
},
}}
ariaLabel="Message"
placeholder="Type here..."
onChange={handleComposerChange}
>
<ClearEditorPlugin />
<SendButtonPlugin onClick={submitMessage} />
<EnterKeySubmitPlugin onKeyDown={submitMessage} />
</ChatComposer>
<ChatComposerContainer>
<ChatComposer
maxHeight="size10"
config={{
namespace: "foo",
onError: (error) => {
throw error;
},
}}
ariaLabel="Message"
placeholder="Type here..."
onChange={handleComposerChange}
editorInstanceRef={editorInstanceRef}
>
<ClearEditorPlugin />
<EnterKeySubmitPlugin onKeyDown={submitMessage} />
</ChatComposer>
<ChatComposerActionGroup>
<Button variant="secondary_icon" size="reset">
<AttachIcon decorative={false} title="attach files to the message" />
</Button>
<Button
variant="primary_icon"
size="reset"
onClick={() => {
submitMessage();
editorInstanceRef.current?.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
}}
>
<SendIcon decorative={false} title="Send" />
</Button>
</ChatComposerActionGroup>
</ChatComposerContainer>
</Box>
</Box>
);
};
render(<ChatDialog />)`.trim();

export const ResponsiveContainedAttachmentsExample = `const ResponsiveContainedAttachmentsExample = () => {
const ExampleAttachment = () => (
<ChatComposerAttachmentCard onDismiss={() => {}} attachmentIcon={<DownloadIcon decorative />}>
<ChatComposerAttachmentLink href="www.google.com">Document-FINAL.doc</ChatComposerAttachmentLink>
<ChatComposerAttachmentDescription>123 MB</ChatComposerAttachmentDescription>
</ChatComposerAttachmentCard>
)
return (
<ChatComposerContainer>
<ChatComposer
ariaLabel="A chat with attachments"
initialValue="This is my initial value"
config={{
namespace: "customer-chat",
onError: (e) => {
throw e;
},
}}
/>
<ChatComposerActionGroup>
<Button variant="secondary_icon" size="reset">
<AttachIcon decorative={false} title="attach files to the message" />
</Button>
<Button variant="primary_icon" size="reset">
<SendIcon decorative={false} title="Send" />
</Button>
</ChatComposerActionGroup>
<ChatComposerAttachmentGroup columns={[1, 1, 2, 3]}>
{Array.from({ length: 6 }).map((_, index) => (
<ExampleAttachment key={index} />
))}
</ChatComposerAttachmentGroup>
</ChatComposerContainer>
)
}
render(<ResponsiveContainedAttachmentsExample />)`.trim();

export const ContainedDisabledExample = `const ContainedDisabledExample = () => {
const [isDisabled, setIsDisabled] = React.useState(true);
return (
<>
<Box marginBottom="space50">
<Checkbox checked={isDisabled} onClick={() => setIsDisabled((disabled) => !disabled)}>
Disable Input
</Checkbox>
</Box>
<ChatComposerContainer variant="contained">
<ChatComposer
ariaLabel="A chat that is disabled"
initialValue="This is my initial value"
config={{
namespace: "customer-chat",
onError: (e) => {
throw e;
},
}}
disabled={isDisabled}
/>
<ChatComposerActionGroup>
<Button variant="secondary_icon" size="reset" aria-disabled={isDisabled} disabled={isDisabled}>
<AttachIcon decorative={false} title="attach files to the message" />
</Button>
<Button variant="primary_icon" size="reset" aria-disabled={isDisabled} disabled={isDisabled}>
<SendIcon decorative={false} title="Send" />
</Button>
</ChatComposerActionGroup>
</ChatComposerContainer>
</>
);
}
render(<ContainedDisabledExample />)`.trim();

export const ContainedExample = `const ContainedExample = () => {
return (
<ChatComposerContainer variant="contained">
<ChatComposer
ariaLabel="A chat with attachments"
initialValue="This is my initial value"
config={{
namespace: "customer-chat",
onError: (e) => {
throw e;
},
}}
/>
<ChatComposerActionGroup>
<Button variant="secondary_icon" size="reset">
<AttachIcon decorative={false} title="attach files to the message" />
</Button>
<Button variant="primary_icon" size="reset">
<SendIcon decorative={false} title="Send" />
</Button>
</ChatComposerActionGroup>
</ChatComposerContainer>
);
}
render(<ContainedExample />)`.trim();
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ export const getStaticProps = async () => {
data: {
...packageJson,
...feature,
nameOverride: 'AI Chat Log',
},
componentApi,
mdxHeadings: [...mdxHeadings, ...componentApiTocData],
navigationData,
pageHeaderData: {
categoryRoute: SidebarCategoryRoutes.COMPONENTS,
githubUrl: "https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/ai-chat-log",
storybookUrl: "/?path=/story/components-chatlog--example-chat-log",
storybookUrl: "/?path=/story/components-ai-chat-log--example-ai-chat-log",
},
},
};
Expand Down
Loading

0 comments on commit 9e54abc

Please sign in to comment.