Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/components/ui/RadioGroup/RadioGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,26 @@ import RadioGroupItem from './fragments/RadioGroupItem';
import RadioGroupIndicator from './fragments/RadioGroupIndicator';
import RadioGroupLabel from './fragments/RadioGroupLabel';

// Empty props type - only supporting fragment exports
export type RadioGroupProps = React.HTMLAttributes<HTMLDivElement> & {
export type RadioGroupElement = React.ElementRef<'div'>;

export type RadioGroupProps = React.ComponentPropsWithoutRef<'div'> & {
children?: React.ReactNode;
};

// Empty implementation - we don't support direct usage
const RadioGroup = () => {
type RadioGroupComponent = React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<RadioGroupElement>> & {
Root: typeof RadioGroupRoot;
Item: typeof RadioGroupItem;
Indicator: typeof RadioGroupIndicator;
Label: typeof RadioGroupLabel;
};

const RadioGroup = React.forwardRef<RadioGroupElement, RadioGroupProps>((_props, _ref) => {
console.warn('Direct usage of RadioGroup is not supported. Please use RadioGroup.Root and RadioGroup.Item instead.');
return null;
};
}) as RadioGroupComponent;

RadioGroup.displayName = 'RadioGroup';

// Export fragments via direct assignment pattern
RadioGroup.Root = RadioGroupRoot;
RadioGroup.Item = RadioGroupItem;
RadioGroup.Indicator = RadioGroupIndicator;
Expand Down
14 changes: 10 additions & 4 deletions src/components/ui/RadioGroup/tests/RadioGroup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('RadioGroup (fragments)', () => {
});
});


it('selects the correct radio on click (uncontrolled)', () => {
render(<StoryRadioGroup defaultValue="css" name="test-group" />);
const itemHtml = screen.getByTestId('item-html');
Expand Down Expand Up @@ -98,20 +99,25 @@ describe('RadioGroup (fragments)', () => {
spy.mockRestore();
});

it('forwards refs to root, item, and indicator', () => {
it('forwards refs to root, label, item, and indicator', () => {
const rootRef = React.createRef<HTMLDivElement>();
const labelRef = React.createRef<HTMLLabelElement>();
const itemRef = React.createRef<HTMLButtonElement>();
const indicatorRef = React.createRef<HTMLSpanElement>();

render(
<RadioGroup.Root ref={rootRef} defaultValue="html">
<RadioGroup.Item ref={itemRef} value="html">
<RadioGroup.Indicator ref={indicatorRef} />
</RadioGroup.Item>
<RadioGroup.Label ref={labelRef}>
<RadioGroup.Item ref={itemRef} value="html">
<RadioGroup.Indicator ref={indicatorRef} />
</RadioGroup.Item>
Option
</RadioGroup.Label>
</RadioGroup.Root>
);

expect(rootRef.current).toBeInstanceOf(HTMLDivElement);
expect(labelRef.current).toBeInstanceOf(HTMLLabelElement);
expect(itemRef.current).toBeInstanceOf(HTMLButtonElement);
expect(indicatorRef.current).toBeInstanceOf(HTMLSpanElement);
});
Expand Down
19 changes: 14 additions & 5 deletions src/core/primitives/RadioGroup/RadioGroupPrimitive.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import React, { DetailedHTMLProps, InputHTMLAttributes, PropsWithChildren } from 'react';
import React from 'react';

import RadioGroupPrimitiveRoot, { RadioGroupPrimitiveRootProps } from './fragments/RadioGroupPrimitiveRoot';
import RadioGroupPrimitiveItem, { RadioGroupPrimitiveItemProps } from './fragments/RadioGroupPrimitiveItem';
import RadioGroupPrimitiveIndicator, { RadioGroupPrimitiveIndicatorProps } from './fragments/RadioGroupPrimitiveIndicator';

export type RadioGroupProps = {
export type RadioGroupPrimitiveElement = React.ElementRef<'div'>;

export type RadioGroupProps = React.ComponentPropsWithoutRef<'div'> & {
children?: React.ReactNode;
};

} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> & PropsWithChildren
type RadioGroupPrimitiveComponent = React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<RadioGroupPrimitiveElement>> & {
Root: typeof RadioGroupPrimitiveRoot;
Item: typeof RadioGroupPrimitiveItem;
Indicator: typeof RadioGroupPrimitiveIndicator;
};

const RadioGroupPrimitive = () => {
const RadioGroupPrimitive = React.forwardRef<RadioGroupPrimitiveElement, RadioGroupProps>((_props, _ref) => {
console.warn('Direct usage of RadioGroup is not supported. Please use RadioGroup.Root, RadioGroup.Item, etc. instead.');
return null;
};
}) as RadioGroupPrimitiveComponent;

RadioGroupPrimitive.displayName = 'RadioGroupPrimitive';

export namespace RadioGroupPrimitiveProps {
export type Root = RadioGroupPrimitiveRootProps;
Expand Down
Loading