Seçim
Tek bir seçeneği belirlemeye yarayan bir açılır menü — ülke alanları, sıralama düzenleri, tema ayarları — kalın neobrütalist kenarlıklar ve keskin gölgelerle.
import {
Select,
SelectContent,Select, seçeneklerden oluşan açılır bir liste sunar ve seçileni tetikleyicisinde gösterir — yerel <select> için stillendirilmiş, forma hazır bir alternatif. Base UI Select bileşeni üzerine kuruludur ve neobrütalist reçeteye göre stillendirilmiştir: kalın kenarlıklar, keskin gölgeler ve iddialı tipografi.
Şu durumlarda tercih edin:
- Sabit seçenekli form alanları — ülke, para birimi, saat dilimi; normalde yerel
<select>kullanacağınız her yer. - Sıralama ve filtre kontrolleri — bir ürün ızgarasını veya tabloyu fiyata, tarihe ya da popülerliğe göre sıralayın.
- Tercih seçiciler — ayarlar panelinde tema, dil veya bildirim sıklığı.
Kurulum#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/select.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/select.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/select.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/select.json
Aşağıdaki bağımlılıkları yükleyin:
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
Aşağıdaki kodu kopyalayıp projenize yapıştırın.
"use client"
import * as React from "react"
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
import { Select as SelectPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Select({
...props
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
return <SelectPrimitive.Root data-slot="select" {...props} />
}
function SelectGroup({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
return (
<SelectPrimitive.Group
data-slot="select-group"
className={cn("scroll-my-1 p-1", className)}
{...props}
/>
)
}
function SelectValue({
...props
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
return <SelectPrimitive.Value data-slot="select-value" {...props} />
}
function SelectTrigger({
className,
size = "default",
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
size?: "sm" | "default"
}) {
return (
<SelectPrimitive.Trigger
data-slot="select-trigger"
data-size={size}
className={cn(
"flex w-fit items-center justify-between gap-1.5 rounded border-2 bg-input py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-sm transition-colors outline-none select-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
)
}
function SelectContent({
className,
children,
position = "item-aligned",
align = "center",
...props
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
data-slot="select-content"
data-align-trigger={position === "item-aligned"}
className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded border-2 bg-popover text-popover-foreground shadow-md duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
position={position}
align={align}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
data-position={position}
className={cn(
"data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
position === "popper" && ""
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
)
}
function SelectLabel({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
return (
<SelectPrimitive.Label
data-slot="select-label"
className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
{...props}
/>
)
}
function SelectItem({
className,
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
return (
<SelectPrimitive.Item
data-slot="select-item"
className={cn(
"relative flex w-full cursor-default items-center gap-1.5 rounded-sm py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
)}
{...props}
>
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<CheckIcon className="pointer-events-none" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
)
}
function SelectSeparator({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
return (
<SelectPrimitive.Separator
data-slot="select-separator"
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
{...props}
/>
)
}
function SelectScrollUpButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
return (
<SelectPrimitive.ScrollUpButton
data-slot="select-scroll-up-button"
className={cn(
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<ChevronUpIcon />
</SelectPrimitive.ScrollUpButton>
)
}
function SelectScrollDownButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
return (
<SelectPrimitive.ScrollDownButton
data-slot="select-scroll-down-button"
className={cn(
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<ChevronDownIcon />
</SelectPrimitive.ScrollDownButton>
)
}
export {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
}
İçe aktarma yollarını proje kurulumunuza göre güncelleyin.
Kullanım#
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"const items = [
{ label: "Light", value: "light" },
{ label: "Dark", value: "dark" },
{ label: "System", value: "system" },
]
<Select items={items}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{items.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>Kompozisyon#
Bir Select oluşturmak için aşağıdaki kompozisyonu kullanın:
Select
├── SelectTrigger
│ └── SelectValue
└── SelectContent
├── SelectGroup
│ ├── SelectLabel
│ ├── SelectItem
│ └── SelectItem
├── SelectSeparator
└── SelectGroup
├── SelectLabel
├── SelectItem
└── SelectItemÖrnekler#
Öğeyi Tetikleyiciyle Hizalama#
Seçili öğenin tetikleyiciyle hizalanıp hizalanmayacağını denetlemek için SelectContent üzerinde alignItemWithTrigger kullanın. true olduğunda (varsayılan), açılır pencere, seçili öğe tetikleyicinin üzerinde görünecek şekilde konumlanır. false olduğunda, açılır pencere tetikleyicinin kenarına hizalanır.
"use client"
import * as React from "react"Gruplar#
Öğeleri düzenlemek için SelectGroup, SelectLabel ve SelectSeparator kullanın.
import {
Select,
SelectContent,Kaydırılabilir#
Kaydırılabilen, çok sayıda öğe içeren bir select.
import {
Select,
SelectContent,Devre Dışı#
import {
Select,
SelectContent,Geçersiz#
Bir hata durumu göstermek için Field bileşenine data-invalid özniteliğini ve SelectTrigger bileşenine aria-invalid özniteliğini ekleyin.
<Field data-invalid>
<FieldLabel>Fruit</FieldLabel>
<SelectTrigger aria-invalid>
<SelectValue />
</SelectTrigger>
</Field>import { Field, FieldError, FieldLabel } from "@/components/ui/field"
import {
Select,RTL#
Neobrutalism'de RTL desteğini etkinleştirmek için RTL yapılandırma kılavuzuna bakın.
"use client"
import * as React from "react"Erişilebilirlik#
Select, WAI-ARIA Combobox deseninin yalnızca-seçim biçimini uygular: tetikleyici, aria-expanded ile daraltılmış bir combobox olarak duyurulur; açılır pencere option öğelerinden oluşan bir listbox olarak işlenir ve aria-selected geçerli değeri izler — tüm bağlantıları primitif kurar.
Klavye etkileşimleri:
| Tuş | Eylem |
|---|---|
Space / Enter | Select'i açar; açıkken vurgulanan öğeyi seçer |
ArrowDown / ArrowUp | Kapalıyken açar; açıkken sonraki / önceki öğeyi vurgular |
Esc | Açılır pencereyi kapatır ve odağı tetikleyiciye geri taşır |
| Karakter yazma | Yazarak arama — eşleşen ilk öğeye atlar |
API Referansı#
Base UI Select belgelerine bakın.