Skip to content

Commit cf3d84e

Browse files
feat(Button/MenuToggle): added support for hamburger/settings animations (#11861)
1 parent 9e7c8ba commit cf3d84e

File tree

60 files changed

+704
-369
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+704
-369
lines changed

packages/react-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"tslib": "^2.8.1"
5555
},
5656
"devDependencies": {
57-
"@patternfly/patternfly": "6.3.0-prerelease.26",
57+
"@patternfly/patternfly": "6.3.0-prerelease.29",
5858
"case-anything": "^3.1.2",
5959
"css": "^3.0.0",
6060
"fs-extra": "^11.3.0"

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { useOUIAProps, OUIAProps } from '../../helpers/OUIA/ouia';
66
import { Badge } from '../Badge';
77
import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon';
88
import OutlinedStarIcon from '@patternfly/react-icons/dist/esm/icons/outlined-star-icon';
9+
import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
10+
import { hamburgerIcon } from './hamburgerIcon';
911

1012
export enum ButtonVariant {
1113
primary = 'primary',
@@ -97,6 +99,14 @@ export interface ButtonProps extends Omit<React.HTMLProps<HTMLButtonElement>, 'r
9799
tabIndex?: number;
98100
/** Adds danger styling to secondary or link button variants */
99101
isDanger?: boolean;
102+
/** Flag indicating whether content the button controls is expanded or not. Required when isHamburger is true. */
103+
isExpanded?: boolean;
104+
/** Flag indicating the button is a settings button. This will override the icon property. */
105+
isSettings?: boolean;
106+
/** Flag indicating the button is a hamburger button. This will override the icon property. */
107+
isHamburger?: boolean;
108+
/** Adjusts and animates the hamburger icon to indicate what will happen upon clicking the button. */
109+
hamburgerVariant?: 'expand' | 'collapse';
100110
/** @hide Forwarded ref */
101111
innerRef?: React.Ref<any>;
102112
/** Adds count number to button */
@@ -117,6 +127,10 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
117127
isAriaDisabled = false,
118128
isLoading = null,
119129
isDanger = false,
130+
isExpanded,
131+
isSettings,
132+
isHamburger,
133+
hamburgerVariant,
120134
spinnerAriaValueText,
121135
spinnerAriaLabelledBy,
122136
spinnerAriaLabel,
@@ -140,10 +154,17 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
140154
countOptions,
141155
...props
142156
}: ButtonProps) => {
143-
if (isFavorite && !ariaLabel && !props['aria-labelledby']) {
157+
if (isHamburger && ![true, false].includes(isExpanded)) {
144158
// eslint-disable-next-line no-console
145159
console.error(
146-
'Button: Each favorite button must have a unique accessible name provided via aria-label or aria-labelledby'
160+
'Button: when the isHamburger property is passed in, you must also pass in a boolean value to the isExpanded property. It is expected that a hamburger button controls the expansion of other content.'
161+
);
162+
}
163+
// TODO: Remove isSettings || isHamburger || isFavorite conditional in breaking change to throw this warning for any button that does not have children or aria name
164+
if ((isSettings || isHamburger || isFavorite) && !ariaLabel && !children && !props['aria-labelledby']) {
165+
// eslint-disable-next-line no-console
166+
console.error(
167+
'Button: you must provide either visible text content or an accessible name via the aria-label or aria-labelledby properties.'
147168
);
148169
}
149170

@@ -152,7 +173,7 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
152173
const isButtonElement = Component === 'button';
153174
const isInlineSpan = isInline && Component === 'span';
154175
const isIconAlignedAtEnd = iconPosition === 'end' || iconPosition === 'right';
155-
const shouldOverrideIcon = isFavorite;
176+
const shouldOverrideIcon = isSettings || isHamburger || isFavorite;
156177

157178
const preventedEvents = inoperableEvents.reduce(
158179
(handlers, eventToPrevent) => ({
@@ -190,6 +211,12 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
190211
);
191212
}
192213

214+
if (isSettings) {
215+
iconContent = <CogIcon />;
216+
}
217+
if (isHamburger) {
218+
iconContent = hamburgerIcon;
219+
}
193220
if (icon && !shouldOverrideIcon) {
194221
iconContent = icon;
195222
}
@@ -202,21 +229,24 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
202229
)
203230
);
204231
};
205-
206232
const _icon = renderIcon();
207233
const _children = children && <span className={css('pf-v6-c-button__text')}>{children}</span>;
208234
// We only want to render the aria-disabled attribute when true, similar to the disabled attribute natively.
209235
const shouldRenderAriaDisabled = isAriaDisabled || (!isButtonElement && isDisabled);
210236

211237
return (
212238
<Component
239+
aria-expanded={isExpanded} // Move this after the spread props in next breaking change
213240
{...props}
214241
{...(isAriaDisabled ? preventedEvents : null)}
215242
{...(shouldRenderAriaDisabled && { 'aria-disabled': true })}
216243
aria-label={ariaLabel}
217244
className={css(
218245
styles.button,
219246
styles.modifiers[variant],
247+
isSettings && styles.modifiers.settings,
248+
isHamburger && styles.modifiers.hamburger,
249+
isHamburger && hamburgerVariant && styles.modifiers[hamburgerVariant],
220250
isBlock && styles.modifiers.block,
221251
isDisabled && !isButtonElement && styles.modifiers.disabled,
222252
isAriaDisabled && styles.modifiers.ariaDisabled,

0 commit comments

Comments
 (0)