Skip to content

Commit 0d6145e

Browse files
committed
feat(portal): add configurable portalTarget support
Introduced a `portalTarget` option in `appConfig.ui` to specify portal mounting targets across various components. Updated portals in components like `ContextMenu`, `Drawer`, `Tooltip`, and others to respect `portalTarget`. Default target is set to `body`.
1 parent 9509c37 commit 0d6145e

File tree

13 files changed

+18
-12
lines changed

13 files changed

+18
-12
lines changed

src/defaults.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ export const getDefaultUiConfig = (colors?: string[]) => ({
1212
error: 'red',
1313
neutral: 'slate'
1414
}, [...(colors || []), 'neutral' as any]),
15-
icons
15+
icons,
16+
portalTarget: 'body'
1617
})
1718

1819
export const defaultOptions = {

src/runtime/components/ContextMenuContent.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
9999
</slot>
100100
</DefineItemTemplate>
101101

102-
<ContextMenu.Portal :disabled="!portal">
102+
<ContextMenu.Portal :disabled="!portal" :to="appConfig.ui.portalTarget">
103103
<component :is="sub ? ContextMenu.SubContent : ContextMenu.Content" :class="props.class" v-bind="contentProps">
104104
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
105105
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">

src/runtime/components/Drawer.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const props = withDefaults(defineProps<DrawerProps>(), {
7575
const emits = defineEmits<DrawerEmits>()
7676
const slots = defineSlots<DrawerSlots>()
7777
78+
const appConfig = useAppConfig()
7879
const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'closeThreshold', 'shouldScaleBackground', 'setBackgroundColorOnScale', 'scrollLockTimeout', 'fixed', 'dismissible', 'modal', 'open', 'defaultOpen', 'nested', 'direction', 'noBodyStyles', 'handleOnly', 'preventScrollRestoration', 'snapPoints'), emits)
7980
const contentProps = toRef(() => props.content)
8081
const contentEvents = {
@@ -93,7 +94,7 @@ const ui = computed(() => drawer({
9394
<slot />
9495
</DrawerTrigger>
9596

96-
<DrawerPortal :disabled="!portal">
97+
<DrawerPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
9798
<DrawerOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
9899

99100
<DrawerContent :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" v-on="contentEvents">

src/runtime/components/DropdownMenuContent.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
105105
</slot>
106106
</DefineItemTemplate>
107107

108-
<DropdownMenu.Portal :disabled="!portal">
108+
<DropdownMenu.Portal :disabled="!portal" :to="appConfig.ui.portalTarget">
109109
<component :is="sub ? DropdownMenu.SubContent : DropdownMenu.Content" :class="props.class" v-bind="contentProps">
110110
<DropdownMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
111111
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">

src/runtime/components/InputMenu.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ defineExpose({
448448
</ComboboxTrigger>
449449
</ComboboxAnchor>
450450

451-
<ComboboxPortal :disabled="!portal">
451+
<ComboboxPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
452452
<ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
453453
<ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
454454
<slot name="empty" :search-term="searchTerm">

src/runtime/components/Modal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ const ui = computed(() => modal({
126126
<slot :open="open" />
127127
</DialogTrigger>
128128

129-
<DialogPortal :disabled="!portal">
129+
<DialogPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
130130
<DialogOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
131131

132132
<DialogContent :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" @after-leave="emits('after:leave')" v-on="contentEvents">

src/runtime/components/Popover.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const props = withDefaults(defineProps<PopoverProps>(), {
6565
const emits = defineEmits<PopoverEmits>()
6666
const slots = defineSlots<PopoverSlots>()
6767
68+
const appConfig = useAppConfig()
6869
const pick = props.mode === 'hover' ? reactivePick(props, 'defaultOpen', 'open', 'openDelay', 'closeDelay') : reactivePick(props, 'defaultOpen', 'open', 'modal')
6970
const rootProps = useForwardPropsEmits(pick, emits)
7071
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as PopoverContentProps)
@@ -95,7 +96,7 @@ const Component = computed(() => props.mode === 'hover' ? HoverCard : Popover)
9596
<slot :open="open" />
9697
</Component.Trigger>
9798

98-
<Component.Portal :disabled="!portal">
99+
<Component.Portal :disabled="!portal" :to="appConfig.ui.portalTarget">
99100
<Component.Content v-bind="contentProps" :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-on="contentEvents">
100101
<slot name="content" />
101102

src/runtime/components/Select.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
263263
</span>
264264
</SelectTrigger>
265265

266-
<SelectPortal :disabled="!portal">
266+
<SelectPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
267267
<SelectContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
268268
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
269269
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">

src/runtime/components/SelectMenu.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
384384
</ComboboxTrigger>
385385
</ComboboxAnchor>
386386

387-
<ComboboxPortal :disabled="!portal">
387+
<ComboboxPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
388388
<ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
389389
<FocusScope trapped :class="ui.focusScope({ class: props.ui?.focusScope })">
390390
<ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>

src/runtime/components/Slideover.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const ui = computed(() => slideover({
130130
<slot :open="open" />
131131
</DialogTrigger>
132132

133-
<DialogPortal :disabled="!portal">
133+
<DialogPortal :disabled="!portal" :to="appConfig.ui.portalTarget">
134134
<DialogOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
135135

136136
<DialogContent :data-side="side" :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" @after-leave="emits('after:leave')" v-on="contentEvents">

0 commit comments

Comments
 (0)