LangSelect dropdown: fixed position, unclipped by the editor panel

This commit is contained in:
2026-09-03 03:06:34 +00:00
parent fb159f0cb0
commit 87b7591bec
+19 -6
View File
@@ -13,10 +13,22 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const open = ref(false) const open = ref(false)
const toggleBtn = ref(null)
const popStyle = ref({})
const current = computed( const current = computed(
() => props.options.find((o) => o.tag === props.modelValue) ?? props.options[0], () => props.options.find((o) => o.tag === props.modelValue) ?? props.options[0],
) )
function toggle() {
open.value = !open.value
if (open.value) {
// Position: fixed so the popup overflows the scrolling editor panel
// onto the page area instead of being clipped by it.
const r = toggleBtn.value.getBoundingClientRect()
popStyle.value = { top: `${r.bottom + 2}px`, left: `${r.left}px` }
}
}
function select(tag) { function select(tag) {
emit('update:modelValue', tag) emit('update:modelValue', tag)
open.value = false open.value = false
@@ -26,15 +38,16 @@ function select(tag) {
<template> <template>
<span v-if="options.length > 1" class="lang-select"> <span v-if="options.length > 1" class="lang-select">
<button <button
ref="toggleBtn"
type="button" type="button"
class="lang-current" class="lang-current"
:class="{ open }" :class="{ open }"
:title="title || (current :title="title || (current
? `language: ${current.name}${current.primary ? ' (primary)' : ''}` ? `language: ${current.name}${current.primary ? ' (primary)' : ''}`
: '')" : '')"
@click="open = !open" @click="toggle"
><span v-if="current?.flag" class="flag" v-html="current.flag" /></button> ><span v-if="current?.flag" class="flag" v-html="current.flag" /></button>
<span v-if="open" class="lang-pop" @mouseleave="open = false"> <span v-if="open" class="lang-pop" :style="popStyle" @mouseleave="open = false">
<button <button
v-for="o in options" v-for="o in options"
:key="o.code" :key="o.code"
@@ -69,11 +82,11 @@ function select(tag) {
border-color: var(--line); border-color: var(--line);
} }
/* The dropdown matches the page's existing popups (.picker-pop look). */ /* The dropdown matches the page's existing popups (.picker-pop look).
Fixed-positioned (anchored to the toggle's viewport rect on open) so it
is not clipped by the editor panel's scrolling overflow. */
.lang-pop { .lang-pop {
position: absolute; position: fixed;
top: 100%;
left: 0;
z-index: 20; z-index: 20;
display: flex; display: flex;
flex-direction: column; flex-direction: column;