Skip to content

Commit

Permalink
fix: User Message Gap + Bottom Padding (DSN-2502) (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaalnaik authored Nov 12, 2024
1 parent db0c7c4 commit 48d9906
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 55 deletions.
10 changes: 0 additions & 10 deletions packages/chat/src/components/Dialog/Dialog.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ export const agentMessage = recipe({
},
],
variants: {
tight: {
true: {
marginTop: '4px',
},
},
isFirst: {
true: {
marginTop: '0px',
Expand All @@ -66,11 +61,6 @@ export const agentMessage = recipe({
export const userMessage = recipe({
base: [baseMessage, { alignSelf: 'flex-end' }],
variants: {
tight: {
true: {
marginTop: '4px',
},
},
isFirst: {
true: {
marginTop: '0px',
Expand Down
2 changes: 1 addition & 1 deletion packages/chat/src/components/NewChat/NewChat.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ export const dialogContainer = style({
export const bottomSpacer = style({
display: 'block',
width: '100%',
height: 12,
height: '24px',
});
12 changes: 8 additions & 4 deletions packages/chat/src/components/NewChat/NewChat.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ const AgentSays = (messages: string[]) => (
messages={messages.map((m) => ({ type: 'text', text: m }))}
/>
);
const UserSays = (text: string) => <UserResponse message={text} timestamp={Date.now()} />;
const UserSays = (text: string, hasAvatar?: boolean) => (
<UserResponse message={text} timestamp={Date.now()} hasAvatar={hasAvatar} />
);

const MockBaseComponent = ({ isLoading }: { isLoading?: boolean }) => {
const [messages, setMessages] = useState([
{ type: 'Agent', text: '👋🏻 Good morning!' },
{ type: 'User', text: 'Cool, great weather ☀️' },
{ type: 'User', text: 'How bout you?' },
{
type: 'User',
text: 'How bout you? What about Bob? How has he been. Is he ok. Should I separate these messages?',
},
{ type: 'Agent', text: 'Howdy, great to meet you!' },
{ type: 'Agent', text: 'What up' },
{ type: 'User', text: 'How bout you?' },
Expand Down Expand Up @@ -87,7 +91,7 @@ const MockBaseComponent = ({ isLoading }: { isLoading?: boolean }) => {
placeholder: 'Message...',
}}
>
{messages.map((msg) => (msg.type === 'Agent' ? AgentSays([msg.text]) : UserSays(msg.text)))}
{messages.map((msg) => (msg.type === 'Agent' ? AgentSays([msg.text]) : UserSays(msg.text, true)))}
{isLoading && <Indicator avatar={EMPTY_IMAGE} />}
</NewChat>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export const SystemMessage: React.FC<SystemMessageProps> = ({
feedback,
message,
withImage,
first,
children,
isLast,
}) => {
Expand All @@ -76,7 +75,7 @@ export const SystemMessage: React.FC<SystemMessageProps> = ({
}

return (
<div className={clsx(ClassName.SYSTEM_RESPONSE, systemMessageContainer({ first }))}>
<div className={clsx(ClassName.SYSTEM_RESPONSE, systemMessageContainer())}>
<Avatar avatar={avatar} className={clsx(withImage ? '' : hide, responseAvatar)} />
<div className={messageContainer}>
{children ??
Expand Down
15 changes: 9 additions & 6 deletions packages/chat/src/components/SystemResponse/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { FeedbackButton } from '../FeedbackButton';
import type { IFeedbackButton } from '../FeedbackButton/FeedbackButton.interface';
import { useAnimatedMessages } from './hooks';
import Indicator from './Indicator/Indicator';
import { actionsContainer } from './styles.css';
import { actionsContainer, responseContainer } from './styles.css';
import type { SystemMessageProps } from './SystemMessage';
import { SystemMessage } from './SystemMessage';
import type { MessageProps } from './types';
Expand Down Expand Up @@ -49,6 +49,11 @@ export interface SystemResponseProps {
*/
isLast?: boolean;

/**
* If true, the system message is the first in a chat.
*/
isFirst?: boolean;

/**
* If provided, will display {@link FeedbackButton} component under the last message.
* @default false
Expand All @@ -73,6 +78,7 @@ export const SystemResponse: React.FC<SystemResponseProps> = ({
messages,
actions = [],
isLast,
isFirst,
Message = SystemMessage,
}) => {
const runtime = useContext(RuntimeStateAPIContext);
Expand All @@ -84,12 +90,9 @@ export const SystemResponse: React.FC<SystemResponseProps> = ({

useAutoScroll([showIndicator, complete, visibleMessages.length]);

// eslint-disable-next-line no-console
console.log({ complete, showIndicator, feedback });

if (!messages.length && !actions.length) return null;
return (
<>
<div className={responseContainer({ first: isFirst })}>
{visibleMessages.map((message, index) => (
<Message
message={message}
Expand All @@ -113,6 +116,6 @@ export const SystemResponse: React.FC<SystemResponseProps> = ({
)}

{showIndicator && <Indicator avatar={avatar} />}
</>
</div>
);
};
11 changes: 10 additions & 1 deletion packages/chat/src/components/SystemResponse/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,19 @@ export const systemMessageContainer = recipe({
marginBottom: 4,
animation: `${fadeInSlideUp} .05s ease-in`,
},
});

export const responseContainer = recipe({
base: {
display: 'block',
},
variants: {
first: {
true: {
marginTop: 12,
marginTop: '0px',
},
false: {
marginTop: '16px',
},
},
},
Expand Down
2 changes: 0 additions & 2 deletions packages/chat/src/components/UserMessage/UserMessage.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export const messageContainer = style({
backgroundColor: PALETTE.colors[500],
color: PALETTE.colors[50],
padding: '11px 16px 10px',
marginBottom: 4,
marginTop: 12,
fontFamily: FAMILY,
position: 'relative',
fontSize: '14px',
Expand Down
20 changes: 16 additions & 4 deletions packages/chat/src/components/UserResponse/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { ClassName } from '@/constants';
import { useAutoScroll } from '@/hooks/useAutoScroll';

import { Tooltip } from '../Tooltip';
import { debugMessage, messageContainer, messageRow, messageStyle } from './styles.css';
import { UserMessage } from '../UserMessage';
import { debugMessage, messageContainer, messageRow } from './styles.css';

export interface DebugActionProps {
label: string;
Expand Down Expand Up @@ -32,23 +33,34 @@ export interface UserResponseProps {
* If provided, adds a caption and optional "debug" message with an action.
*/
debug?: DebugResponseProps;

/**
* If true, this is the first message in the chat.
*/
isFirst?: boolean;

/**
* If true, the chat is using an avatar.
*/

hasAvatar?: boolean;
}

/**
* A user-sent text response.
*
* @see {@link https://voiceflow.github.io/react-chat/?path=/story/components-chat-userresponse--simple}
*/
export const UserResponse: React.FC<UserResponseProps> = ({ message, debug }) => {
export const UserResponse: React.FC<UserResponseProps> = ({ message, debug, isFirst, hasAvatar }) => {
useAutoScroll();

// TODO: Check this in different render modes
// const { config } = useContext(RuntimeStateAPIContext);

return (
<div className={clsx(ClassName.USER_RESPONSE, messageContainer)}>
<div className={messageRow}>
<div className={messageStyle}>{message}</div>
<div className={messageRow({ isFirst, hasAvatar })}>
<UserMessage message={message} />
</div>
{debug && (
<>
Expand Down
61 changes: 47 additions & 14 deletions packages/chat/src/components/UserResponse/styles.css.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,59 @@
import { 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';

export const messageContainer = style({
fontFamily: FAMILY,
fontSize: '14px',
lineHeight: '20px',
display: 'flex',
flexDirection: 'column',
flexShrink: 0,
alignItems: 'flex-end',
marginTop: 12,
import { SMALL_AVATAR_SIZE } from '../Avatar/styles.css';
import { MESSAGE_PADDING } from '../SystemResponse/styles.css';

export const messageContainer = recipe({
base: {
fontFamily: FAMILY,
fontSize: '14px',
lineHeight: '20px',
display: 'flex',
flexDirection: 'column',
flexShrink: 0,
alignItems: 'flex-end',
},
variants: {
isFirst: {
true: {
marginTop: '0px',
},
false: {
marginTop: '16px',
},
},
},
});

export const messageRow = style({
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'flex-end',
export const messageRow = recipe({
base: {
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'flex-end',
marginBottom: '16px',
},
variants: {
isFirst: {
true: {
marginTop: '0px',
},
false: {
marginTop: '16px',
},
},
hasAvatar: {
true: {
paddingLeft: `${SMALL_AVATAR_SIZE + MESSAGE_PADDING}px`,
},
},
},
});

export const messageStyle = style({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const welcomeMessageContainer = style({
flexDirection: 'column',
alignItems: 'center',
fontFamily: FAMILY,
padding: '48px 20px 24px 20px',
padding: '48px 20px 44px 20px',
textAlign: 'center',
});

Expand All @@ -21,11 +21,19 @@ export const welcomeMessageTitle = style({
fontSize: '22px',
fontWeight: 700,
color: COLORS.NEUTRAL_DARK[900],
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
});

export const welcomeMessageDescription = style({
margin: 0,
fontSize: '14px',
fontWeight: 400,
color: COLORS.NEUTRAL_DARK[100],
display: '-webkit-box',
WebkitLineClamp: 3,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ export const Base: Story = {
export const LongContent: Story = {
args: {
avatar: EMPTY_IMAGE,
title: 'Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways',
title:
'Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways. Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways. Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways. Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways. Hello, I am your #1 favourite AI assistant, meant to help you out in all sorts of ways.',
description:
'I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything!',
'I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything! I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything! I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything!I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything! I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything! I can do tons of stuff, like help you with your account, answer questions, and even tell you a joke or two. Just ask me anything!',
},
render: (args) => (
<div>
Expand Down
8 changes: 6 additions & 2 deletions packages/chat/src/components/WelcomeMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ export const WelcomeMessage: React.FC<IWelcomeMessage> = ({ title, description,
<div className={avatarContainer}>
<Avatar size="large" avatar={avatar} />
</div>
<div className={welcomeMessageTitle}>{title}</div>
<div className={welcomeMessageDescription}>{description}</div>
<div className={welcomeMessageTitle} title={title}>
{title}
</div>
<div className={welcomeMessageDescription} title={description}>
{description}
</div>
</div>
);
};
2 changes: 1 addition & 1 deletion packages/chat/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
margin-bottom: 8px;
margin-top: 8px;
font-size: 16px;
font-weight: 600;
font-weight: 700;
}

.markdown h2,
Expand Down
20 changes: 15 additions & 5 deletions packages/chat/src/views/ChatWindow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,24 @@ export const ChatWindow: React.FC<ChatWindowProps> = ({ isMobile }) => {
}}
isMobile={isMobile}
>
{state.session.turns.map((turn, turnIndex) =>
match(turn)
.with({ type: TurnType.USER }, ({ id, ...props }) => <UserResponse {...R.omit(props, ['type'])} key={id} />)
{state.session.turns.map((turn, turnIndex) => {
return match(turn)
.with({ type: TurnType.USER }, ({ id, ...props }) => {
return (
<UserResponse
{...R.omit(props, ['type'])}
isFirst={turnIndex === 0}
hasAvatar={!!assistant.avatar}
key={id}
/>
);
})
.with({ type: TurnType.SYSTEM }, ({ id, ...props }) => (
<SystemResponse
key={id}
{...R.omit(props, ['type'])}
avatar={assistant.avatar}
isFirst={turnIndex === 0}
feedback={
assistant.feedback
? {
Expand All @@ -86,8 +96,8 @@ export const ChatWindow: React.FC<ChatWindowProps> = ({ isMobile }) => {
isLast={turnIndex === state.session.turns.length - 1}
/>
))
.exhaustive()
)}
.exhaustive();
})}
</NewChat>
</div>
);
Expand Down

0 comments on commit 48d9906

Please sign in to comment.