Skip to content

Commit

Permalink
feat: add component documentation (DX-447) (voiceflow#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
effervescentia authored Apr 25, 2023
1 parent 74c939b commit 1774e8c
Show file tree
Hide file tree
Showing 59 changed files with 689 additions and 117 deletions.
7 changes: 0 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@
},
"homepage": "https://github.com/voiceflow/react-chat#readme",
"keywords": [
"combinedReducer",
"react",
"react-redux",
"reducer",
"redux",
"voiceflow"
],
"license": "ISC",
Expand All @@ -36,9 +32,6 @@
"publishConfig": {
"access": "public"
},
"resolutions": {
"root": "portal:/Users/tylerhan/voiceflow/creator-app"
},
"scripts": {
"build": "turbo run build",
"build:all": "yarn build",
Expand Down
6 changes: 6 additions & 0 deletions packages/react-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
"husky": "^8.0.0",
"lint-staged": "13.0.3",
"prettier": "2.7.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"rimraf": "3.0.2",
"storybook-dark-mode": "^1.1.0",
"vite": "3.2.2",
Expand All @@ -76,6 +78,10 @@
],
"license": "MIT",
"main": "build/index.es.js",
"peerDependencies": {
"react": "^18",
"react-dom": "^18"
},
"prettier": "@voiceflow/prettier-config",
"scripts": {
"build": "yarn clean && yarn build:package && yarn build:bundle",
Expand Down
2 changes: 2 additions & 0 deletions packages/react-chat/src/common/listeners.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO: move this entire module into `browser/` if possible?
import { useEffect } from 'react';

import * as PostMessage from './postMessage';
Expand Down Expand Up @@ -35,6 +36,7 @@ const handleMessage = (event: MessageEvent) => {
});
};

