Skip to content
On this page

BnListbox

BnListbox is a wrapper for the Listbox component from HeadlessUI. It is a form component that allows you to select one or more options from a list of options, like a select element.

Basic Usage

The only required props are name and options. The name prop is used to identify the listbox in the form, and the options prop is an array of strings or objects that will be used to populate the listbox.

vue
<script setup lang="ts">
import { ref } from 'vue';
import { BnListbox } from 'banano';

const optionsWithEmpty = ['', 'Option 1', 'Option 2', 'Option 3']
const value = ref<string>();
</script>

<template>
  <bn-listbox
    v-model="value"
    :options="optionsWithEmpty"
    name="listbox"
  />
  <p>Selected value: {{ value }}</p>
</template>

Selected value:

Input Attributes

While the component is not a native select element, it is built to mostly behave like one. The following props are supported: disabled, placeholder and multiple

html
<bn-listbox
  name="disabled"
  disabled
  :options="options"
  placeholder="Disabled"
/>

Multiple

When the multiple prop is set to true, the listbox will allow multiple options to be selected. The v-model prop (and the value of the field in vee-validate) will be an array of the selected options.

html
<bn-listbox
  name="multiple"
  :options="options"
  placeholder="Multiple"
  v-model="multiple"
  multiple
/>
<p>Selected values: {{ multiple }}</p>

Selected values: []

Vee-Validate

BnListbox works with vee-validate out of the box.

vue
<script setup lang="ts">
import { Form } from 'vee-validate';
import isRequired from '../rules';

const validationSchema = {
  input: isRequired,
};
</script>

<template>
  <Form :validation-schema="validationSchema" v-slot="{ values }">
    <bn-listbox
      name="input"
      :options="optionsWithEmpty"
    />
    Selected value: {{ values.input }}
  </Form>
</template>
Selected value:

Rules

If you want to validate a field without being in the context of a Form or an useForm, you can use the rules prop.

WARNING

The rules prop will be ignored if the component is inside a Form or an useForm context with a validationSchema.

vue
<script setup lang="ts">
import isRequired from '../rules';
</script>

<template>
  <bn-listbox
    :rules="isRequired"
    name="input"
    :options="optionsWithEmpty"
    placeholder="Click on me"
  />
</template>

Color

You can change the color accent of the listbox using the color prop.

html
<bn-listbox
  name="listbox"
  color="lime"
  :options="options"
  placeholder="Click me!"
/>

TIP

The color prop only supports the colors set when configuring the library. See Colors for more information.

Slots

BnListbox provides two slots: selected-template and option-template for adding additional content to the listbox.

selected-template

The selected-template slot is used to customize how a selected option is displayed in the listbox button.

html
<bn-listbox
  v-model="selected"
  name="selected-template-example"
  :options="options"
>
  <template #selected-template="{ value }">
    <span class="text-green-600 w-full text-left">
      🚩 {{ value }} 🚩
    </span>
  </template>
</bn-listbox>

option-template

The option-template slot is used to customize how options are displayed in the dropdown list.

html
<bn-listbox
  placeholder="Click me!"
  name="option-template-example"
  :options="options"
>
  <template #option-template="{ option, selected }">
    <span class="text-white" :class="[selected === option ? 'bg-pink-600' : 'bg-blue-600']">
      {{ option }}
    </span>
  </template>
</bn-listbox>

Customization

There are two ways to customize the appearance of the BnListbox component:

classes prop

Every component has a classes prop that will accept an object where each key corresponds to an internal element of the component. The value of each key will be the classes that will be applied to that element. For the values, you can use strings, objects or arrays, the same way it works with Vue's class binding.

html
<bn-listbox
  v-model="selected"
  :classes="{ button: 'border-4 border-purple-500' }"
  :options="['Option 1', 'Option 2', 'Option 3']"
>
  Name
</bn-listbox>

Default styles will still be applied, but the classes you provide will take precedence, so you can use this to override any existing style.

The available keys for this component are:

  • button: The ListboxButton element
  • tag: Every individual tag when using the multiple prop
  • options: The ListboxOptions element
  • option: Every individual ListboxOption element

Theming

You can change the default appearance or even add variants by editing the configuration of the TailwindCSS plugin.

javascript
plugins: [
    require('@tailwindcss/forms'),
    require('@headlessui/tailwindcss'),
    banano.tailwindPlugin({
      theme: {
        BnListbox: {
          '.bn-listbox': {
            '@apply bg-green-600': {},
          }
        }
      }
    }),
  ],

You can find more information about customizing the library in Theme Customization.

API Reference

typescript
type InputValue = number | string | Record<string, unknown> | undefined;

Props

PropDefaultDescription
modelValueundefinedInputValue | InputValue[]

Initial value for the dropdown. Can be a single value, an array of values, or undefined.
options--string[] | Record<string, unknown>[]

Options to be displayed in the dropdown. Can either be an array of strings or an array of objects.
name--string

The name attribute of the dropdown.
color'banano-base'string

Determines the color of the dropdown.
rulesundefinedRuleExpression<InputValue | InputValue[]>

Validation rules for the dropdown. Usually a function that receives the value of the component and returns a boolean or a string if invalid.
disabledfalseboolean

If true, the dropdown will be disabled.
multiplefalseboolean

If true, the dropdown will accept multiple values.
trackByundefinedstring

If using an array of objects for options, trackBy can be used to specify which property of the objects to use for comparison.
optionLabelundefinedstring

If using an array of objects for options, optionLabel can be used to specify which property of the objects to use for displaying.
keepObjectValuefalseboolean

If true, when an object option is selected, the object itself will be emitted instead of just the trackBy value.
placeholderundefinedstring

The placeholder text for the dropdown when no value is selected.
classes{}object

Allows to customize the classes of the dropdown's elements.

Events

EventPayloadDescription
focusEventEmitted when the dropdown is focused.
blurEventEmitted when the dropdown is blurred.
update:modelValueInputValue | InputValue[]Emitted when the selected value(s) in the dropdown changes.

Slots

SlotSlot PropsDescription
selected-template
  • value: InputValue
Use to customize how the selected value is displayed in the unopened Listbox. value is the currently selected value.
selected-multiple-template
  • value: InputValue
Use to customize how the selected values are displayed when multiple is true. value is the currently selected value.
option-template
  • option: string | Record<string, unknown>
  • selected: boolean
Use to customize how the options are displayed when the dropdown is opened. option is the current option, selected is a boolean indicating whether the option is currently selected.
bottom
  • errorMessage: string
  • valid: boolean
  • touched: boolean
Use to input the content at the bottom of the dropdown. errorMessage is the validation error message. valid is a boolean indicating whether the dropdown value is valid. touched is a boolean indicating whether the dropdown has been touched.