diff --git a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx index 1f39a289f8d..8b5cd727118 100644 --- a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx +++ b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx @@ -44,8 +44,10 @@ export interface ExpandableSectionProps extends Omit void; - /** React node that appears in the attached toggle in place of the toggleText property. */ - toggleContent?: React.ReactNode; + /** React node that appears in the attached toggle in place of the toggleText property. + * Can also be a function that receives the expanded state and returns a React node. + */ + toggleContent?: React.ReactNode | ((isExpanded: boolean) => React.ReactNode); /** Text that appears in the attached toggle. */ toggleText?: string; /** Text that appears in the attached toggle when collapsed (will override toggleText if @@ -246,6 +248,9 @@ class ExpandableSection extends Component ); diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx index 22b067f29e5..64a5c9ce36a 100644 --- a/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx +++ b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx @@ -208,3 +208,37 @@ test('Renders with aria-labelledby when toggleAriaLabelledBy is passed', () => { expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); }); +test('Renders toggleContent as a function in uncontrolled mode (collapsed)', () => { + render( + (isExpanded ? 'Hide details' : 'Show details')}> + Test content + + ); + + expect(screen.getByRole('button', { name: 'Show details' })).toBeInTheDocument(); +}); + +test('Renders toggleContent as a function in uncontrolled mode (expanded after click)', async () => { + const user = userEvent.setup(); + + render( + (isExpanded ? 'Hide details' : 'Show details')}> + Test content + + ); + + const button = screen.getByRole('button', { name: 'Show details' }); + await user.click(button); + + expect(screen.getByRole('button', { name: 'Hide details' })).toBeInTheDocument(); +}); + +test('Renders toggleContent as a function in controlled mode', () => { + render( + (isExpanded ? 'Collapse' : 'Expand')}> + Test content + + ); + + expect(screen.getByRole('button', { name: 'Collapse' })).toBeInTheDocument(); +}); diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md index 0396679350e..a2d3eb06544 100644 --- a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md @@ -28,6 +28,14 @@ import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle ``` +### Uncontrolled with dynamic toggle content (function) + +Use `toggleContent` as a function to dynamically render different content based on the expanded state without managing state yourself. + +```ts file="ExpandableSectionUncontrolledDynamicToggleFunction.tsx" + +``` + ### Detached When passing the `isDetached` property into ``, you must also manually pass in the same `toggleId` and `contentId` properties to both `` and ``. This will link the content to the toggle via ARIA attributes. diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx new file mode 100644 index 00000000000..614329918f8 --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx @@ -0,0 +1,13 @@ +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionUncontrolledDynamicToggleFunction: React.FunctionComponent = () => ( + + isExpanded + ? 'Show less uncontrolled dynamic toggle example content' + : 'Show more uncontrolled dynamic toggle example content' + } + > + This content is visible only when the component is expanded. + +);