Radio Group
A mutually exclusive set of selectable options.
- Chromium
- Firefox
- WebKit
- WCAG 2.2 AA
Preview
import { Label } from "@moe-ui/registry/components/ui/label";
import {
RadioGroup,
RadioGroupItem,
} from "@moe-ui/registry/components/ui/radio-group";
import { View } from "react-native";
export default function RadioGroupPreview() {
return (
<RadioGroup defaultValue="option-one">
<View className="flex-row items-center gap-2">
<RadioGroupItem
accessibilityLabel="Option One"
value="option-one"
id="option-one"
/>
<Label htmlFor="option-one">Option One</Label>
</View>
<View className="flex-row items-center gap-2">
<RadioGroupItem
accessibilityLabel="Option Two"
value="option-two"
id="option-two"
/>
<Label htmlFor="option-two">Option Two</Label>
</View>
</RadioGroup>
);
}
One command, your source
Installation
pnpm dlx @moe-ui/cli@beta add radio-groupUsage
The CLI installs editable source into your application. Import the component from your configured UI directory:
import { RadioGroup } from "@/components/ui/radio-group";Variants and composition
Compound parts and variants remain regular source in your project, so you can change them without wrapping a package API.
Public API
The canonical source panel below lists every public export, dependency, and the complete implementation shipped by the registry.
Keyboard and accessibility
Associate the control with a visible label. Keyboard focus, disabled state, and validation semantics are covered by the web test matrix.
Browser support
This beta is release-tested in Chromium, Firefox, and WebKit in light and dark themes. See the web compatibility matrix for the current gate.
Nothing hiddenCanonical source and public exports2 exports
RadioGroupRadioGroupItem"use client";
import { cn } from "../../lib/utils";
import * as RadioGroupPrimitive from "@rn-primitives/radio-group";
import * as React from "react";
import { Platform } from "react-native";
function RadioGroup({
className,
value: valueProp,
defaultValue,
onValueChange,
...props
}: Omit<RadioGroupPrimitive.RootProps, "value" | "onValueChange"> &
React.RefAttributes<RadioGroupPrimitive.RootRef> & {
value?: string;
defaultValue?: string;
onValueChange?: (value: string) => void;
}) {
const [uncontrolledValue, setUncontrolledValue] =
React.useState(defaultValue);
const value = valueProp ?? uncontrolledValue;
return (
<RadioGroupPrimitive.Root
className={cn("gap-3", className)}
value={value}
onValueChange={(nextValue) => {
if (valueProp === undefined) setUncontrolledValue(nextValue);
onValueChange?.(nextValue);
}}
{...props}
/>
);
}
function RadioGroupItem({
className,
...props
}: RadioGroupPrimitive.ItemProps &
React.RefAttributes<RadioGroupPrimitive.ItemRef>) {
return (
<RadioGroupPrimitive.Item
className={cn(
"border-input dark:bg-input/30 aspect-square size-4 shrink-0 items-center justify-center rounded-full border shadow-sm shadow-black/5",
Platform.select({
web: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive outline-none transition-all focus-visible:ring-[3px] disabled:cursor-not-allowed",
}),
props.disabled && "opacity-50",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="bg-primary size-2 rounded-full" />
</RadioGroupPrimitive.Item>
);
}
export { RadioGroup, RadioGroupItem };