From accd6f98cf73ce41b1f2788e3106a49ac1da595c Mon Sep 17 00:00:00 2001 From: xiaomai Date: Sun, 3 May 2026 11:38:32 +0800 Subject: [PATCH] fix(ui): prevent dropdown clipping with fixed positioning Automatically use fixed dropdown strategy for TagsSelect inside modals Dynamically calculate fixed coordinates for Pokemon fetch results dropdown --- frontend/src/components/TagsSelect.vue | 8 ++- frontend/src/styles/main.css | 12 ++-- frontend/src/views/PokemonEdit.vue | 84 +++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/TagsSelect.vue b/frontend/src/components/TagsSelect.vue index 1ee960c..2c5d4a6 100644 --- a/frontend/src/components/TagsSelect.vue +++ b/frontend/src/components/TagsSelect.vue @@ -38,8 +38,7 @@ const props = withDefaults( multiple: true, max: 0, allowCreate: false, - creating: false, - dropdownStrategy: 'absolute' + creating: false } ); @@ -57,6 +56,7 @@ const search = ref(''); const activeIndex = ref(-1); const dropdownStyle = ref({}); const dropdownPlacement = ref<'top' | 'bottom'>('bottom'); +const isInsideModal = ref(false); let positionFrame = 0; const optionRows = computed(() => @@ -111,7 +111,8 @@ const candidateRows = computed(() => { }); const activeCandidate = computed(() => candidateRows.value[activeIndex.value]); const activeDescendant = computed(() => activeCandidate.value?.id); -const usesFixedDropdown = computed(() => props.dropdownStrategy === 'fixed'); +const resolvedDropdownStrategy = computed(() => props.dropdownStrategy ?? (isInsideModal.value ? 'fixed' : 'absolute')); +const usesFixedDropdown = computed(() => resolvedDropdownStrategy.value === 'fixed'); function setDefaultActiveIndex() { const keyword = createName.value.toLowerCase(); @@ -311,6 +312,7 @@ function removePositionListeners() { } onMounted(() => { + isInsideModal.value = root.value?.closest('.modal') !== null; document.addEventListener('pointerdown', onDocumentPointerDown); }); diff --git a/frontend/src/styles/main.css b/frontend/src/styles/main.css index dc2ed3f..8796f34 100644 --- a/frontend/src/styles/main.css +++ b/frontend/src/styles/main.css @@ -796,12 +796,12 @@ button:disabled, } .pokemon-fetch-results { - position: absolute; - top: calc(100% + 6px); - right: 0; - left: 0; - z-index: 35; - max-height: 260px; + position: fixed; + top: auto; + right: auto; + left: auto; + z-index: 80; + max-height: var(--pokemon-fetch-results-max-height, 260px); overflow-y: auto; display: grid; gap: 4px; diff --git a/frontend/src/views/PokemonEdit.vue b/frontend/src/views/PokemonEdit.vue index 05fb548..e544c4f 100644 --- a/frontend/src/views/PokemonEdit.vue +++ b/frontend/src/views/PokemonEdit.vue @@ -1,6 +1,6 @@