mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-04 00:18:40 +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. 
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