Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(16248): RadioButtonGroup supports 'required' prop and attaches it to children RadioButton #16300

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
Original file line number Diff line number Diff line change
Expand Up @@ -6450,6 +6450,9 @@ Map {
"onClick": Object {
"type": "func",
},
"required": Object {
"type": "bool",
},
"slug": Object {
"type": "node",
},
Expand Down Expand Up @@ -6534,6 +6537,9 @@ Map {
"readOnly": Object {
"type": "bool",
},
"required": Object {
"type": "bool",
},
"slug": Object {
"type": "node",
},
Expand Down
12 changes: 12 additions & 0 deletions packages/react/src/components/RadioButton/RadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ export interface RadioButtonProps
* Specify the value of the `<RadioButton>`
*/
value?: string | number;

/**
* `true` to specify if the input is required.
*/
required?: boolean;
}

const RadioButton = React.forwardRef((props: RadioButtonProps, ref) => {
Expand All @@ -105,6 +110,7 @@ const RadioButton = React.forwardRef((props: RadioButtonProps, ref) => {
onChange = () => {},
value = '',
slug,
required,
...rest
} = props;

Expand Down Expand Up @@ -152,6 +158,7 @@ const RadioButton = React.forwardRef((props: RadioButtonProps, ref) => {
disabled={disabled}
value={value}
name={name}
required={required}
/>
<label htmlFor={uniqueId} className={`${prefix}--radio-button__label`}>
<span className={`${prefix}--radio-button__appearance`} />
Expand Down Expand Up @@ -227,6 +234,11 @@ RadioButton.propTypes = {
*/
onClick: PropTypes.func,

/**
* `true` to specify if the control is required.
*/
required: PropTypes.bool,

/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButton` component
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,16 @@ describe('RadioButton', () => {
`${prefix}--radio-button-wrapper--slug`
);
});

it('should set the "required" attribute on the <input> by default', () => {
render(
<RadioButton
name="test-name"
value="test-value"
labelText="test-label"
required
/>
);
expect(screen.getByRole('radio')).toHaveAttribute('required');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -270,5 +270,28 @@ describe('RadioButtonGroup', () => {
expect(screen.getByLabelText('Option two')).toBeChecked();
});
});
it('should place required on every child <RadioButton>', () => {
render(
<RadioButtonGroup name="test" required>
<RadioButton labelText="Option 1" value="option-1" />
<RadioButton labelText="Option 2" value="option-2" />
</RadioButtonGroup>
);

expect(screen.getByDisplayValue('option-1')).toBeRequired();
expect(screen.getByDisplayValue('option-2')).toBeRequired();
});

it('should override required on every child <RadioButton>', () => {
render(
<RadioButtonGroup name="test" required>
<RadioButton labelText="Option 1" value="option-1" required={false} />
<RadioButton labelText="Option 2" value="option-2" />
</RadioButtonGroup>
);

expect(screen.getByDisplayValue('option-1')).toBeRequired();
expect(screen.getByDisplayValue('option-2')).toBeRequired();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ export interface RadioButtonGroupProps
* Specify the value that is currently selected in the group
*/
valueSelected?: string | number;
/**
* `true` to specify if input selection in group is required.
*/
required?: boolean;
}

const RadioButtonGroup = React.forwardRef(
Expand All @@ -136,6 +140,7 @@ const RadioButtonGroup = React.forwardRef(
warn = false,
warnText,
slug,
required,
...rest
} = props;
const prefix = usePrefix();
Expand Down Expand Up @@ -164,6 +169,7 @@ const RadioButtonGroup = React.forwardRef(
value: value,
onChange: handleOnChange,
checked: value === selected,
required: required,
};

if (!selected && (radioButton as ReactElementLike)?.props.checked) {
Expand Down Expand Up @@ -334,6 +340,11 @@ RadioButtonGroup.propTypes = {
*/
readOnly: PropTypes.bool,

/**
* `true` to specify if radio selection in group is required.
*/
required: PropTypes.bool,

/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButtonGroup` component
*/
Expand Down
Loading