1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00

chore: Unleash AI UX adjustments: placement, icon, color (#8521)

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)
This commit is contained in:
Nuno Góis 2024-10-23 15:59:02 +01:00 committed by GitHub
parent b7b5a8ae48
commit ababe9fe75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 52 additions and 18 deletions

View File

@ -0,0 +1,3 @@
<svg width="22" height="19" viewBox="0 0 22 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 7V5C19 3.9 18.1 3 17 3H14C14 1.34 12.66 0 11 0C9.34 0 8 1.34 8 3H5C3.9 3 3 3.9 3 5V7C1.34 7 0 8.34 0 10C0 11.66 1.34 13 3 13V17C3 18.1 3.9 19 5 19H17C18.1 19 19 18.1 19 17V13C20.66 13 22 11.66 22 10C22 8.34 20.66 7 19 7ZM17 17H5V5H17V17ZM8 11C7.17 11 6.5 10.33 6.5 9.5C6.5 8.67 7.17 8 8 8C8.83 8 9.5 8.67 9.5 9.5C9.5 10.33 8.83 11 8 11ZM15.5 9.5C15.5 10.33 14.83 11 14 11C13.17 11 12.5 10.33 12.5 9.5C12.5 8.67 13.17 8 14 8C14.83 8 15.5 8.67 15.5 9.5ZM7 13L11 14L15 13C15 13 15.5 14 15 14.5C14.5 15 11 15.5 11 15.5C11 15.5 7.5 15 7 14.5C6.5 14 7 13 7 13Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 687 B

View File

@ -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';
@ -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',
@ -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': {
@ -44,10 +50,15 @@ 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,
@ -55,13 +66,20 @@ const StyledResizable = styled(Resizable)(({ theme }) => ({
}));
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 }) => ({
@ -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();
@ -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={() => {
@ -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 })}
>

View File

@ -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',
@ -41,7 +44,7 @@ export const AIChatHeader = ({ onNew, onClose }: IAIChatHeaderProps) => {
return (
<StyledHeader>
<StyledTitleContainer>
<SmartToyIcon />
<AIIcon />
<StyledTitle>Unleash AI</StyledTitle>
</StyledTitleContainer>
<StyledActionsContainer>

View File

@ -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';
@ -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,
}));
@ -89,7 +92,7 @@ export const AIChatMessage = ({ from, children }: IAIChatMessageProps) => {
return (
<StyledMessageContainer>
<StyledAvatar>
<SmartToyIcon />
<AIIcon />
</StyledAvatar>
<StyledAIMessage>
<Markdown>{children}</Markdown>

View File

@ -12,6 +12,7 @@ const actionColors = {
};
const theme = {
mode: 'dark',
breakpoints: {
values: {
xs: 0,
@ -309,7 +310,7 @@ const theme = {
series: colors.chartSeries,
},
},
};
} as const;
export default createTheme({
...theme,

View File

@ -4,6 +4,7 @@ import { alpha } from '@mui/material';
import { focusable } from 'themes/themeStyles';
export const theme = {
mode: 'light',
breakpoints: {
values: {
xs: 0,
@ -294,7 +295,7 @@ export const theme = {
series: colors.chartSeries,
},
},
};
} as const;
export default createTheme({
...theme,

View File

@ -3,6 +3,7 @@ import { FormHelperTextOwnProps } from '@mui/material/FormHelperText';
declare module '@mui/material/styles' {
interface CustomTheme {
mode: 'light' | 'dark';
/**
* @deprecated
*/