Skip to content

Commit b0334a5

Browse files
committed
feat: add AlertDialog component and its subcomponents
1 parent 04fc68b commit b0334a5

10 files changed

Lines changed: 246 additions & 0 deletions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogEmits, AlertDialogProps } from 'reka-ui';
3+
import { AlertDialogRoot, useForwardPropsEmits } from 'reka-ui';
4+
5+
const props = defineProps<AlertDialogProps>();
6+
const emits = defineEmits<AlertDialogEmits>();
7+
8+
const forwarded = useForwardPropsEmits(props, emits);
9+
</script>
10+
11+
<template>
12+
<AlertDialogRoot v-slot="slotProps" data-slot="alert-dialog" v-bind="forwarded">
13+
<slot v-bind="slotProps" />
14+
</AlertDialogRoot>
15+
</template>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogActionProps } from 'reka-ui';
3+
import type { HTMLAttributes } from 'vue';
4+
import { reactiveOmit } from '@vueuse/core';
5+
import { AlertDialogAction } from 'reka-ui';
6+
import { cn } from '@/utils';
7+
import { buttonVariants, type ButtonVariants } from '~/components/ui/button/variants';
8+
9+
const props = defineProps<
10+
AlertDialogActionProps & {
11+
class?: HTMLAttributes['class'];
12+
variant?: ButtonVariants['variant'];
13+
size?: ButtonVariants['size'];
14+
}
15+
>();
16+
17+
const delegatedProps = reactiveOmit(props, 'class');
18+
</script>
19+
20+
<template>
21+
<AlertDialogAction
22+
v-bind="delegatedProps"
23+
:class="cn(buttonVariants({ variant, size }), props.class)"
24+
>
25+
<slot />
26+
</AlertDialogAction>
27+
</template>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogCancelProps } from 'reka-ui';
3+
import type { HTMLAttributes } from 'vue';
4+
import { reactiveOmit } from '@vueuse/core';
5+
import { AlertDialogCancel } from 'reka-ui';
6+
import { cn } from '@/utils';
7+
import { buttonVariants, type ButtonVariants } from '~/components/ui/button/variants';
8+
9+
const props = withDefaults(
10+
defineProps<
11+
AlertDialogCancelProps & {
12+
class?: HTMLAttributes['class'];
13+
variant?: ButtonVariants['variant'];
14+
size?: ButtonVariants['size'];
15+
}
16+
>(),
17+
{
18+
variant: 'outline',
19+
class: '',
20+
size: 'lg',
21+
},
22+
);
23+
24+
const delegatedProps = reactiveOmit(props, 'class');
25+
</script>
26+
27+
<template>
28+
<AlertDialogCancel
29+
v-bind="delegatedProps"
30+
:class="cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', props.class)"
31+
>
32+
<slot />
33+
</AlertDialogCancel>
34+
</template>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogContentEmits, AlertDialogContentProps } from 'reka-ui';
3+
import type { HTMLAttributes } from 'vue';
4+
import { reactiveOmit } from '@vueuse/core';
5+
import {
6+
AlertDialogContent,
7+
AlertDialogOverlay,
8+
AlertDialogPortal,
9+
useForwardPropsEmits,
10+
} from 'reka-ui';
11+
import { cn } from '@/utils';
12+
13+
defineOptions({
14+
inheritAttrs: false,
15+
});
16+
17+
const props = defineProps<AlertDialogContentProps & { class?: HTMLAttributes['class'] }>();
18+
const emits = defineEmits<AlertDialogContentEmits>();
19+
20+
const delegatedProps = reactiveOmit(props, 'class');
21+
22+
const forwarded = useForwardPropsEmits(delegatedProps, emits);
23+
</script>
24+
25+
<template>
26+
<AlertDialogPortal>
27+
<AlertDialogOverlay
28+
data-slot="alert-dialog-overlay"
29+
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-dialog-backdrop fixed inset-0 z-50"
30+
/>
31+
<AlertDialogContent
32+
data-slot="alert-dialog-content"
33+
v-bind="{ ...$attrs, ...forwarded }"
34+
:class="
35+
cn(
36+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-[calc(100%-2rem)] max-w-xs translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border p-8 shadow-lg duration-200',
37+
props.class,
38+
)
39+
"
40+
>
41+
<slot />
42+
</AlertDialogContent>
43+
</AlertDialogPortal>
44+
</template>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogDescriptionProps } from 'reka-ui';
3+
import type { HTMLAttributes } from 'vue';
4+
import { reactiveOmit } from '@vueuse/core';
5+
import { AlertDialogDescription } from 'reka-ui';
6+
import { cn } from '@/utils';
7+
8+
const props = defineProps<AlertDialogDescriptionProps & { class?: HTMLAttributes['class'] }>();
9+
10+
const delegatedProps = reactiveOmit(props, 'class');
11+
</script>
12+
13+
<template>
14+
<AlertDialogDescription
15+
data-slot="alert-dialog-description"
16+
v-bind="delegatedProps"
17+
:class="cn('text-muted-foreground text-sm', props.class)"
18+
>
19+
<slot />
20+
</AlertDialogDescription>
21+
</template>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue';
3+
import { cn } from '@/utils';
4+
5+
const props = defineProps<{
6+
class?: HTMLAttributes['class'];
7+
}>();
8+
</script>
9+
10+
<template>
11+
<div data-slot="alert-dialog-footer" :class="cn('flex flex-col gap-3', props.class)">
12+
<slot />
13+
</div>
14+
</template>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue';
3+
import { cn } from '@/utils';
4+
5+
const props = defineProps<{
6+
class?: HTMLAttributes['class'];
7+
}>();
8+
</script>
9+
10+
<template>
11+
<div
12+
data-slot="alert-dialog-header"
13+
:class="cn('flex flex-col gap-2 text-center sm:text-left', props.class)"
14+
>
15+
<slot />
16+
</div>
17+
</template>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogTitleProps } from 'reka-ui';
3+
import type { HTMLAttributes } from 'vue';
4+
import { reactiveOmit } from '@vueuse/core';
5+
import { AlertDialogTitle } from 'reka-ui';
6+
import { cn } from '@/utils';
7+
8+
const props = defineProps<AlertDialogTitleProps & { class?: HTMLAttributes['class'] }>();
9+
10+
const delegatedProps = reactiveOmit(props, 'class');
11+
</script>
12+
13+
<template>
14+
<AlertDialogTitle
15+
data-slot="alert-dialog-title"
16+
v-bind="delegatedProps"
17+
:class="cn('text-lg font-semibold', props.class)"
18+
>
19+
<slot />
20+
</AlertDialogTitle>
21+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script setup lang="ts">
2+
import type { AlertDialogTriggerProps } from 'reka-ui';
3+
import { AlertDialogTrigger } from 'reka-ui';
4+
5+
const props = defineProps<AlertDialogTriggerProps>();
6+
</script>
7+
8+
<template>
9+
<AlertDialogTrigger data-slot="alert-dialog-trigger" v-bind="props">
10+
<slot />
11+
</AlertDialogTrigger>
12+
</template>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<script lang="ts" setup>
2+
const handleConfirm = () => {
3+
// Handle the confirm action here
4+
showToaster('info', 'Confirmed!');
5+
};
6+
7+
const handleCancel = () => {
8+
// Handle the cancel action here
9+
showToaster('info', 'Cancelled!');
10+
};
11+
</script>
12+
13+
<template>
14+
<div>
15+
<UiAlertDialog>
16+
<UiAlertDialogTrigger as-child>
17+
<UiButton>{{ 'Open Alert Dialog' }}</UiButton>
18+
</UiAlertDialogTrigger>
19+
<UiAlertDialogContent>
20+
<UiAlertDialogHeader>
21+
<UiAlertDialogTitle>
22+
{{ 'Log out of @Ahmedamrnabil2?' }}
23+
</UiAlertDialogTitle>
24+
<UiAlertDialogDescription>
25+
{{
26+
"This will only apply to this account, and you'll still be logged in to your other accounts. "
27+
}}
28+
</UiAlertDialogDescription>
29+
</UiAlertDialogHeader>
30+
<UiAlertDialogFooter>
31+
<UiAlertDialogAction @click="handleConfirm">
32+
{{ 'Continue' }}
33+
</UiAlertDialogAction>
34+
<UiAlertDialogCancel @click="handleCancel">
35+
{{ 'Cancel' }}
36+
</UiAlertDialogCancel>
37+
</UiAlertDialogFooter>
38+
</UiAlertDialogContent>
39+
</UiAlertDialog>
40+
</div>
41+
</template>

0 commit comments

Comments
 (0)