npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bs-searchable-select

v1.0.0

Published

A searchable select dropdown component for Bootstrap 5 — zero framework dependencies.

Downloads

105

Readme

bs-searchable-select

A searchable select dropdown component for Bootstrap 5 — zero framework dependencies. Just include Bootstrap CSS, add the script, and go.

Bootstrap Vanilla JS License

Features

  • Search & Filter — Case-insensitive substring matching across all option labels
  • Custom Values — Optionally allow users to type values not in the list
  • Clearable — One-click clear button (can be disabled)
  • Keyboard Navigation — Arrow keys, Enter to select, Escape to close
  • Programmatic APIgetValue(), setValue(), addOption(), removeOption(), clearSelection(), and more
  • Data-Attribute Init — Configure entirely in HTML with data-bss-* attributes
  • Custom Eventsbss.change, bss.show, bss.hide, bss.clear on the container element
  • Styling — Inline colour props, CSS class overrides, or automatic Bootstrap theme integration
  • Validation — Built-in is-invalid support for Bootstrap form validation
  • Dark Mode — Inherits Bootstrap's data-bs-theme automatically
  • Accessible — ARIA combobox / listbox roles, keyboard support

Installation

CDN (quickest)

<!-- CSS (after Bootstrap CSS) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bs-searchable-select@1/dist/bs-searchable-select.min.css">

<!-- JS (after Bootstrap JS, or standalone) -->
<script src="https://cdn.jsdelivr.net/npm/bs-searchable-select@1/dist/bs-searchable-select.min.js"></script>

npm

npm install bs-searchable-select
// ES module
import BsSearchableSelect from 'bs-searchable-select';
import 'bs-searchable-select/dist/bs-searchable-select.css';

// CommonJS
const BsSearchableSelect = require('bs-searchable-select');

Manual

Copy dist/bs-searchable-select.min.js and dist/bs-searchable-select.min.css into your project and include them in your HTML.

Quick Start

JavaScript

<div id="my-select"></div>

<script>
var select = new BsSearchableSelect('#my-select', {
    options: [
        { value: 'apple',  label: 'Apple' },
        { value: 'banana', label: 'Banana' },
        { value: 'cherry', label: 'Cherry' }
    ],
    placeholder: 'Select a fruit...',
    onChange: function (value, option) {
        console.log('Selected:', value);
    }
});
</script>

Data Attributes (no JS required)

<div data-bss-toggle="searchable-select"
     data-bss-placeholder="Pick a fruit..."
     data-bss-options='[
         {"value":"apple","label":"Apple"},
         {"value":"banana","label":"Banana"},
         {"value":"cherry","label":"Cherry"}
     ]'>
</div>

Elements with data-bss-toggle="searchable-select" are automatically initialised on DOMContentLoaded. Listen for events via the DOM:

document.getElementById('my-select')
    .addEventListener('bss.change', function (e) {
        console.log('Selected:', e.detail.value);
    });

Configuration

Pass these as the second argument to new BsSearchableSelect(el, config), or as data-bss-* attributes in HTML.

| Option | Type | Default | Description | |--------|------|---------|-------------| | options | Array<{ value, label }> | [] | Array of selectable options | | value | any | null | Initially selected value | | placeholder | string | 'Select...' | Placeholder text | | maxDropdownHeight | number | 200 | Max dropdown height in pixels | | allowCustomValue | boolean | false | Allow values not in the options list | | disabled | boolean | false | Disable the component | | clearable | boolean | true | Show/hide the clear (×) button | | invalid | boolean | false | Apply Bootstrap .is-invalid styling | | activeBackgroundColor | string | — | Background colour of the selected item | | activeTextColor | string | — | Text colour of the selected item | | activeClassName | string | — | CSS class for the selected item (overrides inline styles) | | inactiveBackgroundColor | string | — | Background colour for unselected items | | inactiveTextColor | string | — | Text colour for unselected items | | inactiveClassName | string | — | CSS class for unselected items (overrides inline styles) | | onChange | function(value, option) | — | Callback on selection change; receives (null, null) on clear |

Data-attribute mapping

Prefix every option with data-bss- and use kebab-case:

<div data-bss-toggle="searchable-select"
     data-bss-placeholder="Pick…"
     data-bss-allow-custom-value="true"
     data-bss-clearable="false"
     data-bss-max-dropdown-height="300"
     data-bss-options='[{"value":"a","label":"A"}]'>
