diff --git a/package.json b/package.json index d0ae9f0f..110b87bc 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@radix-ui/react-dialog": "^1.1.10", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-switch": "^1.2.4", "@radix-ui/react-toggle": "^1.1.9", diff --git a/src/shared/ui/radio/index.tsx b/src/shared/ui/radio/index.tsx new file mode 100644 index 00000000..54db934e --- /dev/null +++ b/src/shared/ui/radio/index.tsx @@ -0,0 +1,53 @@ +'use client'; + +import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; +import { cva } from 'class-variance-authority'; +import * as React from 'react'; +import { cn } from '@/shared/shadcn/lib/utils'; + +function RadioGroup({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +const radioGroupItemVariants = cva( + 'border-border-default hover:bg-fill-neutral-subtle-hover disabled:border-border-disabled disabled:bg-icon-disabled data-[state=checked]:border-border-success rounded-full border-2 bg-white data-[state=checked]:border-4', + { + variants: { + size: { + medium: 'h-[16px] w-[16px]', + large: 'h-[20px] w-[20px]', + }, + }, + defaultVariants: { + size: 'large', + }, + }, +); + +function RadioGroupItem({ + size = 'large', + className, + ...props +}: { size?: 'medium' | 'large' } & React.ComponentProps< + typeof RadioGroupPrimitive.RadioGroupItem +>) { + return ( + + + + ); +} + +export { RadioGroup, RadioGroupItem }; diff --git a/src/stories/ui/radio.stories.tsx b/src/stories/ui/radio.stories.tsx new file mode 100644 index 00000000..5c91f1c4 --- /dev/null +++ b/src/stories/ui/radio.stories.tsx @@ -0,0 +1,49 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { useState } from 'react'; +import Button from '@/shared/ui/button'; +import { RadioGroup, RadioGroupItem } from '@/shared/ui/radio'; + +const meta: Meta = { + component: RadioGroup, + parameters: { + docs: { + description: { + story: 'RadioGroupItem 컴포넌트의 id와 label의 htmlFor을 맞춰주세요.', + }, + }, + }, + tags: ['autodocs'], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => { + const [state, setState] = useState<'first' | 'second'>('first'); + + return ( +
+ setState(value)} + > +
+ + +
+
+ + + +
+
+ + +
+ ); + }, +}; diff --git a/yarn.lock b/yarn.lock index fb80f80e..713ffc5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3024,6 +3024,34 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-radio-group@npm:^1.3.8": + version: 1.3.8 + resolution: "@radix-ui/react-radio-group@npm:1.3.8" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-roving-focus": "npm:1.1.11" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + "@radix-ui/react-use-previous": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/23af8e8b833da1fc4aa4e67c3607dedee4fc5b39278d2e2b820bec7f7b3c0891b006a8a35c57ba436ddf18735bbd8dad9a598d14632a328753a875fde447975c + languageName: node + linkType: hard + "@radix-ui/react-roving-focus@npm:1.1.10": version: 1.1.10 resolution: "@radix-ui/react-roving-focus@npm:1.1.10" @@ -3051,6 +3079,33 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-roving-focus@npm:1.1.11": + version: 1.1.11 + resolution: "@radix-ui/react-roving-focus@npm:1.1.11" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/2cd43339c36e89a3bf1db8aab34b939113dfbde56bf3a33df2d74757c78c9489b847b1962f1e2441c67e41817d120cb6177943e0f655f47bc1ff8e44fd55b1a2 + languageName: node + linkType: hard + "@radix-ui/react-slot@npm:1.2.0": version: 1.2.0 resolution: "@radix-ui/react-slot@npm:1.2.0" @@ -10753,6 +10808,7 @@ __metadata: "@radix-ui/react-dialog": "npm:^1.1.10" "@radix-ui/react-dropdown-menu": "npm:^2.1.15" "@radix-ui/react-progress": "npm:^1.1.7" + "@radix-ui/react-radio-group": "npm:^1.3.8" "@radix-ui/react-slot": "npm:^1.2.2" "@radix-ui/react-switch": "npm:^1.2.4" "@radix-ui/react-toggle": "npm:^1.1.9"