V0.5.0 · Now Available

The Select component
built for Next.js

Accessible, SSR-safe, fully customizable. Single & multi-select, async loading, custom components — all in a tiny, tree-shakeable bundle.

1. Install
$npm install react-next-select
2. Import styles (once) in App.js/App/jsx or Page.js/Page.jsx or any other file
JSimport 'react-next-select/style.css'
⚡

SSR-Safe

Hydration-friendly. Works seamlessly with Next.js App Router & Pages Router.

♿

Accessible

Full keyboard navigation, ARIA roles, and screen-reader announcements out of the box.

🎨

Customizable

Style every part via the `styles` prop, or replace components entirely.

🍃

Lightweight

No heavy dependencies. Tree-shakeable ESM build for tiny bundles.

🎨 Theme Studio

Pick a color, see it live

Every Select on this page updates instantly. Powered by a single CSS variable.

#a78bfargb(167, 139, 250)
:root {
  --rns-accent: 167 139 250;
}

💡 Scroll down — every Select below uses this color too.

🌈 New in 0.5 · Color props

One prop, every state colored

color="purple" tints the background, border, hover glow, focus ring, selected option and chips, each at its own opacity. Per Select, no CSS needed.

color — 19 presets
"purple"
variant — 10 styles
size
Live preview — hover, focus, open
<Select
  options={options}
  color="purple"
  showCheckmark
/>
Every preset, side by side
🎛️ Props Playground

Toggle every option, live

Mix and match props — the live preview and snippet below update as you go.

Props
menuPlacement
placeholder
menuSearchPlaceholder
colornot set
variant
size
radiusdefault
maxSelected
options
debounceMs
Per-part colors
bgColornot set
borderColornot set
focusColornot set
textColornot set
placeholderColornot set
menuBgColornot set
optionHoverColornot set
optionSelectedColornot set
chipColornot set
Live Preview
Generated JSX
<Select
  options={options}
  value={value}
  onChange={setValue}
  isClearable
/>
Live Demos

Try it yourself

Every variant is fully interactive. Click around — keyboard works too.

SingleSearchable

Single · Searchable · Clearable

The classic dropdown. Search to filter, click ✕ to clear.

<Select
  options={options}
  value={value}
  onChange={setValue}
  isClearable
  showMenuSearchInput
  placeholder="Pick a bundler…"
/>
MultiChips

Multi-select

Pick many. Menu stays open while you keep selecting.

<Select
  options={options}
  value={value}
  onChange={setValue}
  isMulti
  isClearable
  closeMenuOnSelect={false}
/>
MultiSearch inside

Multi with in-menu search

A dedicated search field lives inside the menu — great for long lists.

<Select
  options={options}
  isMulti
  showMenuSearchInput
  menuSearchPlaceholder="Search options..."
/>
AsyncDebounced

Async options

Fetch options from anywhere — APIs, databases, anything Promise-based. debounceMs waits for a pause in typing, so you get one request instead of one per keystroke.

<Select
  loadOptions={async (input) => {
    const res = await fetch(`/api/search?q=${input}`)
    return res.json()
  }}
  defaultOptions
  debounceMs={300}
/>
Custom UIComponents

Custom Option component

Swap in your own Option renderer. Show avatars, badges, anything.

<Select
  options={options}
  components={{ Option: MyOption }}
/>
Custom IcondropdownIcon

Custom dropdown icon

Swap the chevron without writing a full component. Pass a string, a ReactNode, or a function that receives { isOpen }. The 180° rotation animates automatically.

<Select
  options={options}
  dropdownIcon={
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth="3"
      strokeLinecap="round" strokeLinejoin="round">
      <polyline points="6 9 12 15 18 9" />
    </svg>
  }
/>
NewGroups

Grouped options

Pass { label, options } items. Search filters inside each group and arrow keys flow across them.

const options = [
  { label: 'UI libraries', options: [
    { value: 'react', label: 'React' }, ...
  ]},
  { label: 'Bundlers', options: [...] },
]

<Select options={options} isMulti showCheckmark color="sky" />
NewDisabled options

Disabled options

Set isDisabled on an option (or pass isOptionDisabled). It's greyed out, can't be clicked, and the keyboard skips it.

const options = [
  { value: 'free', label: 'Free' },
  { value: 'team', label: 'Team — coming soon', isDisabled: true },
  ...
]

