Skip to content

Commit

Permalink
Merge pull request #274 from rebeccaalpert/quick-response
Browse files Browse the repository at this point in the history
feat(QuickResponse): Add quick response buttons
  • Loading branch information
nicolethoen authored Nov 7, 2024
2 parents 141ca8d + a81df62 commit dc1d4e3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,13 @@ The API for a source requires a link at minimum, but we strongly recommend provi
```js file="./MessageWithSources.tsx"

```

### Messages with quick responses

You can offer convenient, clickable responses to messages in the form of quick actions. Quick actions are [PatternFly labels](/components/label/) in a label group, configured to display up to 5 visible labels.

To add quick actions, pass `quickResponses` to `<Message>`. This can be overridden by passing additional `<LabelGroup>` props to `quickResponseContainerProps`, or additional `<Label>` props to `quickResponses`.

```js file="./MessageWithQuickResponses.tsx"

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import Message from '@patternfly/virtual-assistant/dist/dynamic/Message';
import patternflyAvatar from './patternfly_avatar.jpg';

export const MessageWithQuickResponsesExample: React.FunctionComponent = () => (
<>
<Message
name="Bot"
role="bot"
avatar={patternflyAvatar}
content="Did you clear your cache?"
quickResponses={[
{ id: '1', content: 'Yes', onClick: () => alert('Clicked yes') },
{ id: '2', content: 'No', onClick: () => alert('Clicked no') }
]}
/>
<Message
name="Bot"
role="bot"
avatar={patternflyAvatar}
content="What browser are you noticing the issue in?"
quickResponses={[
{ id: '1', content: 'Microsoft Edge', onClick: () => alert('Clicked Edge') },
{ id: '2', content: 'Google Chrome', onClick: () => alert('Clicked Chrome') },
{ id: '3', content: 'Mozilla Firefox', onClick: () => alert('Clicked Firefox') },
{ id: '4', content: 'Apple Safari', onClick: () => alert('Clicked Safari') },
{ id: '5', content: 'Internet Explorer', onClick: () => alert('Clicked Internet Explorer') }
]}
/>
<Message
name="Bot"
role="bot"
avatar={patternflyAvatar}
content="Welcome back! How can I help?"
quickResponses={[
{ id: '1', content: 'Help me with an access issue', onClick: () => alert('Clicked id 1') },
{ id: '2', content: 'Show my critical vulnerabilities', onClick: () => alert('Clicked id 2') },
{ id: '3', content: 'Create new integrations', onClick: () => alert('Clicked id 3') },
{ id: '4', content: 'Get recommendations from an advisor', onClick: () => alert('Clicked id 4') },
{ id: '5', content: 'Something else', onClick: () => alert('Clicked id 5') }
]}
/>
</>
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import Message from '@patternfly/virtual-assistant/dist/dynamic/Message';
import patternflyAvatar from './patternfly_avatar.jpg';

export const AttachmentMenuExample: React.FunctionComponent = () => {
export const MessageWithSourcesExample: React.FunctionComponent = () => {
const onSetPage = (_event: React.MouseEvent | React.KeyboardEvent | MouseEvent, newPage: number) => {
// eslint-disable-next-line no-console
console.log(`Page changed to ${newPage}`);
Expand Down
14 changes: 14 additions & 0 deletions packages/module/src/Message/Message.scss
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@
display: grid;
gap: var(--pf-t--global--spacer--sm);
}

&-quick-response {
.pf-v6-c-label {
--pf-v6-c-label--FontSize: var(--pf-t--global--font--size--md);

@media screen and (min-width: 401px) and (max-width: 600px) {
--pf-v6-c-label__text--MaxWidth: 20ch;
}

@media screen and (max-width: 400px) {
--pf-v6-c-label__text--MaxWidth: 15ch;
}
}
}
}

@import './MessageLoading';
Expand Down
25 changes: 24 additions & 1 deletion packages/module/src/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React from 'react';

import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Avatar, Label, Timestamp } from '@patternfly/react-core';
import { Avatar, Label, LabelGroup, LabelGroupProps, LabelProps, Timestamp } from '@patternfly/react-core';
import MessageLoading from './MessageLoading';
import CodeBlockMessage from './CodeBlockMessage/CodeBlockMessage';
import TextMessage from './TextMessage/TextMessage';
Expand All @@ -17,6 +17,11 @@ import ListItemMessage from './ListMessage/ListItemMessage';
import UnorderedListMessage from './ListMessage/UnorderedListMessage';
import OrderedListMessage from './ListMessage/OrderedListMessage';

export interface QuickResponse extends Omit<LabelProps, 'children'> {
content: string;
id: string;
onClick: () => void;
}
export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'role'> {
/** Unique id for message */
id?: string;
Expand Down Expand Up @@ -58,6 +63,10 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
'aria-label'?: string;
className?: string;
};
/** Props for quick responses */
quickResponses?: QuickResponse[];
/** Props for quick responses container */
quickResponseContainerProps?: Omit<LabelGroupProps, 'ref'>;
}

export const Message: React.FunctionComponent<MessageProps> = ({
Expand All @@ -76,6 +85,8 @@ export const Message: React.FunctionComponent<MessageProps> = ({
botWord = 'AI',
loadingWord = 'Loading message',
codeBlockProps,
quickResponses,
quickResponseContainerProps = { numLabels: 5 },
...props
}: MessageProps) => {
// Configure default values
Expand Down Expand Up @@ -137,6 +148,18 @@ export const Message: React.FunctionComponent<MessageProps> = ({
)}
{!isLoading && sources && <SourcesCard {...sources} />}
{!isLoading && actions && <ResponseActions actions={actions} />}
{!isLoading && quickResponses && (
<LabelGroup
className={`pf-chatbot__message-quick-response ${quickResponseContainerProps?.className}`}
{...quickResponseContainerProps}
>
{quickResponses.map(({ id, onClick, content, ...props }: QuickResponse) => (
<Label variant="outline" color="blue" key={id} onClick={onClick} {...props}>
{content}
</Label>
))}
</LabelGroup>
)}
</div>
{attachmentName && (
<div className="pf-chatbot__message-attachment">
Expand Down

0 comments on commit dc1d4e3

Please sign in to comment.