@@ -6,6 +6,8 @@ import { useOUIAProps, OUIAProps } from '../../helpers/OUIA/ouia';
6
6
import { Badge } from '../Badge' ;
7
7
import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon' ;
8
8
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' ;
9
11
10
12
export enum ButtonVariant {
11
13
primary = 'primary' ,
@@ -97,6 +99,14 @@ export interface ButtonProps extends Omit<React.HTMLProps<HTMLButtonElement>, 'r
97
99
tabIndex ?: number ;
98
100
/** Adds danger styling to secondary or link button variants */
99
101
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' ;
100
110
/** @hide Forwarded ref */
101
111
innerRef ?: React . Ref < any > ;
102
112
/** Adds count number to button */
@@ -117,6 +127,10 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
117
127
isAriaDisabled = false ,
118
128
isLoading = null ,
119
129
isDanger = false ,
130
+ isExpanded,
131
+ isSettings,
132
+ isHamburger,
133
+ hamburgerVariant,
120
134
spinnerAriaValueText,
121
135
spinnerAriaLabelledBy,
122
136
spinnerAriaLabel,
@@ -140,10 +154,17 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
140
154
countOptions,
141
155
...props
142
156
} : ButtonProps ) => {
143
- if ( isFavorite && ! ariaLabel && ! props [ 'aria-labelledby' ] ) {
157
+ if ( isHamburger && ! [ true , false ] . includes ( isExpanded ) ) {
144
158
// eslint-disable-next-line no-console
145
159
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.'
147
168
) ;
148
169
}
149
170
@@ -152,7 +173,7 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
152
173
const isButtonElement = Component === 'button' ;
153
174
const isInlineSpan = isInline && Component === 'span' ;
154
175
const isIconAlignedAtEnd = iconPosition === 'end' || iconPosition === 'right' ;
155
- const shouldOverrideIcon = isFavorite ;
176
+ const shouldOverrideIcon = isSettings || isHamburger || isFavorite ;
156
177
157
178
const preventedEvents = inoperableEvents . reduce (
158
179
( handlers , eventToPrevent ) => ( {
@@ -190,6 +211,12 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
190
211
) ;
191
212
}
192
213
214
+ if ( isSettings ) {
215
+ iconContent = < CogIcon /> ;
216
+ }
217
+ if ( isHamburger ) {
218
+ iconContent = hamburgerIcon ;
219
+ }
193
220
if ( icon && ! shouldOverrideIcon ) {
194
221
iconContent = icon ;
195
222
}
@@ -202,21 +229,24 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
202
229
)
203
230
) ;
204
231
} ;
205
-
206
232
const _icon = renderIcon ( ) ;
207
233
const _children = children && < span className = { css ( 'pf-v6-c-button__text' ) } > { children } </ span > ;
208
234
// We only want to render the aria-disabled attribute when true, similar to the disabled attribute natively.
209
235
const shouldRenderAriaDisabled = isAriaDisabled || ( ! isButtonElement && isDisabled ) ;
210
236
211
237
return (
212
238
< Component
239
+ aria-expanded = { isExpanded } // Move this after the spread props in next breaking change
213
240
{ ...props }
214
241
{ ...( isAriaDisabled ? preventedEvents : null ) }
215
242
{ ...( shouldRenderAriaDisabled && { 'aria-disabled' : true } ) }
216
243
aria-label = { ariaLabel }
217
244
className = { css (
218
245
styles . button ,
219
246
styles . modifiers [ variant ] ,
247
+ isSettings && styles . modifiers . settings ,
248
+ isHamburger && styles . modifiers . hamburger ,
249
+ isHamburger && hamburgerVariant && styles . modifiers [ hamburgerVariant ] ,
220
250
isBlock && styles . modifiers . block ,
221
251
isDisabled && ! isButtonElement && styles . modifiers . disabled ,
222
252
isAriaDisabled && styles . modifiers . ariaDisabled ,
0 commit comments