CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue-select

Everything you wish the HTML select element could do, wrapped up into a lightweight, extensible Vue component.

Pending
Overview
Eval results
Files

keyboard-navigation.mddocs/

Keyboard Navigation

Complete keyboard navigation system with customizable key mappings, type-ahead functionality, and accessibility compliance.

Capabilities

Keyboard Configuration

Properties that control keyboard behavior and key mappings.

/**
 * Array of key codes that will select the current option
 * Default is Enter key (13)
 */
selectOnKeyCodes: Array  // default: [13]

/**
 * Set the tabindex for the input field
 */
tabindex: Number  // default: null

/**
 * Used to modify the default keydown events map for the search input
 * Allows customization of keyboard shortcuts
 * @param map - Default keydown map
 * @param vm - Vue Select instance
 * @returns Modified keydown map
 */
mapKeydown: Function  // default: (map, vm) => map

/**
 * DEPRECATED: When true, hitting tab key will select current value
 * Use selectOnKeyCodes instead
 */
selectOnTab: Boolean  // default: false

/**
 * DEPRECATED: Select current value if selectOnTab is enabled
 * Use selectOnKeyCodes instead
 */
onTab: Function

/**
 * Enable automatic scrolling to keep the highlighted option in view
 * When navigating with keyboard, the dropdown will scroll automatically
 */
autoscroll: Boolean  // default: true

Type-Ahead Pointer System

Properties and methods for keyboard navigation within the dropdown options.

// Data properties
data: {
  /**
   * Current position of keyboard navigation pointer in dropdown
   * -1 means no option is highlighted
   */
  typeAheadPointer: Number  // default: -1
}

// Methods from typeAheadPointer mixin
methods: {
  /**
   * Move the typeAheadPointer visually up the list by
   * setting it to the previous selectable option
   */
  typeAheadUp(): void,
  
  /**
   * Move the typeAheadPointer visually down the list by  
   * setting it to the next selectable option
   */
  typeAheadDown(): void,
  
  /**
   * Select the option at the current typeAheadPointer position
   * Optionally clear the search input on selection
   */
  typeAheadSelect(): void,
  
  /**
   * Move the pointer to the last selected option
   * Useful for maintaining context in multiple selection
   */
  typeAheadToLastSelected(): void
}

Keyboard Event Handlers

Methods that handle various keyboard interactions.

/**
 * Search input keyboard event handler
 * Handles navigation keys, selection keys, and special keys
 * @param e - Keyboard event object
 * @returns Keydown handler function
 */
onSearchKeyDown(e: KeyboardEvent): Function

/**
 * Search input keypress handler  
 * @param e - Keyboard event object
 */
onSearchKeyPress(e: KeyboardEvent): void

/**
 * Handle escape key press
 * Removes search text or closes dropdown
 */
onEscape(): void

/**
 * Delete value on Delete keypress when no text in search input
 * Useful for removing selected options with keyboard
 * @returns Deleted value or undefined
 */
maybeDeleteValue(): any

Auto-Scrolling (from pointerScroll mixin)

Automatic scrolling functionality to keep the keyboard-highlighted option visible.

/**
 * Enable/disable auto-scrolling to keep pointer visible
 */
autoscroll: Boolean  // default: true

/**
 * Adjust the scroll position of the dropdown list
 * if the current pointer is outside of the overflow bounds
 * @returns Scroll adjustment result
 */
maybeAdjustScroll(): any

/**
 * Get the currently viewable portion of the dropdown menu
 * @returns Viewport bounds object
 */
getDropdownViewport(): Object

Usage Examples

Basic Keyboard Navigation

<template>
  <v-select 
    v-model="selected"
    :options="options"
    placeholder="Use arrow keys to navigate, Enter to select..."
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Option 1', 'Option 2', 'Option 3', 'Option 4', 'Option 5']
    };
  }
};
</script>

Custom Key Mappings

<template>
  <v-select 
    v-model="selected"
    :options="options"
    :selectOnKeyCodes="[13, 32]"
    placeholder="Enter or Space to select..."
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Option 1', 'Option 2', 'Option 3']
    };
  }
};
</script>

Advanced Keydown Customization

<template>
  <v-select 
    v-model="selected"
    :options="filteredOptions"
    :mapKeydown="customKeydown"
    placeholder="Custom keyboard shortcuts enabled..."
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry']
    };
  },
  computed: {
    filteredOptions() {
      return this.options;
    }
  },
  methods: {
    customKeydown(map, vm) {
      return {
        ...map,
        // Ctrl+A to select all (for multiple select)
        'ctrl+65': (e) => {
          e.preventDefault();
          if (vm.multiple) {
            vm.selectedValue = [...vm.options];
          }
        },
        // Ctrl+D to clear selection
        'ctrl+68': (e) => {
          e.preventDefault();
          vm.clearSelection();
        },
        // F1 for help
        112: (e) => {
          e.preventDefault();
          alert('Keyboard shortcuts:\n' +
                'Arrow keys: Navigate\n' +
                'Enter/Space: Select\n' +
                'Escape: Close\n' +
                'Ctrl+A: Select all\n' +
                'Ctrl+D: Clear selection');
        }
      };
    }
  }
};
</script>

