Skip to content

Commit

Permalink
[Debt] Updates Toast component and react-toastify (#12426)
Browse files Browse the repository at this point in the history
* Update Toast

* Update story

* Remove role attribute
role is on parent

* Add ToastWithLink

* Fix import order
  • Loading branch information
mnigh authored Jan 13, 2025
1 parent 8e8a21b commit 9407527
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 272 deletions.
3 changes: 2 additions & 1 deletion packages/toast/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
},
"dependencies": {
"@heroicons/react": "^2.2.0",
"react-toastify": "^10.0.6"
"react-toastify": "^11.0.2"
},
"devDependencies": {
"@faker-js/faker": "^9.3.0",
"@gc-digital-talent/eslint-config": "workspace:*",
"@gc-digital-talent/storybook-helpers": "workspace:*",
"@gc-digital-talent/ui": "workspace:*",
"@storybook/react": "^8.4.7",
"@types/react": "^18.3.13",
"eslint": "^8.57.0",
Expand Down
81 changes: 53 additions & 28 deletions packages/toast/src/components/Toast/Toast.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,68 @@
import type { StoryFn, Meta } from "@storybook/react";
import { faker } from "@faker-js/faker/locale/en";
import { useEffect } from "react";
import type { Meta, StoryObj } from "@storybook/react";

import { OverlayOrDialogDecorator } from "@gc-digital-talent/storybook-helpers";
import {
allModes,
OverlayOrDialogDecorator,
} from "@gc-digital-talent/storybook-helpers";
import { Link } from "@gc-digital-talent/ui";

import toast from "../../toast";
import Toast from "./Toast";
import "./toast.css";

interface StoryArgs {
text: string;
longText: string;
}

faker.seed(0);

export default {
const meta = {
component: Toast,
argTypes: {
disableTransition: { control: "boolean" },
autoClose: { control: "boolean" },
},
args: {
text: "Toast text",
longText: faker.lorem.sentences(3),
disableTransition: true,
autoClose: false,
},
decorators: [OverlayOrDialogDecorator],
} as Meta;
parameters: {
chromatic: {
modes: {
light: allModes.light,
dark: allModes.dark,
},
delay: 1500,
},
},
} satisfies Meta<typeof Toast>;
export default meta;

const Template: StoryFn<StoryArgs> = (args) => {
const { text, longText } = args;
type Story = StoryObj<typeof Toast>;

toast.info(text);
toast.info(longText);
toast.success(text);
toast.warning(text);
toast.error(text);
const ToastWithLink = () => (
<>
Toast info with{" "}
<Link href="https://talent.canada.ca" newTab>
link
</Link>
</>
);

// avoid animations with Chromatic snapshots
return (
<div>
<Toast disableTransition autoClose={false} />
</div>
);
const Template = () => {
useEffect(() => {
setTimeout(() => {
toast.info("Toast info text", { autoClose: false });
toast.info(<ToastWithLink />, {
autoClose: false,
});
toast.info(
"Toast info with three sentences. Text sentence two. Toast text sentence three.",
{ autoClose: false },
);
toast.success("Toast success text", { autoClose: false });
toast.warning("Toast warning text", { autoClose: false });
}, 100);
}, []);
return <Toast />;
};

export const Default = Template.bind({});
export const Default: Story = {
render: () => <Template />,
};
2 changes: 1 addition & 1 deletion packages/toast/src/components/Toast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import XCircleIcon from "@heroicons/react/24/solid/XCircleIcon";

import closeButtonStyles from "./styles";

import "react-toastify/dist/ReactToastify.minimal.css";
import "./toast.css";

type CloseButtonProps = ComponentPropsWithoutRef<
Expand Down Expand Up @@ -52,6 +51,7 @@ const Toast = ({ disableTransition, autoClose = 5000 }: ToastProps) => (
closeButton={CloseButton}
icon={false}
autoClose={autoClose}
aria-label={undefined}
/>
);

Expand Down
192 changes: 16 additions & 176 deletions packages/toast/src/components/Toast/toast.css
Original file line number Diff line number Diff line change
@@ -1,191 +1,31 @@
:root {
--toast-space: calc(var(--h2-base-whitespace) * 1rem);
--toastify-toast-width: calc(100vw - calc(2 * var(--toast-space)));
--toastify-toast-offset: 16px;
--toastify-toast-padding: 0;
--toastify-text-color-light: rgba(var(--h2-color-black), 1);
--toastify-font-family: inherit;
}

/** Used to define container behavior: width, position: fixed etc... **/
.Toastify__toast-container {
position: fixed;
width: calc(100vw - calc(2 * var(--toast-space)));
z-index: 999999; /* Display over everything else */
}

@media screen and (min-width: 48rem) {
.Toastify__toast-container {
width: 40vw;
}
}

/** Used to define the position of the ToastContainer **/
.Toastify__toast-container--top-left {
top: var(--toast-space);
left: var(--toast-space);
}

.Toastify__toast-container--top-center {
top: var(--toast-space);
left: 50%;
transform: translateX(-50%);
}

.Toastify__toast-container--top-right {
top: var(--toast-space);
right: var(--toast-space);
}

.Toastify__toast-container--bottom-left {
bottom: var(--toast-space);
left: var(--toast-space);
}

.Toastify__toast-container--bottom-center {
bottom: var(--toast-space);
left: 50%;
transform: translateX(-50%);
.Toastify__toast {
display: block;
}

.Toastify__toast-container--bottom-right {
z-index: 999999; /* Display over everything else */
left: auto;
bottom: var(--toast-space);
right: var(--toast-space);
}

/** Classes for the displayed toast **/
.Toastify__toast {
background-color: rgba(var(--h2-color-foreground), 1);
box-sizing: border-box;
position: relative;
margin-bottom: calc((var(--h2-base-whitespace) * 0.5) * 1rem);
border: 3px solid;
border-radius: var(--h2-radius-rounded);
box-shadow: var(--h2-shadow-largest);
display: flex;
overflow: hidden;
justify-content: space-between;
z-index: 0;
}

.Toastify__toast-body {
align-items: center;
display: flex;
margin: auto 0;
flex: 1 1 auto;
}

.Toastify__toast-body > div:nth-child(2) {
padding-right: calc((var(--h2-base-whitespace) * 2) * 1rem);
}

.Toastify__toast--default {
border-color: rgba(var(--h2-color-black), 1);
}

.Toastify__toast--info {
border-color: rgba(var(--h2-color-secondary-darker), 1);
}

.Toastify__toast--success {
border-color: rgba(var(--h2-color-success-darker), 1);
}

.Toastify__toast--warning {
border-color: rgba(var(--h2-color-warning-darker), 1);
}

.Toastify__toast--error {
border-color: rgba(var(--h2-color-error-darker), 1);
}

.Toastify__toast-icon {
display: flex;
align-items: flex-start;
align-self: stretch;
padding: calc(var(--h2-base-whitespace) * 0.5rem)
calc(var(--h2-base-whitespace) * 1rem);
position: relative;
}

.Toastify__toast--info .Toastify__toast-icon {
background-color: rgba(var(--h2-color-secondary-lightest-locked), 1);
color: rgba(var(--h2-color-secondary-darker-locked), 1);
}

.Toastify__toast--success .Toastify__toast-icon {
background-color: rgba(var(--h2-color-success-lightest-locked), 1);
color: rgba(var(--h2-color-success-darker-locked), 1);
}

.Toastify__toast--warning .Toastify__toast-icon {
background-color: rgba(var(--h2-color-warning-lightest-locked), 1);
color: rgba(var(--h2-color-warning-darker-locked), 1);
}

.Toastify__toast--error .Toastify__toast-icon {
background-color: rgba(var(--h2-color-error-lightest-locked), 1);
color: rgba(var(--h2-color-error-darker-locked), 1);
right: 0.25rem;
}

.Toastify__toast-icon:after {
border-style: solid;
border-width: 10px 0 10px 10px;
bottom: auto;
content: "";
height: 0;
left: 100%;
position: absolute;
top: calc((1 * var(--h2-base-whitespace)) * 1.1rem);
transform: translate(0);
width: 0;
}

.Toastify__toast--info .Toastify__toast-icon:after {
border-color: transparent transparent transparent
rgba(var(--h2-color-secondary-lightest-locked), 1);
}
.Toastify__toast--success .Toastify__toast-icon:after {
border-color: transparent transparent transparent
rgba(var(--h2-color-success-lightest-locked), 1);
}
.Toastify__toast--warning .Toastify__toast-icon:after {
border-color: transparent transparent transparent
rgba(var(--h2-color-warning-lightest-locked), 1);
}
.Toastify__toast--error .Toastify__toast-icon:after {
border-color: transparent transparent transparent
rgba(var(--h2-color-error-lightest-locked), 1);
}

.Toastify--animate {
animation-fill-mode: both;
animation-duration: 0.7s;
}

@keyframes Toastify__slideInUp {
from {
transform: translateY(110%);
opacity: 0;
visibility: visible;
}
to {
transform: translateY(0);
opacity: 1;
@media screen and (min-width: 48rem) {
:root {
--toastify-toast-width: 40vw;
}
}

@keyframes Toastify__slideOutRight {
from {
opacity: 1;
transform: translateX(0);
@media only screen and (max-width: 480px) {
.Toastify__toast {
--toastify-toast-width: calc(100vw - calc(2 * var(--toast-space)));
}
to {
visibility: hidden;
transform: translateX(200%);
opacity: 0;
}
}

.Toastify__slide-enter--bottom-right {
animation-name: Toastify__slideInUp;
}

.Toastify__slide-exit--bottom-right {
animation-name: Toastify__slideOutRight;
}
14 changes: 14 additions & 0 deletions packages/toast/src/components/ToastAlert/ToastAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Alert, AlertProps } from "@gc-digital-talent/ui";

const ToastAlert = ({ type, children }: AlertProps) => (
<Alert.Root live={false} type={type} data-h2-margin="base(0)" tabIndex={0}>
<div
data-h2-padding-right="p-tablet(x2)"
data-h2-line-height="base(var(--h2-base-line-height))"
>
{children}
</div>
</Alert.Root>
);

export default ToastAlert;
16 changes: 0 additions & 16 deletions packages/toast/src/components/ToastMessage/ToastMessage.tsx

This file was deleted.

Loading

0 comments on commit 9407527

Please sign in to comment.