// TODO: avoid this being in the module scope
if (window.addEventListener) {
// For standards-compliant web browsers
window.addEventListener('message', handleMessage, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';

import Chat from '@/components/Chat';
import { VF_ICON } from '@/fixtures';

import AssistantInfo from '.';

Expand All @@ -10,7 +11,7 @@ export default {
args: {
title: 'Assistant Name',
description: "Voiceflow's virtual assistant is here to help.",
image: 'https://source.unsplash.com/random/72x72',
avatar: VF_ICON,
},
} as ComponentMeta<typeof AssistantInfo>;

Expand Down
23 changes: 20 additions & 3 deletions packages/react-chat/src/components/AssistantInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,38 @@ import Avatar from '@/components/Avatar';

import { Container, Description, Title } from './styled';

export interface AssistantHeaderProps {
export interface AssistantInfoProps {
/**
* The title of the assistant.
*/
title: string;

/**
* A short description of the assistant to help frame the conversation.
*/
description: string;

/**
* An image URL that identifies the assistant, such as a brand icon.
*/
avatar: string;
}

const AssistantHeader: React.FC<AssistantHeaderProps> = ({ title, description, avatar }) => (
const AssistantInfo: React.FC<AssistantInfoProps> = ({ title, description, avatar }) => (
<Container>
<Avatar size="large" avatar={avatar} />
<Title>{title}</Title>
<Description>{description}</Description>
</Container>
);

export default Object.assign(AssistantHeader, {
/**
* This component displays introductory information about the assistant.
* It will act as a placeholder before the conversation has started.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/components-chat-assistantinfo--default}
*/
export default Object.assign(AssistantInfo, {
Container,
Title,
Description,
Expand Down
14 changes: 12 additions & 2 deletions packages/react-chat/src/components/Avatar/Avatar.story.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';

import { VF_ICON } from '@/fixtures';

import Avatar from '.';

export default {
title: 'Core/Avatar',
component: Avatar,
argTypes: {
size: {
options: ['small', 'large'],
control: { type: 'radio' },
defaultValue: 'small',
},
},
args: {
avatar: VF_ICON,
},
} as ComponentMeta<typeof Avatar>;

const Template: ComponentStory<typeof Avatar> = (args) => <Avatar {...args} />;

export const Small = Template.bind({});
Small.args = {
size: 'small',
image: 'https://source.unsplash.com/random/26x26',
};

export const Large = Template.bind({});
Large.args = {
size: 'large',
image: 'https://source.unsplash.com/random/72x72',
};
17 changes: 17 additions & 0 deletions packages/react-chat/src/components/Avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import { VariantProp } from '@/types';

import { AvatarContainer } from './styled';

export interface AvatarProps extends React.ComponentProps<typeof AvatarContainer> {
/**
* An image URL which will be rendered as the background.
*/
avatar: string;

/**
* Pre-defined size variants.
*
* @default 'small'
*/
size?: VariantProp<typeof AvatarContainer, 'size'>;
}

const Avatar: React.FC<AvatarProps> = ({ avatar, ...props }) => (
<AvatarContainer {...props} css={{ backgroundImage: `url(${avatar})`, ...props.css }} />
);

/**
* Displays an image in a circular frame.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/core-avatar--small}
*/
export default Object.assign(Avatar, {
Container: AvatarContainer,
});
17 changes: 15 additions & 2 deletions packages/react-chat/src/components/Bubble/Bubble.story.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';

import * as SVGs from '@/assets/svg';

import Bubble from '.';

export default {
Expand All @@ -8,18 +10,29 @@ export default {
args: {
color: '#fff',
},
argTypes: {
size: {
options: ['small', 'large'],
control: { type: 'radio' },
defaultValue: 'large',
},
svg: {
options: Object.keys(SVGs).filter((svg) => svg !== 'topCaret'),
control: { type: 'radio' },
},
},
} as ComponentMeta<typeof Bubble>;

const Template: ComponentStory<typeof Bubble> = (args) => <Bubble {...args} />;

export const Small = Template.bind({});
Small.args = {
size: 'small',
svg: 'arrowUp',
svg: 'smallArrowUp',
};

export const Large = Template.bind({});
Large.args = {
size: 'large',
svg: 'launch',
svg: 'close',
};
18 changes: 18 additions & 0 deletions packages/react-chat/src/components/Bubble/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import Icon, { IconProps } from '@/components/Icon';
import { VariantProp } from '@/types';

import { Container } from './styled';

export interface BubbleProps extends React.ComponentProps<typeof Container> {
/**
* The name of the SVG icon to be rendered or a React component.
*
* @see {@link https://github.com/voiceflow/react-chat/tree/master/packages/react-chat/src/assets/svg the available icons}
*/
svg: IconProps['svg'];

/**
* Pre-defined size variants.
*
* @default 'large'
*/
size?: VariantProp<typeof Container, 'size'>;
}

const Bubble: React.FC<BubbleProps> = ({ svg, color, ...props }) => (
Expand All @@ -12,6 +25,11 @@ const Bubble: React.FC<BubbleProps> = ({ svg, color, ...props }) => (
</Container>
);

/**
* Call-to-action button with an icon.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/core-bubble--small}
*/
export default Object.assign(Bubble, {
Container,
});
12 changes: 11 additions & 1 deletion packages/react-chat/src/components/Button/Button.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ export default {
title: 'Core/Button',
component: Button,
argTypes: {
type: { if: { arg: 'variant', eq: Button.Variant.PRIMARY } },
variant: {
options: Object.values(Button.Variant),
control: { type: 'radio' },
defaultValue: Button.Variant.PRIMARY,
},
type: {
if: { arg: 'variant', eq: Button.Variant.PRIMARY },
options: ['info', 'warn', 'subtle'],
control: { type: 'radio' },
defaultValue: 'info',
},
},
args: {
children: 'Button Label',
Expand Down
5 changes: 5 additions & 0 deletions packages/react-chat/src/components/Button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const VARIANTS = {

const Button = bindVariants(VARIANTS, ButtonVariant.PRIMARY);

/**
* A button with a label.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/core-button--primary-info}
*/
export default Object.assign(Button, {
Variant: ButtonVariant,

Expand Down
10 changes: 8 additions & 2 deletions packages/react-chat/src/components/Card/Card.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export default {
component: Card,
args: {
title: 'Card Header',
image: '',
description: 'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Culpa et aliquam sunt necessitatibus molestiae amet ipsum ut.',
actions: [],
},
} as ComponentMeta<typeof Card>;

Expand All @@ -17,11 +19,15 @@ export const Simple = Template.bind({});

export const WithImage = Template.bind({});
WithImage.args = {
image: 'https://source.unsplash.com/random/248x150',
image: 'https://source.unsplash.com/featured/248x150',
};

export const Actionable = Template.bind({});
Actionable.args = {
...WithImage.args,
actions: [{ label: 'First Button' }, { label: 'Second Button' }, { label: 'Third Button' }],
actions: [
{ request: {} as any, name: 'First Button' },
{ request: {} as any, name: 'Second Button' },
{ request: {} as any, name: 'Third Button' },
],
};
28 changes: 28 additions & 0 deletions packages/react-chat/src/components/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,37 @@ import { Container, Content, Description, Header, Link } from './styled';
import { isValidHttpUrl } from './utils';

export interface CardActionProps {
/**
* The label that will appear on the button.
*/
name: string;

/**
* the request that will be sent by the runtime when the button is clicked.
*/
request: RuntimeAction;
}

export interface CardProps {
/**
* The title of the card.
*/
title: string;

/**
* Text content of the card.
* If the string is a valid URL it will be rendered in a {@link Link}.
*/
description: string;

/**
* An image URL that will render at the top of the card if provided.
*/
image?: string | undefined | null;

/**
* A list of actions that will appear as button controls at the bottom of the card.
*/
actions?: CardActionProps[] | undefined;
}

Expand Down Expand Up @@ -45,6 +68,11 @@ const Card: React.FC<CardProps> = ({ title, description, image, actions = [] })
);
};

/**
* A titled card with content and optional controls.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/components-card--simple}
*/
export default Object.assign(Card, {
Container,
});
Loading

0 comments on commit 1774e8c

Please sign in to comment.