https://github.com/lcvriend/wc-multi-selector
Web component that lets a user select multiple options from an arbitrarily nestable hierarchy within a drop-down menu
https://github.com/lcvriend/wc-multi-selector
js keyboard-navigation multiselect nestable omnibox searchable-dropdown vanilla-js web-component
Last synced: about 1 month ago
JSON representation
Web component that lets a user select multiple options from an arbitrarily nestable hierarchy within a drop-down menu
- Host: GitHub
- URL: https://github.com/lcvriend/wc-multi-selector
- Owner: lcvriend
- License: gpl-3.0
- Created: 2022-11-20T13:00:56.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-02-04T16:08:00.000Z (over 1 year ago)
- Last Synced: 2025-03-11T00:12:33.967Z (over 1 year ago)
- Topics: js, keyboard-navigation, multiselect, nestable, omnibox, searchable-dropdown, vanilla-js, web-component
- Language: JavaScript
- Homepage: https://lcvriend.github.io/wc-multi-selector/
- Size: 72.3 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Multi-Selector Web Component
A lightweight, accessible web component for selecting multiple options from hierarchical data structures. Built with vanilla JavaScript and no external dependencies. Check out [this page](https://lcvriend.github.io/wc-multi-selector/) for several examples.

## Features
- **Hierarchical Data**: Support for arbitrarily nested option groups
- **Multiple Data Sources**: Load from JSON or define options in HTML markup
- **Advanced Search**: Filter by labels or values with instant results
- **Keyboard Navigation**: Full keyboard accessibility with intuitive shortcuts
- **Form Integration**: Native form participation with proper validation
- **Adaptive Theming**: Automatic dark/light mode detection with custom styling
- **Accessibility**: WCAG compliant with proper ARIA attributes and focus management
## Quick Start
```html
Red
Blue
Green
Guitar
Violin
Flute
Trumpet
```
## Installation
Simply include the JavaScript file in your HTML:
```html
```
The component automatically registers itself as ``.
## Data Structure
### JSON Format
Each option should follow this structure:
```json
{
"label": "Display Text", // Optional - falls back to value
"value": "unique_id", // Required
"selected": false, // Optional - preselect option
"children": [] // Optional - for nested groups
}
```
### Simplified Formats
The component automatically converts simpler formats:
```json
// Flat array
["Option 1", "Option 2", "Option 3"]
// Nested object
{
"Group A": ["Item 1", "Item 2"],
"Group B": ["Item 3", "Item 4"]
}
```
## API Reference
### Attributes
| Attribute | Type | Description |
|---------------|-------------------|-------------|
| `src` | string | URL to JSON data source |
| `name` | string | Form field name |
| `placeholder` | string | Text shown when no selections made |
| `disabled` | boolean | Disable the component |
| `mode` | "light" \| "dark" | Force theme mode (auto-detects if not set) |
### Properties
| Property | Type | Description |
|------------------|--------|-------------|
| `data` | Array | Get/set the options data |
| `selectedValues` | Array | Array of currently selected values |
| `selectedLabels` | Array | Array of currently selected labels |
| `settings` | Object | Component configuration options |
### Methods
| Method | Parameters | Description |
|--------------------------|------------|-------------|
| `addSelectedValues()` | ...values | Add values to selection |
| `removeSelectedValues()` | ...values | Remove values from selection |
### Events
| Event | Detail | Description |
|----------|----------------------------|-------------|
| `change` | `{detail: selectedValues}` | Fired when selection changes |
## Keyboard Shortcuts
### Navigation
- `↑` `↓` `←` `→` - Navigate options
- `Home` / `End` - Jump to first/last option
- `Tab` - Standard tab navigation
- `Esc` - Close dropdown
### Filtering & Folding
- `Ctrl` + `\` - Show only selected items
- `Ctrl` + `/` - Clear search filter
- `Ctrl` + `[` - Fold all groups
- `Ctrl` + `]` - Unfold all groups
## Styling
### CSS Custom Properties
The component uses CSS custom properties for theming:
```css
multi-selector {
/* Layout */
--ms-height: calc(2rem + var(--ms-padding-block));
--ms-max-height: 60vh;
--ms-padding-block: .25em;
--ms-padding-inline: 1em;
--ms-border-radius: 5px;
/* Colors */
--ms-text-color: inherit;
--ms-border-color: currentColor;
--ms-dropdown-background: hsl(0, 0%, 100%);
--ms-hover: hsl(0, 0%, 93%);
}
```
### Shadow Parts
Use `::part()` selectors for structural styling:
```css
multi-selector::part(container) {
border-width: 2px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
multi-selector::part(dropdown) {
background: var(--custom-background);
}
```
Available parts:
- `container` - Main dropdown container
- `display` - Selected items display
- `controls` - Control button panel
- `dropdown` - Dropdown content area
- `filter` - Search section
- `options` - Options container
## Form Integration
The component participates in forms like native controls:
```html
Submit
```
Form data is submitted as a JSON string of selected values.
## Advanced Usage
### Dynamic Data Management
```javascript
const selector = document.querySelector('multi-selector')
// Set data programmatically
selector.data = [
{ label: "Option 1", value: "opt1" },
{ label: "Option 2", value: "opt2" }
]
// Listen for changes
selector.addEventListener('change', event => {
console.log('Selected:', event.detail)
})
// Programmatically select options
selector.addSelectedValues('opt1', 'opt2')
```
### Custom Settings
```javascript
selector.settings = {
labels: {
placeholder: "Choose items...",
filter: {
placeholder: "Type to search..."
}
},
titles: {
unfoldGroups: "Expand all groups",
showSelected: "Show selected only"
}
}
// Extend defaults
MultiSelector.defaultSettings.labels.all = "Alle items"
```
## Alternatives
- [BVSelect](https://bmsvieira.github.io/BVSelect-VanillaJS/)
- [vanilla-select](https://vorotina.github.io/vanilla-select/)
- [multiselect-combo-box](https://multiselect-combo-box.web.app/)