Skip to content

Commit 07c2bbf

Browse files
feat(ExpandableSection): Allow more control over toggle icon (#12051)
Allow for custom icons and disabled icons.
1 parent 2b36c61 commit 07c2bbf

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElem
6262
toggleAriaLabel?: string;
6363
/** Accessible name via space delimtted list of IDs for the expandable section toggle. */
6464
toggleAriaLabelledBy?: string;
65+
/** Icon shown in toggle when variant is not truncated. */
66+
toggleIcon?: React.ReactNode;
67+
/** Whether to show a toggle icon when variant is not truncated. If omitted, it is important to ensure the current state of the ExpandableSection is conveyed, most likely by having dynamic toggle text. */
68+
hasToggleIcon?: boolean;
6569
/** Truncates the expandable content to the specified number of lines when using the
6670
* "truncate" variant.
6771
*/
@@ -211,6 +215,8 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
211215
toggleContent,
212216
toggleAriaLabel,
213217
toggleAriaLabelledBy,
218+
toggleIcon = <AngleRightIcon />,
219+
hasToggleIcon = true,
214220
children,
215221
isExpanded,
216222
isDetached,
@@ -267,13 +273,10 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
267273
aria-controls={uniqueContentId}
268274
id={uniqueToggleId}
269275
onClick={(event) => onToggle(event, !propOrStateIsExpanded)}
270-
{...(variant !== ExpandableSectionVariant.truncate && {
271-
icon: (
272-
<span className={css(styles.expandableSectionToggleIcon)}>
273-
<AngleRightIcon />
274-
</span>
275-
)
276-
})}
276+
{...(variant !== ExpandableSectionVariant.truncate &&
277+
hasToggleIcon && {
278+
icon: <span className={css(styles.expandableSectionToggleIcon)}>{toggleIcon}</span>
279+
})}
277280
aria-label={toggleAriaLabel}
278281
aria-labelledby={toggleAriaLabelledBy}
279282
>

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
33

44
import { ExpandableSection, ExpandableSectionVariant } from '../ExpandableSection';
55
import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section';
6+
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
67

78
const props = { contentId: 'content-id', toggleId: 'toggle-id' };
89

@@ -271,3 +272,33 @@ test('Renders with div wrapper when toggleWrapper="div"', () => {
271272
const toggle = screen.getByRole('button').parentElement;
272273
expect(toggle?.tagName).toBe('DIV');
273274
});
275+
276+
test('Can render custom toggle icon', () => {
277+
render(<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />}>Test content</ExpandableSection>);
278+
279+
expect(screen.getByTestId('bell-icon')).toBeInTheDocument();
280+
});
281+
282+
test('Does not render toggle icon when hasToggleIcon is false', () => {
283+
render(<ExpandableSection hasToggleIcon={false}>Test content</ExpandableSection>);
284+
285+
const button = screen.getByRole('button');
286+
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).not.toBeInTheDocument();
287+
});
288+
289+
test('Does not render custom toggle icon when hasToggleIcon is false', () => {
290+
render(
291+
<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />} hasToggleIcon={false}>
292+
Test content
293+
</ExpandableSection>
294+
);
295+
296+
expect(screen.queryByTestId('bell-icon')).not.toBeInTheDocument();
297+
});
298+
299+
test('Renders toggle icon by default when hasToggleIcon is true', () => {
300+
render(<ExpandableSection>Test content</ExpandableSection>);
301+
302+
const button = screen.getByRole('button');
303+
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).toBeInTheDocument();
304+
});

0 commit comments

Comments
 (0)