import { NativeSelect } from "@chakra-ui/react"
const Demo = () => {
return (
<NativeSelect.Root size="sm" width="240px">
<NativeSelect.Field placeholder="Select option">
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)
}
Usage
import { NativeSelect } from "@chakra-ui/react"
<NativeSelect.Root>
<NativeSelect.Field>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
Examples
Sizes
Use the size
prop to change the size of the select component.
import { For, NativeSelect, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="4" width="240px">
<For each={["xs", "sm", "md", "lg", "xl"]}>
{(size) => (
<NativeSelect.Root key={size} size={size}>
<NativeSelect.Field placeholder="Select option">
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)}
</For>
</Stack>
)
}
Variants
Use the variant
prop to change the appearance of the select component.
import { For, NativeSelect, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="4" width="240px">
<For each={["outline", "subtle", "plain"]}>
{(variant) => (
<NativeSelect.Root key={variant} variant={variant}>
<NativeSelect.Field placeholder={`variant (${variant})`}>
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)}
</For>
</Stack>
)
}
Controlled
Use the value
and onChange
props to control the select component.
"use client"
import { NativeSelect } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState("")
return (
<NativeSelect.Root size="sm" width="240px">
<NativeSelect.Field
placeholder="Select option"
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
>
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)
}
Disabled
Pass the disabled
prop to the NativeSelect.Root
component to disable the
select component.
import { NativeSelect } from "@chakra-ui/react"
export const NativeSelectWithDisabled = () => (
<NativeSelect.Root disabled>
<NativeSelect.Field placeholder="Select option">
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)
Invalid
Compose the native and Field
component to set the invalid set and show the
error text.
import { Field, NativeSelect } from "@chakra-ui/react"
export const NativeSelectWithInvalid = () => (
<Field.Root invalid width="240px">
<NativeSelect.Root>
<NativeSelect.Field placeholder="Select option">
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3">Option 3</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
<Field.ErrorText>This is an error</Field.ErrorText>
</Field.Root>
)
Alternatively, you can use the invalid
prop on the NativeSelect.Root
component as well.
import { NativeSelect } from "@chakra-ui/react"
export const NativeSelectWithInvalidRoot = () => (
<NativeSelect.Root invalid width="240px">
<NativeSelect.Field placeholder="Select option">
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3">Option 3</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)
Hook Form
Here is an example of how to use the NativeSelect
component with
react-hook-form
.
"use client"
import { Button, Field, NativeSelect } from "@chakra-ui/react"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
const formSchema = z.object({
framework: z.string().min(1, { message: "Framework is required" }),
})
type FormValues = z.infer<typeof formSchema>
const Demo = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({
resolver: zodResolver(formSchema),
})
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}>
<Field.Root invalid={!!errors.framework}>
<Field.Label>Framework</Field.Label>
<NativeSelect.Root size="sm" width="240px">
<NativeSelect.Field
placeholder="Select option"
{...register("framework")}
>
<option value="react">React</option>
<option value="vue">Vue</option>
<option value="angular">Angular</option>
<option value="svelte">Svelte</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
<Field.ErrorText>{errors.framework?.message}</Field.ErrorText>
</Field.Root>
<Button size="sm" type="submit" mt="4">
Submit
</Button>
</form>
)
}
Ref
Here's how to access the underlying element reference
import { NativeSelect } from "@chakra-ui/react"
const Demo = () => {
const ref = useRef<HTMLSelectElement | null>(null)
return (
<NativeSelect.Root>
<NativeSelect.Field ref={ref}>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</NativeSelect.Field>
<NativeSelect.Indicator />
</NativeSelect.Root>
)
}
Closed Component
Here's how to setup the Native Select for a closed component composition.
"use client"
import { NativeSelect as Select } from "@chakra-ui/react"
import * as React from "react"
type FieldProp = "name" | "value" | "onChange" | "defaultValue"
interface NativeSelectProps
extends Omit<Select.RootProps, FieldProp>,
Pick<Select.FieldProps, FieldProp> {
icon?: React.ReactNode
items: Array<{ label: string; value: string; disabled?: boolean }>
}
export const NativeSelect = React.forwardRef<
HTMLSelectElement,
NativeSelectProps
>(function NativeSelect(props, ref) {
const {
icon,
children,
name,
items,
value,
defaultValue,
onChange,
...rest
} = props
return (
<Select.Root {...rest}>
<Select.Field
ref={ref}
name={name}
value={value}
defaultValue={defaultValue}
onChange={onChange}
>
{children}
{items?.map((item) => (
<option key={item.value} value={item.value} disabled={item.disabled}>
{item.label}
</option>
))}
</Select.Field>
<Select.Indicator>{icon}</Select.Indicator>
</Select.Root>
)
})
Props
Root
Prop | Default | Type |
---|---|---|
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' | 'accent' The color palette of the component |
variant | 'outline' | 'outline' | 'filled' | 'plain' The variant of the component |
size | 'md' | 'lg' | 'md' | 'sm' | 'xs' The size of the component |
as | React.ElementType The underlying element to render. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | boolean Whether to remove the component's style. |