nb-select

This is a select component for Vue.js 3+.

Loading component...

Installation

Yarn
yarn add @vlalg-nimbus/nb-selects
NPM
npm install @vlalg-nimbus/nb-selects

Usage

Vue 3
import { createApp } from 'vue'
import App from './App.vue'

import NbSelectComponents from '@vlalg-nimbus/nb-selects'
import "@vlalg-nimbus/nb-selects/dist/style.css";

const app = createApp(App)
app.use(NbSelectComponents)
app.mount('#app')
Nuxt 3
import NbSelectComponents from '@vlalg-nimbus/nb-selects'
import "@vlalg-nimbus/nb-selects/dist/style.css";

export default defineNuxtPlugin(context => {
  context.vueApp.use(NbSelectComponents)
})

To use, simply call the component, in this case it will be NbSelect or nb-select.

Mode 1
<template>
  <NbSelect />
</template>
Mode 2
<template>
  <nb-select />
</template>
Mode 3
<template>
  <nb-select></nb-select>
</template>

Preview & Playground

Select the component you want to edit/test

Loading Sandbox...

Props

Items with an (*) mean they are required

nameValue typeDefaultDescription
nbId (*)StringSets the id attribute to differentiate from other components
selectNameString'selectX'Sets the name attribute for the select element
displayString'b'Defines the display type. Accepts ib and b.
themeString'light'Defines the theme. Accepts dark and light. When theme is set, uses theme-specific color props.
hasBorderRadiusBooleanfalseDefines if the select should have border-radius.
borderRadiusNumber0.5Defines border-radius.
disabledBooleanfalseDefines if the select is disabled
requiredBooleanfalseDefines if the select is required
fontFamilyString"'Lato', sans-serif"Defines the font-family
fontSizeString'1.6em'Defines the font-size
fontWeightNumber400Defines the font-weight
textAlignString'left'Defines the text alignment. Accepts left, center, right.
selectWidthNumber200Defines the select width in pixels
inputStyleString'background'Defines the input style. Accepts background, line, border.
optionsArrayDefines the list of options. It is an array of objects with value and text properties (or custom keys via valueKey and textKey). For grouped display, add a property with the key given by groupKey (e.g. group) on each option.
selectedOptionOnlyString, Number, Boolean''Defines the selected value for single select. The value must exist in the list options
selectedOptionMultipleArrayDefines the selected values for multiple select. The values must exist in the list options
textKeyString'text'Defines the key name for the text property in options objects
valueKeyString'value'Defines the key name for the value property in options objects
groupKeyString''Key name for the group property in options objects. Used with hasGroups to show options grouped by this value.
hasGroupsBooleanfalseWhen true and groupKey is set, options are displayed in groups; each group shows a label (the group value) and its options below.
groupCollapsibleBooleanfalseWhen true and hasGroups is enabled, clicking on a group header toggles collapsing/expanding that group's options.
multipleBooleanfalseDefines if the select allows multiple selections
hasEmptyOptionBooleantrueDefines if the select should have an empty option (placeholder). In single select it selects the empty value; in multiple select it appears as the first option in the list and clears the selection when clicked. Hidden when the filter has text (same as single).
emptyOptionTextString'Select an option'Defines the text for the empty option
emptyOptionValueString, NumbernullDefines the value for the empty option
hasFilterBooleanfalseEnables a filter input at the top of the dropdown to search/filter options
filterPlaceholderString'Filter...'Placeholder text for the filter input
emptyFilterTextString'not found'Text shown when the filter returns no results
multipleSelectedTextString'items selected'Text shown in the field when multiple options are selected (e.g. "3 items selected"). The number is prepended automatically.
filterPaddingString'8px'Padding of the filter wrap area
filterMarginBottomNumber0Bottom margin of the filter wrap in pixels
filterBorderRadiusNumber0Border radius of the filter input (in rem)
optionsPaddingString'8px 12px'Padding applied to each option item in the dropdown list (single and multiple)
groupPaddingString'6px 8px'Padding applied to each group label header when using grouped display (hasGroups + groupKey).
dropdownScrollClassString''Defines a custom CSS class for the dropdown scroll container
showLabelBooleanfalseDefines if the select should have a label
labelString'Label text'Defines the label text
labelMarginBottomNumber0Defines the bottom margin of the label in pixels
labelMarginLeftNumber0Defines the left margin of the label in pixels
fontFamilyLabelString"'Lato', sans-serif"Defines the font-family for the label
fontSizeLabelString'1em'Defines the font-size for the label
fontWeightLabelNumber400Defines the font-weight for the label
fontSizeLabelActiveString'0.8em'Defines the font-size for the label when active
labelBackgroundString'transparent'Defines the background color for the label when active
labelPaddingString'1px 5px'Defines the padding for the label when active
labelBorderRadiusNumber0Defines the border-radius for the label when active
labelLeftNumber5Defines the left position of the label in pixels
labelActiveTopNumber-13Defines the top position of the label when active in pixels
labelActiveLeftNumber5Defines the left position of the label when active in pixels
labelRightNumber0Defines the right position of the label in pixels
labelActiveRightNumber0Defines the right position of the label when active in pixels
inputLabelMarginActiveNumber15Defines the top margin of the input when the label is active in pixels
labelBreakOnActiveBooleantrueDefines if the label text should break or use ellipsis when active
tabIndexNumber0Defines the tab index. Set this property to make the select focusable by the keyboard.
hasTabIndexEnterBooleantrueEnables the select to be activated with the Enter key when focused.
hasTabIndexSpaceBooleantrueEnables the select to be activated with the Space key when focused.
ariaLabelString'Select'Defines the aria-label attribute for screen readers.
ariaAttrsObject{}Allows passing custom aria attributes as an object. Keys will automatically receive the aria- prefix. Example: { 'describedby': 'help-id', 'invalid': 'false' }
titleString''Tooltip text shown when hovering over the component.
lightBgColorString'#f8f8f2'Defines the background color for light theme. Accepts Color name and Hex
lightBgColorFocusString'#eaeaea'Defines the background color on focus for light theme. Accepts Color name and Hex
lightBorderColorString'#353734'Defines the border color for light theme. Accepts Color name and Hex
lightBorderColorFocusString'#272936'Defines the border color on focus for light theme. Accepts Color name and Hex
lightDisabledBgColorString'#dfdfd9'Defines the disabled background color for light theme. Accepts Color name and Hex
lightTextColorString'#000000'Defines the text color for light theme. Accepts Color name and Hex
lightDisabledBorderColorString'rgba(53, 55, 52, 0.3)'Defines the disabled border color for light theme. Accepts Color name and Hex
lightOptionTextColorString'#000000'Defines the option text color for light theme. Accepts Color name and Hex
lightOptionTextColorSelectedString'#000000'Defines the selected option text color for light theme. Accepts Color name and Hex
lightOptionBgColorSelectedString'#e0e0e0'Defines the selected option background color for light theme. Accepts Color name and Hex
lightPlaceholderColorString'#999999'Defines the placeholder color for light theme. Accepts Color name and Hex
lightFilterTextColorString'#000000'Defines the filter input and selected-value text color for light theme. Accepts Color name and Hex
lightEmptyTextColorString'#999999'Defines the empty/placeholder text color (dropdown placeholder, filter placeholder, "not found" message) for light theme. Accepts Color name and Hex
lightFilterWrapBorderColorString'#353734'Defines the border color of the filter wrap (area above the list) for light theme. If empty, uses lightBorderColor. Accepts Color name and Hex
lightFilterInputBorderColorString'#353734'Defines the border color of the filter input for light theme. If empty, uses lightBorderColor. Accepts Color name and Hex
lightGroupTextColorString''Defines the text color of the group header label for light theme. If empty, uses lightPlaceholderColor. Accepts Color name and Hex
lightGroupBgColorString''Defines the background color of the group header label for light theme. If empty, uses transparent. Accepts Color name and Hex
lightTextColorLabelString'#333333'Defines the label text color for light theme. Accepts Color name and Hex
lightTextColorLabelActiveString'#333333'Defines the label text color when active for light theme. Accepts Color name and Hex
darkBgColorString'#353734'Defines the background color for dark theme. Accepts Color name and Hex
darkBgColorFocusString'#272936'Defines the background color on focus for dark theme. Accepts Color name and Hex
darkBorderColorString'#44475a'Defines the border color for dark theme. Accepts Color name and Hex
darkBorderColorFocusString'rgba(68, 71, 90, 0.4)'Defines the border color on focus for dark theme. Accepts Color name and Hex
darkDisabledBgColorString'rgba(40, 42, 54, 1)'Defines the disabled background color for dark theme. Accepts Color name and Hex
darkTextColorString'#ffffff'Defines the text color for dark theme. Accepts Color name and Hex
darkDisabledBorderColorString'rgba(68, 71, 90, 0.3)'Defines the disabled border color for dark theme. Accepts Color name and Hex
darkOptionTextColorString'#ffffff'Defines the option text color for dark theme. Accepts Color name and Hex
darkOptionTextColorSelectedString'#ffffff'Defines the selected option text color for dark theme. Accepts Color name and Hex
darkOptionBgColorSelectedString'#3d3d3d'Defines the selected option background color for dark theme. Accepts Color name and Hex
darkPlaceholderColorString'#999999'Defines the placeholder color for dark theme. Accepts Color name and Hex
darkFilterTextColorString'#ffffff'Defines the filter input and selected-value text color for dark theme. Accepts Color name and Hex
darkEmptyTextColorString'#999999'Defines the empty/placeholder text color (dropdown placeholder, filter placeholder, "not found" message) for dark theme. Accepts Color name and Hex
darkFilterWrapBorderColorString'#44475a'Defines the border color of the filter wrap (area above the list) for dark theme. If empty, uses darkBorderColor. Accepts Color name and Hex
darkFilterInputBorderColorString'#44475a'Defines the border color of the filter input for dark theme. If empty, uses darkBorderColor. Accepts Color name and Hex
darkGroupTextColorString''Defines the text color of the group header label for dark theme. If empty, uses darkPlaceholderColor. Accepts Color name and Hex
darkGroupBgColorString''Defines the background color of the group header label for dark theme. If empty, uses transparent. Accepts Color name and Hex
darkTextColorLabelString'#ffffff'Defines the label text color for dark theme. Accepts Color name and Hex
darkTextColorLabelActiveString'#ffffff'Defines the label text color when active for dark theme. Accepts Color name and Hex
maxHeightNumber200Defines the maximum height (in pixels) of the dropdown list. Minimum value is 37.58px (when hasEmptyOption is false) or 75.16px (when hasEmptyOption is true)

