diff --git a/app/client/packages/design-system/headless/src/components/Popover/src/PopoverContent.tsx b/app/client/packages/design-system/headless/src/components/Popover/src/PopoverContent.tsx index 3288376320..0905e91883 100644 --- a/app/client/packages/design-system/headless/src/components/Popover/src/PopoverContent.tsx +++ b/app/client/packages/design-system/headless/src/components/Popover/src/PopoverContent.tsx @@ -1,9 +1,8 @@ -import React, { forwardRef } from "react"; +import React, { forwardRef, useEffect } from "react"; import { FloatingFocusManager, FloatingPortal, useMergeRefs, - FloatingOverlay, useTransitionStatus, } from "@floating-ui/react"; import { usePopoverContext } from "./PopoverContext"; @@ -16,65 +15,56 @@ const _PopoverContent = (props: PopoverContentProps, ref: Ref) => { children, closeOnFocusOut = true, contentClassName, - overlayClassName, style, ...rest } = props; - const { context, descriptionId, duration, getFloatingProps, labelId, modal } = - usePopoverContext(); + const { + context, + descriptionId, + duration, + getFloatingProps, + labelId, + onClose, + } = usePopoverContext(); const refs = useMergeRefs([context.refs.setFloating, ref]); const { isMounted, status } = useTransitionStatus(context, { duration }); + useEffect(() => { + if (!isMounted && status === "close" && onClose) { + onClose(); + } + }, [isMounted, status]); + if (!Boolean(isMounted)) return null; const root = context.refs.domReference.current?.closest( "[data-theme-provider]", ) as HTMLElement; - const content = ( -
- {children} -
- ); - - if (modal) { - return ( - - - - {content} - - - - ); - } else { - return ( - - + +
- {content} - - - ); - } + {children} +
+
+
+ ); }; export const PopoverContent = forwardRef(_PopoverContent); diff --git a/app/client/packages/design-system/headless/src/components/Popover/src/PopoverModalContent.tsx b/app/client/packages/design-system/headless/src/components/Popover/src/PopoverModalContent.tsx new file mode 100644 index 0000000000..87309e77a0 --- /dev/null +++ b/app/client/packages/design-system/headless/src/components/Popover/src/PopoverModalContent.tsx @@ -0,0 +1,113 @@ +import React, { forwardRef, useEffect, useState } from "react"; +import { + FloatingFocusManager, + FloatingPortal, + useMergeRefs, + FloatingOverlay, + useTransitionStatus, +} from "@floating-ui/react"; +import { usePopoverContext } from "./PopoverContext"; + +import type { Ref } from "react"; +import type { PopoverModalContentProps } from "./types"; + +const setAriaAttrs = ( + triggerElem: HTMLElement, + referenceProps: Record, +) => { + if (Boolean(referenceProps["aria-controls"])) { + triggerElem?.setAttribute( + "aria-controls", + referenceProps["aria-controls"] as string, + ); + } + + triggerElem?.setAttribute( + "aria-expanded", + referenceProps["aria-expanded"] as string, + ); + + triggerElem?.setAttribute( + "aria-haspopup", + referenceProps["aria-haspopup"] as string, + ); +}; + +const _PopoverModalContent = ( + props: PopoverModalContentProps, + ref: Ref, +) => { + const { + children, + closeOnFocusOut = true, + contentClassName, + overlayClassName, + style, + ...rest + } = props; + const { + context, + descriptionId, + duration, + getFloatingProps, + getReferenceProps, + initialFocus, + labelId, + onClose, + triggerRef, + } = usePopoverContext(); + const refs = useMergeRefs([context.refs.setFloating, ref]); + const [root, setRoot] = useState(null); + + useEffect(() => { + if (triggerRef?.current != null) { + setRoot(triggerRef.current?.closest("[data-theme-provider]")); + } else { + setRoot(document.body.querySelector("[data-theme-provider]")); + } + }, [triggerRef?.current]); + + const referenceProps = getReferenceProps({ ref: refs }); + useEffect(() => { + if (triggerRef?.current != null) { + setAriaAttrs(triggerRef?.current, referenceProps); + } + }, [referenceProps, triggerRef?.current]); + + const { isMounted, status } = useTransitionStatus(context, { duration }); + + useEffect(() => { + if (!isMounted && status === "close" && onClose) { + onClose(); + } + }, [isMounted, status]); + + if (!Boolean(isMounted)) return null; + + return ( + + + +
+ {children} +
+
+
+
+ ); +}; + +export const PopoverModalContent = forwardRef(_PopoverModalContent); diff --git a/app/client/packages/design-system/headless/src/components/Popover/src/index.ts b/app/client/packages/design-system/headless/src/components/Popover/src/index.ts index b64be8d483..1466de1902 100644 --- a/app/client/packages/design-system/headless/src/components/Popover/src/index.ts +++ b/app/client/packages/design-system/headless/src/components/Popover/src/index.ts @@ -1,5 +1,6 @@ export { Popover } from "./Popover"; export { PopoverContent } from "./PopoverContent"; +export { PopoverModalContent } from "./PopoverModalContent"; export { PopoverTrigger } from "./PopoverTrigger"; export { usePopoverContext } from "./PopoverContext"; export * from "./types"; diff --git a/app/client/packages/design-system/headless/src/components/Popover/src/types.ts b/app/client/packages/design-system/headless/src/components/Popover/src/types.ts index 916be85099..214fcac64d 100644 --- a/app/client/packages/design-system/headless/src/components/Popover/src/types.ts +++ b/app/client/packages/design-system/headless/src/components/Popover/src/types.ts @@ -1,3 +1,4 @@ +import type { MutableRefObject } from "react"; import type { CSSProperties } from "react"; import type { ReactNode } from "react"; import type { Dispatch, SetStateAction } from "react"; @@ -42,6 +43,10 @@ export interface PopoverProps { onClose?: () => void; /** Open and close animation durations. */ duration?: number; + /** Ref of trigger element. This ref is necessary for adding aria attributes to trigger */ + triggerRef?: MutableRefObject; + /** Which element to initially focus. Can be either a number (tabbable index as specified by the order) or a ref. */ + initialFocus?: number | MutableRefObject; } export interface PopoverContentProps { @@ -54,12 +59,15 @@ export interface PopoverContentProps { closeOnFocusOut?: boolean; /** Sets inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. Only use as a **last resort**. Use style props instead. */ style?: CSSProperties; - /** Sets the CSS className for the overlay. Only use as a **last resort**. */ - overlayClassName?: string; /** Sets the CSS className for the content popover. Only use as a **last resort**. */ contentClassName?: string; } +export interface PopoverModalContentProps extends PopoverContentProps { + /** Sets the CSS className for the overlay. Only use as a **last resort**. */ + overlayClassName?: string; +} + export interface PopoverTriggerProps { /** The children of the component. */ children: ReactNode; diff --git a/app/client/packages/design-system/headless/src/components/Popover/src/usePopover.ts b/app/client/packages/design-system/headless/src/components/Popover/src/usePopover.ts index 1a9a692f29..8cce903f3d 100644 --- a/app/client/packages/design-system/headless/src/components/Popover/src/usePopover.ts +++ b/app/client/packages/design-system/headless/src/components/Popover/src/usePopover.ts @@ -1,5 +1,5 @@ import type { UseFloatingOptions } from "@floating-ui/react/src/types"; -import React, { useState } from "react"; +import { useState, useMemo } from "react"; import { autoUpdate, flip, @@ -18,17 +18,18 @@ const DEFAULT_POPOVER_OFFSET = 10; export function usePopover({ defaultOpen = false, duration = 0, + initialFocus, isOpen: controlledOpen, modal = false, offset: offsetProp = DEFAULT_POPOVER_OFFSET, onClose, placement = "bottom", setOpen: setControlledOpen, + triggerRef, }: PopoverProps = {}) { const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen); const [labelId, setLabelId] = useState(); const [descriptionId, setDescriptionId] = useState(); - const open = controlledOpen ?? uncontrolledOpen; const setOpen = setControlledOpen ?? setUncontrolledOpen; @@ -48,13 +49,6 @@ export function usePopover({ const data = useFloating({ open, onOpenChange: setOpen, - whileElementsMounted: () => { - return () => { - if (onClose) { - onClose(); - } - }; - }, ...(modal ? {} : config), }); @@ -66,7 +60,7 @@ export function usePopover({ const role = useRole(context); const interactions = useInteractions([click, dismiss, role]); - return React.useMemo( + return useMemo( () => ({ open, setOpen, @@ -78,7 +72,21 @@ export function usePopover({ setLabelId, setDescriptionId, duration, + triggerRef, + initialFocus, + onClose, }), - [open, setOpen, interactions, data, modal, labelId, descriptionId], + [ + open, + setOpen, + interactions, + data, + modal, + labelId, + descriptionId, + triggerRef, + initialFocus, + onClose, + ], ); } diff --git a/app/client/packages/design-system/headless/src/components/Popover/stories/Popover.stories.mdx b/app/client/packages/design-system/headless/src/components/Popover/stories/Popover.stories.mdx index 78473cc45c..340b180585 100644 --- a/app/client/packages/design-system/headless/src/components/Popover/stories/Popover.stories.mdx +++ b/app/client/packages/design-system/headless/src/components/Popover/stories/Popover.stories.mdx @@ -2,6 +2,7 @@ import { Popover, PopoverTrigger, PopoverContent, + PopoverModalContent, Button, } from "@design-system/headless"; import { ControlledPopover } from "./ControlledPopover"; @@ -46,16 +47,31 @@ Based on the [headless Popover component](/?path=/docs/design-system-headless-po A modal is a floating element that displays information that requires immediate attention, appearing over the page content and blocking interactions with the page until it is dismissed. - - - - - - - My modal content - - - +## PopoverModalContent props + + + + { + const [isOpen, setIsOpen] = useState(false); + const ref = useRef(null); + + return ( + <> + + + Controlled popover content + + + ); + +}; +`} +/> # Placement diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/Modal.tsx b/app/client/packages/design-system/widgets/src/components/Modal/src/Modal.tsx index 6532f02225..7f6c000e72 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/src/Modal.tsx +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/Modal.tsx @@ -1,9 +1,5 @@ -import React, { Children } from "react"; -import { - Popover, - PopoverTrigger, - PopoverContent, -} from "@design-system/headless"; +import React from "react"; +import { Popover, PopoverModalContent } from "@design-system/headless"; import styles from "./styles.module.css"; import type { ModalProps } from "./types"; import clsx from "clsx"; @@ -11,23 +7,21 @@ import clsx from "clsx"; export const Modal = (props: ModalProps) => { const { children, - contentClassName, overlayClassName, size = "medium", + triggerRef, ...rest } = props; - const [trigger, ...content] = Children.toArray(children); return ( - - {trigger} - + - {content} - + {children} + ); }; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/ModalContent.tsx b/app/client/packages/design-system/widgets/src/components/Modal/src/ModalContent.tsx new file mode 100644 index 0000000000..a1562263a1 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/ModalContent.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import styles from "./styles.module.css"; +import clsx from "clsx"; + +import type { ModalContentProps } from "./types"; + +export const ModalContent = (props: ModalContentProps) => { + const { children, className } = props; + return
{children}
; +}; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/ModalFooter.tsx b/app/client/packages/design-system/widgets/src/components/Modal/src/ModalFooter.tsx index feee97033c..020c0df2d2 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/src/ModalFooter.tsx +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/ModalFooter.tsx @@ -26,7 +26,7 @@ export const ModalFooter = (props: ModalFooterProps) => { {onSubmit && ( - )} diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/index.ts b/app/client/packages/design-system/widgets/src/components/Modal/src/index.ts index e0d91a2464..8f811e192d 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/src/index.ts +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/index.ts @@ -2,3 +2,4 @@ export * from "./Modal"; export * from "./ModalHeader"; export * from "./ModalFooter"; export * from "./ModalBody"; +export * from "./ModalContent"; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Modal/src/styles.module.css index 4d42fda545..8af3bcc3c1 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/styles.module.css @@ -2,6 +2,7 @@ background: var(--color-bg-neutral-opacity); display: grid; place-items: center; + z-index: var(--z-index-99); } .content { @@ -18,15 +19,15 @@ padding-block: var(--outer-spacing-4); } -.content[data-size="small"] { +[data-size="small"] .content { width: var(--sizing-120); } -.content[data-size="medium"] { +[data-size="medium"] .content { width: var(--sizing-180); } -.content[data-size="large"] { +[data-size="large"] .content { width: 100%; height: 100%; } @@ -47,6 +48,7 @@ .content[data-status="close"], .overlay[data-status="open"], .overlay[data-status="close"] { + /* don't forget to change the duration Modal.tsx as well */ transition-duration: 200ms; } .content[data-status="initial"], diff --git a/app/client/packages/design-system/widgets/src/components/Modal/src/types.ts b/app/client/packages/design-system/widgets/src/components/Modal/src/types.ts index 7e6572113b..07bdb0e2f3 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/src/types.ts +++ b/app/client/packages/design-system/widgets/src/components/Modal/src/types.ts @@ -1,12 +1,15 @@ import type { - PopoverContentProps, + PopoverModalContentProps, PopoverProps, } from "@design-system/headless"; import type { ReactNode } from "react"; export interface ModalProps - extends Pick, - Pick { + extends Pick< + PopoverProps, + "isOpen" | "setOpen" | "onClose" | "triggerRef" | "initialFocus" + >, + Pick { /** Size of the Modal * @default medium */ @@ -15,6 +18,13 @@ export interface ModalProps children: ReactNode; } +export interface ModalContentProps { + /** The children of the component. */ + children: ReactNode; + /** Sets the CSS className for the overlay. Only use as a **last resort**. */ + className?: string; +} + export interface ModalHeaderProps { /** Adds a header modal Title and the necessary aria attributes. */ title: string; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/stories/ControlledModal.tsx b/app/client/packages/design-system/widgets/src/components/Modal/stories/ControlledModal.tsx deleted file mode 100644 index b9e8359a42..0000000000 --- a/app/client/packages/design-system/widgets/src/components/Modal/stories/ControlledModal.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { useState } from "react"; -import { Modal, ModalBody, Button } from "@design-system/widgets"; - -export const ControlledModal = () => { - const [isOpen, setIsOpen] = useState(false); - return ( - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus, - vero! - - - ); -}; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/stories/CustomModal.tsx b/app/client/packages/design-system/widgets/src/components/Modal/stories/CustomModal.tsx new file mode 100644 index 0000000000..d7e2e1ad91 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Modal/stories/CustomModal.tsx @@ -0,0 +1,26 @@ +import React, { useRef, useState } from "react"; +import { Modal, ModalBody, ModalContent, Button } from "@design-system/widgets"; + +export const CustomModal = () => { + const [isOpen, setIsOpen] = useState(false); + const ref = useRef(null); + + return ( + <> + + +
+ + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias + amet animi corporis laboriosam libero voluptas! A, reiciendis, + veniam? + + +
+
+ + ); +}; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/stories/Modal.stories.mdx b/app/client/packages/design-system/widgets/src/components/Modal/stories/Modal.stories.mdx index 817b199bfd..1a75960ef2 100644 --- a/app/client/packages/design-system/widgets/src/components/Modal/stories/Modal.stories.mdx +++ b/app/client/packages/design-system/widgets/src/components/Modal/stories/Modal.stories.mdx @@ -1,24 +1,18 @@ import { - Button, Modal, ModalHeader, - ModalBody, ModalFooter, - ButtonGroup, - ButtonGroupItem, + ModalContent, } from "@design-system/widgets"; -import { Canvas, Meta, Story, ArgsTable, Source } from "@storybook/addon-docs"; -import { ControlledModal } from "./ControlledModal"; +import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; +import { SimpleModal } from "./SimpleModal"; +import { ModalExamples } from "./ModalExamples"; +import { CustomModal } from "./CustomModal"; export const Template = (args) => { - return ( - - -
My modal content
-
- ); + return ; }; # Modal @@ -35,13 +29,17 @@ Modal developed on basis of Popover headless component. Additional information a +## ModalContent props + + + ## ModalHeader props ## ModalBody props -ModalBody component has no props, it is responsible for the correct layout and supports the built-in browser scroll. +`ModalBody` component has no props, it is responsible for the correct layout and supports the built-in browser scroll. ## ModalFooter props @@ -49,101 +47,12 @@ ModalBody component has no props, it is responsible for the correct layout and s # ModalExamples -export const fakeSubmit = async () => { - return new Promise((resolve) => - setTimeout(() => { - alert("Submitted"); - resolve(); - }, 500), - ); -}; - - - - - Small - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad amet - aperiam assumenda cupiditate dicta dolore error expedita explicabo ipsum - iure mollitia nam quo, reiciendis repellat reprehenderit vel vitae. - Delectus dolores illo labore laudantium nihil nobis placeat soluta. - Dolorum esse et laboriosam libero nesciunt non placeat similique? Alias - animi at commodi cum delectus, ducimus earum enim esse exercitationem - facere facilis fugit illo illum laborum laudantium modi numquam officia - pariatur praesentium quos rem suscipit vel voluptas. Ab adipisci - asperiores blanditiis corporis, cum eligendi et, incidunt laborum nulla - odit quaerat quibusdam ut, velit. Animi assumenda at doloremque eius - facilis harum, libero praesentium quo. - - - - - - Medium - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad amet - aperiam assumenda cupiditate dicta dolore error expedita explicabo ipsum - iure mollitia nam quo, reiciendis repellat reprehenderit vel vitae. - Delectus dolores illo labore laudantium nihil nobis placeat soluta. - Dolorum esse et laboriosam libero nesciunt non placeat similique? Alias - animi at commodi cum delectus, ducimus earum enim esse exercitationem - facere facilis fugit illo illum laborum laudantium modi numquam officia - pariatur praesentium quos rem suscipit vel voluptas. Ab adipisci - asperiores blanditiis corporis, cum eligendi et, incidunt laborum nulla - odit quaerat quibusdam ut, velit. Animi assumenda at doloremque eius - facilis harum, libero praesentium quo. - - - - - - Large - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad amet - aperiam assumenda cupiditate dicta dolore error expedita explicabo ipsum - iure mollitia nam quo, reiciendis repellat reprehenderit vel vitae. - Delectus dolores illo labore laudantium nihil nobis placeat soluta. - Dolorum esse et laboriosam libero nesciunt non placeat similique? Alias - animi at commodi cum delectus, ducimus earum enim esse exercitationem - facere facilis fugit illo illum laborum laudantium modi numquam officia - pariatur praesentium quos rem suscipit vel voluptas. Ab adipisci - asperiores blanditiis corporis, cum eligendi et, incidunt laborum nulla - odit quaerat quibusdam ut, velit. Animi assumenda at doloremque eius - facilis harum, libero praesentium quo. - - - - - - + {} -# Controlled Modal +# Custom Modal - - - + {} - - { - const [isOpen, setIsOpen] = useState(false); - return ( - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus, - vero! - - - ); -}; -`} -/> diff --git a/app/client/packages/design-system/widgets/src/components/Modal/stories/ModalExamples.tsx b/app/client/packages/design-system/widgets/src/components/Modal/stories/ModalExamples.tsx new file mode 100644 index 0000000000..c162324e40 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Modal/stories/ModalExamples.tsx @@ -0,0 +1,133 @@ +import React, { useRef, useState } from "react"; +import { + ButtonGroup, + ButtonGroupItem, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, +} from "@design-system/widgets"; + +const fakeSubmit = async () => { + return new Promise((resolve) => + setTimeout(() => { + alert("Submitted"); + resolve(); + }, 500), + ); +}; + +export const ModalExamples = () => { + const [isSmallOpen, setSmallOpen] = useState(false); + const [isMediumOpen, setMediumOpen] = useState(false); + const [isLargeOpen, setLargeOpen] = useState(false); + const smallRef = useRef(null); + const mediumRef = useRef(null); + const largeRef = useRef(null); + + return ( + + setSmallOpen(!isSmallOpen)} + ref={smallRef} + > + Small + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet + animi corporis laboriosam libero voluptas! A, reiciendis, veniam? + + + + + + setMediumOpen(!isMediumOpen)} + ref={mediumRef} + > + Medium + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet + animi corporis laboriosam libero voluptas! A, reiciendis, veniam? + + + + + + setLargeOpen(!isLargeOpen)} + ref={largeRef} + > + Large + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut ex + illo ipsa iste mollitia non nulla qui, sed. Amet aperiam aspernatur + at autem beatae blanditiis commodi, cum delectus dignissimos ea enim + ex hic illum ipsam ipsum iure iusto magnam mollitia nobis nulla odit + pariatur possimus praesentium quaerat quia quo repellat repellendus + sequi similique soluta sunt tempora tempore temporibus? Accusamus + accusantium ad cumque deserunt dolorum enim error, excepturi + exercitationem facere fugiat impedit in ipsum labore laboriosam + minus modi mollitia neque nulla officiis porro, quo quos, sapiente + totam veritatis vitae voluptas voluptatibus? Aliquid amet asperiores + aut exercitationem facilis ipsa itaque magni nam odio reiciendis + repellendus rerum tempore ullam, vero voluptatem! Animi cupiditate + et minus porro recusandae, temporibus tenetur! Aliquid aperiam + aspernatur beatae dolore eius ex exercitationem expedita fuga iste + iusto laboriosam laudantium modi necessitatibus nemo nulla odio + optio perferendis, placeat praesentium quae quidem rem rerum soluta + tempore tenetur unde velit voluptas? At consequuntur corporis + delectus earum eos nihil odio officiis, quae quis sed. Asperiores + excepturi hic molestiae nesciunt nostrum quae temporibus. Commodi + corporis eos illo, ipsum laboriosam molestias neque numquam rerum + veniam veritatis. Doloribus impedit iste nulla quia. Assumenda et + facilis id minima praesentium quaerat similique. Ad adipisci + assumenda aut blanditiis dicta dignissimos eligendi ipsa mollitia + natus nobis, obcaecati possimus quam quia recusandae repellat sed + sit veniam. Animi consectetur libero praesentium temporibus velit! + Amet atque culpa, debitis deleniti eius harum libero maxime odit + officia officiis quibusdam, repellat sunt tempora? Accusantium + atque, cumque doloribus eveniet laudantium magni molestias officia, + sequi temporibus vel velit veritatis vero voluptatibus! Consequuntur + delectus eaque minus obcaecati repellat repudiandae sapiente, + tempora unde. Ab ad autem beatae commodi, culpa cupiditate debitis + dolores doloribus earum eos eveniet ex excepturi expedita explicabo + fuga incidunt inventore maxime minus modi molestias nulla odio, + perspiciatis quam quisquam quo ratione sapiente voluptatem? Autem + inventore quae velit. + + + + + + ); +}; diff --git a/app/client/packages/design-system/widgets/src/components/Modal/stories/SimpleModal.tsx b/app/client/packages/design-system/widgets/src/components/Modal/stories/SimpleModal.tsx new file mode 100644 index 0000000000..eb6abe6f93 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Modal/stories/SimpleModal.tsx @@ -0,0 +1,39 @@ +import React, { useState } from "react"; +import { + Modal, + ModalBody, + ModalHeader, + ModalFooter, + ModalContent, + Button, +} from "@design-system/widgets"; +import type { ModalProps } from "../src/types"; + +const fakeSubmit = async () => { + return new Promise((resolve) => + setTimeout(() => { + alert("Submitted"); + resolve(); + }, 500), + ); +}; + +export const SimpleModal = (props: Omit) => { + const [isOpen, setIsOpen] = useState(false); + + return ( + <> + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet + animi corporis laboriosam libero voluptas! A, reiciendis, veniam? + + + + + + ); +};