스타일이 적용된 select 컴포넌트는 Select 컴포넌트를 참고하세요.
import {
NativeSelect,
NativeSelectOption,Native Select는 브라우저 고유 <select> 요소 위의 얇은 스타일 레이어입니다. 프리미티브도, 포털도, JavaScript도 없습니다. 닫힌 컨트롤에는 두꺼운 테두리, 선명한 그림자, 굵은 서체로 네오브루탈리즘 공식을 입히고, 열린 목록은 OS 피커 그대로입니다.
다음과 같은 경우에 사용합니다.
- 국가·시간대·통화 선택 — 커스텀 팝오버보다 OS가 더 빠르게 그리는 긴 옵션 목록.
- 모바일 중심 폼 — iOS와 Android가 네이티브 피커 휠을 쓰므로 작은 화면에서 커스텀 드롭다운보다 낫습니다.
- 일반 폼 전송 — 실제
<select name="…">라서 폼과 함께 값이 전송되고 하이드레이션 전에도 동작합니다.
설치#
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
다음 코드를 복사해서 프로젝트에 붙여넣습니다.
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 }
import 경로를 프로젝트 구성에 맞게 수정합니다.
사용법#
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>구성#
간단한 구성#
NativeSelectOptGroup 없이 NativeSelect 바로 아래에 옵션을 배치합니다.
NativeSelect
├── NativeSelectOption
├── NativeSelectOption
├── NativeSelectOption
└── NativeSelectOption그룹이 있는 구성#
NativeSelectOptGroup을 사용해서 옵션을 카테고리별로 정리합니다.
NativeSelect
├── NativeSelectOptGroup
│ ├── NativeSelectOption
│ └── NativeSelectOption
└── NativeSelectOptGroup
├── NativeSelectOption
└── NativeSelectOption예제#
그룹#
NativeSelectOptGroup을 사용해서 옵션을 카테고리별로 정리합니다.
import {
NativeSelect,
NativeSelectOptGroup,비활성화#
NativeSelect 컴포넌트에 disabled prop을 추가하면 select를 비활성화할 수 있습니다.
import {
NativeSelect,
NativeSelectOption,오류 상태#
aria-invalid를 사용해서 유효성 검증 오류를 표시하고, 스타일 지정을 위해 Field 컴포넌트에 data-invalid 속성을 추가합니다.
import {
NativeSelect,
NativeSelectOption,Native Select vs Select#
- 네이티브 브라우저 동작, 더 나은 성능, 모바일에 최적화된 드롭다운에는
NativeSelect를 사용하세요. - 커스텀 스타일, 애니메이션, 복잡한 상호작용에는
Select를 사용하세요.
RTL#
Neobrutalism에서 RTL 지원을 활성화하는 방법은 RTL 설정 가이드를 참고하세요.
"use client"
import * as React from "react"접근성#
플랫폼 고유 <select>입니다. 브라우저가 이미 보조 기술에 노출하며, WAI-ARIA select-only combobox 패턴이 흉내 내려는 바로 그 컨트롤입니다. ARIA 배선은 필요 없고, <Label htmlFor> 또는 aria-label로 접근 가능한 이름만 주세요.
키보드 동작은 브라우저가 제공하므로 OS와 브라우저마다 약간 다릅니다. 공통 집합:
키보드 상호작용:
| 키 | 동작 |
|---|---|
Space / Alt + ArrowDown | 옵션 목록 열기 |
ArrowDown / ArrowUp | 다음/이전 옵션 강조 |
Home / End | 첫/마지막 옵션으로 이동 |
Enter | 강조된 옵션을 확정하고 목록 닫기 |
Escape | 값을 바꾸지 않고 목록 닫기 |
| 인쇄 가능한 문자 | 타입어헤드 — 입력과 맞는 다음 옵션으로 이동 |
API 참조#
NativeSelect#
네이티브 HTML select 요소를 감싸는 기본 select 컴포넌트입니다.
<NativeSelect>
<NativeSelectOption value="option1">Option 1</NativeSelectOption>
<NativeSelectOption value="option2">Option 2</NativeSelectOption>
</NativeSelect>NativeSelectOption#
select 안의 개별 옵션을 나타냅니다.
| Prop | Type | Default |
|---|---|---|
value | string | |
disabled | boolean | false |
NativeSelectOptGroup#
관련된 옵션을 함께 묶어 더 체계적으로 정리합니다.
| Prop | Type | Default |
|---|---|---|
label | string | |
disabled | boolean | false |
<NativeSelectOptGroup label="Fruits">
<NativeSelectOption value="apple">Apple</NativeSelectOption>
<NativeSelectOption value="banana">Banana</NativeSelectOption>
</NativeSelectOptGroup>