Skip to content

Commit

Permalink
(EAI-71) [UI] Rich Links in LG Chat
Browse files Browse the repository at this point in the history
  • Loading branch information
nlarew committed Apr 30, 2024
1 parent 3364b54 commit 462a450
Show file tree
Hide file tree
Showing 34 changed files with 1,624 additions and 1,051 deletions.
5 changes: 5 additions & 0 deletions .changeset/angry-hornets-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lg-chat/message': minor
---

Adds the links prop which renders link data as rich links after the message content
27 changes: 14 additions & 13 deletions chat/message/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ return (

## Properties

| Prop | Type | Description | Default |
| -------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `align` | `'left', 'right'` | Determines whether the message is aligned to the left or right | if `isSender === true`, the message is aligned to the right, and otherwise to the left. This prop overrides that behavior |
| `avatar` | `ReactElement` | Avatar element | |
| `componentOverrides` | `Record<MarkdownComponent, ComponentType>` | Uses value to override key'ed markdown elements in terms of how they are rendered | |
| `children` | `string` | Rendered children; only string children are supported | |
| `isSender` | `boolean` | Indicates if the message is from the current user | `true` |
| `markdownProps` | `LGMarkdownProps` | Props passed to the internal ReactMarkdown instance | |
| `messageRatingProps` | `MessageRatingProps` | Props to MessageRating component | |
| `sourceType` | `'markdown', 'text'` | Determines the rendering method of the message | |
| `messageBody` | `string` | Message body text passed to LGMarkdown | |
| `verified` | `{ verifier?: string; verifiedAt?: Date; learnMoreUrl?: string; }` | Sets if an answer is "verified" and controls the content of the message banner. | |
| `...` | `HTMLElementProps<'div'>` | Props spread on the root element | |
| Prop | Type | Description | Default |
| -------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `align` | `'left', 'right'` | Determines whether the message is aligned to the left or right | if `isSender === true`, the message is aligned to the right, and otherwise to the left. This prop overrides that behavior |
| `avatar` | `ReactElement` | Avatar element | |
| `componentOverrides` | `Record<MarkdownComponent, ComponentType>` | Uses value to override key'ed markdown elements in terms of how they are rendered | |
| `children` | `string` | Rendered children; only string children are supported | |
| `isSender` | `boolean` | Indicates if the message is from the current user | `true` |
| `markdownProps` | `LGMarkdownProps` | Props passed to the internal ReactMarkdown instance | |
| `messageRatingProps` | `MessageRatingProps` | Props to MessageRating component | |
| `sourceType` | `'markdown', 'text'` | Determines the rendering method of the message | |
| `messageBody` | `string` | Message body text passed to LGMarkdown | |
| `verified` | `{ verifier?: string; verifiedAt?: Date; learnMoreUrl?: string; }` | Sets if an answer is "verified" and controls the content of the message banner. | |
| `links` | `{ url: string; text: string; imageUrl?: string; variant: string; }` | A list of links to show in a section at the end of the message. | |
| `...` | `HTMLElementProps<'div'>` | Props spread on the root element | |
142 changes: 100 additions & 42 deletions chat/message/src/Message/Message.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { storybookArgTypes, StoryMetaType } from '@lg-tools/storybook-utils';
import { StoryFn } from '@storybook/react';

import { Message, MessageSourceType } from '..';
import { useBaseFontSize } from '@leafygreen-ui/leafygreen-provider';

const MarkdownText = `
# Heading 1
Expand Down Expand Up @@ -61,6 +62,11 @@ sharding to distribute the load across multiple servers.
Let me know if you need any further assistance!
`;

const MessageFeedback = () => {
// @ts-ignore onChange is passed in the story itself
return <MessageFeedbackStory />;
};

const meta: StoryMetaType<typeof Message> = {
title: 'Chat/Message',
component: Message,
Expand All @@ -82,10 +88,9 @@ const meta: StoryMetaType<typeof Message> = {
};
export default meta;

// eslint-disable-next-line react/prop-types
const Template: StoryFn<typeof Message> = ({ darkMode, avatar, ...rest }) => {
const Avatar = avatar ? React.cloneElement(avatar, { darkMode }) : undefined;
return <Message avatar={Avatar} darkMode={darkMode} {...rest} />;
return <Message avatar={Avatar} darkMode={darkMode} {...rest}></Message>;
};

export const Basic: StoryFn<typeof Message> = Template.bind({});
Expand Down Expand Up @@ -117,8 +122,7 @@ WithMessageRating.args = {
isSender: false,
messageBody: MongoText,
avatar: <Avatar variant="mongo" />,
// @ts-ignore onChange is passed in the story itself
children: <MessageFeedbackStory />,
children: <MessageFeedback />,
};

export const VerifiedAnswer: StoryFn<typeof Message> = Template.bind({});
Expand All @@ -130,43 +134,97 @@ VerifiedAnswer.args = {
verifier: 'MongoDB Staff',
verifiedAt: new Date('2023-08-24T16:20:00Z'),
},
// @ts-ignore onChange is passed in the story itself
children: <MessageFeedbackStory />,
children: <MessageFeedback />,
};

function useCorrectBaseFontSize() {
const baseFontSize = useBaseFontSize();
return baseFontSize === 14 ? 13 : baseFontSize;
}

export const MultipleUser = () => {
const baseFontSize = useCorrectBaseFontSize();
return (
<LeafyGreenChatProvider>
<div>
<Basic {...meta.args} {...Basic.args} baseFontSize={baseFontSize} />
<Basic
{...meta.args}
{...Basic.args}
messageBody="Another message!"
baseFontSize={baseFontSize}
/>
</div>
</LeafyGreenChatProvider>
);
};

export const MultipleUser = () => (
<LeafyGreenChatProvider>
<div>
{/* @ts-expect-error baseFontSize is not a number */}
<Basic {...meta.args} {...Basic.args} />
{/* @ts-expect-error baseFontSize is not a number */}
<Basic {...meta.args} {...Basic.args} messageBody="Another message!" />
</div>
</LeafyGreenChatProvider>
);

export const MultipleMongo = () => (
<LeafyGreenChatProvider>
<div>
{/* @ts-expect-error baseFontSize is not a number */}
<Mongo
{...meta.args}
{...Mongo.args}
messageBody="First message! Expect another from me right after this one."
/>
{/* @ts-expect-error baseFontSize is not a number */}
<Mongo {...meta.args} {...Mongo.args} />
</div>
</LeafyGreenChatProvider>
);

export const Alternating = () => (
<LeafyGreenChatProvider>
<div>
{/* @ts-expect-error baseFontSize is not a number */}
<Basic {...meta.args} {...Basic.args} />
{/* @ts-expect-error baseFontSize is not a number */}
<Mongo {...meta.args} {...Mongo.args} />
</div>
</LeafyGreenChatProvider>
);
export const MultipleMongo = () => {
const baseFontSize = useCorrectBaseFontSize();
return (
<LeafyGreenChatProvider>
<div>
<Mongo
{...meta.args}
{...Mongo.args}
messageBody="First message! Expect another from me right after this one."
baseFontSize={baseFontSize}
/>
<Mongo {...meta.args} {...Mongo.args} baseFontSize={baseFontSize} />
</div>
</LeafyGreenChatProvider>
);
};

export const Alternating = () => {
const baseFontSize = useCorrectBaseFontSize();
return (
<LeafyGreenChatProvider>
<div>
<Basic {...meta.args} {...Basic.args} baseFontSize={baseFontSize} />
<Mongo {...meta.args} {...Mongo.args} baseFontSize={baseFontSize} />
</div>
</LeafyGreenChatProvider>
);
};

export const WithRichLinks: StoryFn<typeof Message> = Template.bind({});
WithRichLinks.args = {
isSender: false,
messageBody: MongoText,
avatar: <Avatar variant="mongo" />,
children: <MessageFeedback />,
links: [
{
url: 'https://mongodb.design',
text: 'LeafyGreen UI',
variant: 'Website',
},
{
url: 'https://mongodb.github.io/leafygreen-ui/?path=/docs/overview-introduction--docs',
text: 'LeafyGreen UI Docs',
variant: 'Docs',
},
{
url: 'https://learn.mongodb.com/',
text: 'MongoDB University',
variant: 'Learn',
},
{
url: 'https://mongodb.com/docs',
text: 'MongoDB Docs',
variant: 'Docs',
},
{
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
text: 'Rick Astley - Never Gonna Give You Up',
variant: 'Video',
imageUrl: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg',
},
{
url: 'https://mongodb.com/',
text: 'MongoDB Homepage',
variant: 'Website',
},
],
};
2 changes: 1 addition & 1 deletion chat/message/src/Message/Message.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const avatarClassName = createUniqueClassName('lg-message-avatar');

export const baseStyles = css`
display: flex;
gap: ${spacing[2]}px;
gap: ${spacing[200]}px;
align-items: flex-end;
width: 100%;
Expand Down
10 changes: 10 additions & 0 deletions chat/message/src/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from './Message.styles';
import { Align } from './Message.types';
import { MessageProps } from '.';
import { MessageLinks } from '../MessageLinks';

export const Message = forwardRef(
(
Expand All @@ -46,6 +47,8 @@ export const Message = forwardRef(
className,
children,
componentOverrides,
links,
linksHeading,
markdownProps,
verified,
darkMode: darkModeProp,
Expand Down Expand Up @@ -136,6 +139,13 @@ export const Message = forwardRef(
>
{messageBody ?? ''}
</Polymorph>
{links ? (
<Polymorph
as={componentOverrides?.MessageLinks ?? MessageLinks}
headingText={linksHeading}
links={links}
/>
) : null}
{children}
</Polymorph>
</div>
Expand Down
14 changes: 14 additions & 0 deletions chat/message/src/Message/Message.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { BaseFontSize } from '@leafygreen-ui/tokens';
import { MessageContainerProps } from '../MessageContainer';
import { MessageContentProps } from '../MessageContent';

import { type RichLinkProps } from '@lg-chat/rich-links';
import { MessageLinksProps } from 'src/MessageLinks';

export const Align = {
Right: 'right',
Left: 'left',
Expand All @@ -16,6 +19,7 @@ export type Align = (typeof Align)[keyof typeof Align];
export interface ComponentOverrides {
MessageContainer?: (props: MessageContainerProps) => JSX.Element;
MessageContent?: (props: MessageContentProps) => JSX.Element;
MessageLinks?: (props: MessageLinksProps) => JSX.Element;
}

export interface MessageProps
Expand Down Expand Up @@ -57,6 +61,16 @@ export interface MessageProps
* displays information about the message.
*/
verified?: VerificationInfo;

/**
* A list of links to render as rich links for the message.
*/
links?: Array<RichLinkProps>;

/**
* The heading text to display for the links section.
*/
linksHeading?: string;
}

export interface VerificationInfo {
Expand Down
4 changes: 4 additions & 0 deletions chat/message/src/MessageContainer/MessageContainer.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export const baseStyles = css`
box-shadow: 0px 4px 10px -4px ${palette.black}4D; // 4D is 30% opacity
position: relative;
display: flex;
flex-direction: column;
gap: 8px;
`;

export const variantStyles: Record<Variant, Record<Theme, string>> = {
Expand Down
23 changes: 23 additions & 0 deletions chat/message/src/MessageLinks/MessageLinks.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { css } from '@leafygreen-ui/emotion';
import { Theme } from '@leafygreen-ui/lib';
import { palette } from '@leafygreen-ui/palette';
import { spacing } from '@leafygreen-ui/tokens';

export const baseStyles = css`
container-type: inline-size;
margin-bottom: ${spacing[200]}px;
`;

export const dividingLineStyles: Record<Theme, string> = {
[Theme.Dark]: css`
border: 1px solid ${palette.gray.dark2};
`,
[Theme.Light]: css`
border: 1px solid ${palette.gray.light2};
`,
};

export const linksHeadingStyles = css`
margin-bottom: 8px;
line-height: 28px;
`;
29 changes: 29 additions & 0 deletions chat/message/src/MessageLinks/MessageLinks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { type MessageLinksProps } from './MessageLinks.types';
import { Subtitle } from '@leafygreen-ui/typography';
import { RichLinksArea } from '@lg-chat/rich-links';
import { cx } from '@leafygreen-ui/emotion';
import {
baseStyles,
dividingLineStyles,
linksHeadingStyles,
} from './MessageLinks.styles';
import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';

export function MessageLinks({
darkMode: darkModeProp,
headingText = 'Related Resources',
links,
...divProps
}: MessageLinksProps) {
const { theme } = useDarkMode(darkModeProp);
return (
<div className={cx(baseStyles)} {...divProps}>
<hr className={cx(dividingLineStyles[theme])} />
<Subtitle className={cx(linksHeadingStyles)}>{headingText}</Subtitle>
<RichLinksArea links={links} />
</div>
);
}

MessageLinks.displayName = 'MessageLinks';
16 changes: 16 additions & 0 deletions chat/message/src/MessageLinks/MessageLinks.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { DarkModeProps, HTMLElementProps } from '@leafygreen-ui/lib';
import { type RichLinkProps } from '@lg-chat/rich-links';

export interface MessageLinksProps
extends DarkModeProps,
Omit<HTMLElementProps<'div'>, 'children'> {
/**
* The text to display as the heading of the links section.
*/
headingText?: string;

/**
* An list of link data to render in the links section.
*/
links: Array<RichLinkProps>;
}
2 changes: 2 additions & 0 deletions chat/message/src/MessageLinks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { MessageLinks } from './MessageLinks';
export { type MessageLinksProps } from './MessageLinks.types';
3 changes: 3 additions & 0 deletions chat/message/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,8 @@
{
"path": "../../packages/banner"
},
{
"path": "../rich-links"
},
]
}
Loading

0 comments on commit 462a450

Please sign in to comment.