shadcn/ui'da birbiriyle ilişkili butonları tek bir kutuda birleştirmek için ButtonGroup, açık ya da kapalı olabilen tek bir düğme için Toggle, bu düğmelerden bir set oluşturmak için de ToggleGroup kullanılır. Belgelerin ayrımı açıktır: bir işlem yapan butonları gruplarken ButtonGroup, bir durumu açıp kapatan butonları gruplarken ToggleGroup seçilir. Üçü de npx shadcn@latest add komutuyla projenize ayrı dosyalar olarak eklenir.
Bu yazıda önce ButtonGroup ve yardımcıları ButtonGroupSeparator ile ButtonGroupText bileşenlerini, ardından Toggle ve ToggleGroup bileşenlerini belge sayfaları ve depodaki kaynak kodla anlatıyoruz: yön (orientation), iç içe gruplar, ayırıcı, bölünmüş buton, input ile birlikte kullanım, type="single" ile type="multiple" farkı ve kontrollü kullanım. Tek bir butonun varyantları için Button yazısına, serinin geri kalanı için shadcn/ui öğrenme rehberi sayfasına bakabilirsiniz.
Erişilebilirlik
Belge sayfası üç noktayı vurgular: bileşen role="group" özniteliğine sahiptir, gruptaki butonlar arasında Tab tuşuyla gezinilir ve grubu tanımlamak için aria-label ya da aria-labelledby kullanılmalıdır. Grup rolünün ve etiketlemenin genel anlamı için ARIA yazısına, klavyeyle erişimin önemi için WCAG temelleri yazısına göz atabilirsiniz. Gruptaki ikon butonlarına da tek tek aria-label vermeyi unutmayın; belgedeki örneklerde "Go Back", "More Options" gibi etiketler kullanılır.
Yön ve boyut
orientation özelliği iki değer alır: "horizontal" (varsayılan) ve "vertical". Dikey yönde grup flex-col olur ve köşe düzleştirme kuralları üst ve alt kenarlara uygulanır. Belgedeki örnek, artı ve eksi ikonlu iki butonla dikey bir medya kontrolü kurar:
import { MinusIcon, PlusIcon } from "lucide-react"
<ButtonGroup orientation="vertical" aria-label="Ses kontrolleri" className="h-fit">
<Button variant="outline" size="icon" aria-label="Sesi aç">
<PlusIcon />
</Button>
<Button variant="outline" size="icon" aria-label="Sesi kıs">
<MinusIcon />
</Button>
</ButtonGroup>Grubun kendisinde bir size özelliği yoktur. Belgeler boyutu gruptaki her butona ayrı ayrı size vererek ayarlamanızı söyler. Bu yüzden küçük bir grup kurarken metinli butonlara size="sm", ikonlu butona size="icon-sm" verirsiniz; bu iki boyut aynı yükseklikte olduğu için şerit düzgün görünür.
İç içe gruplar ve ayırıcı
Bir ButtonGroup içine başka ButtonGroup öğeleri koyduğunuzda iç gruplar arasında boşluk oluşur. Bunu sağlayan kaynak kuralı has-[>[data-slot=button-group]]:gap-2 ifadesidir: doğrudan çocukları arasında grup bulunan bir grup, çocuklarını 2 birim aralıkla dizer. Belgedeki örnek, sayfa numaralarını bir grupta, önceki ve sonraki oklarını başka bir grupta tutar.
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
<ButtonGroup>
<ButtonGroup>
<Button variant="outline" size="sm">1</Button>
<Button variant="outline" size="sm">2</Button>
<Button variant="outline" size="sm">3</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline" size="icon-sm" aria-label="Önceki">
<ArrowLeftIcon />
</Button>
<Button variant="outline" size="icon-sm" aria-label="Sonraki">
<ArrowRightIcon />
</Button>
</ButtonGroup>
</ButtonGroup>ButtonGroupSeparator, gruptaki butonların arasına görsel bir çizgi koyar. Belgeler burada önemli bir ayrıntı verir: outline varyantındaki butonların zaten çerçevesi olduğu için ayırıcıya ihtiyacı yoktur; diğer varyantlarda ise görsel hiyerarşiyi güçlendirmek için ayırıcı önerilir. Ayırıcının varsayılan yönü "vertical"'dır, çünkü yatay bir grupta dikey bir çizgi gerekir.
<ButtonGroup>
<Button variant="secondary" size="sm">Kopyala</Button>
<ButtonGroupSeparator />
<Button variant="secondary" size="sm">Yapıştır</Button>
</ButtonGroup>Toggle: iki durumlu buton

