Skip to content

Commit

Permalink
fix(ButtonBase): memoize sx prop (#2323)
Browse files Browse the repository at this point in the history
* fix(ButtonBase): memoize sx prop

* refactor(ButtonBase): pull out inline trailing icon styles

* Create fuzzy-needles-peel.md

* refactor(ButtonBase): memoize sxProp separately
  • Loading branch information
joshblack committed Oct 10, 2022
1 parent d168b69 commit 9c0c107
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-needles-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": patch
---

Update `ButtonBase` to minimize re-renders through stable `sx` prop values
24 changes: 17 additions & 7 deletions src/Button/ButtonBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,36 @@ import {useTheme} from '../ThemeProvider'
import {ButtonProps, StyledButton} from './types'
import {getVariantStyles, getSizeStyles, getButtonStyles} from './styles'

const defaultSxProp = {}
const iconWrapStyles = {
display: 'inline-block'
}
const trailingIconStyles = {
...iconWrapStyles,
ml: 2
}

const ButtonBase = forwardRef<HTMLElement, ButtonProps>(
({children, as: Component = 'button', sx: sxProp = {}, ...props}, forwardedRef): JSX.Element => {
({children, as: Component = 'button', sx: sxProp = defaultSxProp, ...props}, forwardedRef): JSX.Element => {
const {leadingIcon: LeadingIcon, trailingIcon: TrailingIcon, variant = 'default', size = 'medium'} = props
const {theme} = useTheme()
const iconWrapStyles = {
display: 'inline-block'
}
const sxStyles = useMemo(() => {
const baseStyles = useMemo(() => {
return merge.all([getButtonStyles(theme), getSizeStyles(size, variant, false), getVariantStyles(variant, theme)])
}, [theme, size, variant])
const sxStyles = useMemo(() => {
return merge(baseStyles, sxProp as SxProp)
}, [baseStyles, sxProp])

return (
<StyledButton as={Component} sx={merge(sxStyles, sxProp as SxProp)} {...props} ref={forwardedRef}>
<StyledButton as={Component} sx={sxStyles} {...props} ref={forwardedRef}>
{LeadingIcon && (
<Box as="span" data-component="leadingIcon" sx={iconWrapStyles}>
<LeadingIcon />
</Box>
)}
{children && <span data-component="text">{children}</span>}
{TrailingIcon && (
<Box as="span" data-component="trailingIcon" sx={{...iconWrapStyles, ml: 2}}>
<Box as="span" data-component="trailingIcon" sx={trailingIconStyles}>
<TrailingIcon />
</Box>
)}
Expand Down

0 comments on commit 9c0c107

Please sign in to comment.