Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElem
* both are specified; used for uncontrolled expandable with dynamic toggle text).
*/
toggleTextExpanded?: string;
/** Icon shown in toggle when variant is not truncated. */
toggleIcon?: React.ReactNode;
/** Whether to show a toggle icon when variant is not truncated. */
hasToggleIcon?: boolean;
Comment on lines +61 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% about allowing the icon to totally be removed since it kinda removes the indication that you can click to expand/collapse something as well as its current state. If the toggle text updates based on the state + the text indicates somehow that it expands/collapses something, then less of an issue probably.

Maybe if we just have the prop description mention that if an icon is omitted, we recommend the toggle text to indicate the current state of the expandable section. Should we also get design sign off on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort of what I'm thinking could be an issue:

Uncontrolled expandable section without an icon, showing expanded state

I know this is expanded because I clicked it to expand it + knew it started as collapsed, but in other contexts it may not be clear that that is the case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add an error? My concern is that the consumer asked for a way for consumers to provide their own custom icon directly as part of the toggle content.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think allowing a custom icon would be fine - I assume whatever icon they pass in would retain the transition between expanded and collapsed at least. I'd be more wary about allowing the removal of the icon entirely is all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it - let me bug them and see if they can get by with the smaller change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do want to allow removing the icon, then we need to just make sure we tell consumers that it's up to them to ensure the current state of the ExpandableSection is conveyed, most likely by having dynamic toggle text. Idk if it's always going to be clear whether content that follows the toggle is part of the expandable section or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to updating the prop description to note the additional details a user would need to convey the expanded/collapsed state.

I'm also fine with keeping the custom icon and removing the toggle. The benefit of keeping the toggle would be if a user wanted to customize where in the toggle the icon would go (passing it as a child), but we could also have an icon alignment start/end prop instead.

/** Truncates the expandable content to the specified number of lines when using the
* "truncate" variant.
*/
Expand Down Expand Up @@ -196,6 +200,8 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
toggleTextExpanded,
toggleTextCollapsed,
toggleContent,
toggleIcon = <AngleRightIcon />,
hasToggleIcon = true,
children,
isExpanded,
isDetached,
Expand Down Expand Up @@ -247,13 +253,10 @@ class ExpandableSection extends Component<ExpandableSectionProps, ExpandableSect
aria-controls={uniqueContentId}
id={uniqueToggleId}
onClick={(event) => onToggle(event, !propOrStateIsExpanded)}
{...(variant !== ExpandableSectionVariant.truncate && {
icon: (
<span className={css(styles.expandableSectionToggleIcon)}>
<AngleRightIcon />
</span>
)
})}
{...(variant !== ExpandableSectionVariant.truncate &&
hasToggleIcon && {
icon: <span className={css(styles.expandableSectionToggleIcon)}>{toggleIcon}</span>
})}
>
{toggleContent || computedToggleText}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';

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

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

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

expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-detached');
});

test('Can render custom toggle icon', () => {
render(<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />}>Test content</ExpandableSection>);

expect(screen.getByTestId('bell-icon')).toBeInTheDocument();
});

test('Does not render toggle icon when hasToggleIcon is false', () => {
render(<ExpandableSection hasToggleIcon={false}>Test content</ExpandableSection>);

const button = screen.getByRole('button');
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).not.toBeInTheDocument();
});

test('Does not render custom toggle icon when hasToggleIcon is false', () => {
render(
<ExpandableSection toggleIcon={<BellIcon data-testid="bell-icon" />} hasToggleIcon={false}>
Test content
</ExpandableSection>
);

expect(screen.queryByTestId('bell-icon')).not.toBeInTheDocument();
});

test('Renders toggle icon by default when hasToggleIcon is true', () => {
render(<ExpandableSection>Test content</ExpandableSection>);

const button = screen.getByRole('button');
expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).toBeInTheDocument();
});
Loading