Events

nameReturn typeDescription
changedvalueFired when the selected value changes, returns the selected value(s).
changed-complete{ value|values, option|options, index|indices }Fired together with changed, but returns the full option object(s) and index/indices in the options array. For multiple selects, values/options/indices are arrays.
user-changedvalueFired when the user manually changes the selected value, returns the selected value(s).
user-changed-complete{ value|values, option|options, index|indices }Fired together with user-changed, but returns the full option object(s) and index/indices in the options array. For multiple selects, values/options/indices are arrays.
clickedMouseEvent | KeyboardEventFired when the select is clicked. Receives the native DOM event as first argument.
clicked-complete{ event, value|values, option|options, index|indices }Fired together with clicked, returns the original event and the current selection meta (full option object(s) and index/indices in the options array).
focusednothingFired when the select component receives focus (when clicking on the select field or navigating to it via keyboard).
blurrednothingFired when the select component loses focus (when clicking outside or navigating away via keyboard).

Slot

The component has a slot called slot-select-item where you can customize the display of each option.

<template>
  <NbSelect
    nb-id="select-custom"
    select-name="select-custom"
    :options="selectOptions"
    :selected-option-only="selectedValue"
  >
    <template #slot-select-item="{ propRow, propIndex }">
      <div>
        <strong>{{ propRow.text }}</strong>
        <span style="color: #999;"> - {{ propRow.description }}</span>
      </div>
    </template>
  </NbSelect>
