diff --git a/packages/paste-core/components/ai-chat-log/stories/errors.stories.tsx b/packages/paste-core/components/ai-chat-log/stories/errors.stories.tsx new file mode 100644 index 0000000000..e4f4f62fa4 --- /dev/null +++ b/packages/paste-core/components/ai-chat-log/stories/errors.stories.tsx @@ -0,0 +1,372 @@ +// eslint-disable-next-line eslint-comments/disable-enable-pair +/* eslint-disable import/no-extraneous-dependencies */ + +import { Alert } from "@twilio-paste/alert"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { ButtonGroup } from "@twilio-paste/button-group"; +import { ChatComposer, ChatComposerActionGroup, ChatComposerContainer } from "@twilio-paste/chat-composer"; +import { HelpText } from "@twilio-paste/help-text"; +import { AttachIcon } from "@twilio-paste/icons/esm/AttachIcon"; +import { CopyIcon } from "@twilio-paste/icons/esm/CopyIcon"; +import { RefreshIcon } from "@twilio-paste/icons/esm/RefreshIcon"; +import { RepeatIcon } from "@twilio-paste/icons/esm/RepeatIcon"; +import { SendIcon } from "@twilio-paste/icons/esm/SendIcon"; +import { ThumbsDownIcon } from "@twilio-paste/icons/esm/ThumbsDownIcon"; +import { ThumbsUpIcon } from "@twilio-paste/icons/esm/ThumbsUpIcon"; +import { ClearEditorPlugin } from "@twilio-paste/lexical-library"; +import { Text } from "@twilio-paste/text"; +import * as React from "react"; + +import { Callout, CalloutHeading, CalloutText } from "../../callout/src"; +import { + SummaryDetail, + SummaryDetailContent, + SummaryDetailHeading, + SummaryDetailHeadingContent, + SummaryDetailToggleButton, +} from "../../summary-detail/src"; +import { + AIChatLog, + AIChatMessage, + AIChatMessageActionCard, + AIChatMessageActionGroup, + AIChatMessageAuthor, + AIChatMessageBody, +} from "../src"; + +export default { + title: "Components/AI Chat Log/Errors", + component: AIChatLog, +}; + +const Composer = (): JSX.Element => { + return ( + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + ); +}; + +export const MessageGenerationError = (): React.ReactNode => { + return ( + <> + + + + You + + Message filtered (30007) + + + Good Bot + + + There was an error generating a response. + + Please try again, if the error persists please contact us. + + + + + + + + + + + + + + + ); +}; + +MessageGenerationError.parameters = { + a11y: { + disable: true, + }, +}; + +export const AIActionClickError = (): React.ReactNode => { + return ( + <> + + + + You + + Message filtered (30007) + + + Good Bot + + We recommend reviewing our guidelines on filtering and scaling to better manage high volumes of messages. + + + + + + + + + + The action couldn’t be completed. + + Please try again, if the error persists please contact us. + + + + + + + + + + ); +}; + +AIActionClickError.parameters = { + a11y: { + disable: true, + }, +}; + +export const ActionGroupError = (): React.ReactNode => { + return ( + <> + + + + You + + Message body text + + + Good Bot + + Message body text + + + + + + + View data sources + + + + Data Content + + + + + + Is this helpful? + + + + + + + + + The action couldn’t be completed. Please try again. + + + + + + + + ); +}; + +ActionGroupError.parameters = { + a11y: { + disable: true, + }, +}; + +export const SendingMessageError = (): React.ReactNode => { + return ( + <> + + + Good Bot + + Messages from +1 234-292-2349 are failing due to the following top 3 errors which occurred in the past 7 + days: + + + + + + + + + + Is this helpful? + + + + + + + + + + You + + + Message body text + + + + Message failed to send + + + + + + + + + + + + ); +}; + +SendingMessageError.parameters = { + a11y: { + disable: true, + }, +}; + +export const SystemError = (): React.ReactNode => { + return ( + <> + + + + You + + Message body text + + + Good Bot + + Message body text + + + + + + + View data sources + + + + Data Content + + + + + + Is this helpful? + + + + + + + + + + + + + +
+ Something went wrong. +
+ If this issue persists please contact us through our help center. +
+
+ + + + + + ); +}; + +SystemError.parameters = { + a11y: { + disable: true, + }, +}; diff --git a/packages/paste-website/src/component-examples/AIChatLogExamples.ts b/packages/paste-website/src/component-examples/AIChatLogExamples.ts index 5c77fae426..a1622bae7b 100644 --- a/packages/paste-website/src/component-examples/AIChatLogExamples.ts +++ b/packages/paste-website/src/component-examples/AIChatLogExamples.ts @@ -188,7 +188,7 @@ const AIChatLogExample = () => { - Good Bot + Good Bot {}} /> @@ -308,3 +308,407 @@ const AvatarExample = () => { render( )`.trim(); + +export const messageGenerationError = ` +const MessageGenerationError = () => { + return ( + <> + + + + You + + Message filtered (30007) + + + Good Bot + + + There was an error generating a response. + + Please try again, if the error persists please contact us. + + + + + + + + + + + + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + + + ); +}; + +render( + +)`.trim(); + +export const aIActionClickError = ` +const AIActionClickError = () => { + return ( + <> + + + + You + + Message filtered (30007) + + + Good Bot + + We recommend reviewing our guidelines on filtering and scaling to better manage high volumes of messages. + + + + + + + + + + The action couldn’t be completed. + + Please try again, if the error persists please contact us. + + + + + + + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + + + ); +}; + +render( + +)`.trim(); + +export const actionGroupError = ` +const ActionGroupError = () => { + return ( + <> + + + + You + + Message body text + + + Good Bot + + Message body text + + + + + + View data sources + + + Data Content + + + + + + Is this helpful? + + + + + + + + + The action couldn’t be completed. Please try again. + + + + + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + + + ); +}; + +render( + +)`.trim(); + +export const sendingMessageError = ` +const SendingMessageError = () => { + return ( + <> + + + Good Bot + + Messages from +1 234-292-2349 are failing due to the following top 3 errors which occurred in the past 7 + days: + + + + + + + + + + Is this helpful? + + + + + + + + + + You + + + Message body text + + + + Message failed to send + + + + + + + + + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + + + ); +}; + +render( + +)`.trim(); + +export const systemError = ` +const SystemError = () => { + return ( + <> + + + + You + + Message body text + + + Good Bot + + Message body text + + + + + + + View data sources + + + + Data Content + + + + + + Is this helpful? + + + + + + + + + + + + + +
+ Something went wrong. +
+ If this issue persists please contact us through our help center. +
+
+ + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + > + + + + + + + + + + ); +}; + +render( + +)`.trim(); diff --git a/packages/paste-website/src/pages/components/ai-chat-log/index.mdx b/packages/paste-website/src/pages/components/ai-chat-log/index.mdx index 49ac0088c0..feb662d0cb 100644 --- a/packages/paste-website/src/pages/components/ai-chat-log/index.mdx +++ b/packages/paste-website/src/pages/components/ai-chat-log/index.mdx @@ -6,47 +6,63 @@ export const meta = { slug: "/components/ai-chat-log/", }; -import { uid } from "@twilio-paste/uid-library"; -import { HelpText } from "@twilio-paste/help-text"; -import { Button } from "@twilio-paste/button"; -import { ButtonGroup } from "@twilio-paste/button-group"; -import { Stack } from "@twilio-paste/stack"; -import { Paragraph } from "@twilio-paste/paragraph"; import { AIChatLog, + AIChatLogger, AIChatMessage, + AIChatMessageActionCard, + AIChatMessageActionGroup, AIChatMessageAuthor, AIChatMessageBody, AIChatMessageLoading, - AIChatLogger, useAIChatLogger, - AIChatMessageActionCard, - AIChatMessageActionGroup, } from "@twilio-paste/ai-chat-log"; -import { ThumbsUpIcon } from "@twilio-paste/icons/esm/ThumbsUpIcon"; -import { ThumbsDownIcon } from "@twilio-paste/icons/esm/ThumbsDownIcon"; -import { RefreshIcon } from "@twilio-paste/icons/esm/RefreshIcon"; +import Changelog from "@twilio-paste/ai-chat-log/CHANGELOG.md"; +import { Button } from "@twilio-paste/button"; +import { ButtonGroup } from "@twilio-paste/button-group"; +import { HelpText } from "@twilio-paste/help-text"; import { CopyIcon } from "@twilio-paste/icons/esm/CopyIcon"; import { LogoTwilioIcon } from "@twilio-paste/icons/esm/LogoTwilioIcon"; -import Changelog from "@twilio-paste/ai-chat-log/CHANGELOG.md"; +import { RefreshIcon } from "@twilio-paste/icons/esm/RefreshIcon"; +import { ThumbsDownIcon } from "@twilio-paste/icons/esm/ThumbsDownIcon"; +import { ThumbsUpIcon } from "@twilio-paste/icons/esm/ThumbsUpIcon"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { Stack } from "@twilio-paste/stack"; +import { uid } from "@twilio-paste/uid-library"; -import { SidebarCategoryRoutes } from "../../../constants"; import Logo from "../../../assets/logo.svg"; +import { SidebarCategoryRoutes } from "../../../constants"; +import packageJson from "@twilio-paste/ai-chat-log/package.json"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { ChatComposer, ChatComposerActionGroup, ChatComposerContainer } from "@twilio-paste/chat-composer"; +import { AttachIcon } from "@twilio-paste/icons/esm/AttachIcon"; +import { SendIcon } from "@twilio-paste/icons/esm/SendIcon"; +import { RepeatIcon } from "@twilio-paste/icons/esm/RepeatIcon"; +import { ClearEditorPlugin } from "@twilio-paste/lexical-library"; +import { SummaryDetail, SummaryDetailContent, SummaryDetailHeading, SummaryDetailHeadingContent, SummaryDetailToggleButton } from "@twilio-paste/summary-detail"; import { + aIActionClickError, + actionGroupError, + aiChatLoggerExample, + avatarExample, basicBotMessage, basicHumanMessage, + botWithBodyActions, botWithFeedback, - botWithLoadingStopButton, botWithLoading, + botWithLoadingStopButton, kitchenSink, - aiChatLoggerExample, - botWithBodyActions, - avatarExample, + messageGenerationError, + sendingMessageError, + systemError, } from "../../../component-examples/AIChatLogExamples"; -import packageJson from "@twilio-paste/ai-chat-log/package.json"; import ComponentPageLayout from "../../../layouts/ComponentPageLayout"; import { getFeature, getNavigationData } from "../../../utils/api"; +import { Text } from "@twilio-paste/text"; +import { Alert } from "@twilio-paste/alert"; export default ComponentPageLayout; @@ -362,3 +378,203 @@ You can push or pop a chat based on an action or event. In this example it's bas ## Composition Notes Keep any generated responses from the AI contained in the `AIChatMessageBody` component. Each chat message should only have one `AIChatMessageBody` component. + +### Error States + +- Don’t accumulate error states in one screen, just display one error at a time, starting with the most critical one, until the user recovers. +- Check content guidelines for [error states](/patterns/error-state#recommended-phrasings-and-templates). +- Include another way for users to contact support if the error persists. + +#### Message content error + +**An error generating or regenerating a response** + +- Use a Callout to show an inline error. +- The Callout should replace the body message if no response was generated, or appear between the `AIChatMessageBody` and the `AIChatMessageActionGroup` if the response is incomplete. +- Include an in-chat action to recover (For example: regenerate or try again) +- Include a way for users to contact support if the error persists. + + + {messageGenerationError} + + +**An error when clicking on an Action that generates an AI response** + +- The Callout is placed under the response and action +- Include another way for users to contact support if the error persists. + + + {aIActionClickError} + + +#### AI Chat Message Action Group Error + +**An error when clicking actions on AI messages (clicking buttons, links)** + +- Use Help text error variant for actions not directly tied to generating a response or continuing the conversation, such as copying text or rating a response. + + + {actionGroupError} + + +#### Sending errors + +**An error sending a message** + +- The error is placed in the Message Action Card +- Include an action to recover + + + {sendingMessageError} + + +#### System errors + +**Chat History Errors, Timeouts, Network errors...etc.** + +- An Alert will be placed above the Chat Composer +- The Alert will be dismissed once the user refreshes the page or when the error is resolved + + + {systemError} + diff --git a/packages/paste-website/src/pages/patterns/error-state/index.mdx b/packages/paste-website/src/pages/patterns/error-state/index.mdx index e125eb58fa..7cbc312bc4 100644 --- a/packages/paste-website/src/pages/patterns/error-state/index.mdx +++ b/packages/paste-website/src/pages/patterns/error-state/index.mdx @@ -361,6 +361,26 @@ When possible, use an icon and color to indicate an error. When using only an ic
+### AI responses errors + + + + + + + + + + + + + + + + +
TypeRecommended phrasing(s)Notes
An error generating or regenerating a responseThere was an error generating a response.
Please try again, if the error persists please contact us.
If the error is associated to the user’s input having incomplete information use “Please rephrase your message”
+
+ Work with engineers to try to avoid an endless “try again” loop. Explore whether you can offer a series of things to check if the user hits a particular error several times in a row. ## Variations @@ -377,7 +397,7 @@ An empty state is also an error state when content fails to load. Error empty st ### Metrics cards -When cards are used as part of a dashboard to display metrics, error states can occur on individual cards because the data populating a particular card isn’t available. Since these cards are usually small, use error iconography paired with a 3-5 word error message. +When cards are used as part of a dashboard to display metrics, error states can occur on individual cards because the data populating a particular card isn’t available. Since these cards are usually small, use error iconography paired with a 3-5 word error message. ## Specific component guidance