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

@xsolla/xui-select

v0.185.1

Published

A cross-platform React select component for choosing from a list of predefined options with dropdown menu. Works on both React (web) and React Native. <!-- BEGIN:xui-mcp-instructions:select --> A Select lets users choose a single value from a predefined l

Readme

Select

A cross-platform React select component for choosing from a list of predefined options with dropdown menu. Works on both React (web) and React Native.

A Select lets users choose a single value from a predefined list of options. It is commonly used in forms, filters, settings, and toolbars where the set of valid choices is known in advance.

When to use

When the user must pick exactly one value from a fixed, mutually exclusive list (country, currency, status, etc.)

  • When the list of options is known, finite, and does not require typing
  • When vertical space is limited and showing every option (as with radio buttons) would be too large
  • As part of a larger form alongside other controls

When not to use

  • When the user can choose more than one value — use a MultiSelect instead
  • When the list is long or the user benefits from typing to filter — use an Autocomplete instead
  • When the value is freeform text the user must type — use a TextArea instead
  • When there are only two or three options that should always stay visible — use Radio buttons or a Segmented instead
  • When the choice is a simple on/off — use a Switch or Checkbox instead
  • When the value is time or date — use an InputTime or DatePicker instead

Content guidelines

Label each option clearly and concisely — one short phrase, no trailing punctuation.

Use parallel structure across all options in the same group (all nouns, or all short phrases).

Use Description to add clarifying context when the label alone is not sufficient.

List options in a logical order — most common first, alphabetical, or by value.

Avoid negative options (e.g. "Do not notify me") — rephrase positively.

Behaviour guidelines

Only one radio in a group can be checked at a time — selecting one automatically unchecks the others.

A radio cannot be unchecked by clicking it again. To clear a selection, a "None" or "Reset" option must be provided explicitly.

Disable items remain visible but cannot be interacted with.

The Error state is typically applied to all items in the group (or to the group container) when validation fails — not to individual items.

Accessibility

Wrap the group in a with a that names the group, or use role="radiogroup" with aria-labelledby.

Each radio input should use role="radio" with aria-checked="true" or "false".

Apply aria-disabled="true" to disabled items.

Error messages should be linked to the group via aria-describedby.

Never rely on color alone to communicate the error state — always show the error message text.

Installation

npm install @xsolla/xui-select

Demo

Basic Select

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function BasicSelect() {
  const [value, setValue] = React.useState("");

  return (
    <Select
      value={value}
      onChange={setValue}
      options={["Option 1", "Option 2", "Option 3"]}
      placeholder="Select an option"
    />
  );
}

Select with Label

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function LabeledSelect() {
  const [country, setCountry] = React.useState("");

  return (
    <Select
      label="Country"
      value={country}
      onChange={setCountry}
      options={[
        "United States",
        "Canada",
        "United Kingdom",
        "Germany",
        "France",
      ]}
      placeholder="Select a country"
    />
  );
}

Select with Object Options

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function ObjectOptionsSelect() {
  const [status, setStatus] = React.useState("");

  const options = [
    { label: "Active", value: "active" },
    { label: "Pending", value: "pending" },
    { label: "Inactive", value: "inactive" },
  ];

  return (
    <Select
      label="Status"
      value={status}
      onChange={setStatus}
      options={options}
      placeholder="Select status"
    />
  );
}

Select Sizes

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function SelectSizes() {
  const options = ["Small", "Medium", "Large"];

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
      <Select size="xs" options={options} placeholder="Extra Small" />
      <Select size="sm" options={options} placeholder="Small" />
      <Select size="md" options={options} placeholder="Medium (default)" />
      <Select size="lg" options={options} placeholder="Large" />
      <Select size="xl" options={options} placeholder="Extra Large" />
    </div>
  );
}

Select with Icons

import * as React from "react";
import { Select } from "@xsolla/xui-select";
import { Globe } from "@xsolla/xui-icons-base";

export default function SelectWithIcons() {
  return (
    <Select
      iconLeft={<Globe />}
      options={["English", "Spanish", "French", "German"]}
      placeholder="Select language"
    />
  );
}

