Skip to content

Commit 055efb6

Browse files
committed
feat(ExpandableSection): Allow more control over toggle icon
Allow for custom icons and disabled icons.
1 parent fe63802 commit 055efb6

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
@@ -56,6 +56,10 @@ export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElem
5656
* both are specified; used for uncontrolled expandable with dynamic toggle text).
5757
*/
5858
toggleTextExpanded?: string;
59+
/** Icon shown in toggle when variant is not truncated. */
60+
toggleIcon?: React.ReactNode;
61+
/** Whether to show a toggle icon when variant is not truncated. */
62+
hasToggleIcon?: boolean;
5963
/** Truncates the expandable content to the specified number of lines when using the
6064
* "truncate" variant.
6165
*/
@@ -196,6 +200,8 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
196200
toggleTextExpanded,
197201
toggleTextCollapsed,
198202
toggleContent,
203+
toggleIcon = <AngleRightIcon />,
204+
hasToggleIcon = true,
199205
children,
200206
isExpanded,
201207
isDetached,
@@ -247,13 +253,10 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
247253
aria-controls={uniqueContentId}
248254
id={uniqueToggleId}
249255
onClick={(event) => onToggle(event, !propOrStateIsExpanded)}
250-
{...(variant !== ExpandableSectionVariant.truncate && {
251-
icon: (
252-
<span className={css(styles.expandableSectionToggleIcon)}>
253-
<AngleRightIcon />
254-
</span>
255-
)
256-
})}
256+
{...(variant !== ExpandableSectionVariant.truncate &&
257+
hasToggleIcon && {
258+
icon: <span className={css(styles.expandableSectionToggleIcon)}>{toggleIcon}</span>
259+
})}
257260
>
258261
{toggleContent || computedToggleText}
259262
</Button>

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

@@ -191,3 +192,33 @@ test('Renders with class pf-m-detached when isDetached is true and direction is
191192

192193
expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-detached');
193194
});
195+
196+
test('Can render custom toggle icon', () => {
197+
render(<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />}>Test content</ExpandableSection>);
198+
199+
expect(screen.getByTestId('bell-icon')).toBeInTheDocument();
200+
});
201+
202+
test('Does not render toggle icon when hasToggleIcon is false', () => {
203+
render(<ExpandableSection hasToggleIcon={false}>Test content</ExpandableSection>);
204+
205+
const button = screen.getByRole('button');
206+
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).not.toBeInTheDocument();
207+
});
208+
209+
test('Does not render custom toggle icon when hasToggleIcon is false', () => {
210+
render(
211+
<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />} hasToggleIcon={false}>
212+
Test content
213+
</ExpandableSection>
214+
);
215+
216+
expect(screen.queryByTestId('bell-icon')).not.toBeInTheDocument();
217+
});
218+
219+
test('Renders toggle icon by default when hasToggleIcon is true', () => {
220+
render(<ExpandableSection>Test content</ExpandableSection>);
221+
222+
const button = screen.getByRole('button');
223+
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).toBeInTheDocument();
224+
});

0 commit comments

Comments
 (0)