diff --git a/package-lock.json b/package-lock.json index 4561a56..99f8a8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.4", @@ -4372,6 +4373,38 @@ } } }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "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 + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", diff --git a/package.json b/package.json index b4f3ed5..f0c73f4 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.4", diff --git a/src/renderer/components/ui/radio-group.tsx b/src/renderer/components/ui/radio-group.tsx new file mode 100644 index 0000000..d34dfdf --- /dev/null +++ b/src/renderer/components/ui/radio-group.tsx @@ -0,0 +1,41 @@ +import * as React from "react" +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" +import { Circle } from "lucide-react" +import { cn } from "@/lib/utils" + +const RadioGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + + + + + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + +export { RadioGroup, RadioGroupItem } diff --git a/tests/component/ui/radio-group.test.tsx b/tests/component/ui/radio-group.test.tsx new file mode 100644 index 0000000..f091a5e --- /dev/null +++ b/tests/component/ui/radio-group.test.tsx @@ -0,0 +1,18 @@ +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; + +describe('RadioGroup', () => { + it('selects the clicked item', async () => { + const onValueChange = vi.fn(); + render( + + + + + ); + await userEvent.click(screen.getByRole('radio', { name: /b/i })); + expect(onValueChange).toHaveBeenCalledWith('b'); + }); +});