chore: improve popper handling

This commit is contained in:
Benjamin Canac
2022-10-07 13:27:51 +02:00
parent 44b7199c4f
commit 005c18e4c0
10 changed files with 138 additions and 190 deletions

View File

@@ -6,7 +6,7 @@
</slot>
</MenuButton>
<div v-if="open" ref="container" :class="containerClass" @mouseover="onMouseOver">
<div v-if="open" ref="container" :class="[containerClass, widthClass]" @mouseover="onMouseOver">
<transition appear v-bind="transitionClass">
<MenuItems :class="baseClass" static>
<div v-for="(subItems, index) of items" :key="index" class="py-1">
@@ -44,8 +44,10 @@ import { ref, onMounted } from 'vue'
import NuxtLink from '#app/components/nuxt-link'
import Icon from '../elements/Icon.vue'
import Avatar from '../elements/Avatar.vue'
import { classNames, usePopper } from '../../utils'
import { classNames } from '../../utils'
import { usePopper } from '../../composables/usePopper'
import type { Avatar as AvatarType } from '../../types/avatar'
import type { PopperOptions } from './../types'
import $ui from '#build/ui'
const props = defineProps({
@@ -64,20 +66,6 @@ const props = defineProps({
}[][]>,
default: () => []
},
placement: {
type: String,
default: 'bottom-end',
validator: (value: string) => {
return ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'].includes(value)
}
},
strategy: {
type: String,
default: 'fixed',
validator: (value: string) => {
return ['absolute', 'fixed'].includes(value)
}
},
mode: {
type: String,
default: 'click',
@@ -93,6 +81,10 @@ const props = defineProps({
type: String,
default: () => $ui.dropdown.container
},
widthClass: {
type: String,
default: () => $ui.dropdown.width
},
baseClass: {
type: String,
default: () => $ui.dropdown.base
@@ -128,32 +120,17 @@ const props = defineProps({
itemShortcutsClass: {
type: String,
default: () => $ui.dropdown.item.shortcuts
},
popperOptions: {
type: Object as PropType<PopperOptions>,
default: () => ({
placement: 'bottom-end',
strategy: 'fixed'
})
}
})
const [trigger, container] = usePopper({
placement: props.placement,
strategy: props.strategy,
modifiers: [{
name: 'offset',
options: {
offset: 0
}
},
{
name: 'computeStyles',
options: {
gpuAcceleration: false,
adaptive: false
}
},
{
name: 'preventOverflow',
options: {
padding: 8
}
}]
})
const [trigger, container] = usePopper(props.popperOptions)
function resolveItemClass ({ active, disabled }: { active: boolean, disabled: boolean }) {
return classNames(

View File

@@ -27,7 +27,7 @@
</slot>
</ComboboxButton>
<div v-if="open" ref="container" :class="listContainerClass">
<div v-if="open" ref="container" :class="[listContainerClass, listWidthClass]">
<transition appear v-bind="listTransitionClass">
<ComboboxOptions static :class="listBaseClass">
<ComboboxInput
@@ -93,7 +93,9 @@ import {
ComboboxInput
} from '@headlessui/vue'
import Icon from '../elements/Icon.vue'
import { classNames, usePopper } from '../../utils'
import { classNames } from '../../utils'
import { usePopper } from '../../composables/usePopper'
import type { PopperOptions } from './../types'
import $ui from '#build/ui'
const props = defineProps({
@@ -105,20 +107,6 @@ const props = defineProps({
type: Array as PropType<{ disabled?: boolean }[]>,
default: () => []
},
placement: {
type: String,
default: 'bottom-end',
validator: (value: string) => {
return ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'].includes(value)
}
},
strategy: {
type: String,
default: 'absolute',
validator: (value: string) => {
return ['absolute', 'fixed'].includes(value)
}
},
required: {
type: Boolean,
default: false
@@ -189,6 +177,10 @@ const props = defineProps({
type: String,
default: () => $ui.selectCustom.list.container
},
listWidthClass: {
type: String,
default: () => $ui.selectCustom.list.width
},
listInputClass: {
type: String,
default: () => $ui.selectCustom.list.input
@@ -256,34 +248,18 @@ const props = defineProps({
searchAttributes: {
type: Array,
default: null
},
popperOptions: {
type: Object as PropType<PopperOptions>,
default: () => ({
placement: 'bottom-end'
})
}
})
const emit = defineEmits(['update:modelValue'])
const [trigger, container] = usePopper({
placement: props.placement,
strategy: props.strategy,
modifiers: [{
name: 'offset',
options: {
offset: 0
}
},
{
name: 'computeStyles',
options: {
gpuAcceleration: false,
adaptive: false
}
},
{
name: 'preventOverflow',
options: {
padding: 8
}
}]
})
const [trigger, container] = usePopper(props.popperOptions)
const query = ref('')
const searchInput = ref<ComponentPublicInstance<HTMLElement>>()

View File

@@ -6,7 +6,7 @@
</slot>
</PopoverButton>
<div v-if="open" ref="container" :class="containerClass" @mouseover="onMouseOver">
<div v-if="open" ref="container" :class="[containerClass, widthClass]" @mouseover="onMouseOver">
<transition appear v-bind="transitionClass">
<PopoverPanel :class="baseClass" static>
<slot name="panel" :open="open" :close="close" />
@@ -17,21 +17,14 @@
</template>
<script setup lang="ts">
import type { Ref } from 'vue'
import type { Ref, PropType } from 'vue'
import { ref, onMounted } from 'vue'
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { usePopper } from '../../utils'
import { usePopper } from '../../composables/usePopper'
import type { PopperOptions } from './../types'
import $ui from '#build/ui'
const props = defineProps({
placement: {
type: String,
default: 'bottom'
},
strategy: {
type: String,
default: 'fixed'
},
mode: {
type: String,
default: 'click',
@@ -47,6 +40,10 @@ const props = defineProps({
type: String,
default: () => $ui.popover.container
},
widthClass: {
type: String,
default: () => $ui.tooltip.width
},
baseClass: {
type: String,
default: () => $ui.popover.base
@@ -54,32 +51,16 @@ const props = defineProps({
transitionClass: {
type: Object,
default: () => $ui.popover.transition
},
popperOptions: {
type: Object as PropType<PopperOptions>,
default: () => ({
strategy: 'fixed'
})
}
})
const [trigger, container] = usePopper({
placement: props.placement,
strategy: props.strategy,
modifiers: [{
name: 'offset',
options: {
offset: 0
}
},
{
name: 'computeStyles',
options: {
gpuAcceleration: false,
adaptive: false
}
},
{
name: 'preventOverflow',
options: {
padding: 8
}
}]
})
const [trigger, container] = usePopper(props.popperOptions)
const popoverApi: Ref<any> = ref(null)

View File

@@ -4,7 +4,7 @@
Hover me
</slot>
<div v-if="open" ref="container" :class="containerClass">
<div v-if="open" ref="container" :class="[containerClass, widthClass]">
<transition appear v-bind="transitionClass">
<div :class="baseClass">
<slot name="text">
@@ -17,8 +17,10 @@
</template>
<script setup lang="ts">
import type { PropType } from 'vue'
import { ref } from 'vue'
import { usePopper } from '../../utils'
import { usePopper } from '../../composables/usePopper'
import type { PopperOptions } from './../types'
import $ui from '#build/ui'
const props = defineProps({
@@ -26,24 +28,6 @@ const props = defineProps({
type: String,
default: null
},
placement: {
type: String,
default: 'bottom',
validator: (value: string) => {
return ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'].includes(value)
}
},
strategy: {
type: String,
default: 'fixed',
validator: (value: string) => {
return ['absolute', 'fixed'].includes(value)
}
},
flip: {
type: Boolean,
default: true
},
wrapperClass: {
type: String,
default: () => $ui.tooltip.wrapper
@@ -52,6 +36,10 @@ const props = defineProps({
type: String,
default: () => $ui.tooltip.container
},
widthClass: {
type: String,
default: () => $ui.tooltip.width
},
baseClass: {
type: String,
default: () => $ui.tooltip.base
@@ -59,36 +47,17 @@ const props = defineProps({
transitionClass: {
type: Object,
default: () => $ui.tooltip.transition
},
popperOptions: {
type: Object as PropType<PopperOptions>,
default: () => ({
strategy: 'fixed'
})
}
})
const open = ref(false)
const [trigger, container] = usePopper({
placement: props.placement,
strategy: props.strategy,
modifiers: [{
name: 'offset',
options: {
offset: 0
}
},
{
name: 'computeStyles',
options: {
gpuAcceleration: false,
adaptive: false
}
},
{
name: 'preventOverflow',
options: {
padding: 8
}
}, {
name: 'flip',
enabled: props.flip
}]
})
const [trigger, container] = usePopper(props.popperOptions)
</script>
<script lang="ts">