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-multi-select

v0.174.3

Published

A cross-platform multi-select control that lets users pick multiple options from a dropdown list.

Downloads

14,638

Readme

MultiSelect

A cross-platform multi-select control that lets users pick multiple options from a dropdown list.

Installation

npm install @xsolla/xui-multi-select

Imports

import { MultiSelect } from "@xsolla/xui-multi-select";
import type {
  MultiSelectProps,
  MultiSelectOption,
  MultiSelectValue,
  MultiSelectVariant,
  MultiSelectSize,
  MultiSelectState,
} from "@xsolla/xui-multi-select";

Quick start

const options = [
  { label: "React", value: "react" },
  { label: "Vue", value: "vue" },
  { label: "Angular", value: "angular" },
];

const [selected, setSelected] = useState<MultiSelectValue>([]);

<MultiSelect
  label="Frameworks"
  options={options}
  value={selected}
  onChange={setSelected}
  placeholder="Select frameworks"
/>;

External panel (B2B grouped select)

When the option list is rendered elsewhere (for example @xsolla/xui-b2b-group-select), set dropdownMenu={false} so the control does not open the built-in list. Wire the same value / onChange to both components; use onTriggerPress to toggle your panel, menuOpen for chevron/open styling, and menuMinWidth (default 540, aligned with GROUP_SELECT_MIN_PANEL_WIDTH) so the field matches the panel width.

import * as React from "react";
import { MultiSelect } from "@xsolla/xui-multi-select";
import {
  GroupSelect,
  GROUP_SELECT_MIN_PANEL_WIDTH,
  type GroupSelectGroup,
} from "@xsolla/xui-b2b-group-select";

const groups: GroupSelectGroup[] = [
  /* ... */
];
const flatOptions = groups.flatMap((g) =>
  g.items.map((it) => ({ value: it.id, label: it.label }))
);

export default function GroupedFieldShell() {
  const [value, setValue] = React.useState<string[]>([]);
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <MultiSelect
        options={flatOptions}
        value={value}
        onChange={(v) => setValue(v.map(String))}
        placeholder="Select regions"
        size="sm"
        dropdownMenu={false}
        menuOpen={open}
        menuMinWidth={GROUP_SELECT_MIN_PANEL_WIDTH}
        onTriggerPress={() => setOpen((o) => !o)}
      />
      {open && (
        <GroupSelect groups={groups} value={value} onChange={setValue} />
      )}
    </>
  );
}

Add backdrop, click-outside, and Escape handling in your layout as needed (see Storybook).

API Reference

<MultiSelect>

| 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. | | options | MultiSelectOption[] | — | Available options. | | value | MultiSelectValue | [] | Selected values. | | onChange | (values: MultiSelectValue) => void | — | Fired when the selection changes. | | placeholder | string | 'Select' | Placeholder shown when empty. | | label | string | — | Label rendered above the control. | | size | 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Control size. | | state | 'default' \| 'hover' \| 'focus' \| 'disable' \| 'error' | — | Forced visual state. | | disabled | boolean | false | Disable the control. | | errorMessage | string | — | Error message; also marks the control invalid. | | variant | 'tag' \| 'text' | 'tag' | How selected options are displayed. | | flexible | boolean | true | When true the control grows with content; otherwise fixed-height. | | removeTagsButtons | boolean | true | Show a remove button on each tag. | | extraClear | boolean | false | Show a clear-all button. | | maxHeight | number | 300 | Maximum dropdown height in pixels. | | iconLeft | ReactNode | — | Icon rendered on the left of the control. | | iconRight | ReactNode | — | Icon on the right (overrides the default caret). | | dropdownMenu | boolean | true | When false, hides the built-in list and disables click-to-open; use with an external picker (e.g. GroupSelect) wired to the same value / onChange. | | onTriggerPress | () => void | — | When dropdownMenu is false: fired when the user activates the field. Typically toggles the external panel. | | menuOpen | boolean | false | When dropdownMenu is false: drives chevron direction and layering like the built-in open state. | | menuMinWidth | number | 540 | When dropdownMenu is false: field min-width in px (matches GroupSelect). Use 0 for no minimum. |

Inherits ThemeOverrideProps (themeMode, themeProductContext).

Types

type MultiSelectValue = (string | number)[];
type MultiSelectVariant = "tag" | "text";
type MultiSelectSize = "xs" | "sm" | "md" | "lg" | "xl";
type MultiSelectState = "default" | "hover" | "focus" | "disable" | "error";

interface MultiSelectOption {
  label: ReactNode;
  value: string | number;
  disabled?: boolean;
}

Examples

Sizes

const options = [
  { label: 'React', value: 'react' },
  { label: 'Vue', value: 'vue' },
  { label: 'Angular', value: 'angular' },
];

<MultiSelect options={options} size="xs" placeholder="Extra small" />
<MultiSelect options={options} size="sm" placeholder="Small" />
<MultiSelect options={options} size="md" placeholder="Medium" />
<MultiSelect options={options} size="lg" placeholder="Large" />
<MultiSelect options={options} size="xl" placeholder="Extra large" />

Text variant with clear-all

const options = [
  { label: "React", value: "react" },
  { label: "Vue", value: "vue" },
  { label: "Angular", value: "angular" },
];

const [selected, setSelected] = useState<MultiSelectValue>([]);

<MultiSelect
  options={options}
  value={selected}
  onChange={setSelected}
  variant="text"
  extraClear
/>;

Error state

const options = [
  { label: "Design", value: "design" },
  { label: "Engineering", value: "engineering" },
  { label: "Product", value: "product" },
];

const [skills, setSkills] = useState<MultiSelectValue>([]);

<MultiSelect
  label="Skills"
  options={options}
  value={skills}
  onChange={setSkills}
  errorMessage="Please select at least one skill"
/>;

Disabled

const options = [
  { label: "React", value: "react" },
  { label: "Vue", value: "vue" },
  { label: "Angular", value: "angular" },
];

<MultiSelect options={options} value={["react"]} disabled />;

Accessibility

  • Selection is rendered as a checkbox list inside the dropdown.
  • The dropdown is keyboard navigable; selection state is announced to assistive technology.
  • An errorMessage marks the control as invalid for screen readers.