diff --git a/src/components/feedback/Dialog.tsx b/src/components/feedback/Dialog.tsx index 145965c5..0744c2d7 100644 --- a/src/components/feedback/Dialog.tsx +++ b/src/components/feedback/Dialog.tsx @@ -60,7 +60,7 @@ export type PanelDialogProps = PresentationalProps & variant?: 'panel'; }; -type CustomDialogProps = PresentationalProps & +export type CustomDialogProps = PresentationalProps & ComponentProps & { /** `custom` allows any layout of Dialog children */ variant: 'custom'; diff --git a/src/components/feedback/ModalDialog.tsx b/src/components/feedback/ModalDialog.tsx index 2b7b6050..1495a3a8 100644 --- a/src/components/feedback/ModalDialog.tsx +++ b/src/components/feedback/ModalDialog.tsx @@ -5,7 +5,7 @@ import { useTabKeyNavigation } from '../../hooks/use-tab-key-navigation'; import { downcastRef } from '../../util/typing'; import Overlay from '../layout/Overlay'; import Dialog from './Dialog'; -import type { PanelDialogProps } from './Dialog'; +import type { CustomDialogProps, PanelDialogProps } from './Dialog'; type ModalSize = 'sm' | 'md' | 'lg' | 'custom'; @@ -33,12 +33,20 @@ type ComponentProps = { size?: ModalSize; }; -export type ModalDialogProps = Omit< +export type PanelModalDialogProps = Omit< PanelDialogProps, 'restoreFocus' | 'closeOnEscape' > & ComponentProps; +export type CustomModalDialogProps = Omit< + CustomDialogProps, + 'restoreFocus' | 'closeOnEscape' +> & + ComponentProps; + +export type ModalDialogProps = PanelModalDialogProps | CustomModalDialogProps; + /** * Show a modal dialog */ @@ -47,7 +55,7 @@ export default function ModalDialog({ disableCloseOnEscape = false, disableFocusTrap = false, disableRestoreFocus = false, - size, + size = 'md', classes, elementRef, @@ -59,8 +67,6 @@ export default function ModalDialog({ ...htmlAndPanelAttributes }: ModalDialogProps) { - // Prefer `size` prop but support deprecated `width` if present - const modalSize = size ?? 'md'; const modalRef = useSyncedRef(elementRef); useTabKeyNavigation(modalRef, { enabled: !disableFocusTrap }); @@ -90,17 +96,15 @@ export default function ModalDialog({ 'tall:fixed tall:max-h-[80vh] tall:top-[10vh]', { // Max-width rules will ensure actual width never exceeds 90vw - 'w-[30rem]': modalSize === 'sm', - 'w-[36rem]': modalSize === 'md', // default - 'w-[42rem]': modalSize === 'lg', - // No width classes are added if width is 'custom' + 'w-[30rem]': size === 'sm', + 'w-[36rem]': size === 'md', // default + 'w-[42rem]': size === 'lg', + // No width classes are added if `size` is 'custom' }, classes, )} elementRef={downcastRef(modalRef)} - // Testing affordance. TODO: Remove once deprecated `width` prop - // no longer supported. - data-modal-size={modalSize} + data-modal-size={size} > {children} diff --git a/src/components/feedback/test/ModalDialog-test.js b/src/components/feedback/test/ModalDialog-test.js index e555a1c3..66843bc6 100644 --- a/src/components/feedback/test/ModalDialog-test.js +++ b/src/components/feedback/test/ModalDialog-test.js @@ -116,7 +116,7 @@ describe('ModalDialog', () => { .getAttribute('data-modal-size'); } - it('sets a default size if neither `size` nor `width` provided', () => { + it('sets a default size if `size` is not provided', () => { const wrapper = mount( This is my dialog, ); @@ -129,11 +129,5 @@ describe('ModalDialog', () => { assert.equal(modalSize(wrapper), 'lg'); }); - - it('prefers `size` over `width` to set size', () => { - const wrapper = sizedModal({ size: 'lg', width: 'sm' }); - - assert.equal(modalSize(wrapper), 'lg'); - }); }); }); diff --git a/src/pattern-library/components/patterns/feedback/DialogPage.tsx b/src/pattern-library/components/patterns/feedback/DialogPage.tsx index f8a8164d..acd2f323 100644 --- a/src/pattern-library/components/patterns/feedback/DialogPage.tsx +++ b/src/pattern-library/components/patterns/feedback/DialogPage.tsx @@ -18,7 +18,10 @@ import { TabList, } from '../../../../'; import { ModalDialog } from '../../../../components/feedback'; -import type { ModalDialogProps } from '../../../../components/feedback/ModalDialog'; +import type { + CustomModalDialogProps, + PanelModalDialogProps, +} from '../../../../components/feedback/ModalDialog'; import { confirm } from '../../../../util/prompts'; import Library from '../../Library'; import { LoremIpsum, nabokovNovels } from '../samples'; @@ -120,7 +123,7 @@ function Confirm() { ); } -type ModalDialog_Props = ModalDialogProps & { +type ModalDialog_Props = PanelModalDialogProps & { /** Pattern-wrapping prop. Not visible in source view */ _nonCloseable?: boolean; _alwaysShowButton?: boolean; @@ -169,6 +172,25 @@ function ModalDialog_({ ); } +function CustomModalDialog_(dialogProps: CustomModalDialogProps) { + const [dialogOpen, setDialogOpen] = useState(false); + + return ( + <> + + {dialogOpen && ( + setDialogOpen(false)} + closeOnClickAway + /> + )} + + ); +} + export default function DialogPage() { const inputRef = useRef(null); @@ -728,6 +750,16 @@ export default function DialogPage() { + + + +
+
Custom dialog content
+ +
+
+
+