</template>

Example

Light Theme (default)

<template>
  <NbSelect
    nb-id="select-light"
    select-name="select-light"
    theme="light"
    :options="selectOptions"
    :selected-option-only="selectedValue"
    light-bg-color="#dbeafe"
    light-bg-color-focus="#bfdbfe"
    light-border-color="#93c5fd"
    light-border-color-focus="#60a5fa"
    light-text-color="#1e40af"
    light-placeholder-color="#64748b"
    light-option-text-color="#1e40af"
    light-option-text-color-selected="#ffffff"
    light-option-bg-color-selected="#3b82f6"
    :border-radius="0.375"
    @changed="handleChange($event)"
    @user-changed="handleUserChange($event)"
  />
</template>

<script setup>
import { ref } from 'vue';

defineOptions({
  name: 'CompSelect',
});

const selectOptions = [
  { value: 'option1', text: 'Option 1' },
  { value: 'option2', text: 'Option 2' },
  { value: 'option3', text: 'Option 3' }
];

const selectedValue = ref('option1');

const handleChange = (value) => {
  selectedValue.value = value;
  console.log('Changed:', value);
};

const handleUserChange = (value) => {
  console.log('User changed:', value);
};
</script>

Dark Theme

<template>
  <NbSelect
    nb-id="select-dark"
    select-name="select-dark"
    theme="dark"
    :options="selectOptions"
    :selected-option-only="selectedValue"
    dark-bg-color="#8b5cf6"
    dark-bg-color-focus="#7c3aed"
    dark-border-color="#a78bfa"
    dark-border-color-focus="#8b5cf6"
    dark-text-color="#f3f4f6"
    dark-placeholder-color="#c4b5fd"
    dark-option-text-color="#f3f4f6"
    dark-option-text-color-selected="#ffffff"
    dark-option-bg-color-selected="#6d28d9"
    :border-radius="0.5"
    @changed="handleChange($event)"
    @user-changed="handleUserChange($event)"
  />
