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:
parent
b7b5a8ae48
commit
ababe9fe75
3
frontend/src/assets/icons/AI.svg
Normal file
3
frontend/src/assets/icons/AI.svg
Normal 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 |
@ -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 })}
|
||||
>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -3,6 +3,7 @@ import { FormHelperTextOwnProps } from '@mui/material/FormHelperText';
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface CustomTheme {
|
||||
mode: 'light' | 'dark';
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user