<Select options={options} color="amber" variant="filled" />
NewValidation

Error state

isInvalid switches to a danger border and ring and sets aria-invalid. Open and close without picking to see it.

<Select
  options={countries}
  value={country}
  onChange={setCountry}
  onMenuClose={() => setTouched(true)}
  isInvalid={touched && !country}
/>
NewColor props

Every color, your call

Set individual parts with bgColor, borderColor, focusColor, textColor, menuBgColor, optionHoverColor, optionSelectedColor, chipColor and radius.

<Select
  options={options}
  color="orange"            // hover, scrollbar, icons
  bgColor="#fff7ed"
  borderColor="#fdba74"
  focusColor="#ea580c"
  textColor="#7c2d12"
  placeholderColor="#c2410c"
  menuBgColor="#fff7ed"
  optionHoverColor="#ffedd5"
  optionSelectedColor="#fed7aa"
  radius={8}
  style={{ '--rns-muted': '#9a3412' }} // any --rns-* token
/>
NewCreatable

Create new options

isCreatable offers “Create …” when the text matches nothing. Handle it with onCreateOption, or let the Select pick the new option itself.

<Select
  options={tags}
  value={value}
  onChange={setValue}
  isMulti
  isCreatable
  onCreateOption={(text) => {
    const tag = { value: text, label: text }
    setTags((t) => [...t, tag])
    setValue((v) => [...v, tag])
  }}
/>
NewSelect allLimit

Select all + max limit

showSelectAll adds a Select all / Clear all row (it respects the search). maxSelected disables the rest once the limit is hit.

0 / 5 selected
<Select
  options={options}
  isMulti
  showSelectAll
  maxSelected={5}
  showCheckmark
/>
NewIconsHighlight

Icons, descriptions & match highlight

Give an option an icon and a description and they render automatically. highlightMatch underlines what you typed.

const options = [
  { value: 'card', label: 'Credit card',
    icon: '💳', description: 'Visa, Mastercard, Amex' },
  ...
]

<Select options={options} highlightMatch showCheckmark />
NewPortal

Menu portal

Inside an overflow: hidden box (a modal, a table cell) the menu gets cut off. menuPortalTarget renders it into document.body instead.

Without portal
menuPortalTarget
<Select
  options={options}
  menuPortalTarget={document.body}
/>
SimpleDefaults

Plain & minimal

Drop it in with zero config — sensible defaults, accessible from day one.

<Select options={options} onChange={setValue} />
📜 Changelog

Version History

What changed in each release — newest at the top.

v0.5.0● LatestOct 2026featurefix

Color props, creatable, select all, portal & more

  • `isCreatable` — offer “Create …” for new text; handle it with `onCreateOption` or let the Select pick it. Customize with `formatCreateLabel`, `isValidNewOption`, `getNewOptionData`.
  • `showSelectAll` (Select all / Clear all, respects the search) and `maxSelected` for multi-select.
  • `highlightMatch` underlines the typed text in option labels; `icon` and `description` on an option render automatically.
  • `menuPortalTarget` renders the menu into another element (e.g. `document.body`) so modals and `overflow: hidden` parents can't clip it.
  • `debounceMs` for async search — one request after typing pauses instead of one per keystroke.
  • Fix: multi-select keeps focus after picking an option, so arrow keys / Enter / Escape keep working (`blurInputOnSelect` now defaults to `!isMulti`).
  • Fix: narrow Selects no longer wrap the input onto a second row.
  • Test suite (Vitest + Testing Library, 70 tests) and GitHub Actions CI.
  • `color` prop — 19 presets (`purple`, `emerald`, `rose`, …) or any hex / rgb() / hsl() value. Border, hover glow, focus ring, selected option, chips and scrollbar all retint, and the control gets a soft tinted background.
  • Per-part color props: `bgColor`, `borderColor`, `focusColor`, `textColor`, `placeholderColor`, `menuBgColor`, `optionHoverColor`, `optionSelectedColor`, `chipColor`, plus `radius`.
  • `variant` prop — 10 styles: `outline` (default), `filled`, `flushed`, `ghost`, `solid` (accent fill, white text at 4.5:1+), `elevated`, `glass`, `gradient` (two-stop gradient border), `glow`, `pill`. `size` prop — `sm`, `md` (default), `lg`.
  • Props Playground now covers every prop — color presets, all variants, size, radius, per-part colors, creatable, select all, max limit, portal, grouped / icon datasets, async + debounce.
  • Grouped options — pass `{ label, options: [...] }`. Search filters inside groups and the keyboard moves across them. New `GroupHeading` component slot.
  • Disabled options via `option.isDisabled` or a custom `isOptionDisabled` — greyed out, unclickable, and skipped by Arrow / Home / End.
  • `isInvalid` error state (danger border + ring, `aria-invalid`) and `showCheckmark` for a ✓ on selected options.
  • Fix: `menuPlacement="auto"` was typed but not implemented — it now opens the menu upward when there isn't room below.
  • Hover effect on the control (accent border, faint tint, soft glow). New `getThemeVars()` and `colorPresets` exports to theme a whole section at once.
