Slim Select 4.0.0
The select dropdown, reimagined — again. v4 adds modal mode for mobile-friendly picking, a faster sync and search engine, tighter CSS variable sizing, and a much larger test suite (523 tests).
Docs: https://slimselectjs.com
Get started: https://slimselectjs.com/get-started
Highlights
Modal mode
- New
settings.modal:'off'|'on'|'mobile'(default:'mobile') - On viewports ≤768px (or always with
'on'), the option panel opens as a centered modal with backdrop, close button, Escape/backdrop dismiss, and body scroll lock - Modal header uses the associated
<label>text oraria-label; override withsettings.modalTitle - Theme with
--ss-modal-height,--ss-modal-width, and--ss-modal-z-index - Skipped when
alwaysOpen: true(inline panels stay inline)
Performance & search
- Local search filters existing DOM nodes in place instead of rebuilding the list each keystroke
- Selection-only updates avoid full native
<select>and dropdown rebuilds - API search results are temporary — clearing search restores the catalog baseline while keeping selection
keepSearch: truere-runs the active query when reopening- Long lists use
content-visibility: auto; dropdown positioning usesResizeObserverinstead of polling
Styling
--ss-search-heightand--ss-option-heightdefault tovar(--ss-main-height)so single, multi, search, and options stay aligned when you customize height- Scrollbars use
--ss-primary-colorand--ss-bg-color(no separate scroll/track variables) prefers-reduced-motionhonored for panel transitions and value chip removal
Quality
- 477 Vitest unit tests + 46 Playwright E2E tests
- Expanded a11y, keyboard, API search, hideSelected, and addable coverage
Install
npm install slim-select@4.0.0import SlimSelect from 'slim-select'
import 'slim-select/styles'Migration guide (3.x → 4.0)
1. Vue & React — options via data prop (breaking)
Native <option> children / slots are no longer supported in the framework wrappers. Pass options explicitly:
<!-- Vue -->
<SlimSelect v-model="selected" :data="options" />// React
<SlimSelect data={options} value={selected} onChange={setSelected} />Same shape as core SlimSelect (text, value, optgroups, etc.).
2. events.search callback signature (breaking if you use extra args)
search: (
searchValue: string,
selected: Option[], // was less clearly typed before
catalog?: (Option | Optgroup)[] // NEW — baseline list when search clears
) => Promise<...> | ...Use catalog to merge API results without losing the original option set. Clearing search restores catalog automatically.
3. Optgroup select-all label (breaking)
selectAllText on optgroups and data-selectalltext on <optgroup> are removed. Labels are always "Select All" or "Unselect All" when every option in the group is selected.
4. Modal default on mobile (behavior change)
modal defaults to 'mobile'. Mobile users get a modal instead of a dropdown unless you opt out:
settings: { modal: 'off' } // previous dropdown-only behavior everywhere5. Custom CSS variables
If you set only --ss-main-height, search and option rows now follow it. Override explicitly if you need different heights:
--ss-main-height: 44px;
--ss-search-height: 40px; /* optional override */
--ss-option-height: 36px; /* optional override */6. Option.data from HTML
Options read from data-* attributes now expose option.data as a plain object, not a live DOMStringMap. Code that relied on DOMStringMap behavior or saw [object DOMStringMap] when stringifying should read properties from option.data directly.
7. Closable optgroups (behavior change)
Closable optgroups act as an accordion — opening one closes other open closable groups (including groups that were open because they contained a selected option).
8. Vanilla JS / core API
No import path changes. slim-select, slim-select/vue, slim-select/react, slim-select/styles, and slim-select/scss are unchanged.
Full changelog
See CHANGELOG.md for the complete list of fixes and internal refactors (sync coordinator, lifecycle scheduler, animation helpers, min/max behavior, and more).