1import { Label } from "@/components/ui/pxl/label";2import { RadioGroup, RadioGroupItem } from "@/components/ui/pxl/radio-group";3
4export default function RadioGroupPreview() {5 return (6 <div className="flex items-center justify-center">7 <RadioGroup className="w-auto" defaultValue="comfortable">8 <div className="flex items-center gap-2">9 <RadioGroupItem id="r1" value="default" />10 <Label htmlFor="r1">Default</Label>11 </div>12 <div className="flex items-center gap-2">13 <RadioGroupItem id="r2" value="comfortable" />14 <Label htmlFor="r2">Comfortable</Label>15 </div>16 <div className="flex items-center gap-2">17 <RadioGroupItem id="r3" value="compact" />18 <Label htmlFor="r3">Compact</Label>19 </div>20 </RadioGroup>21 </div>22 );23}Installation
Section titled “Installation”pnpm dlx shadcn@latest add pxl-ui/registry/radio-group
Install the following dependencies:
pnpm add @base-ui/react
Copy and paste the following code into your project.
1"use client";2
3import { Radio as RadioPrimitive } from "@base-ui/react/radio";4import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";5import { cva } from "class-variance-authority";6import {7 type ComponentProps,8 type ComponentType,9 createContext,10 useContext,11} from "react";12
13import { cn } from "@/lib/utils";14
15const radioGroupVariants = cva("grid w-full gap-3", {16 variants: {17 variant: {18 default: "[--radio-accent:var(--foreground)]",19 primary: "[--radio-accent:var(--primary-foreground)]",20 success: "[--radio-accent:var(--success-foreground)]",21 warning: "[--radio-accent:var(--warning-foreground)]",22 info: "[--radio-accent:var(--info-foreground)]",23 danger: "[--radio-accent:var(--danger-foreground)]",24 },25 },26 defaultVariants: {27 variant: "default",28 },29});30
31const RadioGroupContext = createContext<{32 indicator?: ComponentType;33}>({});34
35function RadioGroupCheckIndicator() {36 return (37 <svg38 className="size-3.5 text-(--radio-accent)"39 xmlns="http://www.w3.org/2000/svg"40 fill="currentColor"41 viewBox="0 0 24 24"42 >43 <path d="M10 18H8v-2h2v2Zm-2-2H6v-2h2v2Zm4-2v2h-2v-2h2Zm-6 0H4v-2h2v2Zm8 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2Zm2-2h-2V6h2v2Z" />44 </svg>45 );46}47function RadioGroupCrossIndicator() {48 return (49 <svg50 className="size-3.5 text-(--radio-accent)"51 xmlns="http://www.w3.org/2000/svg"52 fill="currentColor"53 viewBox="0 0 24 24"54 >55 <path d="M7 19H5v-2h2v2Zm12 0h-2v-2h2v2ZM9 15v2H7v-2h2Zm8 2h-2v-2h2v2Zm-6-2H9v-2h2v2Zm4 0h-2v-2h2v2Zm-2-2h-2v-2h2v2Zm-2-2H9V9h2v2Zm4 0h-2V9h2v2ZM9 9H7V7h2v2Zm8 0h-2V7h2v2ZM7 7H5V5h2v2Zm12 0h-2V5h2v2Z" />56 </svg>57 );58}59
60function RadioGroupCircleIndicator() {61 return (62 <svg63 className="size-2 text-(--radio-accent)"64 xmlns="http://www.w3.org/2000/svg"65 fill="currentColor"66 viewBox="0 0 24 24"67 >68 <path d="M18 4h2v2h2v12h-2v2h-2v2H6v-2H4v-2H2V6h2V4h2V2h12v2Z"></path>69 </svg>70 );71}72
73function RadioGroupMinusIndicator() {74 return (75 <svg76 className="size-3.5 text-(--radio-accent)"77 xmlns="http://www.w3.org/2000/svg"78 fill="currentColor"79 viewBox="0 0 24 24"80 >81 <path d="M4 11h16v2H4z"></path>82 </svg>83 );84}85
86function RadioGroupPlusIndicator() {87 return (88 <svg89 className="size-3.5 text-(--radio-accent)"90 xmlns="http://www.w3.org/2000/svg"91 fill="currentColor"92 viewBox="0 0 24 24"93 >94 <path d="M13 11h7v2h-7v7h-2v-7H4v-2h7V4h2v7Z"></path>95 </svg>96 );97}98
99function RadioGroupSlashIndicator() {100 return (101 <svg102 className="size-3.5 text-(--radio-accent) -rotate-45"103 xmlns="http://www.w3.org/2000/svg"104 fill="currentColor"105 viewBox="0 0 24 24"106 >107 <path d="M4 11h16v2H4z"></path>108 </svg>109 );110}111
112function RadioGroup({113 className,114 variant = "default",115 indicator = RadioGroupCircleIndicator,116 ...props117}: RadioGroupPrimitive.Props &118 ComponentProps<typeof radioGroupVariants> & {119 indicator?: ComponentType;120 }) {121 return (122 <RadioGroupContext.Provider value={{ indicator }}>123 <RadioGroupPrimitive124 data-slot="radio-group"125 className={cn(radioGroupVariants({ variant }), className)}126 {...props}127 />128 </RadioGroupContext.Provider>129 );130}131
132function RadioGroupItem({133 className,134 indicator,135 ...props136}: RadioPrimitive.Root.Props & {137 indicator?: ComponentType;138}) {139 const ctx = useContext(RadioGroupContext);140 const Indicator = indicator ?? ctx.indicator;141
142 return (143 <RadioPrimitive.Root144 data-slot="radio-group-item"145 className={cn(146 "group/radio-group-item peer relative flex aspect-square size-4 shrink-0 pixel-rounded pixel-border pixel-size-md pixel-color-input outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:pixel-color-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:pixel-color-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:pixel-color-[color-mix(in_oklab,var(--destructive)_50%,transparent)] dark:aria-invalid:ring-destructive/40",147 "data-checked:[--pixel-color:var(--radio-accent)]",148 className,149 )}150 {...props}151 >152 <RadioPrimitive.Indicator153 data-slot="radio-group-indicator"154 className="flex size-4 items-center justify-center"155 >156 {Indicator && <Indicator />}157 </RadioPrimitive.Indicator>158 </RadioPrimitive.Root>159 );160}161
162export {163 RadioGroup,164 RadioGroupCheckIndicator,165 RadioGroupCircleIndicator,166 RadioGroupCrossIndicator,167 RadioGroupItem,168 RadioGroupMinusIndicator,169 RadioGroupPlusIndicator,170 RadioGroupSlashIndicator,171};Update the import paths to match your project setup.
import { Label } from "@/components/ui/pxl/label"import { RadioGroup, RadioGroupItem } from "@/components/ui/pxl/radio-group"<RadioGroup defaultValue="option-one"> <div className="flex items-center gap-3"> <RadioGroupItem value="option-one" id="option-one" /> <Label htmlFor="option-one">Option One</Label> </div> <div className="flex items-center gap-3"> <RadioGroupItem value="option-two" id="option-two" /> <Label htmlFor="option-two">Option Two</Label> </div></RadioGroup>Composition
Section titled “Composition”Use the following composition to build a RadioGroup:
RadioGroup├── RadioGroupItem└── RadioGroupItemVariants
Section titled “Variants”1import { Label } from "@/components/ui/pxl/label";2import {3 RadioGroup,4 RadioGroupCheckIndicator,5 RadioGroupCrossIndicator,6 RadioGroupItem,7 RadioGroupMinusIndicator,8 RadioGroupPlusIndicator,9 RadioGroupSlashIndicator,10} from "@/components/ui/pxl/radio-group";11
12export default function RadioGroupVariants() {13 return (14 <div className="flex flex-row flex-wrap gap-8 items-center justify-center">15 <RadioGroup16 variant="primary"17 indicator={RadioGroupPlusIndicator}18 className="w-auto"19 defaultValue="default"20 >21 <div className="flex items-center gap-2">22 <RadioGroupItem id="primary_r1" value="default" />23 <Label htmlFor="primary_r1">Default</Label>24 </div>25 <div className="flex items-center gap-2">26 <RadioGroupItem id="primary_r2" value="comfortable" />27 <Label htmlFor="primary_r2">Comfortable</Label>28 </div>29 <div className="flex items-center gap-2">30 <RadioGroupItem id="primary_r3" value="compact" />31 <Label htmlFor="primary_r3">Compact</Label>32 </div>33 </RadioGroup>34 <RadioGroup35 variant="success"36 indicator={RadioGroupCheckIndicator}37 className="w-auto"38 defaultValue="comfortable"39 >40 <div className="flex items-center gap-2">41 <RadioGroupItem id="success_r1" value="default" />42 <Label htmlFor="success_r1">Default</Label>43 </div>44 <div className="flex items-center gap-2">45 <RadioGroupItem id="success_r2" value="comfortable" />46 <Label htmlFor="success_r2">Comfortable</Label>47 </div>48 <div className="flex items-center gap-2">49 <RadioGroupItem id="success_r3" value="compact" />50 <Label htmlFor="success_r3">Compact</Label>51 </div>52 </RadioGroup>53 <RadioGroup54 variant="danger"55 indicator={RadioGroupCrossIndicator}56 className="w-auto"57 defaultValue="compact"58 >59 <div className="flex items-center gap-2">60 <RadioGroupItem id="danger_r1" value="default" />61 <Label htmlFor="danger_r1">Default</Label>62 </div>63 <div className="flex items-center gap-2">64 <RadioGroupItem id="danger_r2" value="comfortable" />65 <Label htmlFor="danger_r2">Comfortable</Label>66 </div>67 <div className="flex items-center gap-2">68 <RadioGroupItem id="danger_r3" value="compact" />69 <Label htmlFor="danger_r3">Compact</Label>70 </div>71 </RadioGroup>72 <RadioGroup73 variant="warning"74 indicator={RadioGroupMinusIndicator}75 className="w-auto"76 defaultValue="comfortable"77 >78 <div className="flex items-center gap-2">79 <RadioGroupItem id="warning_r1" value="default" />80 <Label htmlFor="warning_r1">Default</Label>81 </div>82 <div className="flex items-center gap-2">83 <RadioGroupItem id="warning_r2" value="comfortable" />84 <Label htmlFor="warning_r2">Comfortable</Label>85 </div>86 <div className="flex items-center gap-2">87 <RadioGroupItem id="warning_r3" value="compact" />88 <Label htmlFor="warning_r3">Compact</Label>89 </div>90 </RadioGroup>91 <RadioGroup92 variant="info"93 indicator={RadioGroupSlashIndicator}94 className="w-auto"95 defaultValue="default">96 <div className="flex items-center gap-2">97 <RadioGroupItem id="info_r1" value="default" />98 <Label htmlFor="info_r1">Default</Label>99 </div>100 <div className="flex items-center gap-2">101 <RadioGroupItem id="info_r2" value="comfortable" />102 <Label htmlFor="info_r2">Comfortable</Label>103 </div>104 <div className="flex items-center gap-2">105 <RadioGroupItem id="info_r3" value="compact" />106 <Label htmlFor="info_r3">Compact</Label>107 </div>108 </RadioGroup>109 </div>110 );111}API Reference
Section titled “API Reference”See the Base UI Radio Group documentation.