Radio group
קבוצת כפתורי רדיו מובנים עם מיקוד מקלדת נודד.
- דפדפנים
- Chrome 123+Firefox 121+Safari 17.5+
- שכבה
- 0
- גודל חבילה דחוסה
- 1.34 kB
- מגבלת פריסה כפויה
- 0 ms
- מגבלת Axe
- 0
- תואם SSR
- כן
- מבוסס על
- elements/choice
- חוזה מפורסם
- סביבת בדיקות
מגרש ניסויים
import { RadioGroup } from "@gunkin/uiify";
export default function Example() {
return (
<RadioGroup
className=""
id="plan"
aria-label="Billing plan"
defaultValue="pro"
items={[
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
]}
slotProps={{
item: { className: "" },
input: { className: "" },
label: { className: "" },
}}
/>
);
}/* Checkbox, Radio, Switch — all native <input>s styled with appearance:none.
State comes from :checked / :indeterminate (works uncontrolled) and the
[data-state] / [data-disabled] attributes (set when controlled). Thumbs and
checkmarks are pseudo-elements on the input itself. */
@layer components {
:where([data-uiify-checkbox] > input, [data-uiify-radio]) {
appearance: none;
inline-size: 1.25rem;
block-size: 1.25rem;
margin: 0;
border: var(--border-width) solid var(--input);
background-color: var(--card);
display: inline-grid;
place-content: center;
cursor: pointer;
transition: var(--transition-colors);
}
[data-uiify-checkbox] {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
cursor: pointer;
user-select: none;
color: var(--foreground);
font-size: var(--text-sm);
line-height: var(--leading-normal);
}
[data-uiify-checkbox] > input {
border-radius: var(--radius-xs);
}
[data-uiify-radio] {
border-radius: var(--radius-full);
}
/* Checked fill (covers controlled [data-state] and uncontrolled :checked). */
[data-uiify-checkbox] > input:checked,
[data-uiify-checkbox] > input[data-state="checked"] {
border-color: var(--primary);
background-color: var(--primary);
}
/* Radio checked state is a thick accent ring around a white center, not a
filled dot — matches the 2a/2b handoff's target/bullseye radio anatomy. */
[data-uiify-radio]:checked,
[data-uiify-radio][data-state="checked"] {
border-width: 5px;
border-color: var(--primary);
background-color: var(--card);
}
/* Checkmark. */
[data-uiify-checkbox] > input::before {
content: "";
inline-size: 1rem;
block-size: 1rem;
transform: scale(0);
transition: transform var(--duration-fast) var(--ease-out);
background-color: var(--primary-foreground);
clip-path: polygon(28.4% 46.4%, 20% 59%, 42.8% 80%, 80% 33.2%, 70.4% 23.6%, 42.8% 60.8%);
}
[data-uiify-checkbox] > input:checked::before,
[data-uiify-checkbox] > input[data-state="checked"]::before {
transform: scale(1);
}
/* Indeterminate dash. */
[data-uiify-checkbox] > input:indeterminate,
[data-uiify-checkbox] > input[data-state="indeterminate"] {
border-color: var(--primary);
background-color: var(--primary);
}
[data-uiify-checkbox] > input:indeterminate::before,
[data-uiify-checkbox] > input[data-state="indeterminate"]::before {
transform: scale(1);
clip-path: inset(42% 12% 42% 12%);
}
:where([data-uiify-checkbox] > input, [data-uiify-radio]):disabled,
:where([data-uiify-checkbox] > input, [data-uiify-radio])[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
[data-uiify-checkbox]:has(> input:disabled) {
opacity: 0.5;
cursor: not-allowed;
}
[data-uiify-radio-group] {
display: flex;
flex-direction: column;
gap: var(--space-md);
}
/* Switch — a pill track with a sliding thumb pseudo-element. */
[data-uiify-switch] {
appearance: none;
position: relative;
inline-size: 2.25rem;
block-size: 1.25rem;
margin: 0;
flex: none;
border: none;
border-radius: var(--radius-full);
background-color: var(--input);
cursor: pointer;
transition: background-color var(--duration-fast) var(--ease-out);
}
[data-uiify-switch]::before {
content: "";
position: absolute;
inset-block-start: 2px;
inset-inline-start: 2px;
inline-size: calc(1.25rem - 4px);
block-size: calc(1.25rem - 4px);
border-radius: var(--radius-full);
background-color: var(--gray-0);
box-shadow: var(--shadow-1);
transition: translate var(--duration-fast) var(--ease-out);
}
[data-uiify-switch]:checked,
[data-uiify-switch][data-state="checked"] {
background-color: var(--primary);
}
[data-uiify-switch]:checked::before,
[data-uiify-switch][data-state="checked"]::before {
translate: 1rem 0;
}
[data-uiify-switch]:disabled,
[data-uiify-switch][data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
}
@layer components {
label:has([data-uiify-radio]),
[data-uiify-radio-group] label {
user-select: none;
cursor: pointer;
}
}import { RadioGroup } from "@gunkin/uiify";
export default function Example() {
return (
<RadioGroup
className="flex flex-col gap-md p-md data-[orientation=horizontal]:flex-row"
id="plan"
aria-label="Billing plan"
defaultValue="pro"
items={[
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
]}
slotProps={{
item: { className: "flex items-center gap-sm" },
input: {
className:
"appearance-none inline-grid size-5 flex-none place-content-center m-0 " +
"border-[length:var(--border-width)] border-solid border-input rounded-full " +
"bg-card cursor-pointer [transition:var(--transition-colors)] " +
"checked:border-[5px] checked:border-primary data-[state=checked]:border-[5px] " +
"data-[state=checked]:border-primary focus-visible:outline-none " +
"focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_20%,_transparent)] " +
"disabled:opacity-50 disabled:cursor-not-allowed data-[disabled]:opacity-50 " +
"data-[disabled]:cursor-not-allowed",
},
label: { className: "flex-auto cursor-pointer select-none" },
}}
/>
);
}API
RadioGroup
| מאפיין | טיפוס | ברירת מחדל | תיאור |
|---|---|---|---|
id* | string | — | קידומת מזהה לקבוצה ולכל קלט רדיו שנוצר. |
items* | RadioGroupItem[] | — | האפשרויות להצגה; הקבוצה מונעת מנתונים ולא מורכבת מחלקים. |
defaultValue | string | — | הערך המסומן בהצגה הראשונה; מכאן והלאה הדפדפן מנהל את הבחירה, ולכן הקבוצה פועלת ללא JavaScript. |
name | string | — | שם שדה הטופס המשותף לכל קלטי הרדיו בקבוצה. |
disabled | boolean | false | משבית את כל קלטי הרדיו בקבוצה. |
orientation | "horizontal" | "vertical" | "vertical" | כיוון הפריסה המדווח לטכנולוגיות מסייעות ומשמש לעיצוב. |
className | string | — | המחלקה המוחלת על אלמנט הקבוצה. |
slotProps | RadioGroupSlotProps | — | מאפיינים מובנים לאלמנטי הפריט, הקלט והתווית שנוצרים; ניתן למקד משבצות חוזרות בפריט לפי ערכו. |
aria-label | string | — | שם נגיש לקבוצת הרדיו. |
RadioGroupItem
| מאפיין | טיפוס | ברירת מחדל | תיאור |
|---|---|---|---|
value* | string | — | הערך הנשלח כשקלט רדיו זה נבחר. |
label* | ReactNode | — | תוכן התווית המוצג לצד קלט רדיו זה. |
disabled | boolean | — | משבית רק את קלט הרדיו הזה. |
className | string | — | המחלקה המוחלת על קלט הרדיו המובנה של פריט זה. |
מקלדת
| מקש | פעולה |
|---|---|
| Tab | העברת המיקוד לקבוצה |
| Arrow keys | מעבר ובחירה בין אפשרויות |
נגישות
כפתורי רדיו מובנים בקבוצה עם מיקוד נודד.
נקודות חיבור לעיצוב
data-statedata-disabled