Fixed dropdown clipping
This commit is contained in:
1 parent
d0886cd9a3
commit
4196db1759
1 file changed
+26
-19
+26
-19
@@ -14,6 +14,7 @@ const props = defineProps<DropdownMenuProps>()
|
|||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
const placement = ref<"bottom" | "top">("bottom")
|
const placement = ref<"bottom" | "top">("bottom")
|
||||||
const root = useTemplateRef("root")
|
const root = useTemplateRef("root")
|
||||||
|
const menuPosition = ref({ top: 0, left: 0 })
|
||||||
|
|
||||||
const toggle = async () => {
|
const toggle = async () => {
|
||||||
open.value = !open.value
|
open.value = !open.value
|
||||||
@@ -37,16 +38,12 @@ const updatePlacement = () => {
|
|||||||
// TODO: Calculate height instead
|
// TODO: Calculate height instead
|
||||||
const menuHeight = 220
|
const menuHeight = 220
|
||||||
|
|
||||||
console.log(
|
const showAbove = spaceBelow < menuHeight && spaceAbove > spaceBelow
|
||||||
spaceBelow,
|
placement.value = showAbove ? "top" : "bottom"
|
||||||
menuHeight,
|
menuPosition.value = {
|
||||||
spaceAbove,
|
top: showAbove ? rect.top : rect.bottom,
|
||||||
spaceBelow < menuHeight && spaceAbove > spaceBelow,
|
left: rect.right,
|
||||||
spaceBelow < menuHeight && spaceAbove > spaceBelow ? "top" : "bottom",
|
}
|
||||||
)
|
|
||||||
|
|
||||||
placement.value =
|
|
||||||
spaceBelow < menuHeight && spaceAbove > spaceBelow ? "top" : "bottom"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleOutsideClick = (e: MouseEvent) => {
|
const handleOutsideClick = (e: MouseEvent) => {
|
||||||
@@ -84,7 +81,16 @@ onBeforeMount(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Transition name="dropdown">
|
<Transition name="dropdown">
|
||||||
<div v-show="open" class="menu" :class="placement">
|
<Teleport to="body">
|
||||||
|
<div
|
||||||
|
v-show="open"
|
||||||
|
class="dropdown-menu"
|
||||||
|
:class="placement"
|
||||||
|
:style="{
|
||||||
|
top: `${menuPosition.top}px`,
|
||||||
|
left: `${menuPosition.left}px`,
|
||||||
|
}"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(group, i) in items"
|
v-for="(group, i) in items"
|
||||||
:key="`group-${i}`"
|
:key="`group-${i}`"
|
||||||
@@ -105,7 +111,8 @@ onBeforeMount(() => {
|
|||||||
<span>{{ item.label }}</span>
|
<span>{{ item.label }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Teleport>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -116,10 +123,11 @@ onBeforeMount(() => {
|
|||||||
.dropdown {
|
.dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.menu {
|
.dropdown-menu {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
right: 0;
|
z-index: 1000;
|
||||||
|
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
@@ -131,18 +139,17 @@ onBeforeMount(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
z-index: 1000;
|
transform: translateX(-100%);
|
||||||
|
|
||||||
&.bottom {
|
&.bottom {
|
||||||
top: calc(100% + 0.5rem);
|
transform: translate(-100%, 0.5rem);
|
||||||
transform-origin: top right;
|
transform-origin: top right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.top {
|
&.top {
|
||||||
bottom: calc(100% + 0.5rem);
|
transform: translate(-100%, calc(-100% - 0.5rem));
|
||||||
transform-origin: bottom right;
|
transform-origin: bottom right;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.group {
|
.group {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
Reference in new issue
Block a user