|
| 1 | +<script setup lang="ts"> |
| 2 | +import { useMediaQuery, useResizeObserver, useScreenSafeArea } from '@vueuse/core' |
| 3 | +import { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, VisuallyHidden } from 'reka-ui' |
| 4 | +import { DrawerContent, DrawerHandle, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTrigger } from 'vaul-vue' |
| 5 | +import { onMounted } from 'vue' |
| 6 | +
|
| 7 | +import HearingConfig from './hearing-config.vue' |
| 8 | +
|
| 9 | +const props = defineProps<{ |
| 10 | + overlayDim?: boolean |
| 11 | + overlayBlur?: boolean |
| 12 | +}>() |
| 13 | +const showDialog = defineModel('show', { type: Boolean, default: false, required: false }) |
| 14 | +
|
| 15 | +const isDesktop = useMediaQuery('(min-width: 768px)') |
| 16 | +const screenSafeArea = useScreenSafeArea() |
| 17 | +
|
| 18 | +useResizeObserver(document.documentElement, () => screenSafeArea.update()) |
| 19 | +onMounted(() => screenSafeArea.update()) |
| 20 | +</script> |
| 21 | + |
| 22 | +<template> |
| 23 | + <DialogRoot v-if="isDesktop" :open="showDialog" @update:open="value => showDialog = value"> |
| 24 | + <DialogTrigger as-child> |
| 25 | + <slot /> |
| 26 | + </DialogTrigger> |
| 27 | + <DialogPortal> |
| 28 | + <DialogOverlay |
| 29 | + :class="[ |
| 30 | + props.overlayDim ? 'bg-black/50' : '', |
| 31 | + props.overlayBlur ? 'backdrop-blur-sm' : '', |
| 32 | + ]" |
| 33 | + class="fixed inset-0 z-[9999] data-[state=closed]:animate-fadeOut data-[state=open]:animate-fadeIn" |
| 34 | + /> |
| 35 | + <DialogContent class="fixed left-1/2 top-1/2 z-[9999] max-h-full max-w-5xl w-[92dvw] transform overflow-y-scroll rounded-2xl bg-white p-6 shadow-xl outline-none backdrop-blur-md scrollbar-none -translate-x-1/2 -translate-y-1/2 data-[state=closed]:animate-contentHide data-[state=open]:animate-contentShow dark:bg-neutral-900"> |
| 36 | + <VisuallyHidden> |
| 37 | + <DialogTitle>Hearing Input</DialogTitle> |
| 38 | + </VisuallyHidden> |
| 39 | + <HearingConfig @close="showDialog = false" /> |
| 40 | + </DialogContent> |
| 41 | + </DialogPortal> |
| 42 | + </DialogRoot> |
| 43 | + <DrawerRoot v-else :open="showDialog" should-scale-background @update:open="value => showDialog = value"> |
| 44 | + <DrawerTrigger as-child> |
| 45 | + <slot /> |
| 46 | + </DrawerTrigger> |
| 47 | + <DrawerPortal> |
| 48 | + <DrawerOverlay class="fixed inset-0" /> |
| 49 | + <DrawerContent class="fixed bottom-0 left-0 right-0 z-1000 mt-20 h-full max-h-[50%] flex flex-col rounded-t-2xl bg-neutral-50 px-4 pt-4 outline-none backdrop-blur-md dark:bg-neutral-900/95" :style="{ paddingBottom: `${Math.max(Number.parseFloat(screenSafeArea.bottom.value.replace('px', '')), 24)}px` }"> |
| 50 | + <DrawerHandle /> |
| 51 | + <HearingConfig @close="showDialog = false" /> |
| 52 | + </DrawerContent> |
| 53 | + </DrawerPortal> |
| 54 | + </DrawerRoot> |
| 55 | +</template> |
0 commit comments