</template>

<script setup>
import { ref } from 'vue';

defineOptions({
  name: 'CompSelectDark',
});

const selectOptions = [
  { value: 'option1', text: 'Option 1' },
  { value: 'option2', text: 'Option 2' },
  { value: 'option3', text: 'Option 3' }
];

const selectedValue = ref('option2');

const handleChange = (value) => {
  selectedValue.value = value;
  console.log('Changed:', value);
};

const handleUserChange = (value) => {
  console.log('User changed:', value);
};
</script>

Multiple Selection

<template>
  <NbSelect
    nb-id="select-multiple"
    select-name="select-multiple"
    theme="light"
    :multiple="true"
    :options="selectOptions"
    :selected-option-multiple="selectedValues"
    @changed="handleChange($event)"
    @user-changed="handleUserChange($event)"
  />
</template>

<script setup>
import { ref } from 'vue';

defineOptions({
  name: 'CompSelectMultiple',
});

const selectOptions = [
  { value: 'option1', text: 'Option 1' },
  { value: 'option2', text: 'Option 2' },
  { value: 'option3', text: 'Option 3' }
];

const selectedValues = ref(['option1', 'option2']);

const handleChange = (value) => {
  selectedValues.value = value;
  console.log('Changed:', value);
};

const handleUserChange = (value) => {
  console.log('User changed:', value);
};
</script>

Grouped options

When has-groups is true and group-key is set, options are displayed in groups. Each option object must include the group key (e.g. group).

<template>
  <NbSelect
    nb-id="select-groups"
    select-name="select-groups"
    theme="light"
    :options="selectOptionsWithGroups"
    :selected-option-only="selectedValue"
    group-key="group"
    :has-groups="true"
    @changed="handleChange($event)"
  />
</template>

<script setup>
import { ref } from 'vue';

const selectOptionsWithGroups = [
  { value: 'a1', text: 'Option A1', group: 'Group A' },
  { value: 'a2', text: 'Option A2', group: 'Group A' },
  { value: 'b1', text: 'Option B1', group: 'Group B' },
  { value: 'b2', text: 'Option B2', group: 'Group B' }
];

const selectedValue = ref('a1');

const handleChange = (value) => {
  selectedValue.value = value;
};
</script>

Behavior

Auto-close

The component dropdown closes automatically in two situations:

  1. When focus leaves the component: When using Tab to navigate away from the component or clicking on another element on the page, the dropdown closes automatically.
  2. When another select is opened: When opening a new select (single or multiple), all other open selects close automatically. This ensures only one select is open at a time.

Multiple mode

In multiple mode (multiple="true"), the dropdown stays open after selecting an option, allowing you to select multiple options without reopening the dropdown. The dropdown only closes when:

  • Focus leaves the component
  • Another select is opened
  • You click outside the component (left-click; right-click does not close it)

When hasEmptyOption is enabled, the empty option appears as the first row in the list in multiple mode; clicking it clears the selection (equivalent to "deselect all").

Limitations

Overflow Hidden

The component dropdown uses position: absolute for positioning. If the component is inside a parent container with overflow: hidden, the dropdown may be clipped or hidden.

Solution: Remove or adjust the overflow: hidden property on the component's parent container so the dropdown can be displayed correctly.

<!-- ❌ Problem: dropdown will be clipped -->
<div style="overflow: hidden;">
  <NbSelect nb-id="select-1" :options="options" />
</div>

<!-- ✅ Solution: remove overflow: hidden or use overflow: visible -->
<div style="overflow: visible;">
  <NbSelect nb-id="select-1" :options="options" />
</div>