Files
KanbanGit/resources/js/components/ui/dialog/DialogContent.vue
T
Twyco f4a8bdd134
CI/CD / test_and_check_app (push) Canceled after 0s
CI/CD / Publish immutable image (push) Canceled after 0s
CI/CD / test_and_check_app (pull_request) Canceled after 0s
CI/CD / Publish immutable image (pull_request) Canceled after 0s
feat(KAN-20): unify dialogs feedback and protect ticket drafts
2026-09-11 14:17:10 +02:00

68 lines
2.6 KiB
Vue

<script setup lang="ts">
import type { DialogContentEmits, DialogContentProps } from "reka-ui";
import type { HTMLAttributes } from "vue";
import { reactiveOmit } from "@vueuse/core";
import { X } from "lucide-vue-next";
import {
DialogClose,
DialogContent,
DialogPortal,
useForwardPropsEmits,
} from "reka-ui";
import { cn } from "@/lib/utils";
import DialogOverlay from "./DialogOverlay.vue";
import { useDialogFocus } from "@/composables/useDialogFocus";
import { useLocalization } from "@/composables/useLocalization";
defineOptions({
inheritAttrs: false,
});
const props = withDefaults(
defineProps<
DialogContentProps & {
class?: HTMLAttributes["class"];
showCloseButton?: boolean;
}
>(),
{
showCloseButton: true,
},
);
const emits = defineEmits<DialogContentEmits>();
const delegatedProps = reactiveOmit(props, "class", "showCloseButton");
const { restoreFocus } = useDialogFocus();
const { t } = useLocalization();
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DialogPortal>
<DialogOverlay />
<DialogContent
data-slot="dialog-content"
v-bind="{ ...$attrs, ...forwarded }"
@close-auto-focus="restoreFocus"
:class="
cn(
'bg-card text-card-foreground 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 max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-column overflow-y-auto overscroll-contain rounded-md border p-page shadow-lg duration-200 motion-reduce:animate-none sm:max-w-lg',
props.class,
)
"
>
<slot />
<DialogClose
v-if="showCloseButton"
data-slot="dialog-close"
class="ring-offset-background focus-visible:ring-ring absolute top-1 right-1 flex size-control items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
<X />
<span class="sr-only">{{ t("common.close") }}</span>
</DialogClose>
</DialogContent>
</DialogPortal>
</template>