Skip to content

Commit 35bd150

Browse files
committed
feat(dialog): add beforeClose prop to DialogClose component to control closing behavior
1 parent 90919ef commit 35bd150

File tree

6 files changed

+25
-6
lines changed

6 files changed

+25
-6
lines changed

headless/src/components/alert-dialog/alert-dialog-close.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const { setCancelElement } = useAlertDialogContentContext('AlertDialogClose');
1313
</script>
1414

1515
<template>
16-
<DialogClose :ref="setCancelElement" :as="as" :as-child="asChild">
16+
<DialogClose :ref="setCancelElement" :as="as" :as-child="asChild" :before-close="beforeClose">
1717
<slot />
1818
</DialogClose>
1919
</template>

headless/src/components/dialog/dialog-close.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,17 @@ const props = defineProps<DialogCloseProps>();
1313
const { onOpenChange } = useDialogRootContext('DialogClose');
1414
1515
const tag = computed(() => (props.as === 'button' ? 'button' : undefined));
16+
17+
const onClose = async () => {
18+
const result = await props.beforeClose?.();
19+
if (result !== false) {
20+
onOpenChange(false);
21+
}
22+
};
1623
</script>
1724

1825
<template>
19-
<Primitive :as="as" :as-child="asChild" :type="tag" @click="onOpenChange(false)">
26+
<Primitive :as="as" :as-child="asChild" :type="tag" @click="onClose">
2027
<slot />
2128
</Primitive>
2229
</template>

headless/src/components/dialog/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
DismissableLayerProps,
66
FocusScopeEmits,
77
ForceMountProps,
8+
MaybePromise,
89
PropsToContext,
910
TrapFocusProps
1011
} from '../../types';
@@ -56,7 +57,13 @@ export interface DialogTitleProps extends /** @vue-ignore */ HTMLAttributes {}
5657

5758
export interface DialogDescriptionProps extends /** @vue-ignore */ HTMLAttributes {}
5859

59-
export interface DialogCloseProps extends PrimitiveProps, /** @vue-ignore */ ButtonHTMLAttributes {}
60+
export interface DialogCloseProps extends PrimitiveProps, /** @vue-ignore */ ButtonHTMLAttributes {
61+
/**
62+
* Called before the dialog is closed. Can be used to prevent the dialog from closing.
63+
* @returns A boolean or a promise that resolves to a boolean. if returns `false`, the dialog will not close.
64+
*/
65+
beforeClose?: () => MaybePromise<boolean>;
66+
}
6067

6168
export interface DialogHeaderProps extends /** @vue-ignore */ HTMLAttributes {}
6269

src/components/alert-dialog/alert-dialog-action.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const { size } = useSizeContext('AlertDialogAction');
1919
</script>
2020

2121
<template>
22-
<DialogClose as-child>
22+
<DialogClose as-child :before-close="beforeClose">
2323
<slot name="content">
2424
<Button v-bind="forwardedProps" :size="size">
2525
<slot>{{ text }}</slot>

src/components/alert-dialog/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AlertDialogRootEmits } from '@soybeanjs/headless';
1+
import type { AlertDialogRootEmits, MaybePromise } from '@soybeanjs/headless';
22
import type { ThemeColor } from '@/theme';
33
import type { DialogProps } from '../dialog/types';
44
import type { ButtonProps } from '../button/types';
@@ -27,4 +27,9 @@ export interface AlertDialogActionProps extends ButtonProps {
2727
* @defaultValue 'Confirm'
2828
*/
2929
text?: string;
30+
/**
31+
* Called before the dialog is closed. Can be used to prevent the dialog from closing.
32+
* @returns A boolean or a promise that resolves to a boolean. if returns `false`, the dialog will not close.
33+
*/
34+
beforeClose?: () => MaybePromise<boolean>;
3035
}

src/components/dialog/dialog-close.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const { size } = useSizeContext('DialogClose');
1313
</script>
1414

1515
<template>
16-
<DialogClose :size="size" as-child>
16+
<DialogClose :size="size" as-child :before-close="beforeClose">
1717
<slot />
1818
</DialogClose>
1919
</template>

0 commit comments

Comments
 (0)