Skip to content

Commit

Permalink
Replace popper.js with floating-ui (#3406)
Browse files Browse the repository at this point in the history
* Replace popper.js with floating-ui

Signed-off-by: Olga Bulat <[email protected]>

* Enable activation on hover

Signed-off-by: Olga Bulat <[email protected]>

* Update border

Signed-off-by: Olga Bulat <[email protected]>

* Remove fixed width

Signed-off-by: Olga Bulat <[email protected]>

* Update snapshots

Signed-off-by: Olga Bulat <[email protected]>

---------

Signed-off-by: Olga Bulat <[email protected]>
  • Loading branch information
obulat authored Dec 7, 2023
1 parent bb9d54a commit cec6b8c
Show file tree
Hide file tree
Showing 26 changed files with 200 additions and 173 deletions.
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"create:component": "./bin/create-component.sh"
},
"dependencies": {
"@floating-ui/dom": "^1.5.3",
"@nuxt/components": "^2.2.1",
"@nuxt/vue-app": "^2.17.2",
"@nuxtjs/composition-api": "^0.33.1",
Expand All @@ -66,7 +67,6 @@
"@nuxtjs/sitemap": "^2.4.0",
"@nuxtjs/svg-sprite": "0.5.2",
"@pinia/nuxt": "0.2.1",
"@popperjs/core": "^2.11.8",
"@vueuse/core": "^10.2.1",
"@wordpress/is-shallow-equal": "^4.6.0",
"async-mutex": "^0.3.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
:hide-on-click-outside="false"
:label="$t('mediaDetails.contentReport.long').toString()"
placement="bottom-end"
width="w-80"
>
<template #trigger="{ a11yProps }">
<VContentReportButton v-bind="a11yProps" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
ref="contentMenuPopover"
:label="$t('searchType.label').toString()"
placement="bottom-end"
width="w-66"
:clippable="true"
:trap-focus="false"
>
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/VContentSwitcher/VSearchTypes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
:size="size"
:bordered="bordered"
type="radiogroup"
:class="{ 'w-66': size === 'small' }"
>
<div
v-for="(category, index) in contentTypeGroups"
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/VHomepageContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
:trap-focus="false"
:visible="isContentSwitcherVisible"
:trigger-element="triggerElement"
width="w-66"
aria-labelledby="search-type-button"
>
<VSearchTypes
Expand Down
44 changes: 29 additions & 15 deletions frontend/src/components/VPopover/VPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
ref="triggerContainerRef"
class="flex w-min items-stretch whitespace-nowrap"
@click="onTriggerClick"
@mouseenter="onTriggerMouseEnter"
@focusin="onTriggerMouseEnter"
@mouseleave="onTriggerMouseLeave"
@focusout="onTriggerMouseLeave"
>
<!--
@slot The trigger, should be a button 99.99% of the time. If you need custom event handling on the trigger button, ensure bubbling is not prevented or else the popover will not open
Expand All @@ -21,7 +25,6 @@
<VPopoverContent
v-if="triggerRef"
:z-index="zIndex"
:width="width"
:visible="visibleRef"
:trigger-element="triggerRef"
:placement="placement"
Expand Down Expand Up @@ -54,7 +57,7 @@ import { useDialogControl } from "~/composables/use-dialog-control"
import VPopoverContent from "~/components/VPopover/VPopoverContent.vue"
import type { Placement, PositioningStrategy } from "@popperjs/core"
import type { Placement, Strategy } from "@floating-ui/dom"
export default defineComponent({
name: "VPopover",
Expand All @@ -64,6 +67,10 @@ export default defineComponent({
* default for each of them can take over.
*/
props: {
/**
* Whether the popover should show when the trigger is hovered on.
*/
activateOnHover: { type: Boolean, default: undefined },
/**
* Whether the popover should hide when the <kbd>Escape</kbd> key is pressed.
*
Expand Down Expand Up @@ -93,9 +100,9 @@ export default defineComponent({
autoFocusOnHide: { type: Boolean, default: undefined },
/**
* The placement of the popover relative to the trigger. Should be one of the options
* for `placement` passed to popper.js.
* for `placement` passed to floating-ui.
*
* @see https://popper.js.org/docs/v2/constructors/#options
* @see https://floating-ui.com/docs/tutorial#placements
*
* @default 'bottom'
*/
Expand All @@ -106,12 +113,12 @@ export default defineComponent({
* The positioning strategy of the popover. If your reference element is in a fixed container
* use the fixed strategy; otherwise use the default, absolute strategy.
*
* @see https://popper.js.org/docs/v2/constructors/#strategy
* @see https://floating-ui.com/docs/computeposition#strategy
*
* @default 'absolute'
*/
strategy: {
type: String as PropType<PositioningStrategy>,
type: String as PropType<Strategy>,
},
/**
* The label of the popover content. Must be provided if `labelledBy` is empty.
Expand Down Expand Up @@ -147,12 +154,6 @@ export default defineComponent({
* @default true
*/
trapFocus: { type: Boolean, default: undefined },
/**
* Optional Tailwind class for fixed width popover content.
*
* @default undefined
*/
width: { type: String },
},
emits: [
/**
Expand All @@ -164,13 +165,13 @@ export default defineComponent({
*/
"close",
],
setup(_, { emit }) {
setup(props, { emit }) {
const visibleRef = ref(false)
const triggerContainerRef = ref<HTMLElement | null>(null)
const triggerRef = computed(() =>
triggerContainerRef.value?.firstChild
? (triggerContainerRef.value.firstChild as HTMLElement)
triggerContainerRef.value?.firstElementChild
? (triggerContainerRef.value.firstElementChild as HTMLElement)
: undefined
)
Expand All @@ -179,13 +180,26 @@ export default defineComponent({
emit: emit as SetupContext["emit"],
})
const onTriggerMouseEnter = () => {
if (props.activateOnHover) {
open()
}
}
const onTriggerMouseLeave = () => {
if (props.activateOnHover) {
close()
}
}
return {
open,
close,
visibleRef,
triggerContainerRef,
triggerRef,
onTriggerClick,
onTriggerMouseEnter,
onTriggerMouseLeave,
triggerA11yProps,
}
},
Expand Down
41 changes: 13 additions & 28 deletions frontend/src/components/VPopover/VPopoverContent.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
<template>
<div
v-show="visible"
class="h-0 w-0"
ref="popoverRef"
role="dialog"
aria-modal="true"
class="popover-content w-max-content absolute left-0 top-0 overflow-y-auto overflow-x-hidden rounded-sm border border-light-gray bg-white shadow"
:class="`z-${zIndex}`"
:style="{ ...heightProperties, ...style }"
:tabindex="-1"
:aria-hidden="!visible"
v-on="$listeners"
@blur="onBlur"
@keydown="onKeyDown"
>
<div
ref="popoverRef"
role="dialog"
aria-modal="true"
class="popover-content overflow-y-auto overflow-x-hidden rounded-sm border border-light-gray bg-white shadow"
:class="[`z-${zIndex}`, width]"
:style="heightProperties"
:tabindex="-1"
v-bind="$attrs"
@blur="onBlur"
>
<slot />
</div>
<slot />
</div>
</template>

Expand All @@ -37,7 +31,7 @@ import { defineEvent } from "~/types/emits"
import { zIndexValidator } from "~/constants/z-indices"
import type { Placement, PositioningStrategy } from "@popperjs/core"
import type { Placement, Strategy } from "@floating-ui/dom"
import type { SetupContext } from "vue"
Expand All @@ -47,7 +41,6 @@ export const VPopoverContentContextKey = Symbol(
export default defineComponent({
name: "VPopoverContent",
inheritAttrs: false,
props: {
visible: {
type: Boolean,
Expand Down Expand Up @@ -84,7 +77,7 @@ export default defineComponent({
default: "bottom-end",
},
strategy: {
type: String as PropType<PositioningStrategy>,
type: String as PropType<Strategy>,
default: "absolute",
},
zIndex: {
Expand All @@ -100,12 +93,6 @@ export default defineComponent({
type: Boolean,
default: true,
},
/**
* Optional Tailwind class for fixed width.
*/
width: {
type: String,
},
},
/**
* This is the only documented emitted event but in reality we pass through `$listeners`
Expand All @@ -119,21 +106,19 @@ export default defineComponent({
const propsRefs = toRefs(props)
const popoverRef = ref<HTMLElement | null>(null)
const { onKeyDown, onBlur, heightProperties } = usePopoverContent({
const { onKeyDown, onBlur, heightProperties, style } = usePopoverContent({
popoverRef,
popoverPropsRefs: propsRefs,
emit: emit as SetupContext["emit"],
attrs,
})
return { popoverRef, onKeyDown, onBlur, heightProperties }
return { popoverRef, onKeyDown, onBlur, heightProperties, style }
},
})
</script>
<style>
.popover-content {
height: var(--popover-height, auto);
scrollbar-gutter: stable;
overflow-x: hidden;
}
</style>
17 changes: 15 additions & 2 deletions frontend/src/components/VPopover/meta/VPopover.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@ import {
Story,
} from "@storybook/addon-docs"

import { placements as popoverPlacements } from "@popperjs/core"

import VPopover from "~/components/VPopover/VPopover.vue"
import VButton from "~/components/VButton.vue"

export const popoverPlacements = [
"top",
"top-start",
"top-end",
"bottom",
"bottom-start",
"bottom-end",
"left",
"left-start",
"left-end",
"right",
"right-start",
"right-end",
]

<Meta
title="Components/VPopover"
components={VPopover}
Expand Down
Loading

0 comments on commit cec6b8c

Please sign in to comment.