Skip to content

Commit e76636d

Browse files
committed
feat(ExpandableSection): allow function toggleContent
Signed-off-by: gitdallas <[email protected]>
1 parent 526ae27 commit e76636d

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElem
4444
* use the onToggle property of the expandable section toggle sub-component.
4545
*/
4646
onToggle?: (event: React.MouseEvent, isExpanded: boolean) => void;
47-
/** React node that appears in the attached toggle in place of the toggleText property. */
48-
toggleContent?: React.ReactNode;
47+
/** React node that appears in the attached toggle in place of the toggleText property.
48+
* Can also be a function that receives the expanded state and returns a React node.
49+
*/
50+
toggleContent?: React.ReactNode | ((isExpanded: boolean) => React.ReactNode);
4951
/** Text that appears in the attached toggle. */
5052
toggleText?: string;
5153
/** Text that appears in the attached toggle when collapsed (will override toggleText if
@@ -238,6 +240,9 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
238240
propOrStateIsExpanded
239241
);
240242

243+
const computedToggleContent =
244+
typeof toggleContent === 'function' ? toggleContent(propOrStateIsExpanded) : toggleContent;
245+
241246
const expandableToggle = !isDetached && (
242247
<div className={`${styles.expandableSection}__toggle`}>
243248
<Button
@@ -255,7 +260,7 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
255260
)
256261
})}
257262
>
258-
{toggleContent || computedToggleText}
263+
{computedToggleContent || computedToggleText}
259264
</Button>
260265
</div>
261266
);

packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,38 @@ test('Renders with class pf-m-detached when isDetached is true and direction is
191191

192192
expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-detached');
193193
});
194+
195+
test('Renders toggleContent as a function in uncontrolled mode (collapsed)', () => {
196+
render(
197+
<ExpandableSection toggleContent={(isExpanded) => (isExpanded ? 'Hide details' : 'Show details')}>
198+
Test content
199+
</ExpandableSection>
200+
);
201+
202+
expect(screen.getByRole('button', { name: 'Show details' })).toBeInTheDocument();
203+
});
204+
205+
test('Renders toggleContent as a function in uncontrolled mode (expanded after click)', async () => {
206+
const user = userEvent.setup();
207+
208+
render(
209+
<ExpandableSection toggleContent={(isExpanded) => (isExpanded ? 'Hide details' : 'Show details')}>
210+
Test content
211+
</ExpandableSection>
212+
);
213+
214+
const button = screen.getByRole('button', { name: 'Show details' });
215+
await user.click(button);
216+
217+
expect(screen.getByRole('button', { name: 'Hide details' })).toBeInTheDocument();
218+
});
219+
220+
test('Renders toggleContent as a function in controlled mode', () => {
221+
render(
222+
<ExpandableSection isExpanded={true} toggleContent={(isExpanded) => (isExpanded ? 'Collapse' : 'Expand')}>
223+
Test content
224+
</ExpandableSection>
225+
);
226+
227+
expect(screen.getByRole('button', { name: 'Collapse' })).toBeInTheDocument();
228+
});

0 commit comments

Comments
 (0)