(react) add Modal

Here it is! Our really wanted Modal component, based on Figma sketches.
This commit is contained in:
Nathan Vasse
2024-01-18 14:38:48 +01:00
committed by NathanVss
parent 81e4da1d36
commit 1445f4a222
32 changed files with 1723 additions and 111 deletions

View File

@@ -1,6 +1,6 @@
import { ReactNode } from "react";
import { ToastType } from ":/components/Toast/ToastProvider";
import { ButtonProps } from ":/components/Button";
import { VariantType } from ":/utils/VariantUtils";
/**
* This function is used for doc purpose only.
@@ -16,7 +16,7 @@ export const toast = ({
/** Message displayed inside the toast */
message: string;
/** Type of the toast */
type?: ToastType;
type?: VariantType;
/** Various options */
options?: {
duration: number;

View File

@@ -2,19 +2,12 @@ import React, { PropsWithChildren, useContext, useMemo, useRef } from "react";
import { Toast, ToastProps } from ":/components/Toast/index";
import { tokens } from ":/cunningham-tokens";
import { Queue } from ":/utils/Queue";
export enum ToastType {
INFO = "info",
SUCCESS = "success",
WARNING = "warning",
ERROR = "error",
NEUTRAL = "neutral",
}
import { VariantType } from ":/utils/VariantUtils";
export interface ToastProviderContext {
toast: (
message: string,
type?: ToastType,
type?: VariantType,
options?: Partial<Omit<ToastInterface, "message" | "type">>,
) => void;
}
@@ -57,7 +50,7 @@ export const ToastProvider = ({ children }: PropsWithChildren) => {
const context: ToastProviderContext = useMemo(
() => ({
toast: (message, type = ToastType.NEUTRAL, options = {}) => {
toast: (message, type = VariantType.NEUTRAL, options = {}) => {
// We want to wait for the previous toast to be added ( taking into account the animation )
// before adding a new one, that's why we use a queue.
queue.current?.push(

View File

@@ -8,8 +8,9 @@ import {
import userEvent from "@testing-library/user-event";
import { within } from "@testing-library/dom";
import { CunninghamProvider } from ":/components/Provider";
import { ToastType, useToastProvider } from ":/components/Toast/ToastProvider";
import { useToastProvider } from ":/components/Toast/ToastProvider";
import { Button } from ":/components/Button";
import { VariantType } from ":/utils/VariantUtils";
describe("<Toast />", () => {
const Wrapper = ({ children }: PropsWithChildren) => {
@@ -22,7 +23,7 @@ describe("<Toast />", () => {
return (
<Button
onClick={() =>
toast("Toast content", ToastType.NEUTRAL, { duration: 50 })
toast("Toast content", VariantType.NEUTRAL, { duration: 50 })
}
>
Create toast
@@ -54,7 +55,7 @@ describe("<Toast />", () => {
return (
<Button
onClick={() =>
toast("Toast content", ToastType.NEUTRAL, {
toast("Toast content", VariantType.NEUTRAL, {
primaryLabel: "Action",
primaryOnClick: () => {
flag = true;
@@ -95,7 +96,7 @@ describe("<Toast />", () => {
return (
<Button
onClick={() =>
toast("Toast content", ToastType.NEUTRAL, {
toast("Toast content", VariantType.NEUTRAL, {
actions: <Button color="tertiary">Tertiary</Button>,
})
}
@@ -123,11 +124,11 @@ describe("<Toast />", () => {
});
it.each([
[ToastType.INFO, "info"],
[ToastType.SUCCESS, "check_circle"],
[ToastType.WARNING, "error_outline"],
[ToastType.ERROR, "cancel"],
[ToastType.NEUTRAL, undefined],
[VariantType.INFO, "info"],
[VariantType.SUCCESS, "check_circle"],
[VariantType.WARNING, "error_outline"],
[VariantType.ERROR, "cancel"],
[VariantType.NEUTRAL, undefined],
])("shows a %s toast", async (type, iconName) => {
const Inner = () => {
const { toast } = useToastProvider();

View File

@@ -3,7 +3,8 @@ import React, { useEffect } from "react";
import { faker } from "@faker-js/faker";
import { ProgressBar, Toast } from ":/components/Toast/index";
import { Button } from ":/components/Button";
import { ToastType, useToastProvider } from ":/components/Toast/ToastProvider";
import { useToastProvider } from ":/components/Toast/ToastProvider";
import { VariantType } from ":/utils/VariantUtils";
const meta: Meta<typeof Toast> = {
title: "Components/Toast",
@@ -22,15 +23,15 @@ export const Demo: Story = {
render: () => {
const { toast } = useToastProvider();
const TYPES = [
ToastType.INFO,
ToastType.SUCCESS,
ToastType.WARNING,
ToastType.ERROR,
ToastType.NEUTRAL,
VariantType.INFO,
VariantType.SUCCESS,
VariantType.WARNING,
VariantType.ERROR,
VariantType.NEUTRAL,
];
useEffect(() => {
toast(faker.lorem.sentence({ min: 5, max: 10 }), ToastType.SUCCESS, {
toast(faker.lorem.sentence({ min: 5, max: 10 }), VariantType.SUCCESS, {
primaryLabel: "Read more",
primaryOnClick: () => {
// eslint-disable-next-line no-alert
@@ -62,20 +63,20 @@ export const Demo: Story = {
export const Info: Story = {
args: {
type: ToastType.INFO,
type: VariantType.INFO,
},
};
export const InfoWithButton: Story = {
args: {
type: ToastType.INFO,
type: VariantType.INFO,
primaryLabel: "Primary",
},
};
export const InfoCustom: Story = {
args: {
type: ToastType.INFO,
type: VariantType.INFO,
actions: (
<>
<Button color="primary">Primary</Button>
@@ -87,25 +88,25 @@ export const InfoCustom: Story = {
export const Success: Story = {
args: {
type: ToastType.SUCCESS,
type: VariantType.SUCCESS,
},
};
export const Warning: Story = {
args: {
type: ToastType.WARNING,
type: VariantType.WARNING,
},
};
export const Error: Story = {
args: {
type: ToastType.ERROR,
type: VariantType.ERROR,
},
};
export const Neutral: Story = {
args: {
type: ToastType.NEUTRAL,
type: VariantType.NEUTRAL,
},
};

View File

@@ -6,13 +6,12 @@ import React, {
useRef,
} from "react";
import classNames from "classnames";
import { ToastType } from ":/components/Toast/ToastProvider";
import { iconFromType } from ":/components/Alert/Utils";
import { Button, ButtonProps } from ":/components/Button";
import { iconFromType, VariantType } from ":/utils/VariantUtils";
export interface ToastProps extends PropsWithChildren {
duration: number;
type: ToastType;
type: VariantType;
onDelete?: () => void;
icon?: ReactNode;
primaryLabel?: string;