File tree Expand file tree Collapse file tree 2 files changed +26
-11
lines changed Expand file tree Collapse file tree 2 files changed +26
-11
lines changed Original file line number Diff line number Diff line change 11<script setup lang="ts">
2- import { nextTick , ref , watch } from " vue" ;
2+ import { ref , watch } from " vue" ;
33
44const props = defineProps <{
5+ menu: HTMLDivElement | null ;
6+ index: number ;
57 isFocused: boolean ;
68 isSelected: boolean ;
79}>();
@@ -15,15 +17,24 @@ const option = ref<HTMLButtonElement | null>(null);
1517// Scroll the focused option into view when it's out of the menu's viewport.
1618watch (
1719 () => props .isFocused ,
18- async () => {
19- if (props .isFocused ) {
20- // Use nextTick to wait for the next DOM render.
21- await nextTick (() => {
22- option .value ?.parentElement ?.scrollTo ({
23- top: option .value ?.offsetTop - option .value ?.parentElement ?.offsetHeight + option .value ?.offsetHeight ,
24- behavior: " instant" ,
25- });
26- });
20+ () => {
21+ if (props .isFocused && props .menu ) {
22+ // Get child element with index
23+ const option = props .menu .children [props .index ] as HTMLDivElement ;
24+
25+ const optionTop = option .offsetTop ;
26+ const optionBottom = optionTop + option .clientHeight ;
27+ const menuScrollTop = props .menu .scrollTop ;
28+ const menuHeight = props .menu .clientHeight ;
29+
30+ if (optionTop < menuScrollTop ) {
31+ // eslint-disable-next-line vue/no-mutating-props
32+ props .menu .scrollTop = optionTop ;
33+ }
34+ else if (optionBottom > menuScrollTop + menuHeight ) {
35+ // eslint-disable-next-line vue/no-mutating-props
36+ props .menu .scrollTop = optionBottom - menuHeight ;
37+ }
2738 }
2839 },
2940);
Original file line number Diff line number Diff line change @@ -98,8 +98,9 @@ const selected = defineModel<string | string[]>({
9898 },
9999});
100100
101- const container = ref <HTMLElement | null >(null );
101+ const container = ref <HTMLDivElement | null >(null );
102102const input = ref <HTMLInputElement | null >(null );
103+ const menu = ref <HTMLDivElement | null >(null );
103104
104105const search = ref (" " );
105106const menuOpen = ref (false );
@@ -384,6 +385,7 @@ onBeforeUnmount(() => {
384385 <Teleport :to =" teleport" :disabled =" !teleport" >
385386 <div
386387 v-if =" menuOpen"
388+ ref =" menu"
387389 class =" menu"
388390 role =" listbox"
389391 :aria-label =" aria?.labelledby"
@@ -400,6 +402,8 @@ onBeforeUnmount(() => {
400402 type =" button"
401403 class =" menu-option"
402404 :class =" { focused: focusedOption === i, selected: option.value === selected }"
405+ :menu =" menu"
406+ :index =" i"
403407 :is-focused =" focusedOption === i"
404408 :is-selected =" option.value === selected"
405409 @select =" setOption(option.value)"
You can’t perform that action at this time.
0 commit comments