HextaUI

Radio group

Bir kümeden tek seçenek seçin; seçimler arasında devredilen bir nokta ve seçim halkası yeni seçime kayan kartlarla.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

const options = [
  { value: "all", label: "All new messages" },
  { value: "mentions", label: "Direct messages and mentions" },
  { value: "none", label: "Nothing" },
]

export function RadioGroupDemo() {
  return (
    <RadioGroup
      aria-label="Notify me about"
      defaultValue="mentions"
      className="w-fit"
    >
      {options.map((option) => (
        <label key={option.value} className="flex items-center gap-3 text-sm">
          <RadioGroupItem value={option.value} />
          {option.label}
        </label>
      ))}
    </RadioGroup>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/radio-group.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
<RadioGroup aria-label="Notify me about" defaultValue="mentions">
  <label className="flex items-center gap-3">
    <RadioGroupItem value="all" />
    All new messages
  </label>
  <label className="flex items-center gap-3">
    <RadioGroupItem value="mentions" />
    Direct messages and mentions
  </label>
</RadioGroup>

Seçim değiştiğinde eski nokta küçülüp kaybolurken yenisi yay gibi belirir; böylece göz iki şeyin aynı anda yanıp sönmesi yerine seçimi izler. Tüm satır tıklanabilir olsun diye her öğeyi bir <label> ile sarın.

RadioGroup
├── RadioGroupItem
└── RadioGroupCard
    ├── RadioGroupCardTitle
    └── RadioGroupCardDescription

Kartlar

variant="card" ile söyleyecek daha çok şeyi olan seçenekler için RadioGroupCard kullanın. Seçim halkası yeni karta kayarken yüzeyi solarak belirir.

import {
  RadioGroup,
  RadioGroupCard,
  RadioGroupCardDescription,
  RadioGroupCardTitle,
} from "@/components/ui/radio-group"

const plans = [
  {
    value: "hobby",
    title: "Hobby",
    price: "Free",
    description: "For side projects and trying things out.",
  },
  {
    value: "pro",
    title: "Pro",
    price: "$20/mo",
    description: "Unlimited projects, analytics and priority builds.",
  },
  {
    value: "team",
    title: "Team",
    price: "$60/mo",
    description: "Everything in Pro, plus roles and audit logs.",
  },
]

export function RadioGroupCards() {
  return (
    <RadioGroup
      variant="card"
      aria-label="Plan"
      defaultValue="pro"
      className="max-w-md"
    >
      {plans.map((plan) => (
        <RadioGroupCard key={plan.value} value={plan.value}>
          <span className="flex items-baseline justify-between gap-3">
            <RadioGroupCardTitle>{plan.title}</RadioGroupCardTitle>
            <span className="text-muted-foreground tabular-nums">
              {plan.price}
            </span>
          </span>
          <RadioGroupCardDescription>
            {plan.description}
          </RadioGroupCardDescription>
        </RadioGroupCard>
      ))}
    </RadioGroup>
  )
}

Yatay

Kartlar bir satırda veya herhangi bir ızgarada durabilir. Halka onları nerede olurlarsa olsunlar izler.

import {
  RadioGroup,
  RadioGroupCard,
  RadioGroupCardTitle,
} from "@/components/ui/radio-group"

const sizes = ["S", "M", "L", "XL"]

export function RadioGroupHorizontal() {
  return (
    <RadioGroup
      variant="card"
      aria-label="Size"
      defaultValue="M"
      className="w-full max-w-sm grid-cols-2 sm:grid-cols-4"
    >
      {sizes.map((size) => (
        <RadioGroupCard key={size} value={size}>
          <RadioGroupCardTitle>{size}</RadioGroupCardTitle>
        </RadioGroupCard>
      ))}
    </RadioGroup>
  )
}

Form

Field ve FieldSet içinde grup bir başlık, zorunlu doğrulama ve bir hata mesajı alır.

"use client"

import * as React from "react"
import { Form } from "@base-ui/react/form"

import { Button } from "@/components/ui/button"
import {
  Field,
  FieldError,
  FieldItem,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

export function RadioGroupForm() {
  const [submitted, setSubmitted] = React.useState<string>()

  return (
    <Form
      className="flex w-full max-w-xs flex-col items-start gap-4"
      onSubmit={(event) => {
        event.preventDefault()
        setSubmitted(String(new FormData(event.currentTarget).get("shipping")))
      }}
    >
      <Field name="shipping">
        <FieldSet render={<RadioGroup required />}>
          <FieldLegend variant="label">Shipping</FieldLegend>
          {["Standard", "Express", "Overnight"].map((option) => (
            <FieldItem key={option}>
              <RadioGroupItem value={option.toLowerCase()} />
              <FieldLabel>{option}</FieldLabel>
            </FieldItem>
          ))}
        </FieldSet>
        <FieldError match="valueMissing">Choose a shipping speed.</FieldError>
      </Field>
      <Button type="submit" size="sm">
        Continue
      </Button>
      <output className="text-sm text-muted-foreground">
        {submitted ? `shipping=${submitted}` : "Nothing submitted yet."}
      </output>
    </Form>
  )
}

Devre dışı ve salt okunur

Tek bir seçeneği devre dışı bırakın ya da değişemeyen bir değeri göstermek için tüm grubu readOnly yapın.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

export function RadioGroupStates() {
  return (
    <div className="flex flex-wrap gap-12 text-sm">
      <RadioGroup aria-label="Theme" defaultValue="system" className="w-fit">
        <label className="flex items-center gap-3">
          <RadioGroupItem value="light" />
          Light
        </label>
        <label className="flex items-center gap-3">
          <RadioGroupItem value="dark" disabled />
          Dark (coming soon)
        </label>
        <label className="flex items-center gap-3">
          <RadioGroupItem value="system" />
          System
        </label>
      </RadioGroup>
      <RadioGroup
        aria-label="Region"
        defaultValue="eu"
        readOnly
        className="w-fit"
      >
        <label className="flex items-center gap-3">
          <RadioGroupItem value="us" />
          United States
        </label>
        <label className="flex items-center gap-3">
          <RadioGroupItem value="eu" />
          Europe (locked)
        </label>
      </RadioGroup>
    </div>
  )
}

Kontrollü

value ve onValueChange verin. Dışarıdan gelen değişiklikler tıklamalarla aynı şekilde animasyonlanır.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

const speeds = ["0.5×", "1×", "1.5×", "2×"]

export function RadioGroupControlled() {
  const [speed, setSpeed] = React.useState("1×")

  return (
    <div className="flex flex-col items-start gap-4 text-sm">
      <RadioGroup
        aria-label="Playback speed"
        value={speed}
        onValueChange={setSpeed}
        className="flex w-fit flex-wrap"
      >
        {speeds.map((value) => (
          <label key={value} className="flex items-center gap-2 tabular-nums">
            <RadioGroupItem value={value} />
            {value}
          </label>
        ))}
      </RadioGroup>
      <Button
        variant="outline"
        size="sm"
        onClick={() =>
          setSpeed(speeds[(speeds.indexOf(speed) + 1) % speeds.length])
        }
      >
        Next speed
      </Button>
    </div>
  )
}

Sağdan sola

Radyolar ve kartlar okuma yönünü izler.

import {
  RadioGroup,
  RadioGroupCard,
  RadioGroupCardDescription,
  RadioGroupCardTitle,
} from "@/components/ui/radio-group"

export function RadioGroupRtl() {
  return (
    <div dir="rtl" className="w-full max-w-sm">
      <RadioGroup variant="card" aria-label="طريقة الدفع" defaultValue="card">
        <RadioGroupCard value="card">
          <RadioGroupCardTitle>بطاقة ائتمان</RadioGroupCardTitle>
          <RadioGroupCardDescription>
            فيزا أو ماستركارد.
          </RadioGroupCardDescription>
        </RadioGroupCard>
        <RadioGroupCard value="cash">
          <RadioGroupCardTitle>الدفع عند الاستلام</RadioGroupCardTitle>
          <RadioGroupCardDescription>
            ادفع نقدًا عند التوصيل.
          </RadioGroupCardDescription>
        </RadioGroupCard>
      </RadioGroup>
    </div>
  )
}
TuşAction
TabOdağı gruba, seçili seçeneğe ya da ilkine taşır.
↑↓←→Önceki veya sonraki seçeneğe gider ve onu seçer; uçlarda başa sarar.
SpaceOdaktaki seçeneği seçer.
  • Grubu aria-label, aria-labelledby veya bir FieldLegend ile adlandırın.
  • Her radyonun 36px, dokunmatik ekranlarda 44px'lik bir tıklama alanı vardır; ekranda 16px kalır.
  • Azaltılmış harekette nokta ve kart halkası hareket etmez.
PropTürVarsayılan
variantcard, kayan seçim halkasını ekler.
"default" | "card""default"
value
Value–
defaultValue
Value–
onValueChange
(value, details) => void–
name
string–
required
booleanfalse
disabled
booleanfalse
readOnly
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="radio-group"Grup; data-variant ile.
data-slot="radio-group-highlight"Kartlar arasında kayan halka.
data-disabledGrup devre dışı.
PropTürVarsayılan
value
Value–
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<span>
ÖznitelikAçıklama
data-slot="radio-group-item"Radyo.
data-checked / data-uncheckedSeçili seçenek olup olmadığı.
data-disabled / data-readonlyDeğiştirilemediğinde bulunur.
PropTürVarsayılan
value
Value–
disabled
booleanfalse
radioClassNameKartın içindeki radyo için sınıflar.
string–

Radyonun yerleşik olduğu bir <label>. İçine RadioGroupCardTitle ve RadioGroupCardDescription ya da başka herhangi bir şey koyun.