From ae0b3d2c935f1d7519a39d8c8000ad5640985482 Mon Sep 17 00:00:00 2001 From: amcdnl Date: Fri, 12 Jul 2024 08:27:53 -0400 Subject: [PATCH 1/2] add confirm dialog --- .../ConfirmDialog/ConfirmDialog.story.tsx | 43 +++++++++++++++++ src/layers/ConfirmDialog/ConfirmDialog.tsx | 40 ++++++++++++++++ src/layers/ConfirmDialog/index.ts | 2 + src/layers/ConfirmDialog/useConfirmDialog.tsx | 48 +++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/layers/ConfirmDialog/ConfirmDialog.story.tsx create mode 100644 src/layers/ConfirmDialog/ConfirmDialog.tsx create mode 100644 src/layers/ConfirmDialog/index.ts create mode 100644 src/layers/ConfirmDialog/useConfirmDialog.tsx diff --git a/src/layers/ConfirmDialog/ConfirmDialog.story.tsx b/src/layers/ConfirmDialog/ConfirmDialog.story.tsx new file mode 100644 index 00000000..fa01c13d --- /dev/null +++ b/src/layers/ConfirmDialog/ConfirmDialog.story.tsx @@ -0,0 +1,43 @@ +import React, { useState } from 'react'; +import { Meta, Story } from '@storybook/react'; +import { ConfirmDialog, ConfirmDialogProps } from './ConfirmDialog'; + +export default { + title: 'Components/Layers/Confirmation Dialog', + component: ConfirmDialog, + argTypes: { + header: { control: 'text' }, + description: { control: 'text' }, + confirmLabel: { control: 'text' }, + cancelLabel: { control: 'text' }, + onConfirm: { action: 'confirmed' }, + onCancel: { action: 'cancelled' } + } +} as Meta; + +const Template: Story = args => { + const [isOpen, setIsOpen] = useState(true); + + return ( + { + args.onConfirm(); + setIsOpen(false); + }} + onCancel={() => { + args.onCancel(); + setIsOpen(false); + }} + /> + ); +}; + +export const Default = Template.bind({}); +Default.args = { + header: 'Confirm Action', + description: 'Are you sure you want to proceed?', + confirmLabel: 'Confirm', + cancelLabel: 'Cancel' +}; diff --git a/src/layers/ConfirmDialog/ConfirmDialog.tsx b/src/layers/ConfirmDialog/ConfirmDialog.tsx new file mode 100644 index 00000000..da7f2a10 --- /dev/null +++ b/src/layers/ConfirmDialog/ConfirmDialog.tsx @@ -0,0 +1,40 @@ +// ConfirmDialog.tsx +import React, { ReactNode } from 'react'; +import { Dialog } from '@/layers/Dialog'; +import { Button } from '@/elements/Button'; + +export interface ConfirmDialogProps { + open: boolean; + header: string | ReactNode; + description: string | ReactNode; + confirmLabel?: string; + cancelLabel?: string; + onConfirm?: () => void; + onCancel?: () => void; +} + +export const ConfirmDialog: React.FC = ({ + open, + header, + description, + confirmLabel = 'Confirm', + cancelLabel = 'Cancel', + onConfirm, + onCancel +}) => ( + + {() => ( + <> +

{description}

+
+ + +
+ + )} +
+); diff --git a/src/layers/ConfirmDialog/index.ts b/src/layers/ConfirmDialog/index.ts new file mode 100644 index 00000000..5ddb77e0 --- /dev/null +++ b/src/layers/ConfirmDialog/index.ts @@ -0,0 +1,2 @@ +export * from './ConfirmDialog'; +export * from './useConfirmDialog'; diff --git a/src/layers/ConfirmDialog/useConfirmDialog.tsx b/src/layers/ConfirmDialog/useConfirmDialog.tsx new file mode 100644 index 00000000..f2320fdd --- /dev/null +++ b/src/layers/ConfirmDialog/useConfirmDialog.tsx @@ -0,0 +1,48 @@ +import React, { useState, useCallback, ReactNode } from 'react'; +import { ConfirmDialog } from './ConfirmDialog'; + +interface OpenConfirmDialogProps { + header: ReactNode | string; + description: ReactNode | string; + confirmLabel?: string; + cancelLabel?: string; + onConfirm: () => void; + onCancel?: () => void; +} + +export const useConfirmDialog = () => { + const [isOpen, setIsOpen] = useState(false); + const [dialogProps, setDialogProps] = useState( + null + ); + + const closeDialog = useCallback(() => { + setIsOpen(false); + setDialogProps(null); + }, []); + + const openConfirmDialog = useCallback( + (props: OpenConfirmDialogProps) => { + setDialogProps({ + ...props, + onCancel: props.onCancel || closeDialog + }); + setIsOpen(true); + }, + [closeDialog] + ); + + const DialogComponent = useCallback(() => { + if (!dialogProps) { + return null; + } + + return ; + }, [isOpen, dialogProps]); + + return { + openConfirmDialog, + closeDialog, + DialogComponent + }; +}; From 89c9ad8a3684d2c971cfcb49761a39e22851b6a4 Mon Sep 17 00:00:00 2001 From: amcdnl Date: Fri, 12 Jul 2024 08:29:56 -0400 Subject: [PATCH 2/2] fix type --- src/layers/ConfirmDialog/ConfirmDialog.story.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layers/ConfirmDialog/ConfirmDialog.story.tsx b/src/layers/ConfirmDialog/ConfirmDialog.story.tsx index fa01c13d..8e0ad4fe 100644 --- a/src/layers/ConfirmDialog/ConfirmDialog.story.tsx +++ b/src/layers/ConfirmDialog/ConfirmDialog.story.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Meta, Story } from '@storybook/react'; +import { Meta, StoryFn } from '@storybook/react'; import { ConfirmDialog, ConfirmDialogProps } from './ConfirmDialog'; export default { @@ -15,7 +15,7 @@ export default { } } as Meta; -const Template: Story = args => { +const Template: StoryFn = args => { const [isOpen, setIsOpen] = useState(true); return (