Skip to content

Commit 4988971

Browse files
committed
wip: feat: radio-group and radio
1 parent 17722f9 commit 4988971

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import type { Meta } from '@storybook/react';
2+
3+
import { Radio, RadioGroup } from '@/components/ui/radio-group';
4+
5+
export default {
6+
title: 'Radio Group',
7+
} satisfies Meta<typeof RadioGroup>;
8+
9+
const astrobears = [
10+
{
11+
value: 'bearstrong',
12+
label: 'Bearstrong',
13+
},
14+
{
15+
value: 'pawdrin',
16+
label: 'Buzz Pawdrin',
17+
},
18+
{
19+
value: 'grizzlyrin',
20+
label: 'Yuri Grizzlyrin',
21+
},
22+
{
23+
value: 'jemibear',
24+
label: 'Mae Jemibear',
25+
disabled: true,
26+
},
27+
{
28+
value: 'ridepaw',
29+
label: 'Sally Ridepaw',
30+
},
31+
{
32+
value: 'michaelpawanderson',
33+
label: 'Michael Paw Anderson',
34+
},
35+
] as const;
36+
37+
export const Default = () => {
38+
return (
39+
<RadioGroup>
40+
{astrobears.map(({ value, label }) => {
41+
return (
42+
<Radio key={value} value={value} id={value}>
43+
{label}
44+
</Radio>
45+
);
46+
})}
47+
</RadioGroup>
48+
);
49+
};
50+
51+
export const DefaultValue = () => {
52+
return (
53+
<RadioGroup defaultValue={astrobears[1].value}>
54+
{astrobears.map(({ value, label }) => {
55+
return (
56+
<Radio key={value} value={value} id={value}>
57+
{label}
58+
</Radio>
59+
);
60+
})}
61+
</RadioGroup>
62+
);
63+
};
64+
65+
export const Disabled = () => {
66+
return (
67+
<RadioGroup defaultValue={astrobears[1].value} disabled>
68+
{astrobears.map(({ value, label }) => {
69+
return (
70+
<Radio key={value} value={value} id={value}>
71+
{label}
72+
</Radio>
73+
);
74+
})}
75+
</RadioGroup>
76+
);
77+
};
78+
79+
export const Row = () => {
80+
return (
81+
<RadioGroup className="flex-row gap-4">
82+
{astrobears.map(({ value, label }) => {
83+
return (
84+
<Radio key={value} value={value} id={value}>
85+
{label}
86+
</Radio>
87+
);
88+
})}
89+
</RadioGroup>
90+
);
91+
};

app/components/ui/radio-group.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use client';
2+
3+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
4+
import { Circle } from 'lucide-react';
5+
import * as React from 'react';
6+
7+
import { cn } from '@/lib/tailwind/utils';
8+
9+
type RadioGroupProps = React.ComponentProps<typeof RadioGroupPrimitive.Root>;
10+
function RadioGroup({ className, ...props }: RadioGroupProps) {
11+
return (
12+
<RadioGroupPrimitive.Root
13+
className={cn('flex flex-col gap-2', className)}
14+
{...props}
15+
/>
16+
);
17+
}
18+
19+
type RadioProps = React.ComponentProps<typeof RadioGroupPrimitive.Item> & {
20+
containerProps?: React.ComponentProps<'div'>;
21+
labelProps?: React.ComponentProps<'label'>;
22+
};
23+
function Radio({
24+
containerProps,
25+
labelProps,
26+
className,
27+
value,
28+
children,
29+
...props
30+
}: RadioProps) {
31+
return (
32+
<div
33+
{...containerProps}
34+
className={cn('flex items-center space-x-2', containerProps?.className)}
35+
>
36+
<RadioGroupPrimitive.Item
37+
className={cn(
38+
'peer aspect-square h-4 w-4 cursor-pointer rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
39+
className
40+
)}
41+
id={value}
42+
value={value}
43+
{...props}
44+
>
45+
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
46+
<Circle className="h-2.5 w-2.5 fill-current text-current" />
47+
</RadioGroupPrimitive.Indicator>
48+
</RadioGroupPrimitive.Item>
49+
<label
50+
htmlFor={value}
51+
{...labelProps}
52+
className={cn(
53+
'cursor-pointer peer-disabled:cursor-not-allowed',
54+
labelProps?.className
55+
)}
56+
>
57+
{children}
58+
</label>
59+
</div>
60+
);
61+
}
62+
export { Radio, RadioGroup };

0 commit comments

Comments
 (0)