Select
Single select combobox widget to allow selection from a fixed set of options.
#
Documentation
#
#
Usage
#
"use client";
import type { ComponentPropsWithoutRef } from "react";
import { Field } from "@optiaxiom/react";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
export function App({
description,
error,
label = "Input label",
required = false,
}: Pick<
ComponentPropsWithoutRef<typeof Field>,
"description" | "error" | "label" | "required"
>) {
return (
<Field
description={description}
error={error}
label={label}
required={required}
>
<Select
options={[
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
]}
>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
</Field>
);
}
#
Anatomy
#
import { Select, SelectContent, SelectTrigger } from "@optiaxiom/react";
export default () => (
<Select>
<SelectTrigger />
<SelectContent />
</Select>
);
#
Structure
#
Select works with lists of items provided via the options
prop. The basic structure includes the main component provider, a trigger, and the content.
Select
SelectTrigger
SelectContent
Items must be an array of objects of SelectOption
type and at minimum must contain the following two properties:
label
value
The trigger can be provided a placeholder
to display in case no values have been selected yet (or if an empty value is selected).
"use client";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
export function App() {
return (
<Select
options={[
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
]}
>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
);
}
#
Content
#
Select options use the label
property as the display text. We can add the addon
and description
properties to show additional content inside the items.
"use client";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
import {
IconCircle,
IconProgress,
IconProgressCheck,
IconProgressX,
} from "@tabler/icons-react";
export function App() {
return (
<Select
options={[
{
addon: <IconCircle size={16} />,
label: "Todo",
value: "Todo",
},
{
addon: <IconProgress size={16} />,
label: "In progress",
value: "In progress",
},
{
addon: <IconProgressCheck size={16} />,
label: "Done",
value: "Done",
},
{
addon: <IconProgressX size={16} />,
label: "Closed",
value: "Closed",
},
]}
>
<SelectTrigger placeholder="Choose status" w="224" />
<SelectContent />
</Select>
);
}
#
Controlled
#
Use the value
and defaultValue
props to toggle between controlled and uncontrolled usage. And combine it with onValueChange
/ onChange
to listen for changes to the state.
Using onValueChange
:
Selected:
"use client";
import { Flex, Text } from "@optiaxiom/react";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
import { useState } from "react";
const priorities = [
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
];
export function App() {
const [value, setValue] = useState("");
return (
<Flex>
<Select onValueChange={setValue} options={priorities} value={value}>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
<Text fontSize="md">Selected: {value}</Text>
</Flex>
);
}
Using onChange
:
Selected:
"use client";
import { Flex, Text } from "@optiaxiom/react";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
import { useState } from "react";
const priorities = [
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
];
export function App() {
const [value, setValue] = useState("");
return (
<Flex>
<Select
onChange={(event) => setValue(event.target.value)}
options={priorities}
value={value}
>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
<Text fontSize="md">Selected: {value}</Text>
</Flex>
);
}
#
Form usage
#
Use the name
prop (and optionally ref
and onChange
) to integrate Select
with forms.
"use client";
import { Button, Flex, Text } from "@optiaxiom/react";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
import { useState } from "react";
const priorities = [
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
];
export function App() {
const [value, setValue] = useState("");
return (
<form
onSubmit={(event) => {
event.preventDefault();
if (event.target instanceof HTMLFormElement) {
setValue(event.target.priority.value);
}
}}
>
<Flex alignItems="start">
<Select defaultValue={value} name="priority" options={priorities}>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
<Button appearance="primary">Submit</Button>
<Text fontSize="md">Submitted: {value}</Text>
</Flex>
</form>
);
}
#
Disabled state
#
Enable the disabled
prop on Select
to toggle the disabled state of the input field.
"use client";
import type { ComponentPropsWithoutRef } from "react";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
export function App({
disabled = true,
}: Pick<ComponentPropsWithoutRef<typeof Select>, "disabled">) {
return (
<Select
disabled={disabled}
options={[
{ label: "No priority", value: "" },
{ label: "Urgent", value: "Urgent" },
{ label: "High", value: "High" },
{ label: "Medium", value: "Medium" },
{ label: "Low", value: "Low" },
]}
>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
);
}
#
Group
#
We can group options using the group
property.
"use client";
import {
Select,
SelectContent,
SelectTrigger,
} from "@optiaxiom/react/unstable";
const groups = {
none: {
hidden: true,
label: "No priority",
},
values: {
label: "Priorities",
separator: true,
},
};
export function App() {
return (
<Select
options={[
{
group: groups.none,
label: "No priority",
value: "",
},
{
group: groups.values,
label: "Urgent",
value: "Urgent",
},
{
group: groups.values,
label: "High",
value: "High",
},
{
group: groups.values,
label: "Medium",
value: "Medium",
},
{
group: groups.values,
label: "Low",
value: "Low",
},
]}
>
<SelectTrigger placeholder="Set priority" w="224" />
<SelectContent />
</Select>
);
}
#
Related
#
Menu
Multi-purpose combobox widget to allow selection from a dynamic set of options.
DropdownMenu
Display a dropdown menu.
#
Props
#
#
Select
#
Doesn't render its own HTML element.
Prop |
---|
defaultOpen The initial open state in uncontrolled mode.
Default: |
defaultValue The initial selected value in uncontrolled mode.
|
disabled Whether the select is disabled.
|
loading Whether to show loading spinner inside the menu.
|
name
|
onBlur
|
onChange
|
onOpenChange Handler that is called when the open state changes.
|
onValueChange Handler that is called when the selected value changes.
|
open The open state in controlled mode.
|
options* The select items/options we want to render.
|
required
|
value The selected value in controlled mode.
|
#
SelectTrigger
#
Supports all Button props in addition to its own. Renders a <button>
element.
Prop |
---|
addonAfter Display content inside the button after
|
addonBefore Display content inside the button before
|
appearance Control the appearance by selecting between the different button types.
|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
icon Display an icon before or after the button content or omit
|
iconPosition Control whether to show the icon before or after the button content.
|
loading Whether to show loading spinner inside the button.
|
placeholder
|
size Control the size of the button.
|
square Whether button should have square shape.
|
virtualRef
|
#
SelectContent
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
align
Default: |
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
maxH Whether to restrict the max-height of the content. Content is also restricted by the available height in the screen relative to the trigger.
|
minW Whether to set the min-width to the width of the trigger.
|
side
Default: |
#
Changelog
#
#
1.3.0
#
-
Renamed
items
prop tooptions
:// Before <Select items={[]} /> // After <Select options={[]} />
-
Removed
itemToLabel
,itemToValue
, andisItemDisabled
props in favor of fixed properties on options:// Before <Select items={[ { id: "1", name: "Sample", }, ]} itemToLabel={(item) => item.name} itemToValue={(item) => item.id} /> // After <Select options={[ { label: "Sample", value: "1", }, ]} />
#
0.2.0
#
- Added component