Select gốc
Thành phần select HTML gốc được thiết kế lại dành cho biểu mẫu, bộ lọc và công cụ chọn quốc gia — menu thả xuống được hệ điều hành hiển thị với viền và bóng theo phong cách neobrutalist.
Để có một component select đã được tạo kiểu, hãy xem component Select.
import {
NativeSelect,
NativeSelectOption,Native select là một lớp tạo kiểu mỏng phủ lên chính thẻ <select> của trình duyệt — không primitive, không portal, không JavaScript. Phần điều khiển khi đóng mang công thức neobrutalist — viền dày, bóng đổ đậm và kiểu chữ đậm — còn danh sách khi mở vẫn là bộ chọn của hệ điều hành.
Nên dùng khi:
- Bộ chọn quốc gia, múi giờ và tiền tệ — những danh sách tùy chọn rất dài mà hệ điều hành render nhanh hơn bất kỳ popover tùy chỉnh nào.
- Biểu mẫu chủ yếu dùng trên mobile — iOS và Android thay bằng bánh xe chọn native của chúng, tiện hơn hẳn một dropdown tùy chỉnh trên màn hình nhỏ.
- Gửi form thuần — đây là một
<select name="…">thật, nên giá trị được gửi kèm form và hoạt động cả trước khi hydrate.
Cài đặt#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/native-select.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/native-select.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/native-select.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/native-select.json
Sao chép và dán đoạn mã sau vào dự án của bạn.
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { cn } from "@/lib/utils"
type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
size?: "sm" | "default"
}
function NativeSelect({
className,
size = "default",
...props
}: NativeSelectProps) {
return (
<div
className={cn(
"group/native-select relative w-fit has-[select:disabled]:opacity-50",
className
)}
data-slot="native-select-wrapper"
data-size={size}
>
<select
data-slot="native-select"
data-size={size}
className="h-8 w-full min-w-0 appearance-none rounded border-2 bg-input py-2 pr-8 pl-3 text-sm shadow-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive data-[size=sm]:h-7 data-[size=sm]:rounded data-[size=sm]:py-0.5"
{...props}
/>
<ChevronDownIcon
className="pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none"
aria-hidden="true"
data-slot="native-select-icon"
/>
</div>
)
}
function NativeSelectOption({
className,
...props
}: React.ComponentProps<"option">) {
return (
<option
data-slot="native-select-option"
className={cn("bg-[Canvas] text-[CanvasText]", className)}
{...props}
/>
)
}
function NativeSelectOptGroup({
className,
...props
}: React.ComponentProps<"optgroup">) {
return (
<optgroup
data-slot="native-select-optgroup"
className={cn("bg-[Canvas] text-[CanvasText]", className)}
{...props}
/>
)
}
export { NativeSelect, NativeSelectOptGroup, NativeSelectOption }
Cập nhật các đường dẫn import cho phù hợp với thiết lập dự án của bạn.
Cách dùng#
import {
NativeSelect,
NativeSelectOptGroup,
NativeSelectOption,
} from "@/components/ui/native-select"<NativeSelect>
<NativeSelectOption value="">Select a fruit</NativeSelectOption>
<NativeSelectOption value="apple">Apple</NativeSelectOption>
<NativeSelectOption value="banana">Banana</NativeSelectOption>
<NativeSelectOption value="blueberry">Blueberry</NativeSelectOption>
<NativeSelectOption value="pineapple">Pineapple</NativeSelectOption>
</NativeSelect>Kết hợp#
Đơn giản#
Các tùy chọn được đặt trực tiếp bên trong NativeSelect (không có NativeSelectOptGroup).
NativeSelect
├── NativeSelectOption
├── NativeSelectOption
├── NativeSelectOption
└── NativeSelectOptionVới nhóm#
Dùng NativeSelectOptGroup để sắp xếp các tùy chọn thành các danh mục.
NativeSelect
├── NativeSelectOptGroup
│ ├── NativeSelectOption
│ └── NativeSelectOption
└── NativeSelectOptGroup
├── NativeSelectOption
└── NativeSelectOptionVí dụ#
Nhóm#
Dùng NativeSelectOptGroup để sắp xếp các tùy chọn thành các danh mục.
import {
NativeSelect,
NativeSelectOptGroup,Vô hiệu hóa#
Thêm prop disabled vào component NativeSelect để vô hiệu hóa select.
import {
NativeSelect,
NativeSelectOption,Không hợp lệ#
Dùng aria-invalid để hiển thị lỗi xác thực và thuộc tính data-invalid trên component Field để tạo kiểu.
import {
NativeSelect,
NativeSelectOption,Native Select vs Select#
- Dùng
NativeSelectcho hành vi gốc của trình duyệt, hiệu năng tốt hơn hoặc các danh sách thả xuống tối ưu cho di động. - Dùng
Selectcho kiểu dáng tùy chỉnh, hoạt ảnh hoặc các tương tác phức tạp.
RTL#
Để bật hỗ trợ RTL trong Neobrutalism, hãy xem hướng dẫn cấu hình RTL.
"use client"
import * as React from "react"Khả năng truy cập#
Đây chính là thẻ <select> của nền tảng, thứ mà trình duyệt vốn đã phơi bày sẵn cho công nghệ hỗ trợ — cũng chính là điều khiển mà mẫu combobox chỉ-chọn của WAI-ARIA tồn tại để mô phỏng. Không cần kết nối ARIA gì cả; chỉ cần cho nó một tên gọi truy cập được qua <Label htmlFor> hoặc aria-label.
Hành vi bàn phím do trình duyệt cung cấp, nên các tổ hợp phím khác nhau đôi chút tùy hệ điều hành và trình duyệt. Bộ phím phổ biến:
| Phím | Hành động |
|---|---|
Space / Alt + ArrowDown | Mở danh sách tùy chọn |
ArrowDown / ArrowUp | Làm nổi bật tùy chọn kế tiếp / trước đó |
Home / End | Nhảy đến tùy chọn đầu / cuối |
Enter | Chốt tùy chọn đang được làm nổi bật và đóng danh sách |
Escape | Đóng danh sách mà không thay đổi giá trị |
| Ký tự in được | Typeahead — nhảy đến tùy chọn kế tiếp khớp với những gì bạn gõ |
Tham chiếu API#
NativeSelect#
Component select chính, bao bọc phần tử select HTML gốc.
<NativeSelect>
<NativeSelectOption value="option1">Option 1</NativeSelectOption>
<NativeSelectOption value="option2">Option 2</NativeSelectOption>
</NativeSelect>NativeSelectOption#
Đại diện cho một tùy chọn riêng lẻ bên trong select.
| Prop | Type | Default |
|---|---|---|
value | string | |
disabled | boolean | false |
NativeSelectOptGroup#
Nhóm các tùy chọn liên quan với nhau để sắp xếp tốt hơn.
| Prop | Type | Default |
|---|---|---|
label | string | |
disabled | boolean | false |
<NativeSelectOptGroup label="Fruits">
<NativeSelectOption value="apple">Apple</NativeSelectOption>
<NativeSelectOption value="banana">Banana</NativeSelectOption>
</NativeSelectOptGroup>