diff --git a/packages/syntax-core/src/Dialog/Dialog.tsx b/packages/syntax-core/src/Dialog/Dialog.tsx index dfad9f6f..25f6ab6a 100644 --- a/packages/syntax-core/src/Dialog/Dialog.tsx +++ b/packages/syntax-core/src/Dialog/Dialog.tsx @@ -11,7 +11,7 @@ import classNames from "classnames"; type DialogSize = "sm" | "md" | "lg"; type DialogRounding = "lg" | "xl"; -type DialogProps = { +export type DialogProps = { /** Test id for the floating dialog */ "data-testid"?: string; /** aria-label for the dialog */ diff --git a/packages/syntax-core/src/Dialog/ModalDialog.module.css b/packages/syntax-core/src/Dialog/ModalDialog.module.css new file mode 100644 index 00000000..3246acd5 --- /dev/null +++ b/packages/syntax-core/src/Dialog/ModalDialog.module.css @@ -0,0 +1,14 @@ +.racModalOverlay, +.racModal { + visibility: visible; + box-sizing: border-box; +} + +.racModalOverlay { + position: fixed; + inset: 0; +} + +.racModal { + max-height: 100%; +} diff --git a/packages/syntax-core/src/Dialog/ModalDialog.tsx b/packages/syntax-core/src/Dialog/ModalDialog.tsx new file mode 100644 index 00000000..732612cb --- /dev/null +++ b/packages/syntax-core/src/Dialog/ModalDialog.tsx @@ -0,0 +1,129 @@ +import React, { type ReactElement, forwardRef } from "react"; +import { + Modal as RACModal, + ModalOverlay as RACModalOverlay, +} from "react-aria-components"; +import Dialog, { type DialogProps } from "./Dialog"; +import OverlayVisibility from "../react-aria-utils/OverlayVisibility"; +import styles from "./ModalDialog.module.css"; +import Box from "../Box/Box"; +import IconButton from "../IconButton/IconButton"; + +function XIcon({ color = "#000" }: { color?: string; className?: string }) { + return ( + + + + ); +} + +type ModalDialogProps = DialogProps & { + /** Whether dialog can be dismissed with click outside / Escape key */ + dismissable?: boolean; + /** render visible initially. */ + initialOpen?: boolean; + /** Optional handler for change of visibility for dialog content. For analytics and control */ + onChangeContentVisibility?: (visible: boolean) => void; + /** Optional boolean to control open state of modal dialog externally */ + open?: boolean; + /** Optional override for default dismiss button accessibility label */ + dismissAccessibilityLabel?: string; +}; + +/** + * ModalDialog is a controlled component -- visibility is managed with the `open` prop. + * + * Example Usage: + ``` + I am some content} + onChangeContentVisibility={(visible) => ...} + > + + ... some content goes here + + + ``` + */ +const ModalDialog = forwardRef( + function ModalDialog(props, ref): ReactElement { + const { + "data-testid": dataTestId, + accessibilityLabel, + children, + dismissable = true, + dismissAccessibilityLabel = "Dismiss", + initialOpen, + onChangeContentVisibility, + open, + } = props; + + return ( + + {({ state }) => ( + + + {({ isEntering, isExiting }) => ( + <> + + + + state.close()} + color="tertiary" + accessibilityLabel={dismissAccessibilityLabel} + icon={XIcon} + /> + + {children} + + + )} + + + )} + + ); + }, +); + +export default ModalDialog; diff --git a/packages/syntax-core/src/Popover/Popover.module.css b/packages/syntax-core/src/Popover/Popover.module.css index f4f23d8b..85d8020a 100644 --- a/packages/syntax-core/src/Popover/Popover.module.css +++ b/packages/syntax-core/src/Popover/Popover.module.css @@ -4,20 +4,6 @@ padding: 4px 16px 16px; display: flex; flex-direction: column; -} - -.racPopover, -.racModalOverlay, -.racModal { visibility: visible; box-sizing: border-box; } - -.racModalOverlay { - position: fixed; - inset: 0; -} - -.racModal { - max-height: 100%; -} diff --git a/packages/syntax-core/src/Popover/Popover.tsx b/packages/syntax-core/src/Popover/Popover.tsx index cdd3d3ee..d68da65c 100644 --- a/packages/syntax-core/src/Popover/Popover.tsx +++ b/packages/syntax-core/src/Popover/Popover.tsx @@ -1,23 +1,15 @@ -import React, { - type ReactNode, - forwardRef, - type ReactElement, - type ComponentProps, -} from "react"; +import React, { type ReactNode, forwardRef, type ReactElement } from "react"; import { type Placement as RAPlacement } from "react-aria"; import { Popover as RACPopover, DialogTrigger as RACDialogTrigger, - Modal as RACModal, - ModalOverlay as RACModalOverlay, } from "react-aria-components"; -import Box from "../Box/Box"; import Typography from "../Typography/Typography"; -import IconButton from "../IconButton/IconButton"; import styles from "./Popover.module.css"; import Triggerable from "../react-aria-utils/Triggerable"; import OverlayVisibility from "../react-aria-utils/OverlayVisibility"; import Dialog from "../Dialog/Dialog"; +import ModalDialog from "../Dialog/ModalDialog"; type Placement = "top" | "end" | "bottom" | "start"; @@ -156,123 +148,3 @@ const Popover = forwardRef(function Popover( }); export default Popover; - -function XIcon({ color = "#000" }: { color?: string; className?: string }) { - return ( - - - - ); -} - -/** - * ModalDialog is a controlled component -- visibility is managed with the `open` prop. - * - * Example Usage: - ``` - ...} - > - - ... some content goes here - - - ``` - */ -const ModalDialog = forwardRef< - HTMLDivElement, - ComponentProps & { - /** Whether dialog can be dismissed with click outside / Escape key */ - dismissable?: boolean; - /** render visible initially. */ - initialOpen?: boolean; - /** Optional handler for change of visibility for dialog content. For analytics and control */ - onChangeContentVisibility?: (visible: boolean) => void; - /** Optional boolean to control open state of modal dialog externally */ - open?: boolean; - } ->(function ModalDialog(props, ref): ReactElement { - const { - "data-testid": dataTestId, - accessibilityLabel, - children, - dismissable = true, - initialOpen, - onChangeContentVisibility, - open, - } = props; - - return ( - - {({ state }) => ( - - - {({ isEntering, isExiting }) => ( - <> - - - - state.close()} - color="tertiary" - // TODO(remove this comment before merge): - // internationalize? rac dialog already includes - // hidden dismiss element, accessible to screen readers, - // and that aria-label _is_ i18n'ed "dismiss" - accessibilityLabel="Dismiss" - icon={XIcon} - /> - - {children} - - - )} - - - )} - - ); -}); - -export { ModalDialog };