Tab Navigation with Custom Tabindex

<template>
  <div>
    <input tabindex="1" placeholder="First input" />
    
    <v-select 
      v-model="selected"
      :options="options"
      :tabindex="2"
      placeholder="Select with tabindex 2..."
    />
    
    <input tabindex="3" placeholder="Third input" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Option 1', 'Option 2', 'Option 3']
    };
  }
};
</script>

Multiple Selection with Keyboard Management

<template>
  <v-select 
    v-model="selectedItems"
    :options="options"
    multiple
    placeholder="Use Backspace to remove last item..."
    @keydown.delete="handleDelete"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedItems: [],
      options: [
        'JavaScript', 'Python', 'Java', 'C++', 'Go',
        'React', 'Vue.js', 'Angular', 'Node.js'
      ]
    };
  },
  methods: {
    handleDelete(event) {
      // Custom delete handling
      if (this.selectedItems.length > 0 && !this.$refs.vSelect.search) {
        console.log('Removing last selected item via keyboard');
      }
    }
  }
};
</script>

Disabled Auto-Scroll

<template>
  <v-select 
    v-model="selected"
    :options="manyOptions"
    :autoscroll="false"
    placeholder="Navigate without auto-scrolling..."
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      manyOptions: Array.from({ length: 50 }, (_, i) => `Option ${i + 1}`)
    };
  }
};
</script>

Keyboard Navigation Event Handling

<template>
  <v-select 
    v-model="selected"
    :options="options"
    @search:focus="onFocus"
    @search:blur="onBlur"
    placeholder="Keyboard event monitoring..."
    ref="vSelect"
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Option 1', 'Option 2', 'Option 3']
    };
  },
  methods: {
    onFocus() {
      console.log('Search input focused - keyboard navigation active');
    },
    onBlur() {
      console.log('Search input blurred - keyboard navigation inactive');
    }
  },
  mounted() {
    // Monitor typeAheadPointer changes
    this.$watch('$refs.vSelect.typeAheadPointer', (newPointer) => {
      if (newPointer >= 0) {
        const option = this.$refs.vSelect.filteredOptions[newPointer];
        console.log('Keyboard pointer moved to:', option);
      }
    });
  }
};
</script>

Programmatic Keyboard Control

<template>
  <div>
    <v-select 
      v-model="selected"
      :options="options"
      ref="vSelect"
      placeholder="Use buttons to control keyboard navigation..."
    />
    
    <div class="controls">
      <button @click="moveUp">↑ Up</button>
      <button @click="moveDown">↓ Down</button>
      <button @click="selectCurrent">✓ Select</button>
      <button @click="focusSearch">🔍 Focus</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: ['Option 1', 'Option 2', 'Option 3', 'Option 4', 'Option 5']
    };
  },
  methods: {
    moveUp() {
      if (this.$refs.vSelect.open) {
        this.$refs.vSelect.typeAheadUp();
      }
    },
    moveDown() {
      if (this.$refs.vSelect.open) {
        this.$refs.vSelect.typeAheadDown();
      }
    },
    selectCurrent() {
      if (this.$refs.vSelect.open) {
        this.$refs.vSelect.typeAheadSelect();
      }
    },
    focusSearch() {
      this.$refs.vSelect.searchEl.focus();
    }
  }
};
</script>

<style scoped>
.controls {
  margin-top: 10px;
}
.controls button {
  margin-right: 10px;
  padding: 5px 10px;
}
</style>

Accessibility-Enhanced Navigation

<template>
  <v-select 
    v-model="selected"
    :options="options"
    :inputId="'accessible-select'"
    aria-label="Choose your preferred programming language"
    placeholder="Select programming language..."
  />
</template>

<script>
export default {
  data() {
    return {
      selected: null,
      options: [
        'JavaScript', 'Python', 'Java', 'C#', 'Go',
        'Rust', 'TypeScript', 'Kotlin', 'Swift'
      ]
    };
  }
};
</script>

Default Key Mappings

Vue Select includes these default keyboard shortcuts:

  • Arrow Up/Down: Navigate through options
  • Enter: Select highlighted option
  • Escape: Close dropdown or clear search
  • Tab: Move to next focusable element (or select if selectOnTab enabled)
  • Backspace/Delete: Remove last selected item (multiple mode) when search is empty
  • Page Up/Down: Navigate quickly through long option lists
  • Home/End: Jump to first/last option

Install with Tessl CLI

npx tessl i tessl/npm-vue-select

docs

ajax-loading.md

customization.md

index.md

keyboard-navigation.md

search-filtering.md

selection.md

tagging.md

tile.json