No-frills.

The best? Not sure, but it is definitely easy to use.

No framework I18n ready Keyboard friendly

When you need a richer select without going overboard, Selectamelo adds search, multi, and clear while staying small and dependency-free. It keeps the native select in the DOM so forms keep working, and it remains keyboard-first by default.

No jQuery, no framework, just a light upgrade to the native control. You get disabled and readonly states, clean events, and a UI that stays fast even on short lists.

Standard

Base, simple version.

Base version without search.

Search

Filter fast and handle empty states.

Use ↑ ↓ and Enter to select.

Multi select

Chips with inline removal.

Backspace removes the last chip.

States and accessibility

Selectamelo mirrors native select semantics: disabled, readonly, and live change updates. Here are two common cases.

Disabled

Readonly

Integrate in a minute

Installation

Choose the global build or the package.

npm install selectamelo
import { Selectamelo } from "selectamelo";
<link rel="stylesheet" href="./styles.css" />
<script src="./selectamelo.global.js"></script>

The global build exposes Selectamelo on window.

Minimal HTML

A native select, no custom markup.

<select id="team" data-selectamelo>
  <option value=""></option>
  <option value="design">Design</option>
  <option value="dev">Dev</option>
</select>

Visible placeholder: add an <option value=""></option> at the top.

Init JS

Call create and keep the instance.

const select = document.getElementById("team");
const inst = Selectamelo.create(select, {
  placeholder: "Choose a team",
  allowClear: true,
});

If the select is already initialized, create returns the same instance.

JS options

Parameters passed to create.

Option Type Default Notes
searchable boolean true Enable search.
placeholder string "" Text shown when nothing is selected.
allowClear boolean true Show the X to clear the value.
hideSearch boolean false Hide the search input.
disabled boolean false Disable the select and do not submit the value.
readonly boolean false Lock the UI but still submit the value.
i18n object - UI and accessibility strings.

disabled and readonly can also be changed via API.

Data attributes

Configuration directly in HTML.

Attribute Type Notes
data-selectamelo flag Selector used for batch initialization.
data-allow-clear boolean Show or hide the X.
data-hide-search boolean Hide the search box.
data-searchable boolean Enable or disable search.
data-disabled boolean Disable the native select.
data-readonly boolean Lock the UI without disabling submission.
data-selectamelo-placeholder string Main placeholder.
data-selectamelo-search-placeholder string Search box placeholder.
data-selectamelo-clear-title string X tooltip.
data-selectamelo-clear-aria-label string X aria-label.
data-selectamelo-remove-chip-aria-label string Aria-label for removing a chip.
data-selectamelo-no-results string Text when there are no results.

Booleans: "", true, 1 = true; false, 0 = false.

I18n

UI and accessibility strings.

const inst = Selectamelo.create(select, {
  i18n: {
    placeholder: "Select...",
    searchPlaceholder: "Search...",
    clearTitle: "Clear",
    clearAriaLabel: "Clear selection",
    removeChipAriaLabel: "Remove",
    noResults: "No results",
  },
});
Key Notes
placeholder Default text in the control.
searchPlaceholder Search input placeholder.
clearTitle X title for tooltip.
clearAriaLabel X aria-label.
removeChipAriaLabel Aria-label for chip removal.
noResults Message when the list is empty.

Static API

Methods available on Selectamelo.

const inst = Selectamelo.create(select);
const same = Selectamelo.get(select);
Selectamelo.destroy(select);

destroy restores the original select and removes the wrapper.

Instance methods

Full control via JS.

Method Signature Notes
open () Open the dropdown.
close () Close the dropdown.
setValue (value | value[] | null) Set the selected value.
getValue () Returns string or array.
clearOptions (keepPlaceholder?) Remove all options.
setOptions (options, keepPlaceholder?) Replace the options list.
addOption (option, selectIt?) Add a new option.
removeOption (value) Remove an option.
updateOption (value, patch) Update label or disabled.
upsertOption (option, selectIt?) Create or update an option.
refresh () Recompute label and clear state.
setLoading (isLoading) Temporarily lock the UI.
setDisabled (isDisabled) Disable the native select.
setReadonly (isReadonly) Lock the UI without disabling.
isDisabled () Disabled state.
isReadonly () Readonly state.
destroy () Remove the component and restore the select.

Events

Hooks to integrate external logic.

Event Detail When
zselect:change { value } When the value changes.
zselect:open - When the dropdown opens.
zselect:close - When the dropdown closes.
zselect:search { q } When the search filter changes.
zselect:clear - When the user clears the value.
select.addEventListener("zselect:change", e => {
  console.log("Value:", e.detail.value);
});

Keyboard

Full keyboard navigation.

Key Action
ArrowDown Open and move to the next option.
ArrowUp Open and move to the previous option.
Enter Select the active option.
Escape Close the dropdown.
Tab Close and move focus to the next element.
Backspace In multi, remove the last chip.

Recipes

Multi select

Enable with multiple on the select.

<select id="channels" data-selectamelo multiple>
  <option value=""></option>
  <option value="email">Email</option>
  <option value="sms">SMS</option>
</select>

Backspace removes the last selected chip.

Search on/off

Disable search for short lists.

<select data-selectamelo data-searchable="false"></select>
Selectamelo.create(select, {
  searchable: false,
  hideSearch: true,
});

Dynamic options

Load options from an API and manage loading.

inst.setLoading(true);
fetch("/api/options")
  .then(r => r.json())
  .then(items => {
    inst.setOptions(items, true);
  })
  .finally(() => inst.setLoading(false));

Live API

Dynamic management: setOptions, loading state, and value updates.

Events