Toggle, açık ya da kapalı olabilen bir düğmedir ve Radix'in Toggle ilkeli üzerine kuruludur. Kurulum komutu npx shadcn@latest add toggle, elle kurulumda gereken paket @radix-ui/react-toggle'dır. Kaynaktaki toggleVariants iki varyant (default, outline) ve üç boyut (default, sm, lg) tanımlar. Açık durumda Radix öğeye data-state="on" yazar; temel sınıflardaki data-[state=on]:bg-accent kuralı da düğmeyi vurgular.
import { Italic } from "lucide-react"
import { Toggle } from "@/components/ui/toggle"
export function ItalikDugmesi() {
return (
<Toggle aria-label="İtalik">
<Italic />
İtalik
</Toggle>
)
}Belgedeki ana örnek, açık durumdaki görünümü className ile değiştirir: arka plan rengini kaldırır ve ikonu maviyle doldurur. Bunun için data-[state=on]: önekli sınıflar kullanılır. Bu yöntem, durum bilgisinin bir data-* özniteliğinde tutulmasının güzel bir sonucudur; ek JavaScript yazmadan açık ve kapalı durumlar için farklı stil verebilirsiniz.
import { BookmarkIcon } from "lucide-react"
<Toggle
aria-label="Yer imi"
size="sm"
variant="outline"
className="data-[state=on]:bg-transparent data-[state=on]:*:[svg]:fill-blue-500 data-[state=on]:*:[svg]:stroke-blue-500"
>
<BookmarkIcon />
Yer imi
</Toggle>| Toggle değeri | Kaynaktaki sınıflar |
|---|---|
| variant default | bg-transparent |
| variant outline | border border-input bg-transparent shadow-xs, üzerine gelince bg-accent |
| size sm | h-8 px-1.5 min-w-8 |
| size default | h-9 px-2 min-w-9 |
| size lg | h-10 px-2.5 min-w-10 |
Tablodaki yükseklikler bilinçli olarak butonla aynıdır: sm toggle ile sm buton 8, varsayılanlar 9, lg boyutlar 10 birim yüksekliktedir. Bu sayede bir araç çubuğunda toggle'ları ve butonları yan yana koyduğunuzda satır hizası bozulmaz. min-w-* sınıfları ise yalnızca ikon içeren bir toggle'ın kare görünmesini sağlar.
Toggle'ın açık olup olmadığını kodda izlemek için kullanılacak özellikler Radix Toggle API'sinde tanımlıdır; shadcn/ui belge sayfası bunları ayrıca listelemez ve sayfanın üst kısmındaki bağlantıyla Radix belgesine yönlendirir. disabled özelliği ise belgedeki "Disabled" örneğinde gösterilir ve temel sınıflardaki disabled:opacity-50 ile soluklaştırılır.
ToggleGroup: tekli ve çoklu seçim
ToggleGroup, bir dizi toggle düğmesini tek bir grupta toplar. Kurulum npx shadcn@latest add toggle-group, elle kurulumda gereken paket @radix-ui/react-toggle-group'dır. En önemli özellik type'tır: "single" değerinde aynı anda yalnızca bir öğe açık olabilir, "multiple" değerinde birden çok öğe açılabilir. Belgedeki örnek kalın, italik ve altı çizili biçimlendirme düğmeleriyle çoklu seçimi gösterir:
import { Bold, Italic, Underline } from "lucide-react"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
export function BicimDugmeleri() {
return (
<ToggleGroup variant="outline" type="multiple">
<ToggleGroupItem value="bold" aria-label="Kalın">
<Bold className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="İtalik">
<Italic className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Altı çizili">
<Underline className="h-4 w-4" />
</ToggleGroupItem>
</ToggleGroup>
)
}Her ToggleGroupItem için value zorunludur ve belge, erişilebilirlik için her öğeye aria-label eklemenizi hatırlatır. Grubun variant ve size değerleri, kaynakta bir React context ile öğelere aktarılır; bu yüzden değerleri bir kez grupta yazmanız yeterlidir. Öğelerin görünümü toggle.tsx içindeki toggleVariants fonksiyonundan gelir, yani toggle-group dosyası toggle bileşenine bağımlıdır.
| Prop (ToggleGroup) | Tür | Varsayılan |
|---|---|---|
| type | single veya multiple | single |
| variant | default veya outline | default |
| size | default, sm veya lg | default |
| spacing | number | 0 |
| className | string | yok |
spacing ve kontrollü kullanım
spacing değeri 0 iken öğeler birleşik bir şerit oluşturur: köşeler yalnızca ilk ve son öğede yuvarlaktır, outline varyantında aradaki çift çerçeveler kaldırılır. Belgedeki gibi spacing={2} verdiğinizde öğeler ayrı düğmeler gibi aralıklı dizilir. Kaynak bu değeri --gap CSS değişkenine yazar ve aralığı onunla hesaplar.
Seçili değeri React durumunda tutmak için depodaki dashboard bloğu iyi bir örnektir. Orada type="single" bir grup, value ve onValueChange ile bir useState değerine bağlanır; aynı durum, dar ekranlarda gösterilen bir Select bileşenine de bağlanır:
"use client"
import * as React from "react"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
export function ZamanAraligi() {
const [timeRange, setTimeRange] = React.useState("90d")
return (
<ToggleGroup
type="single"
value={timeRange}
onValueChange={setTimeRange}
variant="outline"
>
<ToggleGroupItem value="90d">Son 3 ay</ToggleGroupItem>
<ToggleGroupItem value="30d">Son 30 gün</ToggleGroupItem>
<ToggleGroupItem value="7d">Son 7 gün</ToggleGroupItem>
</ToggleGroup>
)
}Mini örnek: metin editörü araç çubuğu
İki bileşen ailesinin farkını en iyi gösteren yer bir metin editörünün araç çubuğudur. Geri al ve yinele birer işlemdir, bir durum tutmazlar; bu yüzden bir ButtonGroup içinde durur. Kalın, italik ve altı çizili ise açılıp kapanan biçimlerdir ve aynı anda birkaçı açık olabilir; bu yüzden type="multiple" bir ToggleGroup kullanılır. Hizalama (sola, ortaya, sağa) da bir durumdur ama aynı anda yalnızca biri seçilebilir; ona type="single" uygundur. Aşağıdaki örnek bu üç parçayı belgedeki bileşenlerle birleştirir:
import {
AlignCenter,
AlignLeft,
AlignRight,
Bold,
Italic,
Redo2,
Underline,
Undo2,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
export function EditorAracCubugu() {
return (
<div className="flex items-center gap-2">
<ButtonGroup aria-label="Geçmiş">
<Button variant="outline" size="icon" aria-label="Geri al">
<Undo2 />
</Button>
<Button variant="outline" size="icon" aria-label="Yinele">
<Redo2 />
</Button>
</ButtonGroup>
<ToggleGroup type="multiple" variant="outline" aria-label="Biçim">
<ToggleGroupItem value="bold" aria-label="Kalın">
<Bold />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="İtalik">
<Italic />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Altı çizili">
<Underline />
</ToggleGroupItem>
</ToggleGroup>
<ToggleGroup type="single" variant="outline" defaultValue="left" aria-label="Hizalama">
<ToggleGroupItem value="left" aria-label="Sola hizala">
<AlignLeft />
</ToggleGroupItem>
<ToggleGroupItem value="center" aria-label="Ortala">
<AlignCenter />
</ToggleGroupItem>
<ToggleGroupItem value="right" aria-label="Sağa hizala">
<AlignRight />
</ToggleGroupItem>
</ToggleGroup>
</div>
)
}Butonlar ve toggle öğeleri aynı yükseklikte olduğu için (ikisi de varsayılan boyutta 9 birim) satır düzgün hizalanır. İkonlara ayrıca boyut sınıfı vermeye gerek yoktur; hem buttonVariants hem toggleVariants, size-* sınıfı olmayan SVG'leri 4 birime ayarlar. defaultValue, kontrolsüz kullanımda başlangıçta seçili öğeyi belirler; Radix ToggleGroup'un bu ve benzeri özellikleri için sayfadaki Radix bağlantısına bakabilirsiniz.
Sık yapılan hatalar
- Grubun etiketini atlamak. Belge,
ButtonGroupiçinaria-labelya daaria-labelledbyönerir; ikon düğmelerine de tek tek etiket verin. - Grupta size aramak.
ButtonGroup'ta boyut özelliği yoktur; boyutu butonlara verin.ToggleGroup'ta ise boyut gruba verilir. - Outline butonlar arasına ayırıcı koymak. Çerçeveler zaten ayrım sağlar; belge ayırıcıyı diğer varyantlar için önerir.
- Durum için ButtonGroup kullanmak. Seçili olanı göstermek istiyorsanız
ToggleGroupkullanın; o hem görünümü hem dedata-statebilgisini yönetir. - ToggleGroupItem'a value vermemek. Belgedeki API tablosunda
valuezorunlu olarak işaretlidir. - separator dosyasını eksik bırakmak. Elle kurulumda
button-group.tsxiçe aktardığıseparatorbileşenini de ister.
Sık Sorulan Sorular
ButtonGroup Radix kullanıyor mu?
Grubun kendisi düz bir div öğesidir. Radix yalnızca ButtonGroupText içindeki Slot ve ButtonGroupSeparator içindeki Separator üzerinden işin içine girer. Değişiklik günlüğü de Ekim 2025 bileşenlerinin Radix, Base UI ya da React Aria gibi farklı kütüphanelerle birlikte çalıştığını söyler.
ToggleGroup'u bir formda nasıl kullanırım?
Değeri value ve onValueChange ile kontrol edip form kütüphanenize bağlarsınız. Form tarafındaki kalıplar React Hook Form ve Zod yazısında anlatılıyor.
Gruptaki bir butonu diğerlerinden farklı renkte gösterebilir miyim?
Evet. ButtonGroup butonların varyantına dokunmaz; yalnızca köşe ve çerçeve birleştirmesini yapar. Bu yüzden bir gruptaki butonlara farklı variant değerleri verebilirsiniz. Belgenin ayırıcı notu burada da geçerlidir: dolu varyantları yan yana koyuyorsanız aralarına ButtonGroupSeparator eklemek sınırları belirginleştirir.
Toggle ile Switch arasındaki fark nedir?
İkisi de iki durumlu kontrollerdir. Toggle buton görünümündedir; belgedeki örneklerde kalın, italik, yer imi gibi araç çubuğu düğmeleri olarak kullanılır. Switch ise belgedeki "Airplane Mode" örneğindeki gibi bir ayarı açıp kapatan anahtar görünümündedir. Switch Checkbox, Radio Group, Switch ve Slider yazısında anlatılıyor.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: shadcn/ui öğrenme rehberi · Button varyantları · cva ile özelleştirme · Input ve Input Group · Dropdown Menu

