Common

useListNavigation

Composable interno per navigazione tastiera in liste con skip disabilitati e auto-scroll.

Composable interno — utilizzato dai componenti dropdown della libreria (Select, MultiSelect, AutoComplete, ecc.).

Firma TypeScript

export function useListNavigation(options: UseListNavigationOptions): UseListNavigationResult

export interface UseListNavigationOptions {
  itemCount: () => number;
  isItemDisabled?: (index: number) => boolean;
  containerRef?: Ref<HTMLElement | null>;
  itemSelector?: string;          // default: '[data-list-item]'
  circular?: boolean;             // default: false
  autoScroll?: boolean;           // default: true
  scrollBehavior?: ScrollLogicalPosition; // default: 'nearest'
  scrollMode?: ScrollBehavior;    // default: 'smooth'
}

export interface UseListNavigationResult {
  focusedIndex: Ref<number>;    // -1 se nessuno
  navigateDown: () => void;
  navigateUp: () => void;
  navigateFirst: () => void;
  navigateLast: () => void;
  navigateTo: (index: number) => void;
  scrollToFocused: () => void;
  scrollToIndex: (index: number) => void;
  resetFocus: () => void;
  focusFirst: () => void;
}

Parametri

ParametroTipoDescrizione
itemCount() => numberGetter reattivo del numero di elementi
isItemDisabled(index: number) => booleanFunzione per verificare se un elemento e disabilitato
containerRefRef<HTMLElement | null>Container scrollabile per auto-scroll
itemSelectorstringSelettore CSS degli elementi (default: [data-list-item])
circularbooleanNavigazione circolare (torna all'inizio dalla fine)
autoScrollbooleanAuto-scroll quando cambia focusedIndex (default: true)

Valore di Ritorno

ProprietàTipoDescrizione
focusedIndexRef<number>Indice elemento con focus (-1 se nessuno)
navigateDown() => voidSposta focus al successivo
navigateUp() => voidSposta focus al precedente
navigateFirst() => voidSposta focus al primo non-disabilitato
navigateLast() => voidSposta focus all'ultimo non-disabilitato
navigateTo(index: number) => voidSposta focus a un indice specifico
scrollToFocused() => voidScrolla all'elemento focused
resetFocus() => voidRimuove il focus (imposta -1)

Esempio

const { focusedIndex, navigateDown, navigateUp, resetFocus } = useListNavigation({
  itemCount: () => filteredOptions.value.length,
  isItemDisabled: (index) => filteredOptions.value[index]?.disabled,
  containerRef: listRef,
  circular: false,
})

// In handler keydown del componente
const onKeydown = (event: KeyboardEvent) => {
  if (event.key === 'ArrowDown') { event.preventDefault(); navigateDown() }
  if (event.key === 'ArrowUp') { event.preventDefault(); navigateUp() }
  if (event.key === 'Escape') resetFocus()
}

Note

  • Salta automaticamente gli elementi disabilitati durante la navigazione.
  • L'auto-scroll avviene tramite nextTick per attendere il render DOM prima di scrollare.
  • In modalita non-circular, raggiunto il bordo della lista il focus rimane sull'ultimo elemento valido.
  • focusedIndex e -1 inizialmente; il componente deve mapparlo a una classe CSS per l'evidenziazione visiva.