Skip to content

Commit 7550ae8

Browse files
committed
fix menu / popover inside dialog
1 parent 64d144a commit 7550ae8

7 files changed

Lines changed: 51 additions & 18 deletions

File tree

resources/js/components/ui/dropdown-menu/DropdownMenuContent.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from 'reka-ui'
1010
import { cn } from '@/utils/cn'
1111
import { useMenuBoundaryElement } from "@/Layouts/Layout.vue";
12+
import { useParentDialogElement } from "@/composables/useParentDialogElement";
1213
1314
const props = withDefaults(
1415
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes['class'] }>(),
@@ -27,10 +28,11 @@ const delegatedProps = computed(() => {
2728
2829
const forwarded = useForwardPropsEmits(delegatedProps, emits)
2930
const menuBoundary = useMenuBoundaryElement();
31+
const parentDialogElement = useParentDialogElement();
3032
</script>
3133

3234
<template>
33-
<DropdownMenuPortal>
35+
<DropdownMenuPortal :to="parentDialogElement ?? undefined">
3436
<DropdownMenuContent
3537
v-bind="forwarded"
3638
:collision-boundary="typeof props.collisionBoundary === 'undefined' ? menuBoundary : props.collisionBoundary"

resources/js/components/ui/popover/PopoverContent.vue

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useForwardPropsEmits,
1010
} from 'reka-ui'
1111
import { cn } from '@/utils/cn'
12+
import { useParentDialogElement } from "@/composables/useParentDialogElement";
1213
1314
defineOptions({
1415
inheritAttrs: false,
@@ -30,21 +31,12 @@ const delegatedProps = computed(() => {
3031
return delegated
3132
})
3233
33-
const dialogContext = injectDialogRootContext(null);
3434
const forwarded = useForwardPropsEmits(delegatedProps, emits)
35-
const parentDialogElement = ref<HTMLElement>();
36-
37-
onMounted(() => {
38-
if(dialogContext) {
39-
nextTick(() => {
40-
parentDialogElement.value = dialogContext.contentElement.value.parentElement;
41-
});
42-
}
43-
});
35+
const parentDialogElement = useParentDialogElement();
4436
</script>
4537

4638
<template>
47-
<PopoverPortal :to="parentDialogElement">
39+
<PopoverPortal :to="parentDialogElement ?? undefined">
4840
<PopoverContent
4941
v-bind="{ ...forwarded, ...$attrs }"
5042
:class="

resources/js/components/ui/select/SelectContent.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import {
1010
} from 'reka-ui'
1111
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
1212
import { cn } from '@/utils/cn'
13+
import { useParentDialogElement } from "@/composables/useParentDialogElement";
1314
1415
defineOptions({
1516
inheritAttrs: false,
1617
})
1718
1819
const props = withDefaults(
19-
defineProps<SelectContentProps & { class?: HTMLAttributes['class'], teleportTo?: HTMLElement }>(),
20+
defineProps<SelectContentProps & { class?: HTMLAttributes['class'] }>(),
2021
{
2122
position: 'popper',
2223
},
@@ -30,10 +31,12 @@ const delegatedProps = computed(() => {
3031
})
3132
3233
const forwarded = useForwardPropsEmits(delegatedProps, emits);
34+
35+
const parentDialogElement = useParentDialogElement();
3336
</script>
3437

3538
<template>
36-
<SelectPortal :to="teleportTo">
39+
<SelectPortal :to="parentDialogElement ?? undefined">
3740
<SelectContent
3841
v-bind="{ ...forwarded, ...$attrs }" :class="cn(
3942
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',

resources/js/components/ui/tooltip/TooltipContent.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { type HTMLAttributes, computed } from 'vue'
33
import { TooltipContent, type TooltipContentEmits, type TooltipContentProps, TooltipPortal, useForwardPropsEmits } from 'reka-ui'
44
import { cn } from '@/utils/cn'
5+
import { useParentDialogElement } from "@/composables/useParentDialogElement";
56
67
defineOptions({
78
inheritAttrs: false,
@@ -20,10 +21,11 @@ const delegatedProps = computed(() => {
2021
})
2122
2223
const forwarded = useForwardPropsEmits(delegatedProps, emits)
24+
const parentDialogElement = useParentDialogElement();
2325
</script>
2426

2527
<template>
26-
<TooltipPortal>
28+
<TooltipPortal :to="parentDialogElement ?? undefined">
2729
<TooltipContent v-bind="{ ...forwarded, ...$attrs }" :class="cn('z-50 overflow-hidden max-w-sm rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)">
2830
<slot />
2931
</TooltipContent>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { computed, ComputedRef, inject, nextTick, onMounted, provide, ref, Ref } from "vue";
2+
import { injectDialogRootContext } from "reka-ui";
3+
4+
export function provideParentDialogElement(dialog: Ref<HTMLElement>) {
5+
provide<ComputedRef<HTMLDialogElement | undefined>>(
6+
'parentDialog',
7+
computed(() =>
8+
dialog.value instanceof HTMLDialogElement
9+
? dialog.value
10+
: undefined
11+
)
12+
);
13+
}
14+
15+
export function useParentDialogElement() {
16+
const parentDialogElement = inject<ComputedRef<HTMLDialogElement | undefined>>('parentDialog', undefined);
17+
const rekaDialogContext = injectDialogRootContext(null);
18+
19+
if(rekaDialogContext) {
20+
const rekaDialogElement = ref<HTMLElement | undefined>();
21+
22+
onMounted(async () => {
23+
await nextTick();
24+
rekaDialogElement.value = rekaDialogContext?.contentElement.value?.parentElement;
25+
});
26+
27+
return computed(() => parentDialogElement.value ?? rekaDialogElement.value);
28+
}
29+
30+
return parentDialogElement;
31+
}

resources/js/form/components/FormFieldLocaleSelect.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { FormFieldEmits, FormFieldProps } from "@/form/types";
77
import { FormFieldData } from "@/types";
88
import { useParentForm } from "@/form/useParentForm";
99
10-
const props = defineProps<FormFieldProps<FormFieldData, any> & { teleportTo?: HTMLElement, isFieldLayout?: boolean }>();
10+
const props = defineProps<FormFieldProps<FormFieldData, any> & { isFieldLayout?: boolean }>();
1111
const emit = defineEmits<FormFieldEmits>();
1212
const form = useParentForm();
1313
</script>
@@ -19,7 +19,7 @@ const form = useParentForm();
1919
:class="{ '-my-2': isFieldLayout }"
2020
:aria-label="__('sharp::form.field_locale_selector.aria_label', { field_label:field.label })"
2121
/>
22-
<SelectContent :teleport-to="teleportTo">
22+
<SelectContent>
2323
<template v-for="itemLocale in form.locales" :key="itemLocale">
2424
<SelectItem :value="itemLocale">
2525
<div class="flex items-center">

resources/js/form/components/fields/editor/Editor.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import FormFieldLocaleSelect from "@/form/components/FormFieldLocaleSelect.vue";
5555
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
5656
import { vScrollIntoView } from "@/directives/scroll-into-view";
57+
import { provideParentDialogElement } from "@/composables/useParentDialogElement";
5758
5859
const emit = defineEmits<FormFieldEmits<FormEditorFieldData>>();
5960
const props = defineProps<FormFieldProps<FormEditorFieldData>>();
@@ -67,13 +68,15 @@
6768
const uploadModal = ref<InstanceType<typeof EditorUploadModal>>();
6869
6970
const embedManager = new ContentEmbedManager(form, props.field.embeds, props.value?.embeds);
70-
const el = useTemplateRef<HTMLDialogElement>('el');
71+
const el = useTemplateRef<HTMLDialogElement | HTMLDivElement>('el');
7172
const embedModal = ref<InstanceType<typeof EditorEmbedModal>>();
7273
const linkDropdown = ref<InstanceType<typeof LinkDropdown>>();
7374
const isMounted = ref(false);
7475
const isUnmounting = ref(false);
7576
const isFullscreen = ref(false);
7677
78+
provideParentDialogElement(el);
79+
7780
provide<ParentEditor>('editor', {
7881
props,
7982
uploadManager,

0 commit comments

Comments
 (0)