NativeSelect

Native select element based on Input

Import

Usage

NativeSelect component supports Input and Input.Wrapper components features and all select element props. NativeSelect documentation does not include all features supported by the component – see Input documentation to learn about all available features.

Input description

Variant
Size
Radius
import { NativeSelect } from '@mantine/core';

function Demo() {
  return <NativeSelect label="Input label" description="Input description" data={['React', 'Angular', 'Vue']} />;
}

Controlled

import { useState } from 'react';
import { NativeSelect } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState('');

  return (
    <NativeSelect
      value={value}
      onChange={(event) => setValue(event.currentTarget.value)}
      data={['React', 'Angular', 'Svelte', 'Vue']}
    />
  );
}

Adding options

NativeSelect allows passing options in two ways:

  • data prop array
  • children prop with option components

Note that if children is used, data will be ignored.

data prop

data prop accepts values in one of the following formats:

  1. Array of strings:
import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect data={['React', 'Angular', 'Svelte', 'Vue']} />
  );
}
  1. Array of objects with label, value and disabled keys:
import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect
      data={[
        { label: 'React', value: 'react' },
        { label: 'Angular', value: 'angular' },
        { label: 'Svelte', value: 'svelte', disabled: true },
        { label: 'Vue', value: 'vue' },
      ]}
    />
  );
}
  1. Array of grouped options (string format):
import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect
      data={[
        {
          group: 'Frontend libraries',
          items: ['React', 'Angular', 'Svelte', 'Vue'],
        },
        {
          group: 'Backend libraries',
          items: ['Express', 'Koa', 'Django'],
        },
      ]}
    />
  );
}
  1. Array of grouped options (object format):
import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect
      data={[
        {
          group: 'Frontend libraries',
          items: [
            { label: 'React', value: 'react' },
            { label: 'Angular', value: 'angular' },
            { label: 'Vue', value: 'vue', disabled: true },
          ],
        },
        {
          group: 'Backend libraries',
          items: [
            { label: 'Express', value: 'express' },
            { label: 'Koa', value: 'koa' },
            { label: 'Django', value: 'django' },
          ],
        },
      ]}
    />
  );
}

Example of data prop with array of grouped options:

import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect
      data={[
        {
          group: 'Frontend libraries',
          items: [
            { label: 'React', value: 'react' },
            { label: 'Angular', value: 'angular' },
            { label: 'Vue', value: 'vue', disabled: true },
          ],
        },
        {
          group: 'Backend libraries',
          items: [
            { label: 'Express', value: 'express' },
            { label: 'Koa', value: 'koa' },
            { label: 'Django', value: 'django' },
          ],
        },
      ]}
    />
  );
}

children options

To add options with children prop, use option elements to add options and optgroup elements to group them:

import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect label="With children options">
      <optgroup label="Frontend libraries">
        <option value="react">React</option>
        <option value="angular">Angular</option>
        <option value="vue" disabled>
          Vue
        </option>
      </optgroup>

      <optgroup label="Backend libraries">
        <option value="express">Express</option>
        <option value="koa">Koa</option>
        <option value="django">Django</option>
      </optgroup>
    </NativeSelect>
  );
}

With dividers

Use hr tags to add dividers between options:

import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <NativeSelect label="With dividers">
      <option>Select library</option>

      <hr />

      <optgroup label="Frontend libraries">
        <option value="react">React</option>
        <option value="angular">Angular</option>
        <option value="vue">Vue</option>
      </optgroup>

      <hr />

      <optgroup label="Backend libraries">
        <option value="express">Express</option>
        <option value="koa">Koa</option>
        <option value="django">Django</option>
      </optgroup>
    </NativeSelect>
  );
}

Left and right sections

NativeSelect supports leftSection and rightSection props. These sections are rendered with absolute position inside the input wrapper. You can use them to display icons, input controls or any other elements.

You can use the following props to control sections styles and content:

  • rightSection/leftSection – React node to render on the corresponding side of input
  • rightSectionWidth/leftSectionWidth – controls width of the right section and padding on the corresponding side of the input. By default, it is controlled by component size prop.
  • rightSectionPointerEvents/leftSectionPointerEvents – controls pointer-events property of the section. If you want to render a non-interactive element, set it to none to pass clicks through to the input.
import { NativeSelect, rem } from '@mantine/core';
import { IconChevronDown, IconHash } from '@tabler/icons-react';

function Demo() {
  return (
    <>
      <NativeSelect
        leftSection={<IconHash style={{ width: rem(16), height: rem(16) }} />}
        leftSectionPointerEvents="none"
        label="Left section"
        data={['React', 'Angular']}
      />

      <NativeSelect
        rightSection={<IconChevronDown style={{ width: rem(16), height: rem(16) }} />}
        label="Right section"
        data={['React', 'Angular']}
        mt="md"
      />
    </>
  );
}

Disabled state

import { NativeSelect } from '@mantine/core';

function Demo() {
  return <NativeSelect disabled data={['React', 'Angular']} label="Disabled NativeSelect" />;
}

Error state

Error message

import { NativeSelect } from '@mantine/core';

function Demo() {
  return (
    <>
      <NativeSelect error label="Boolean error" data={['React', 'Angular']} />
      <NativeSelect
        error="Error message"
        label="React node error"
        data={['React', 'Angular']}
        mt="md"
      />
    </>
  );
}

Styles API

NativeSelect supports Styles API, you can add styles to any inner element of the component withclassNames prop. Follow Styles API documentation to learn more.

NativeSelect description

NativeSelect error

Component Styles API

Hover over selectors to highlight corresponding elements

/*
 * Hover over selectors to apply outline styles
 *
 */

Accessibility

If NativeSelect is used without label prop, it will not be announced properly by screen reader:

import { NativeSelect } from '@mantine/core';

// Inaccessible input – screen reader will not announce it properly
function Demo() {
  return <NativeSelect />;
}

Set aria-label to make the input accessible. In this case label will not be visible, but screen reader will announce it:

import { NativeSelect } from '@mantine/core';

// Accessible input – it has aria-label
function Demo() {
  return <NativeSelect aria-label="My input" />;
}

If label prop is set, input will be accessible it is not required to set aria-label:

import { NativeSelect } from '@mantine/core';

// Accessible input – it has associated label element
function Demo() {
  return <NativeSelect label="My input" />;
}