Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: VoiceWidget (DSN-2548) #370

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
33 changes: 33 additions & 0 deletions apps/documentation/src/pages/compositions/voice-widget.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { StoryEmbed } from '../../components/StoryEmbed';

# Voice Widget

## Default

<div style={{ width: '400px' }}>
<StoryEmbed clientOnly for="VoiceWidget" name="Base" />
</div>

## Listening

<div style={{ width: '400px' }}>
<StoryEmbed clientOnly for="VoiceWidget" name="Listening" />
</div>

## Talking

<div style={{ width: '400px' }}>
<StoryEmbed clientOnly for="VoiceWidget" name="Talking" />
</div>

## Compact

<div style={{ width: '400px' }}>
<StoryEmbed clientOnly for="VoiceWidget" name="Compact" />
</div>

## Expanded

<div style={{ width: '400px' }}>
<StoryEmbed clientOnly for="VoiceWidget" name="Expand" />
</div>
3 changes: 3 additions & 0 deletions packages/chat/src/assets/svg/end-call.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/chat/src/assets/svg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export { default as closeV2 } from './closeV2.svg?react';
export { default as copy } from './copy.svg?react';
export { default as documentPdf } from './document-pdf.svg?react';
export { default as documentUrl } from './document-url.svg?react';
export { default as endCall } from './end-call.svg?react';
export { default as largeArrowLeft } from './large-arrow-left.svg?react';
export { default as microphone } from './microphone.svg?react';
export { default as minus } from './minus.svg?react';
export { default as mute } from './mute.svg?react';
export { default as phone } from './phone.svg?react';
export { default as reset } from './reset.svg?react';
export { default as smallArrowUp } from './small-arrow-up.svg?react';
export { default as sound } from './sound.svg?react';
Expand Down
3 changes: 3 additions & 0 deletions packages/chat/src/assets/svg/phone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions packages/chat/src/components/Button/ButtonIcon/ButtonIcon.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { style } from '@vanilla-extract/css';

import { COLORS } from '@/styles/colors';
import { transition } from '@/styles/transitions';

import { buttonStyles } from '../styles.css';

const PRIMARY_BUTTON = buttonStyles.classNames.variants.type.primary;
const SECONDARY_BUTTON = buttonStyles.classNames.variants.type.secondary;

export const buttonIconStyles = style({
transition: transition(['color']),
selectors: {
[`${PRIMARY_BUTTON} &`]: {
color: COLORS.ACCENT[50],
},
[`${SECONDARY_BUTTON} &`]: {
color: COLORS.NEUTRAL_DARK[400],
},
[`${SECONDARY_BUTTON}:active &`]: {
color: COLORS.NEUTRAL_DARK[800],
},
},
});
14 changes: 14 additions & 0 deletions packages/chat/src/components/Button/ButtonIcon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import clsx from 'clsx';

import type { IconProps } from '../../Icon';
import { Icon } from '../../Icon';
import { buttonIconStyles } from './ButtonIcon.css';

interface IButtonIcon {
svg: IconProps['svg'];
className?: string;
}