Anatomy

Import the component and use it directly:

import { Select } from "@xsolla/xui-select";

<Select
  label="Field Label" // Optional label above select
  value={value} // Controlled selected value
  onChange={setValue} // Value change handler
  options={["A", "B", "C"]} // Array of options (strings or objects)
  placeholder="Select..." // Placeholder text
  iconLeft={<Icon />} // Optional left icon
  iconRight={<Icon />} // Optional right icon (default: ChevronDown)
  filled // Whether to show filled background
  state="error" // State: "default" | "disable" | "error"
  errorMessage="Error message" // Error message (shown when state="error")
/>;

Examples

Error State

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function ErrorSelect() {
  return (
    <Select
      label="Required Field"
      state="error"
      errorMessage="Please select an option"
      options={["Option 1", "Option 2", "Option 3"]}
      placeholder="Select an option"
    />
  );
}

Disabled Select

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function DisabledSelect() {
  return (
    <Select
      label="Disabled Field"
      value="Option 1"
      state="disable"
      options={["Option 1", "Option 2", "Option 3"]}
    />
  );
}

Unfilled/Transparent Background

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function UnfilledSelect() {
  return (
    <Select
      filled={false}
      options={["Option 1", "Option 2", "Option 3"]}
      placeholder="Transparent background"
    />
  );
}

Icon Only Select

import * as React from "react";
import { Select } from "@xsolla/xui-select";
import { Settings } from "@xsolla/xui-icons";

export default function IconOnlySelect() {
  return (
    <Select
      iconOnly
      iconLeft={<Settings />}
      options={["Settings", "Preferences", "Advanced"]}
    />
  );
}

Full Width Select

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function FullWidthSelect() {
  return (
    <div style={{ display: "flex", gap: 16 }}>
      <Select
        fullWidth
        options={["Option 1", "Option 2", "Option 3"]}
        placeholder="Stretches to fill container"
      />
      <Select
        fullWidth={false}
        options={["Option 1", "Option 2", "Option 3"]}
        placeholder="Intrinsic width"
      />
    </div>
  );
}

Custom Popover Width

By default the dropdown popover matches the trigger width. Use popoverWidth to size the popover independently — handy when option labels are wider than the field. Pass a number (pixels) or any CSS width string.

import * as React from "react";
import { Select } from "@xsolla/xui-select";

export default function CustomPopoverWidth() {
  return (
    <div style={{ width: 200 }}>
      <Select
        popoverWidth={320}
        options={[
          "Account overview and billing details",
          "Subscription management",
          "Payment history and transactions",
        ]}
        placeholder="Custom popover width"
      />
    </div>
  );
}

Form with Select

import * as React from "react";
import { Select } from "@xsolla/xui-select";
import { Input } from "@xsolla/xui-input";
import { Button } from "@xsolla/xui-button";

export default function FormWithSelect() {
  const [form, setForm] = React.useState({
    name: "",
    category: "",
    priority: "",
  });

  return (
    <div
      style={{ display: "flex", flexDirection: "column", gap: 16, width: 300 }}
    >
      <Input
        label="Task Name"
        value={form.name}
        onChangeText={(name) => setForm((prev) => ({ ...prev, name }))}
        placeholder="Enter task name"
      />
      <Select
        label="Category"
        value={form.category}
        onChange={(category) => setForm((prev) => ({ ...prev, category }))}
        options={["Development", "Design", "Marketing", "Sales"]}
        placeholder="Select category"
      />
      <Select
        label="Priority"
        value={form.priority}
        onChange={(priority) => setForm((prev) => ({ ...prev, priority }))}
        options={[
          { label: "High", value: "high" },
          { label: "Medium", value: "medium" },
          { label: "Low", value: "low" },
        ]}
        placeholder="Select priority"
      />
      <Button>Create Task</Button>
    </div>
  );
}

Dropdown Positioning

By default the dropdown always opens on the side (default "bottom"). Pass autoFlip to let it flip to the opposite side when there isn't enough viewport space.

import * as React from "react";
import { Select } from "@xsolla/xui-select";

