Select 选择器
下拉选择器,支持禁用单个选项与完整键盘导航,基于 Base UI Select 构建。
安装
bash
npx polyui add select原生默认
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeDefault() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select default</Label>
<NativeSelect id={id}>
<NativeSelectOption value="1">Male</NativeSelectOption>
<NativeSelectOption value="2">Female</NativeSelectOption>
<NativeSelectOption value="3">Other</NativeSelectOption>
</NativeSelect>
</div>
)
}原生占位符
tsx
import { useId } from "react"
import { Select } from "@polyui/react/select"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeWithPlaceholder() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select with placeholder</Label>
<NativeSelect id={id} defaultValue="">
<NativeSelectOption value="" disabled>
Select gender
</NativeSelectOption>
<NativeSelectOption value="1">Male</NativeSelectOption>
<NativeSelectOption value="2">Female</NativeSelectOption>
<NativeSelectOption value="3">Other</NativeSelectOption>
</NativeSelect>
</div>
)
}原生带图标
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
import { FilmIcon } from "lucide-react"
export function SelectNativeWithIcon() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select with icon</Label>
<div className="group relative">
<NativeSelect id={id} className="pl-9" defaultValue="">
<NativeSelectOption value="" disabled>
Pick a movie
</NativeSelectOption>
<NativeSelectOption value="1">Godfather</NativeSelectOption>
<NativeSelectOption value="2">A Working Man</NativeSelectOption>
<NativeSelectOption value="3">The Dark Knight</NativeSelectOption>
<NativeSelectOption value="4">Inception</NativeSelectOption>
</NativeSelect>
<div className="text-muted-foreground/80 pointer-events-none absolute inset-y-0 left-0 flex items-center justify-center pl-3 group-has-[select[disabled]]:opacity-50">
<FilmIcon size={16} aria-hidden="true" />
</div>
</div>
</div>
)
}原生辅助文字
Select the city you reside in.
tsx
import { useId } from "react"
import { Select } from "@polyui/react/select"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeWithHelperText() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select with helper text</Label>
<NativeSelect id={id}>
<NativeSelectOption value="1">Florida</NativeSelectOption>
<NativeSelectOption value="2">California</NativeSelectOption>
<NativeSelectOption value="3">San Francisco</NativeSelectOption>
<NativeSelectOption value="4">Alabama</NativeSelectOption>
</NativeSelect>
<p className="text-muted-foreground mt-2 text-xs" role="region" aria-live="polite">
Select the city you reside in.
</p>
</div>
)
}原生错误状态
Please select a valid option.
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeWithError() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select with error</Label>
<NativeSelect id={id} aria-invalid>
<NativeSelectOption value="1">IST (Indian Standard Time)</NativeSelectOption>
<NativeSelectOption value="2">EST (Eastern Standard Time)</NativeSelectOption>
<NativeSelectOption value="3">PST (Pacific Standard Time)</NativeSelectOption>
<NativeSelectOption value="4">GMT (Greenwich Mean Time)</NativeSelectOption>
</NativeSelect>
<p className="text-destructive mt-2 text-xs" role="alert" aria-live="polite">
Please select a valid option.
</p>
</div>
)
}原生必填
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeRequired() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id} className="gap-1">
Native select required <span className="text-destructive">*</span>
</Label>
<NativeSelect id={id} required>
<NativeSelectOption value="1">Action</NativeSelectOption>
<NativeSelectOption value="2">Comedy</NativeSelectOption>
<NativeSelectOption value="3">Romance</NativeSelectOption>
<NativeSelectOption value="4">Thriller</NativeSelectOption>
</NativeSelect>
</div>
)
}原生选项组
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption, NativeSelectOptGroup } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeWithOptionGroups() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select with option groups</Label>
<NativeSelect id={id}>
<NativeSelectOptGroup label="Frontend Technologies">
<NativeSelectOption value="1">HTML</NativeSelectOption>
<NativeSelectOption value="2">CSS</NativeSelectOption>
<NativeSelectOption value="3">JavaScript</NativeSelectOption>
</NativeSelectOptGroup>
<NativeSelectOptGroup label="Backend Technologies">
<NativeSelectOption value="4">Node.js</NativeSelectOption>
<NativeSelectOption value="5">Python</NativeSelectOption>
<NativeSelectOption value="6">Java</NativeSelectOption>
</NativeSelectOptGroup>
</NativeSelect>
</div>
)
}原生悬浮标签
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
export function SelectNativeOverlappingLabel() {
const id = useId()
return (
<div className="group relative w-full max-w-xs">
<label
htmlFor={id}
className="bg-background text-foreground absolute top-0 left-2 z-10 block -translate-y-1/2 px-1 text-xs font-medium group-has-[select[disabled]]:opacity-50"
>
Overlapping label
</label>
<NativeSelect id={id}>
<NativeSelectOption value="1">Developer</NativeSelectOption>
<NativeSelectOption value="2">Designer</NativeSelectOption>
<NativeSelectOption value="3">Manager</NativeSelectOption>
<NativeSelectOption value="4">QA Engineer</NativeSelectOption>
</NativeSelect>
</div>
)
}原生内嵌标签
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
export function SelectNativeInsetLabel() {
const id = useId()
return (
<div className="border-input bg-background focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive relative w-full max-w-xs rounded-md border shadow-xs transition-[color,box-shadow] outline-none focus-within:ring-[3px] has-[select:disabled]:cursor-not-allowed has-[select:disabled]:opacity-50">
<label htmlFor={id} className="text-foreground block px-3 pt-1 text-xs font-medium">
Inset label
</label>
<NativeSelect id={id} defaultValue="" className="border-none bg-transparent shadow-none focus-visible:ring-0">
<NativeSelectOption value="" disabled>
Pick a movie
</NativeSelectOption>
<NativeSelectOption value="1">Interstellar</NativeSelectOption>
<NativeSelectOption value="2">Dune</NativeSelectOption>
<NativeSelectOption value="3">The Matrix</NativeSelectOption>
<NativeSelectOption value="4">Catch Me If You Can</NativeSelectOption>
</NativeSelect>
</div>
)
}默认
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectDefault() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Select default</Label>
<Select defaultValue="apple">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}带占位符
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithPlaceholder() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Select with placeholder</Label>
<Select>
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}带图标
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
import { FilmIcon } from "lucide-react"
export function SelectWithIcon() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Select with icon</Label>
<Select defaultValue="god of wars">
<SelectTrigger id={id} className="relative w-full pl-9">
<div className="text-muted-foreground/80 pointer-events-none absolute inset-y-0 left-0 flex items-center justify-center pl-3">
<FilmIcon size={16} aria-hidden="true" />
</div>
<SelectValue placeholder="Select a time" />
</SelectTrigger>
<SelectContent>
<SelectItem value="god of wars">God of Wars</SelectItem>
<SelectItem value="ghost rider">Ghost Rider</SelectItem>
<SelectItem value="the cloth">The Cloth</SelectItem>
<SelectItem value="the possession">The Possession</SelectItem>
</SelectContent>
</Select>
</div>
)
}带辅助文字
Select the city you reside in.
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithHelperText() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Select with helper text</Label>
<Select defaultValue="3">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Florida</SelectItem>
<SelectItem value="2">New York</SelectItem>
<SelectItem value="3">California</SelectItem>
<SelectItem value="4">Texas</SelectItem>
</SelectContent>
</Select>
<p className="text-muted-foreground mt-2 text-xs" role="region" aria-live="polite">
Select the city you reside in.
</p>
</div>
)
}错误状态
Please select a valid option.
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithError() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Select with error</Label>
<Select defaultValue="1">
<SelectTrigger id={id} aria-invalid className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Tesla</SelectItem>
<SelectItem value="2">BMW</SelectItem>
<SelectItem value="3">Audi</SelectItem>
<SelectItem value="4">Mercedes-Benz</SelectItem>
</SelectContent>
</Select>
<p className="text-destructive mt-2 text-xs" role="alert" aria-live="polite">
Please select a valid option.
</p>
</div>
)
}尺寸
tsx
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
export function SelectSizes() {
return (
<div className="w-full max-w-xs space-y-2">
<Select>
<SelectTrigger size="sm" className="w-full">
<SelectValue placeholder="Small select" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<Select>
<SelectTrigger className="w-full">
<SelectValue placeholder="Default select" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<Select>
<SelectTrigger className="!h-10 w-full">
<SelectValue placeholder="Large select" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}彩色边框
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectColoredBorder() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Colored border</Label>
<Select defaultValue="1">
<SelectTrigger
id={id}
className="w-full focus-visible:border-indigo-500 focus-visible:ring-indigo-500/20 dark:focus-visible:ring-indigo-500/40"
>
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Electronics</SelectItem>
<SelectItem value="2">Clothing</SelectItem>
<SelectItem value="3">Home Appliances</SelectItem>
<SelectItem value="4">Books</SelectItem>
</SelectContent>
</Select>
</div>
)
}背景颜色
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectBackgroundColor() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Background color</Label>
<Select defaultValue="hindi">
<SelectTrigger className="w-full border-sky-600 bg-sky-600/10 text-sky-600 shadow-none focus-visible:border-sky-600 focus-visible:ring-sky-600/20 dark:bg-sky-400/10 dark:text-sky-400 dark:hover:bg-sky-400/10 dark:focus-visible:ring-sky-400/40 [&_svg]:!text-sky-600 dark:[&_svg]:!text-sky-400">
<SelectValue placeholder="Select a language" />
</SelectTrigger>
<SelectContent>
<SelectGroup className="[&_div:focus]:bg-sky-600/20 [&_div:focus]:text-sky-600 dark:[&_div:focus]:bg-sky-400/20 dark:[&_div:focus]:text-sky-400">
<SelectLabel>Languages</SelectLabel>
<SelectItem value="hindi">Hindi</SelectItem>
<SelectItem value="english">English</SelectItem>
<SelectItem value="spanish">Spanish</SelectItem>
<SelectItem value="mandarin">Mandarin</SelectItem>
<SelectItem value="french">French</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}幽灵样式
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectGhost() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Ghost</Label>
<Select defaultValue="apple">
<SelectTrigger className="hover:bg-accent w-full border-none shadow-none dark:bg-transparent">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}禁用
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectDisabled() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Disabled</Label>
<Select defaultValue="apple" disabled>
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}禁用选项
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectDisabledOptions() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Disabled options</Label>
<Select defaultValue="apple">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana" disabled>
Banana
</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes" disabled>
Grapes
</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}必填
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectRequired() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id} className="gap-1">
Required <span className="text-destructive">*</span>
</Label>
<Select defaultValue="2">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">United States</SelectItem>
<SelectItem value="2">Japan</SelectItem>
<SelectItem value="3">Australia</SelectItem>
<SelectItem value="4">Brazil</SelectItem>
</SelectContent>
</Select>
</div>
)
}带选项组
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithOptionGroups() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>With option groups</Label>
<Select defaultValue="7">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>North America</SelectLabel>
<SelectItem value="1">United States</SelectItem>
<SelectItem value="2">Canada</SelectItem>
<SelectItem value="3">Mexico</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel>Europe</SelectLabel>
<SelectItem value="4">United Kingdom</SelectItem>
<SelectItem value="5">Germany</SelectItem>
<SelectItem value="6">France</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel>Asia</SelectLabel>
<SelectItem value="7">India</SelectItem>
<SelectItem value="8">Japan</SelectItem>
<SelectItem value="9">China</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}带分隔线
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithSeparator() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>With separator</Label>
<Select defaultValue="7">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>North America</SelectLabel>
<SelectItem value="1">United States</SelectItem>
<SelectItem value="2">Canada</SelectItem>
<SelectItem value="3">Mexico</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Europe</SelectLabel>
<SelectItem value="4">United Kingdom</SelectItem>
<SelectItem value="5">Germany</SelectItem>
<SelectItem value="6">France</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Asia</SelectLabel>
<SelectItem value="7">India</SelectItem>
<SelectItem value="8">Japan</SelectItem>
<SelectItem value="9">China</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}悬浮标签
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
export function SelectOverlappingLabel() {
const id = useId()
return (
<div className="group relative w-full max-w-xs">
<label
htmlFor={id}
className="bg-background text-foreground absolute top-0 left-2 z-10 block -translate-y-1/2 px-1 text-xs font-medium group-has-disabled:opacity-50"
>
Overlapping label
</label>
<Select>
<SelectTrigger id={id} className="dark:!bg-background w-full">
<SelectValue placeholder="Select a city" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">New York</SelectItem>
<SelectItem value="2">London</SelectItem>
<SelectItem value="3">Tokyo</SelectItem>
<SelectItem value="4">Paris</SelectItem>
</SelectContent>
</Select>
</div>
)
}内嵌标签
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
export function SelectInsetLabel() {
const id = useId()
return (
<div className="border-input group bg-background focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive relative w-full max-w-xs rounded-md border shadow-xs transition-[color,box-shadow] outline-none focus-within:ring-[3px] has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50">
<label
htmlFor={id}
className="text-foreground dark:bg-input/30 dark:group-hover:bg-input/50 block px-3 pt-1 text-xs font-medium"
>
Inset label
</label>
<Select>
<SelectTrigger
id={id}
className="dark:group-hover:bg-input/50 w-full rounded-t-none border-none bg-transparent shadow-none focus-visible:ring-0"
>
<SelectValue placeholder="Select payment method" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Credit Card</SelectItem>
<SelectItem value="2">Google Pay</SelectItem>
<SelectItem value="3">PayPal</SelectItem>
<SelectItem value="4">Bitcoin</SelectItem>
</SelectContent>
</Select>
</div>
)
}时区
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectTimezone() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Timezone</Label>
<Select>
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a timezone" />
</SelectTrigger>
<SelectContent className="max-h-100">
<SelectGroup>
<SelectLabel>North America</SelectLabel>
<SelectItem value="est">Eastern Standard Time (EST)</SelectItem>
<SelectItem value="cst">Central Standard Time (CST)</SelectItem>
<SelectItem value="pst">Pacific Standard Time (PST)</SelectItem>
<SelectItem value="hst">Hawaii Standard Time (HST)</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel>Europe & Africa</SelectLabel>
<SelectItem value="gmt">Greenwich Mean Time (GMT)</SelectItem>
<SelectItem value="cet">Central European Time (CET)</SelectItem>
<SelectItem value="eet">Eastern European Time (EET)</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel>Asia</SelectLabel>
<SelectItem value="ist">India Standard Time (IST)</SelectItem>
<SelectItem value="jst">Japan Standard Time (JST)</SelectItem>
<SelectItem value="kst">Korea Standard Time (KST)</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel>Australia & Pacific</SelectLabel>
<SelectItem value="aest">Australian Eastern Standard Time (AEST)</SelectItem>
<SelectItem value="nzst">New Zealand Standard Time (NZST)</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}选项带图标
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
import { GuitarIcon, HeadphonesIcon, MicVocalIcon, MusicIcon } from "lucide-react"
export function SelectOptionsWithIcon() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Options with icon</Label>
<Select defaultValue="rock">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a music genre" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Music Genres</SelectLabel>
<SelectItem value="rock">
<GuitarIcon />
Rock
</SelectItem>
<SelectItem value="electronic">
<HeadphonesIcon />
Electronic
</SelectItem>
<SelectItem value="pop">
<MicVocalIcon />
Pop
</SelectItem>
<SelectItem value="jazz">
<MusicIcon />
Jazz
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}带前置文字
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithLeadingText() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>With leading text</Label>
<Select defaultValue="1">
<SelectTrigger id={id} className="w-full">
<span>
Favorite movie: <SelectValue placeholder="Select a movie" />
</span>
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Inception</SelectItem>
<SelectItem value="2">Interstellar</SelectItem>
<SelectItem value="3">The Dark Knight</SelectItem>
<SelectItem value="4">Pulp Fiction</SelectItem>
</SelectContent>
</Select>
</div>
)
}状态
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
import { CircleIcon } from "lucide-react"
export function SelectStatus() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Status</Label>
<Select defaultValue="1">
<SelectTrigger
id={id}
className="w-full [&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_svg]:shrink-0"
>
<SelectValue placeholder="Select a status" />
</SelectTrigger>
<SelectContent className="[&_*[role=option]>span>svg]:text-muted-foreground/80 [&_*[role=option]]:pr-8 [&_*[role=option]]:pl-2 [&_*[role=option]>span]:right-2 [&_*[role=option]>span]:left-auto [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2 [&_*[role=option]>span>svg]:shrink-0">
{[
{ value: "1", label: "In Progress", color: "fill-violet-500 text-violet-500" },
{ value: "2", label: "Pending", color: "fill-amber-500 text-amber-500" },
{ value: "3", label: "Completed", color: "fill-emerald-600 text-emerald-600" },
{ value: "4", label: "Cancelled", color: "fill-gray-500 text-gray-500" },
{ value: "5", label: "Rejected", color: "fill-red-500 text-red-500" },
].map(({ value, label, color }) => (
<SelectItem key={value} value={value}>
<span className="flex items-center gap-2">
<CircleIcon className={`size-2 ${color}`} />
<span className="truncate">{label}</span>
</span>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}带国旗
tsx
import { useId } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectWithFlags() {
const id = useId()
const countries = [
{ value: "1", label: "India", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/india.png" },
{ value: "2", label: "China", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/china.png" },
{ value: "3", label: "Monaco", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/monaco.png" },
{ value: "4", label: "Serbia", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/serbia.png" },
{ value: "5", label: "Romania", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/romania.png" },
{ value: "6", label: "Iraq", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/iraq.png" },
{ value: "7", label: "Korea", flag: "https://cdn.shadcnstudio.com/ss-assets/flags/korea.png" },
]
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>With flags</Label>
<Select defaultValue="1">
<SelectTrigger
id={id}
className="w-full [&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_svg]:shrink-0"
>
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent className="max-h-100 [&_*[role=option]]:pr-8 [&_*[role=option]]:pl-2 [&_*[role=option]>span]:right-2 [&_*[role=option]>span]:left-auto [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2">
{countries.map((country) => (
<SelectItem key={country.value} value={country.value}>
<img src={country.flag} alt={`${country.label} flag`} className="h-4 w-5" />
<span className="truncate">{country.label}</span>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}带头像
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
import { Avatar, AvatarFallback, AvatarImage } from "@polyui/react/avatar"
export function SelectWithAvatars() {
const id = useId()
const users = [
{
id: "1",
src: "https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-1.png",
fallback: "PG",
name: "Phillip George",
},
{
id: "2",
src: "https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-2.png",
fallback: "JD",
name: "Jaylon Donin",
},
{
id: "3",
src: "https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-3.png",
fallback: "TC",
name: "Tiana Curtis",
},
]
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>With avatars</Label>
<Select defaultValue="1">
<SelectTrigger
id={id}
className="w-full pl-2 [&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_img]:shrink-0"
>
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectContent className="[&_*[role=option]]:pr-8 [&_*[role=option]]:pl-2 [&_*[role=option]>span]:right-2 [&_*[role=option]>span]:left-auto [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2">
<SelectGroup>
<SelectLabel className="pl-2">Impersonate user</SelectLabel>
{users.map((item) => (
<SelectItem key={item.id} value={item.id}>
<Avatar className="size-5">
<AvatarImage src={item.src} alt={item.name} className="rounded-full" />
<AvatarFallback className="text-xs">{item.fallback}</AvatarFallback>
</Avatar>
<span className="truncate">{item.name}</span>
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}原生多选
tsx
import { useId } from "react"
import { NativeSelect, NativeSelectOption } from "@polyui/react/native-select"
import { Label } from "@polyui/react/label"
export function SelectNativeMultiple() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Native select multiple</Label>
<div className="border-input overflow-hidden rounded-md border">
<NativeSelect id={id} multiple className="rounded-none border-none">
<NativeSelectOption value="1">Vegetarian</NativeSelectOption>
<NativeSelectOption value="2">Vegan</NativeSelectOption>
<NativeSelectOption value="3">Gluten-Free</NativeSelectOption>
<NativeSelectOption value="4">Halal</NativeSelectOption>
<NativeSelectOption value="5">Kosher</NativeSelectOption>
<NativeSelectOption value="6">Dairy-Free</NativeSelectOption>
</NativeSelect>
</div>
</div>
)
}滑入
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectSlideIn() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Slide-in animation</Label>
<Select defaultValue="apple">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent className="data-[state=open]:slide-in-from-bottom-8 data-[state=open]:zoom-in-100 duration-400">
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}缩放动画
tsx
import { useId } from "react"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@polyui/react/select"
import { Label } from "@polyui/react/label"
export function SelectZoomIn() {
const id = useId()
return (
<div className="w-full max-w-xs space-y-2">
<Label htmlFor={id}>Zoom-in animation</Label>
<Select defaultValue="apple">
<SelectTrigger id={id} className="w-full">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent className="data-[state=open]:!zoom-in-0 origin-center duration-400">
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}属性 — Select
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | string | — | 当前选中的值(受控模式)。 |
onValueChange | (value: string) => void | — | 选中值变化时的回调函数。 |
disabled | boolean | false | 禁用整个选择器,阻止用户交互。 |
placeholder | string | — | 未选中时触发器显示的占位文本。 |
属性 — SelectItem
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | string | — | 该选项的值,必填,用于标识和受控绑定。 |
disabled | boolean | false | 禁用该选项,禁用后仍在列表中显示但不可选择。 |