export const ButtonIcon: React.FC<IButtonIcon> = ({ svg, className, ...props }) => {
return <Icon svg={svg} className={clsx(buttonIconStyles, className)} {...props} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { style } from '@vanilla-extract/css';

import { COLORS } from '@/styles/colors';
import { PALETTE } from '@/styles/colors.css';
import { FAMILY } from '@/styles/font';
import { SIZES } from '@/styles/sizes';
import { transition } from '@/styles/transitions';

export const footerLinksContainer = style({
color: COLORS.NEUTRAL_DARK[100],
fontFamily: FAMILY,
fontSize: '12px',
lineHeight: '17px',
width: '100%',
minHeight: 20,
padding: '10px 0',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
});

export const separator = style({
height: '2px',
width: '2px',
borderRadius: SIZES.radius.round,
backgroundColor: COLORS.NEUTRAL_LIGHT[500],
});

export const extraLinkStyles = style({
color: COLORS.NEUTRAL_DARK[100],
fontFamily: FAMILY,
fontSize: '12px',
lineHeight: '17px',
textDecorationColor: 'transparent',
transition: transition(['color', 'text-decoration-color']),
selectors: {
'&:hover': {
textDecoration: 'underline',
color: PALETTE.colors[500],
textDecorationColor: PALETTE.colors[500],
},
'&:active': {
color: PALETTE.colors[600],
textDecorationColor: PALETTE.colors[600],
},
},
});

export const voiceflowLink = style({
color: COLORS.NEUTRAL_DARK[100],
textDecoration: 'underline',
textDecorationColor: 'transparent',
transition: transition(['color', 'text-decoration-color']),
selectors: {
'&:hover': {
color: PALETTE.colors[500],
textDecorationColor: PALETTE.colors[500],
},
'&:active': {
color: PALETTE.colors[600],
textDecorationColor: 'transparent',
},
},
});
34 changes: 34 additions & 0 deletions packages/chat/src/components/NewFooter/BottomLinks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import clsx from 'clsx';

import { extraLinkStyles, footerLinksContainer, separator, voiceflowLink } from './BottomLinks.css';

const VOICEFLOW_URL = 'https://www.voiceflow.com/';

interface IBottomLinks {
showPoweredBy?: boolean;
extraLinkText?: string;
extraLinkUrl?: string;
className?: string;
}

export const BottomLinks: React.FC<IBottomLinks> = ({ showPoweredBy, extraLinkText, extraLinkUrl, className }) => {
const showExtraLink = extraLinkText && extraLinkUrl;

return (
<div className={clsx(footerLinksContainer, className)}>
{showPoweredBy && (
<div>
<a href={VOICEFLOW_URL} target="_blank" rel="noreferrer" className={voiceflowLink}>
Powered by Voiceflow
</a>
</div>
)}
{showPoweredBy && showExtraLink && <div className={separator} />}
{showExtraLink && (
<a href={extraLinkUrl} target="_blank" className={extraLinkStyles}>
{extraLinkText}
</a>
)}
</div>
);
};
62 changes: 0 additions & 62 deletions packages/chat/src/components/NewFooter/NewFooter.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { keyframes, style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';

import { COLORS } from '@/styles/colors';
import { PALETTE } from '@/styles/colors.css';
import { FAMILY } from '@/styles/font';
import { SIZES } from '@/styles/sizes';
import { transition } from '@/styles/transitions';
import { widgetContainer } from '@/views/ChatWidget/styles.css';

const BUTTON_ROW_MARGIN = 10;
Expand Down Expand Up @@ -100,61 +96,3 @@ export const messageInputContainer = style({
borderTopLeftRadius: '20px',
borderTopRightRadius: '20px',
});

export const footerLinksContainer = style({
color: COLORS.NEUTRAL_DARK[100],
fontFamily: FAMILY,
fontSize: '12px',
lineHeight: '17px',
width: '100%',
minHeight: 20,
padding: '10px 0',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
});

export const separator = style({
height: '2px',
width: '2px',
borderRadius: SIZES.radius.round,
backgroundColor: COLORS.NEUTRAL_LIGHT[500],
});

export const extraLinkStyles = style({
color: COLORS.NEUTRAL_DARK[100],
fontFamily: FAMILY,
fontSize: '12px',
lineHeight: '17px',
textDecorationColor: 'transparent',
transition: transition(['color', 'text-decoration-color']),
selectors: {
'&:hover': {
textDecoration: 'underline',
color: PALETTE.colors[500],
textDecorationColor: PALETTE.colors[500],
},
'&:active': {
color: PALETTE.colors[600],
textDecorationColor: PALETTE.colors[600],
},
},
});

export const voiceflowLink = style({
color: COLORS.NEUTRAL_DARK[100],
textDecoration: 'underline',
textDecorationColor: 'transparent',
transition: transition(['color', 'text-decoration-color']),
selectors: {
'&:hover': {
color: PALETTE.colors[500],
textDecorationColor: PALETTE.colors[500],
},
'&:active': {
color: PALETTE.colors[600],
textDecorationColor: 'transparent',
},
},
});
30 changes: 3 additions & 27 deletions packages/chat/src/components/NewFooter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,8 @@ import type { IMessageInput } from '../MessageInput';
import { MessageInput } from '../MessageInput';
import { promptContainer } from '../Prompt/styles.css';
import { ScrollToBottom } from '../ScrollToBottom';
import {
buttonsContainer,
extraLinkStyles,
footerContainer,
footerLinksContainer,
messageContainer,
separator,
voiceflowLink,
} from './NewFooter.css';

const VOICEFLOW_URL = 'https://www.voiceflow.com/';
import { BottomLinks } from './BottomLinks';
import { buttonsContainer, footerContainer, messageContainer } from './NewFooter.css';

export interface INewFooter {
buttons?: { label: string; onClick: () => void }[];
Expand Down Expand Up @@ -50,7 +41,6 @@ export const NewFooter: React.FC<INewFooter> = ({
scrollableAreaRef,
onStart,
}) => {
const showExtraLink = extraLinkText && extraLinkUrl;
return (
<div className={clsx(ClassName.FOOTER, footerContainer)}>
<div className={promptContainer({ visible: messageInputProps.hasEnded })}>
Expand All @@ -72,21 +62,7 @@ export const NewFooter: React.FC<INewFooter> = ({
<div className={messageContainer()}>
<ScrollToBottom scrollableAreaRef={scrollableAreaRef} />
<MessageInput {...messageInputProps} />
<div className={footerLinksContainer}>
{showPoweredBy && (
<div>
<a href={VOICEFLOW_URL} target="_blank" rel="noreferrer" className={voiceflowLink}>
Powered by Voiceflow
</a>
</div>
)}
{showPoweredBy && showExtraLink && <div className={separator} />}
{showExtraLink && (
<a href={extraLinkUrl} target="_blank" className={extraLinkStyles}>
{extraLinkText}
</a>
)}
</div>
<BottomLinks extraLinkText={extraLinkText} extraLinkUrl={extraLinkUrl} showPoweredBy={showPoweredBy} />
</div>
</div>
);
Expand Down
33 changes: 33 additions & 0 deletions packages/chat/src/components/VoiceWidget/MockVoiceWidgetImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable no-secrets/no-secrets */
export const MockImage = () => {
return (
<svg
width="58"
height="58"
viewBox="0 0 58 58"
fill="none"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<g filter="url(#filter0_i_2871_565)">
<g clip-path="url(#clip0_2871_565)">
<rect width="58" height="58" fill="url(#pattern0_2871_565)" />
</g>
</g>
<defs>
<pattern id="pattern0_2871_565" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlinkHref="#image0_2871_565" transform="scale(0.00333333)" />
</pattern>
<clipPath id="clip0_2871_565">
<rect width="58" height="58" rx="29" fill="white" />
</clipPath>
<image
id="image0_2871_565"
width="300"
height="300"
xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAACXBIWXMAADddAAA3XQEZgEZdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAP/SURBVHgB7dZbDYRAAATB3VN0RjALQkARDxH700mVhkln5n7ez4DFtv8csNpvAEQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkzOczYLHjMivW87CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgIwX968M0Tho/IMAAAAASUVORK5CYII="
/>
</defs>
</svg>
);
};
Loading
Loading