diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
index f5adc03f59f9..60dcf5d7b2a5 100644
--- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
+++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
@@ -6433,6 +6433,9 @@ Map {
"className": Object {
"type": "string",
},
+ "decorator": Object {
+ "type": "node",
+ },
"defaultChecked": Object {
"type": "bool",
},
@@ -6470,9 +6473,7 @@ Map {
"required": Object {
"type": "bool",
},
- "slug": Object {
- "type": "node",
- },
+ "slug": [Function],
"value": Object {
"args": Array [
Array [
@@ -6498,6 +6499,9 @@ Map {
"className": Object {
"type": "string",
},
+ "decorator": Object {
+ "type": "node",
+ },
"defaultSelected": Object {
"args": Array [
Array [
@@ -6557,9 +6561,7 @@ Map {
"required": Object {
"type": "bool",
},
- "slug": Object {
- "type": "node",
- },
+ "slug": [Function],
"valueSelected": Object {
"args": Array [
Array [
diff --git a/packages/react/src/components/RadioButton/RadioButton.stories.js b/packages/react/src/components/RadioButton/RadioButton.stories.js
index 052ee3f3544f..664b14843297 100644
--- a/packages/react/src/components/RadioButton/RadioButton.stories.js
+++ b/packages/react/src/components/RadioButton/RadioButton.stories.js
@@ -132,7 +132,7 @@ export const withAILabel = {
render: () => (
` should be checked by default
*/
@@ -83,6 +89,7 @@ export interface RadioButtonProps
onClick?: (evt: React.MouseEvent) => void;
/**
+ * @deprecated please use decorator instead.
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButton` component
*/
slug?: ReactNode;
@@ -102,6 +109,7 @@ const RadioButton = React.forwardRef(
(props, ref) => {
const {
className,
+ decorator,
disabled,
hideLabel,
id,
@@ -137,17 +145,29 @@ const RadioButton = React.forwardRef(
[`${prefix}--radio-button-wrapper--label-${labelPosition}`]:
labelPosition !== 'right',
[`${prefix}--radio-button-wrapper--slug`]: slug,
+ [`${prefix}--radio-button-wrapper--decorator`]: decorator,
}
);
const inputRef = useRef(null);
- let normalizedSlug: React.ReactElement | undefined;
- if (slug && React.isValidElement(slug)) {
- const size = slug.props?.['kind'] === 'inline' ? 'md' : 'mini';
- normalizedSlug = React.cloneElement(slug as React.ReactElement, {
- size,
- });
+ let normalizedDecorator = React.isValidElement(slug ?? decorator)
+ ? (slug ?? decorator)
+ : null;
+ if (
+ normalizedDecorator &&
+ normalizedDecorator['type']?.displayName === 'AILabel'
+ ) {
+ const size =
+ (normalizedDecorator as ReactElement).props?.['kind'] === 'inline'
+ ? 'md'
+ : 'mini';
+ normalizedDecorator = React.cloneElement(
+ normalizedDecorator as React.ReactElement,
+ {
+ size,
+ }
+ );
}
return (
@@ -169,7 +189,16 @@ const RadioButton = React.forwardRef(
{labelText && (
{labelText}
- {normalizedSlug}
+ {slug ? (
+ normalizedDecorator
+ ) : decorator ? (
+
+ {normalizedDecorator}
+
+ ) : (
+ ''
+ )}
)}
@@ -191,6 +220,11 @@ RadioButton.propTypes = {
*/
className: PropTypes.string,
+ /**
+ * **Experimental**: Provide a decorator component to be rendered inside the `RadioButton` component
+ */
+ decorator: PropTypes.node,
+
/**
* Specify whether the `` should be checked by default
*/
@@ -247,7 +281,10 @@ RadioButton.propTypes = {
/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButton` component
*/
- slug: PropTypes.node,
+ slug: deprecate(
+ PropTypes.node,
+ 'The `slug` prop has been deprecated and will be removed in the next major version. Use the decorator prop instead.'
+ ),
/**
* Specify the value of the ``
diff --git a/packages/react/src/components/RadioButton/__tests__/RadioButton-test.js b/packages/react/src/components/RadioButton/__tests__/RadioButton-test.js
index 0f228936ef62..489f60ccd718 100644
--- a/packages/react/src/components/RadioButton/__tests__/RadioButton-test.js
+++ b/packages/react/src/components/RadioButton/__tests__/RadioButton-test.js
@@ -136,7 +136,38 @@ describe('RadioButton', () => {
expect(ref).toHaveBeenCalledWith(screen.getByRole('radio'));
});
- it('should respect slug prop', () => {
+ it('should respect decorator prop', () => {
+ const { container } = render(
+ }
+ />
+ );
+
+ expect(container.firstChild).toHaveClass(
+ `${prefix}--radio-button-wrapper--decorator`
+ );
+ });
+
+ it('should update AILabel size', () => {
+ const { container } = render(
+ }
+ />
+ );
+
+ expect(container.querySelector(`.${prefix}--ai-label__button`)).toHaveClass(
+ `${prefix}--ai-label__button--md`
+ );
+ });
+
+ it('should respect the deprecated slug prop', () => {
+ const spy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const { container } = render(
{
expect(container.firstChild).toHaveClass(
`${prefix}--radio-button-wrapper--slug`
);
+ spy.mockRestore();
});
it('should set the "required" attribute on the by default', () => {
diff --git a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup-test.js b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup-test.js
index 12330a76eccf..7c08617bbe0f 100644
--- a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup-test.js
+++ b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup-test.js
@@ -233,7 +233,21 @@ describe('RadioButtonGroup', () => {
);
});
- it('should respect slug prop', () => {
+ it('should respect decorator prop', () => {
+ const { container } = render(
+ } name="test" legendText="test">
+
+
+
+ );
+
+ expect(container.firstChild.firstChild).toHaveClass(
+ `${prefix}--radio-button-group--decorator`
+ );
+ });
+
+ it('should respect deprecated slug prop', () => {
+ const spy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const { container } = render(
} name="test" legendText="test">
@@ -244,6 +258,7 @@ describe('RadioButtonGroup', () => {
expect(container.firstChild.firstChild).toHaveClass(
`${prefix}--radio-button-group--slug`
);
+ spy.mockRestore();
});
it('should call `onChange` when the value of the group changes', async () => {
diff --git a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx
index 3f5d0a65ab2b..8f85542c4bf3 100644
--- a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx
+++ b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx
@@ -18,6 +18,7 @@ import type { RadioButtonProps } from '../RadioButton';
import { Legend } from '../Text';
import { usePrefix } from '../../internal/usePrefix';
import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
+import deprecate from '../../prop-types/deprecate';
import mergeRefs from '../../tools/mergeRefs';
import { useId } from '../../internal/useId';
@@ -40,6 +41,11 @@ export interface RadioButtonGroupProps
*/
className?: string;
+ /**
+ * **Experimental**: Provide a decorator component to be rendered inside the `RadioButtonGroup` component
+ */
+ decorator?: ReactNode;
+
/**
* Specify the `` to be selected by default
*/
@@ -102,6 +108,7 @@ export interface RadioButtonGroupProps
readOnly?: boolean;
/**
+ * @deprecated please use decorator instead.
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButtonGroup` component
*/
slug?: ReactNode;
@@ -132,6 +139,7 @@ const RadioButtonGroup = React.forwardRef(
const {
children,
className,
+ decorator,
defaultSelected,
disabled,
helperText,
@@ -220,6 +228,7 @@ const RadioButtonGroup = React.forwardRef(
[`${prefix}--radio-button-group--invalid`]: !readOnly && invalid,
[`${prefix}--radio-button-group--warning`]: showWarning,
[`${prefix}--radio-button-group--slug`]: slug,
+ [`${prefix}--radio-button-group--decorator`]: decorator,
});
const helperClasses = classNames(`${prefix}--form__helper-text`, {
@@ -238,13 +247,21 @@ const RadioButtonGroup = React.forwardRef(
const divRef = useRef(null);
- // Slug is always size `mini`
- let normalizedSlug: ReactElement | undefined;
- if (slug && slug['type']?.displayName === 'AILabel') {
- normalizedSlug = React.cloneElement(slug as React.ReactElement, {
- size: 'mini',
- kind: 'default',
- });
+ // AILabel is always size `mini`
+ let normalizedDecorator = React.isValidElement(slug ?? decorator)
+ ? (slug ?? decorator)
+ : null;
+ if (
+ normalizedDecorator &&
+ normalizedDecorator['type']?.displayName === 'AILabel'
+ ) {
+ normalizedDecorator = React.cloneElement(
+ normalizedDecorator as React.ReactElement,
+ {
+ size: 'mini',
+ kind: 'default',
+ }
+ );
}
return (
@@ -258,7 +275,16 @@ const RadioButtonGroup = React.forwardRef(
{legendText && (
)}
{getRadioButtons()}
@@ -298,6 +324,11 @@ RadioButtonGroup.propTypes = {
*/
className: PropTypes.string,
+ /**
+ * **Experimental**: Provide a decorator component to be rendered inside the `RadioButtonGroup` component
+ */
+ decorator: PropTypes.node,
+
/**
* Specify the `` to be selected by default
*/
@@ -363,7 +394,10 @@ RadioButtonGroup.propTypes = {
/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioButtonGroup` component
*/
- slug: PropTypes.node,
+ slug: deprecate(
+ PropTypes.node,
+ 'The `slug` prop has been deprecated and will be removed in the next major version. Use the decorator prop instead.'
+ ),
/**
* Specify the value that is currently selected in the group
diff --git a/packages/styles/scss/components/radio-button/_radio-button.scss b/packages/styles/scss/components/radio-button/_radio-button.scss
index a3f542f29f84..8ecb9eadb497 100644
--- a/packages/styles/scss/components/radio-button/_radio-button.scss
+++ b/packages/styles/scss/components/radio-button/_radio-button.scss
@@ -289,12 +289,23 @@ $radio-border-width: 1px !default;
}
// AILabel styles
+ .#{$prefix}--radio-button-group--decorator legend.#{$prefix}--label,
+ .#{$prefix}--radio-button-wrapper--decorator
+ .#{$prefix}--radio-button__label-text,
.#{$prefix}--radio-button-group--slug legend.#{$prefix}--label,
.#{$prefix}--radio-button-wrapper--slug
.#{$prefix}--radio-button__label-text {
display: flex;
}
+ .#{$prefix}--radio-button-group--decorator
+ legend.#{$prefix}--label
+ .#{$prefix}--radio-button-group-inner--decorator
+ > *,
+ .#{$prefix}--radio-button-wrapper--decorator
+ .#{$prefix}--radio-button__label-text
+ .#{$prefix}--radio-button-wrapper-inner--decorator
+ > *,
.#{$prefix}--radio-button-group--slug
legend.#{$prefix}--label
.#{$prefix}--ai-label,
@@ -310,6 +321,9 @@ $radio-border-width: 1px !default;
margin-inline-start: $spacing-03;
}
+ .#{$prefix}--radio-button-wrapper--decorator
+ .#{$prefix}--radio-button__label-text
+ .#{$prefix}--ai-label__button--inline,
.#{$prefix}--radio-button-wrapper--slug
.#{$prefix}--radio-button__label-text
.#{$prefix}--ai-label__button--inline,