</div>

Methods

All methods are available on the instance returned by new BsSearchableSelect(...).

| Method | Returns | Description | |--------|---------|-------------| | getValue() | any | Current value (selected option value or custom text) | | setValue(value) | void | Programmatically select a value | | isCustomValue() | boolean | true if the current value is not from the options list | | getInputText() | string | Raw text currently shown in the input | | clearSelection() | void | Clear the selection | | addOption({ value, label }) | void | Add an option (duplicates ignored) | | removeOption(value) | void | Remove an option; clears selection if it was active | | setOptions(options) | void | Replace the entire options list | | getOptions() | Array | Get a copy of the current options list | | enable() | void | Enable the component | | disable() | void | Disable the component | | setInvalid(bool) | void | Toggle Bootstrap .is-invalid styling | | dispose() | void | Tear down: unbind events, remove DOM, clean up |

Static Methods

| Method | Description | |--------|-------------| | BsSearchableSelect.initAll() | Initialise all [data-bss-toggle="searchable-select"] elements | | BsSearchableSelect.getInstance(el) | Retrieve existing instance from a container element | | BsSearchableSelect.fromDataAttributes(el) | Create instance from an element's data-bss-* attributes |

Events

Custom DOM events are dispatched on the container element:

| Event | e.detail | Description | |-------|------------|-------------| | bss.change | { value, option } | Selection changed | | bss.show | {} | Dropdown opened | | bss.hide | {} | Dropdown closed | | bss.clear | {} | Selection cleared |

document.querySelector('#my-select')
    .addEventListener('bss.change', function (e) {
        console.log('New value:', e.detail.value);
        console.log('Option object:', e.detail.option); // null if custom
    });

Examples

Custom Values

var select = new BsSearchableSelect('#el', {
    options: myOptions,
    allowCustomValue: true,
    placeholder: 'Select or type…'
});

// Later:
select.getValue();       // the selected/typed value
select.isCustomValue();  // true if the user typed something not in the list

Inline Colour Styling

new BsSearchableSelect('#el', {
    options: myOptions,
    activeBackgroundColor: '#198754',
    activeTextColor: '#fff',
    inactiveBackgroundColor: '#f8f9fa',
    inactiveTextColor: '#333'
});

CSS Class Styling

new BsSearchableSelect('#el', {
    options: myOptions,
    activeClassName: 'my-active',
    inactiveClassName: 'my-inactive'
});
.my-active {
    background-color: #6f42c1 !important;
    color: #fff !important;
    border-left: 3px solid #4a2a8a;
}
.my-inactive:hover {
    background-color: #e9ecef;
}

Form Validation

var select = new BsSearchableSelect('#el', {
    options: myOptions,
    invalid: true
});

// Clear invalid when a value is selected
document.querySelector('#el').addEventListener('bss.change', function (e) {
    if (e.detail.value) select.setInvalid(false);
});

Non-Clearable

new BsSearchableSelect('#el', {
    options: myOptions,
    clearable: false
});

Disabled State

var select = new BsSearchableSelect('#el', {
    options: myOptions,
    disabled: true,
    value: 'banana'
});

// Toggle at runtime
select.enable();
select.disable();

Dynamic Options

var select = new BsSearchableSelect('#el', {
    options: []
});

// Fetch from API and populate
fetch('/api/items')
    .then(function (r) { return r.json(); })
    .then(function (data) {
        select.setOptions(data.map(function (d) {
            return { value: d.id, label: d.name };
        }));
    });

Bootstrap Theme Integration

The active item uses Bootstrap's --bs-primary CSS variable by default. If you customise $primary in your Bootstrap SCSS, the component picks it up automatically. The component also inherits Bootstrap's dark mode (data-bs-theme="dark") with no extra configuration.

Demo

Open index.html in a browser to see all features in action — no build step required.

# Or use a local server:
npx serve .

Building

To generate minified dist files:

npm install
npm run build

This produces:

  • dist/bs-searchable-select.js — unminified copy
  • dist/bs-searchable-select.min.js — minified
  • dist/bs-searchable-select.css — unminified copy
  • dist/bs-searchable-select.min.css — minified

License

MIT © Hussein Al Bayati