Skip to content

Commit

Permalink
chore: Unleash AI UX adjustments: placement, icon, color (#8521)
Browse files Browse the repository at this point in the history
https://linear.app/unleash/issue/2-2870/ux-adjustments-following-the-breakathon-placement-on-demo-bot-icon-and

Post-breakathon UX adjustments, including:
- Properly positions the Unleash AI chat option to the left of the demo
steps, when the demo steps are visible.
- Replaces the bot icon with a friendlier, more upbeat version.
- Switches the chat purple color in the light theme to `primary.main`
for better accessibility.

Additionally, I’ve added the mode property to our themes for easier
future maintenance. This makes it simple to check the currently active
theme.


![image](https://github.com/user-attachments/assets/bc0c2f99-5460-4bc7-8aa0-e8d94156b669)
  • Loading branch information
nunogois authored Oct 23, 2024
1 parent b7b5a8a commit ababe9f
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 18 deletions.
3 changes: 3 additions & 0 deletions frontend/src/assets/icons/AI.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 32 additions & 10 deletions frontend/src/component/ai/AIChat.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mutate } from 'swr';
import SmartToyIcon from '@mui/icons-material/SmartToy';
import { IconButton, styled } from '@mui/material';
import { ReactComponent as AIIcon } from 'assets/icons/AI.svg';
import { IconButton, styled, useMediaQuery } from '@mui/material';
import { useEffect, useRef, useState } from 'react';
import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';
Expand All @@ -16,6 +16,7 @@ import { AIChatHeader } from './AIChatHeader';
import { Resizable } from 'component/common/Resizable/Resizable';
import { AIChatDisclaimer } from './AIChatDisclaimer';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import theme from 'themes/theme';

const AI_ERROR_MESSAGE = {
role: 'assistant',
Expand All @@ -26,10 +27,15 @@ type ScrollOptions = ScrollIntoViewOptions & {
onlyIfAtEnd?: boolean;
};

const StyledAIIconContainer = styled('div')(({ theme }) => ({
const StyledAIIconContainer = styled('div', {
shouldForwardProp: (prop) => prop !== 'demoStepsVisible',
})<{ demoStepsVisible: boolean }>(({ theme, demoStepsVisible }) => ({
position: 'fixed',
bottom: 20,
right: 20,
...(demoStepsVisible && {
right: 260,
}),
zIndex: theme.zIndex.fab,
animation: 'fadeInBottom 0.5s',
'@keyframes fadeInBottom': {
Expand All @@ -44,24 +50,36 @@ const StyledAIIconContainer = styled('div')(({ theme }) => ({
},
}));

const StyledAIChatContainer = styled(StyledAIIconContainer)({
const StyledAIChatContainer = styled(StyledAIIconContainer, {
shouldForwardProp: (prop) => prop !== 'demoStepsVisible',
})<{ demoStepsVisible: boolean }>(({ demoStepsVisible }) => ({
bottom: 10,
right: 10,
});
...(demoStepsVisible && {
right: 250,
}),
}));

const StyledResizable = styled(Resizable)(({ theme }) => ({
boxShadow: theme.boxShadows.popup,
borderRadius: theme.shape.borderRadiusLarge,
}));

const StyledAIIconButton = styled(IconButton)(({ theme }) => ({
background: theme.palette.primary.light,
background:
theme.mode === 'light'
? theme.palette.primary.main
: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
boxShadow: theme.boxShadows.popup,
transition: 'background 0.3s',
'&:hover': {
background: theme.palette.primary.dark,
},
'& > svg': {
width: theme.spacing(3),
height: theme.spacing(3),
},
}));

const StyledChat = styled('div')(({ theme }) => ({
Expand All @@ -84,6 +102,8 @@ const StyledChatContent = styled('div')(({ theme }) => ({

export const AIChat = () => {
const unleashAIEnabled = useUiFlag('unleashAI');
const demoEnabled = useUiFlag('demo');
const isSmallScreen = useMediaQuery(theme.breakpoints.down(768));
const {
uiConfig: { unleashAIAvailable },
} = useUiConfig();
Expand Down Expand Up @@ -169,13 +189,15 @@ export const AIChat = () => {
newChat();
};

const demoStepsVisible = demoEnabled && !isSmallScreen;

if (!unleashAIEnabled || !unleashAIAvailable) {
return null;
}

if (!open) {
return (
<StyledAIIconContainer>
<StyledAIIconContainer demoStepsVisible={demoStepsVisible}>
<StyledAIIconButton
size='large'
onClick={() => {
Expand All @@ -187,18 +209,18 @@ export const AIChat = () => {
setOpen(true);
}}
>
<SmartToyIcon />
<AIIcon />
</StyledAIIconButton>
</StyledAIIconContainer>
);
}

return (
<StyledAIChatContainer>
<StyledAIChatContainer demoStepsVisible={demoStepsVisible}>
<StyledResizable
handlers={['top-left', 'top', 'left']}
minSize={{ width: '270px', height: '250px' }}
maxSize={{ width: '90vw', height: '90vh' }}
maxSize={{ width: '80vw', height: '90vh' }}
defaultSize={{ width: '320px', height: '500px' }}
onResize={() => scrollToEnd({ onlyIfAtEnd: true })}
>
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/component/ai/AIChatHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { IconButton, styled, Tooltip, Typography } from '@mui/material';
import SmartToyIcon from '@mui/icons-material/SmartToy';
import { ReactComponent as AIIcon } from 'assets/icons/AI.svg';
import EditNoteIcon from '@mui/icons-material/EditNote';
import CloseIcon from '@mui/icons-material/Close';

const StyledHeader = styled('div')(({ theme }) => ({
background: theme.palette.primary.light,
background:
theme.mode === 'light'
? theme.palette.primary.main
: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
display: 'flex',
alignItems: 'center',
Expand Down Expand Up @@ -41,7 +44,7 @@ export const AIChatHeader = ({ onNew, onClose }: IAIChatHeaderProps) => {
return (
<StyledHeader>
<StyledTitleContainer>
<SmartToyIcon />
<AIIcon />
<StyledTitle>Unleash AI</StyledTitle>
</StyledTitleContainer>
<StyledActionsContainer>
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/component/ai/AIChatMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Avatar, styled } from '@mui/material';
import SmartToyIcon from '@mui/icons-material/SmartToy';
import { ReactComponent as AIIcon } from 'assets/icons/AI.svg';
import { Markdown } from 'component/common/Markdown/Markdown';
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import type { ChatMessage } from 'hooks/api/actions/useAIApi/useAIApi';
Expand Down Expand Up @@ -62,7 +62,10 @@ const StyledUserMessage = styled(StyledAIMessage)(({ theme }) => ({
const StyledAvatar = styled(Avatar)(({ theme }) => ({
width: theme.spacing(4.5),
height: theme.spacing(4.5),
backgroundColor: theme.palette.primary.light,
backgroundColor:
theme.mode === 'light'
? theme.palette.primary.main
: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
}));

Expand All @@ -89,7 +92,7 @@ export const AIChatMessage = ({ from, children }: IAIChatMessageProps) => {
return (
<StyledMessageContainer>
<StyledAvatar>
<SmartToyIcon />
<AIIcon />
</StyledAvatar>
<StyledAIMessage>
<Markdown>{children}</Markdown>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/themes/dark-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const actionColors = {
};

const theme = {
mode: 'dark',
breakpoints: {
values: {
xs: 0,
Expand Down Expand Up @@ -309,7 +310,7 @@ const theme = {
series: colors.chartSeries,
},
},
};
} as const;

export default createTheme({
...theme,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/themes/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { alpha } from '@mui/material';
import { focusable } from 'themes/themeStyles';

export const theme = {
mode: 'light',
breakpoints: {
values: {
xs: 0,
Expand Down Expand Up @@ -294,7 +295,7 @@ export const theme = {
series: colors.chartSeries,
},
},
};
} as const;

export default createTheme({
...theme,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/themes/themeTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FormHelperTextOwnProps } from '@mui/material/FormHelperText';

declare module '@mui/material/styles' {
interface CustomTheme {
mode: 'light' | 'dark';
/**
* @deprecated
*/
Expand Down

0 comments on commit ababe9f

Please sign in to comment.