const options = ["Option 1", "Option 2", "Option 3"];

// Always opens below (default — no surprises for existing layouts)
<Select options={options} placeholder="Default" />

// Always opens above
<Select side="top" options={options} placeholder="Opens above" />

// Opens below, flips above when near the bottom of the viewport
<Select autoFlip options={options} placeholder="Auto-flip enabled" />

// Opens above, flips below when near the top of the viewport
<Select side="top" autoFlip options={options} placeholder="Prefers top, flips if needed" />

API Reference

Select

The main select component. Renders a button trigger with dropdown menu.

Select Props:

| Prop | Type | Default | Description | | :---------------- | :-------------------------------------------------------- | :---------------- | :------------------------------------------------------------------------------------------------------------ | | testID | string | — | Test ID for testing frameworks. On web this renders as data-testid; on React Native it renders as testID. | | value | string | - | The controlled selected value. | | placeholder | string | "Select" | Placeholder text when no value selected. | | onPress | () => void | - | Callback when select trigger is pressed. | | size | "xl" \| "lg" \| "md" \| "sm" \| "xs" | "md" | The size of the select. | | state | "default" \| "hover" \| "focus" \| "disable" \| "error" | "default" | The visual state of the select. | | label | string | - | Label text displayed above the select. | | disabled | boolean | false | Whether the select is disabled. Also triggered when state="disable". | | errorMessage | string | - | Error message displayed below the select (also sets error styling). | | iconLeft | ReactNode | - | Icon displayed on the left side. | | iconRight | ReactNode | <ChevronDown /> | Icon displayed on the right side. | | filled | boolean | true | Whether to show filled background. | | iconOnly | boolean | false | Whether to show only icon without text. | | options | (string \| SelectOption)[] | [] | Array of options to display. | | onChange | (value: string) => void | - | Callback when value changes. | | searchable | boolean | false | Whether to show a search input in the dropdown. | | searchPlaceholder | string | "Search" | Placeholder text for the search input. | | noOptionsMessage | string | "No results" | Message shown when no options match the search. | | clearable | boolean | false | Show a clear button to reset the selected value (field variant only). | | onClear | () => void | - | Callback when the clear button is pressed. | | maxHeight | number | 300 | Maximum height of the dropdown in pixels. | | popoverWidth | number \| string | "100%" | Width of the dropdown popover/menu. Defaults to the trigger width; pass a number (px) or CSS width string to size it independently of the trigger. | | fullWidth | boolean | true | Whether the select should stretch to fill the full width of its container. | | overlayThemeMode | ThemeMode | themeMode | Theme mode for the dropdown overlay. | | overlayThemeProductContext | ProductContext | themeProductContext | Product context for the dropdown overlay. | | side | "top" \| "bottom" | "bottom" | Preferred side for the dropdown. | | autoFlip | boolean | false | When true, the dropdown flips to the opposite side when there isn't enough viewport space on the preferred side. |

SelectOption Type:

interface SelectOption {
  label: string; // Display text
  value: any; // Value to be selected
  disabled?: boolean; // Whether this option is disabled
}

React Native Notes

The Select component works on React Native with the following differences:

| Feature | Web | React Native | | --------------------- | ----------------------------- | ----------------------------------- | | Searchable dropdown | Supported (searchable prop) | Not available — prop is ignored | | Dropdown shadow | CSS box-shadow | Android elevation: 4 | | Scroll behavior | overflowY: auto | Native ScrollView | | Cursor styles | pointer / not-allowed | Ignored | | Click-outside dismiss | document.addEventListener | Not active (guarded by isNative) |

Accessibility

  • Trigger has role="combobox", aria-haspopup="listbox", and aria-expanded (updates on open/close)
  • Trigger links to its label via aria-labelledby when the label prop is set
  • Dropdown has role="listbox"; each option has role="option" and aria-selected
  • Disabled trigger and disabled options expose aria-disabled="true"
  • Search input has aria-label matching searchPlaceholder
  • Selected item auto-scrolls into view when the dropdown opens (web only)
  • Disabled state properly communicated to assistive technology