RAC Pending Button
Closes https://github.com/adobe/react-spectrum/issues/3662
I've opted to re-implement it in RAC as opposed to pushing it down into the hooks because the hacks we use to work around AT require a bunch of dom nodes, which either leads to a lot of oddly named collections of element props being returned by the useButton hook, or a new hook which handles it. Either way results in API additions which would be not great to maintain.
โ Pull Request Checklist:
- [ ] Included link to corresponding React Spectrum GitHub Issue.
- [ ] Added/updated unit tests and storybook for this change (for new code or code which already has tests).
- [ ] Filled out test instructions.
- [ ] Updated documentation (if it already exists for this component).
- [ ] Looked at the Accessibility Practices for this feature - Aria Practices
๐ Test Instructions:
๐งข Your Project:
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
## API Changes
react-aria-components
/react-aria-components:Button
Button {
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode | ((ButtonRenderProps & {
defaultChildren: ReactNode | undefined
})) => ReactNode
className?: string | ((ButtonRenderProps & {
defaultClassName: string | undefined
})) => string
excludeFromTabOrder?: boolean
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onFocusChange?: (boolean) => void
onHoverEnd?: (HoverEvent) => void
onHoverStart?: (HoverEvent) => void
onKeyDown?: (KeyboardEvent) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
slot?: string | null
style?: CSSProperties | ((ButtonRenderProps & {
defaultStyle: CSSProperties
})) => CSSProperties
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
}
/react-aria-components:ButtonProps
ButtonProps {
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode | ((ButtonRenderProps & {
defaultChildren: ReactNode | undefined
})) => ReactNode
className?: string | ((ButtonRenderProps & {
defaultClassName: string | undefined
})) => string
excludeFromTabOrder?: boolean
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onFocusChange?: (boolean) => void
onHoverEnd?: (HoverEvent) => void
onHoverStart?: (HoverEvent) => void
onKeyDown?: (KeyboardEvent) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
slot?: string | null
style?: CSSProperties | ((ButtonRenderProps & {
defaultStyle: CSSProperties
})) => CSSProperties
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
}
/react-aria-components:ButtonRenderProps
ButtonRenderProps {
isDisabled: boolean
isFocusVisible: boolean
isFocused: boolean
isHovered: boolean
+ isPending?: boolean
isPressed: boolean
}
@react-aria/live-announcer
/@react-aria/live-announcer:announce
announce {
message: string
assertiveness: Assertiveness
timeout: any
+ mode: 'message' | 'ids'
returnVal: undefined
}
@react-spectrum/s2
/@react-spectrum/s2:ActionButton
ActionButton {
UNSAFE_className?: string
UNSAFE_style?: CSSProperties
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode
excludeFromTabOrder?: boolean
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
isQuiet?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onKeyDown?: (KeyboardEvent) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
slot?: string | null
staticColor?: 'black' | 'white'
styles?: StylesProp
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
}
/@react-spectrum/s2:Button
Button {
UNSAFE_className?: string
UNSAFE_style?: CSSProperties
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode
excludeFromTabOrder?: boolean
fillStyle?: 'fill' | 'outline' = 'fill'
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onFocusChange?: (boolean) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
size?: 'S' | 'M' | 'L' | 'XL' = 'M'
slot?: string | null
staticColor?: 'white' | 'black'
styles?: StylesProp
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
variant?: 'primary' | 'secondary' | 'accent' | 'negative' = 'primary'
}
/@react-spectrum/s2:ActionButtonProps
ActionButtonProps {
UNSAFE_className?: string
UNSAFE_style?: CSSProperties
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode
excludeFromTabOrder?: boolean
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
isQuiet?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onKeyDown?: (KeyboardEvent) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
slot?: string | null
staticColor?: 'black' | 'white'
styles?: StylesProp
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
}
/@react-spectrum/s2:ButtonProps
ButtonProps {
UNSAFE_className?: string
UNSAFE_style?: CSSProperties
aria-controls?: string
aria-describedby?: string
aria-details?: string
aria-expanded?: boolean | 'true' | 'false'
aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
aria-label?: string
aria-labelledby?: string
aria-pressed?: boolean | 'true' | 'false' | 'mixed'
autoFocus?: boolean
children?: ReactNode
excludeFromTabOrder?: boolean
fillStyle?: 'fill' | 'outline' = 'fill'
form?: string
formAction?: string
formEncType?: string
formMethod?: string
formNoValidate?: boolean
formTarget?: string
id?: string
isDisabled?: boolean
+ isPending?: boolean
name?: string
onBlur?: (FocusEvent<Target>) => void
onFocus?: (FocusEvent<Target>) => void
onFocusChange?: (boolean) => void
onKeyUp?: (KeyboardEvent) => void
onPress?: (PressEvent) => void
onPressChange?: (boolean) => void
onPressEnd?: (PressEvent) => void
onPressStart?: (PressEvent) => void
onPressUp?: (PressEvent) => void
preventFocusOnPress?: boolean
size?: 'S' | 'M' | 'L' | 'XL' = 'M'
slot?: string | null
staticColor?: 'white' | 'black'
styles?: StylesProp
type?: 'button' | 'submit' | 'reset' = 'button'
value?: string
variant?: 'primary' | 'secondary' | 'accent' | 'negative' = 'primary'
}