v0.4.0Aug 2026feature

TypeScript types & npm discoverability

  • Ships hand-written type definitions (`dist/index.d.ts`) — `Select<Option>` is now generic, with typed `SelectProps`, `SelectOption`, `SelectComponents`, and `SelectStyles`. No `@types/react-next-select` needed.
  • Wired `types` and `exports["."].types` in `package.json` so editors resolve types automatically.
  • Added `repository`, `homepage`, and `bugs` fields to `package.json` for npm quality/discoverability scoring.
  • Expanded npm keywords (`react-component`, `custom-select`, `select-dropdown`, `typescript`, etc.) for better search ranking.
  • New `npm run typecheck` script, run automatically before publish.
v0.3.1Jun 2026featurefix

Demo-parity default styles

  • Default control now matches the demo look out of the box — 44px height, 10px radius, accent-tinted borders, soft focus glow.
  • Premium menu shadow + 10px radius; rounded option pills with margin (hover/focus look like the demo).
  • Multi-value chip background bumped to 25% accent + 35% accent border for clear visibility on dark themes.
  • Scoped scrollbar styling on `.rns__menu-list` (accent thumb, transparent track) — no more browser-default thick gray bar.
  • Clear (×) and multi-value remove (×) replaced with crisp SVG icons that align perfectly with the chevron.
  • Indicators standardized to 32×32 fixed boxes so the clear and dropdown buttons are pixel-aligned.
  • New `rns__option--focused` and `rns__option--selected` class hooks for keyboard-nav and selection styling.
  • New `--rns-control-min-height` and `--rns-menu-max-height` CSS variables; `--rns-radius` default bumped from 6px → 10px.
  • Menu max-height bumped 240px → 320px so more options fit without partial-row cuts at the bottom.
  • Auto-elevated wrapper (`z-index: 100` when menu is open) so the dropdown escapes parent stacking contexts created by `backdrop-filter`, `transform`, or `opacity` — no more siblings overlapping the menu.
  • Smooth 0.15s–0.2s transitions on borders, backgrounds, colors, and shadows everywhere.
v0.2.1Jun 2026feature

Themable via CSS variables

  • New `--rns-accent`, `--rns-border`, `--rns-bg`, `--rns-text`, `--rns-muted`, `--rns-radius` tokens.
  • One-line theming — override `--rns-accent: 167 139 250` on `:root` and the whole control retints.
  • Multi-value chips, focus ring, and selected option now derive from theme tokens.
  • Default stylesheet refactored with sensible fallbacks — no breaking change for existing users.
v0.1.2May 2026featuredemo

Custom dropdown icon

  • `dropdownIcon` prop accepts a string, JSX element, or render function — wrapper handles 180° open/close rotation automatically.
  • Redesigned demo site with hero, features grid, Theme Studio, and Props Playground.
  • Netlify deploy config added.
v0.1.1Apr 2026fixdemo

Polish & demo enhancements

  • Animated fixed navigation bar that drops in on scroll.
  • Scroll-to-top button.
  • Stability fixes for menu placement and outside-click handling.
v0.1.0Mar 2026release

Initial release

  • Single and multi-select with chip rendering.
  • Synchronous and async options with race-safe loader.
  • Searchable dropdown — inline or dedicated in-menu search input.
  • Full keyboard navigation (Arrow / Home / End / Enter / Esc / Tab) with ARIA combobox semantics.
  • SSR-safe — works out of the box with Next.js App Router and Pages Router.
  • Hidden `<input name>` for native `<form>` submission.
Last Updated
—
Total Hits
···
Total Visitors
···
npm Downloads
···