Skip to content

Commit

Permalink
chore(unl-204): make toasts smaller (#8935)
Browse files Browse the repository at this point in the history
This PR makes toasts smaller and less intrusive, and gives them a new
color scheme.

Changes include:
- new color scheme
- no description, only title
- new padding
- removes confetti code (even when rendered, they're invisible; UX also
says to cut it)
- use warning triangle for error messages 

I've also set a max height on the container and made it scrollable if
it's too tall to deal with super long messages.

I'll remove the description and confetti props in a separate PR to keep
this one cleaner.

Light mode:

![image](https://github.com/user-attachments/assets/05666259-bc40-4c87-8e51-9900bc67310e)

![image](https://github.com/user-attachments/assets/25dfca09-af5f-4a2a-8490-1169f6d8accb)


Dark mode:

![image](https://github.com/user-attachments/assets/8fa199aa-3cb5-47b4-acaa-1b0fcfd668eb)

![image](https://github.com/user-attachments/assets/eca7d26e-f695-43f9-b281-a64315544212)


With line break (min-width):

![image](https://github.com/user-attachments/assets/2ebd9117-a7c2-4a96-8b4b-c217ba12993b)

With line break (max-width):

![image](https://github.com/user-attachments/assets/8015c761-fc1e-4ff9-992d-a0e9ec27a4f9)

With very long message on phone in landscape mode:


![image](https://github.com/user-attachments/assets/7dc34d25-026c-46c3-9906-dc1348daf208)
  • Loading branch information
thomasheartman authored Dec 10, 2024
1 parent 7ff6a9c commit 2f7bece
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 148 deletions.
49 changes: 17 additions & 32 deletions frontend/src/component/common/CheckmarkBadge/CheckMarkBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,31 @@
import Check from '@mui/icons-material/Check';
import Close from '@mui/icons-material/Close';
import Check from '@mui/icons-material/CheckCircle';
import Warning from '@mui/icons-material/Warning';
import { styled } from '@mui/material';

interface ICheckMarkBadgeProps {
className: string;
type?: string;
}

const StyledBatch = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.background.alternative,
width: '75px',
height: '75px',
borderRadius: '50px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
[theme.breakpoints.down('sm')]: {
width: '50px',
height: '50px',
},
const StyledCheck = styled(Check)(({ theme }) => ({
color:
theme.mode === 'light'
? theme.palette.secondary.border
: theme.palette.primary.main,
}));

const StyledClose = styled(Close)(({ theme }) => ({
color: theme.palette.common.white,
width: '35px',
height: '35px',
}));
const StyledCheck = styled(Check)(({ theme }) => ({
color: theme.palette.common.white,
width: '35px',
height: '35px',
const StyledCancel = styled(Warning)(({ theme }) => ({
color:
theme.mode === 'light'
? theme.palette.warning.border
: theme.palette.warning.main,
}));

const CheckMarkBadge = ({ type, className }: ICheckMarkBadgeProps) => {
return (
<StyledBatch className={className}>
{type === 'error' ? (
<StyledClose titleAccess='Error' />
) : (
<StyledCheck />
)}
</StyledBatch>
const CheckMarkBadge = ({ type }: ICheckMarkBadgeProps) => {
return type === 'error' ? (
<StyledCancel titleAccess='Error' />
) : (
<StyledCheck />
);
};

Expand Down
59 changes: 26 additions & 33 deletions frontend/src/component/common/ToastRenderer/Toast/Toast.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,49 @@ import { makeStyles } from 'tss-react/mui';

export const useStyles = makeStyles()((theme) => ({
container: {
maxWidth: '450px',
background: theme.palette.background.paper,
alignItems: 'center',
background:
// the background color for this doesn't exist in the theme yet and it's not synchronized across dark/light modes yet.
theme.mode === 'light' ? '#201E42' : theme.palette.background.paper,

borderRadius: theme.shape.borderRadiusMedium,
boxShadow: theme.boxShadows.popup,
zIndex: 500,
display: 'flex',
flexDirection: 'row',
gap: theme.spacing(2),
margin: '0 0.8rem',
borderRadius: '12.5px',
padding: '2rem',
},
innerContainer: {
position: 'relative',
maxWidth: '450px',
padding: theme.spacing(1),
paddingLeft: theme.spacing(2),
zIndex: theme.zIndex.snackbar,
color: theme.palette.common.white,
},
starting: {
opacity: 0,
},
headerContainer: {
display: 'flex',
alignItems: 'center',
},
confettiContainer: {
position: 'relative',
maxWidth: '600px',
margin: '0 auto',
display: 'flex',
},
textContainer: {
marginLeft: '1rem',
wordBreak: 'break-word',
},
headerStyles: {
fontSize: theme.typography.body1.fontSize,
fontWeight: 'normal',
margin: 0,
marginBottom: '0.5rem',
},
createdContainer: {
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
maxHeight: '75vh',
overflowY: 'auto',
'&::first-letter': {
textTransform: 'uppercase',
},
},
anim: {
animation: `$drop 10s 3s`,
},
checkMark: {
width: '65px',
height: '65px',
marginLeft: theme.spacing(1),
},
buttonStyle: {
position: 'absolute',
top: '-33px',
right: '-33px',
color: theme.palette.common.white,
svg: {
fontSize: '1em',
},
},

'@keyframes drop': {
'0%': {
opacity: '0%',
Expand Down
88 changes: 14 additions & 74 deletions frontend/src/component/common/ToastRenderer/Toast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,93 +4,33 @@ import { useContext } from 'react';
import { IconButton, Tooltip } from '@mui/material';
import CheckMarkBadge from 'component/common/CheckmarkBadge/CheckMarkBadge';
import UIContext from 'contexts/UIContext';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import Close from '@mui/icons-material/Close';
import type { IToast } from 'interfaces/toast';
import { TOAST_TEXT } from 'utils/testIds';

const Toast = ({ title, text, type, confetti }: IToast) => {
const Toast = ({ title, type }: IToast) => {
const { setToast } = useContext(UIContext);

const { classes: styles } = useStyles();
const confettiColors = ['#d13447', '#ffbf00', '#263672'];
const confettiAmount = 200;

const getRandomNumber = (input: number) => {
return Math.floor(Math.random() * input) + 1;
};

const renderConfetti = () => {
const elements = new Array(confettiAmount).fill(1);

const styledElements = elements.map((el, index) => {
const width = getRandomNumber(8);
const length = getRandomNumber(100);

const style = {
position: 'absolute' as const,
width: `${width}px`,
height: `${width * 0.4}px`,
backgroundColor: confettiColors[getRandomNumber(2)],
left: `${length}%`,
transform: `rotate(${getRandomNumber(101)}deg)`,
animationDelay: `${getRandomNumber(5)}s`,
animationDuration: `${getRandomNumber(3)}s`,
animationEase: `${getRandomNumber(2)}s`,
};

return (
<div
key={index}
style={style}
className={classnames(styles.starting, styles.anim)}
/>
);
});

return styledElements;
};

const hide = () => {
setToast((prev: IToast) => ({ ...prev, show: false }));
};

return (
<div className={classnames(styles.container, 'dropdown-outline')}>
<div className={styles.innerContainer}>
<div className={styles.confettiContainer}>
{confetti && renderConfetti()}
<div className={styles.createdContainer}>
<div className={styles.headerContainer}>
<div>
<CheckMarkBadge
type={type}
className={styles.checkMark}
/>
</div>
<div className={styles.textContainer}>
<h3 className={styles.headerStyles}>{title}</h3>

<ConditionallyRender
condition={Boolean(text)}
show={
<p data-testid={TOAST_TEXT}>{text}</p>
}
/>
</div>
</div>
<Tooltip title='Close' arrow>
<IconButton
onClick={hide}
className={styles.buttonStyle}
size='large'
>
<Close />
</IconButton>
</Tooltip>
</div>
</div>
</div>
<CheckMarkBadge type={type} className={styles.checkMark} />

<h3 className={styles.headerStyles}>{title}</h3>

<Tooltip title='Close' arrow>
<IconButton
onClick={hide}
className={styles.buttonStyle}
size='small'
>
<Close />
</IconButton>
</Tooltip>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const ToastRenderer = () => {
const timeout = setTimeout(() => {
hide();
}, toastData.autoHideDuration);

return () => {
clearTimeout(timeout);
};
Expand All @@ -36,7 +35,7 @@ const ToastRenderer = () => {
right: 0,
left: 0,
margin: '0 auto',
maxWidth: '450px',
width: 'fit-content',
},
enter: fadeInBottomEnter,
leave: fadeInBottomLeave,
Expand Down
6 changes: 0 additions & 6 deletions frontend/src/component/user/PasswordAuth.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ test('should show deleted stale sessions info for Password Auth', async () => {
button.click();

await screen.findByText('Maximum Session Limit Reached');
await screen.findByText(
'You can have up to 3 active sessions at a time. To enhance your account security, we’ve ended 1 session(s) on other browsers.',
);
});

test('should show deleted stale sessions info for Hosted Auth', async () => {
Expand All @@ -76,7 +73,4 @@ test('should show deleted stale sessions info for Hosted Auth', async () => {
button.click();

await screen.findByText('Maximum Session Limit Reached');
await screen.findByText(
'You can have up to 3 active sessions at a time. To enhance your account security, we’ve ended 1 session(s) on other browsers.',
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,6 @@ test('handle error', async () => {

checkbox.click();

await screen.findByText('user error');
await screen.findByText('Something went wrong');
expect(changed).toBe(true);
});

0 comments on commit 2f7bece

Please sign in to comment.