Skip to content

Commit

Permalink
fix(elements): fix prefixed props passing & logic in Button & IconButton
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangabriele committed Sep 9, 2024
1 parent 6575ba0 commit 708db85
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 88 deletions.
82 changes: 19 additions & 63 deletions src/elements/Button.tsx → src/elements/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import classnames from 'classnames'
import { useCallback, useMemo, type MouseEvent, type ButtonHTMLAttributes, type FunctionComponent } from 'react'
import styled from 'styled-components'

import { Accent, Size } from '../constants'
import { type IconProps } from '../types/definitions'
import { stopMouseEventPropagation } from '../utils/stopMouseEventPropagation'
import { interpolatePrimaryButtonThemedCss, interpolateSecondaryButtonThemedCss } from './utils'
import { Accent, Size } from '../../constants'
import { type IconProps } from '../../types/definitions'
import { stopMouseEventPropagation } from '../../utils/stopMouseEventPropagation'

const ICON_SIZE: Record<Size, number> = {
[Size.LARGE]: 20,
Expand Down Expand Up @@ -56,14 +57,13 @@ export function Button({
[children, Icon, size]
)

const commonProps = useMemo(
const commonProps: BaseButtonProps = useMemo(
() => ({
as: StyledButton,
$isFullWidth: isFullWidth,
$size: size,
children: commonChildren,
className: classnames('Element-Button', className),
isFullWidth,
onClick: handleClick,
size,
type,
...nativeProps
}),
Expand Down Expand Up @@ -96,7 +96,12 @@ const PADDING: Record<Size, string> = {
[Size.NORMAL]: '6px 12px',
[Size.SMALL]: '5px 8px 4px'
}
const StyledButton = styled.button<{

type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
$isFullWidth: boolean
$size: Size
}
const BaseButton = styled.button<{
$isFullWidth: boolean
$size: Size
}>`
Expand All @@ -122,61 +127,11 @@ const ButtonLabel = styled.span`
white-space: nowrap;
`

export const PrimaryButton = styled.button`
background-color: ${p => p.theme.color.charcoal};
border: 1px solid ${p => p.theme.color.charcoal};
color: ${p => p.theme.color.gainsboro};
&:hover,
&._hover {
background-color: ${p => p.theme.color.blueYonder};
border: 1px solid ${p => p.theme.color.blueYonder};
color: ${p => p.theme.color.white};
}
const PrimaryButton = styled(BaseButton)(interpolatePrimaryButtonThemedCss)

&:active,
&._active {
background-color: ${p => p.theme.color.blueGray};
border: 1px solid ${p => p.theme.color.blueGray};
color: ${p => p.theme.color.white};
}
&:disabled,
&._disabled {
background-color: ${p => p.theme.color.lightGray};
border: 1px solid ${p => p.theme.color.lightGray};
color: ${p => p.theme.color.cultured};
}
`

export const SecondaryButton = styled.button`
background-color: transparent;
border: 1px solid ${p => p.theme.color.charcoal};
color: ${p => p.theme.color.charcoal};
const SecondaryButton = styled(BaseButton)(interpolateSecondaryButtonThemedCss)

&:hover,
&._hover {
background-color: ${p => p.theme.color.blueYonder25};
border: 1px solid ${p => p.theme.color.blueYonder};
color: ${p => p.theme.color.blueYonder};
}
&:active,
&._active {
background-color: ${p => p.theme.color.blueGray25};
border: 1px solid ${p => p.theme.color.blueGray};
color: ${p => p.theme.color.blueGray};
}
&:disabled,
&._disabled {
background-color: transparent;
border: 1px solid ${p => p.theme.color.lightGray};
color: ${p => p.theme.color.lightGray};
}
`

export const TertiaryButton = styled.button`
const TertiaryButton = styled(BaseButton)`
background-color: ${p => p.theme.color.white};
border: 1px solid ${p => p.theme.color.white};
color: ${p => p.theme.color.charcoal};
Expand All @@ -202,7 +157,8 @@ export const TertiaryButton = styled.button`
color: ${p => p.theme.color.lightGray};
}
`
export const WarningButton = styled.button`

const WarningButton = styled(BaseButton)`
background-color: transparent;
border: 1px solid ${p => p.theme.color.goldenPoppy};
color: ${p => p.theme.color.charcoal};
Expand All @@ -229,7 +185,7 @@ export const WarningButton = styled.button`
color: ${p => p.theme.color.lightGray};
}
`
export const ErrorButton = styled.button`
const ErrorButton = styled(BaseButton)`
background-color: transparent;
border: 1px solid ${p => p.theme.color.maximumRed};
color: ${p => p.theme.color.charcoal};
Expand Down
59 changes: 59 additions & 0 deletions src/elements/Button/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { css } from 'styled-components'

export function interpolatePrimaryButtonThemedCss() {
return css`
background-color: ${p => p.theme.color.charcoal};
border: 1px solid ${p => p.theme.color.charcoal};
color: ${p => p.theme.color.gainsboro};
&:hover,
&._hover {
background-color: ${p => p.theme.color.blueYonder};
border: 1px solid ${p => p.theme.color.blueYonder};
color: ${p => p.theme.color.white};
}
&:active,
&._active {
background-color: ${p => p.theme.color.blueGray};
border: 1px solid ${p => p.theme.color.blueGray};
color: ${p => p.theme.color.white};
}
&:disabled,
&._disabled {
background-color: ${p => p.theme.color.lightGray};
border: 1px solid ${p => p.theme.color.lightGray};
color: ${p => p.theme.color.cultured};
}
`
}

export function interpolateSecondaryButtonThemedCss() {
return css`
background-color: transparent;
border: 1px solid ${p => p.theme.color.charcoal};
color: ${p => p.theme.color.charcoal};
&:hover,
&._hover {
background-color: ${p => p.theme.color.blueYonder25};
border: 1px solid ${p => p.theme.color.blueYonder};
color: ${p => p.theme.color.blueYonder};
}
&:active,
&._active {
background-color: ${p => p.theme.color.blueGray25};
border: 1px solid ${p => p.theme.color.blueGray};
color: ${p => p.theme.color.blueGray};
}
&:disabled,
&._disabled {
background-color: transparent;
border: 1px solid ${p => p.theme.color.lightGray};
color: ${p => p.theme.color.lightGray};
}
`
}
57 changes: 32 additions & 25 deletions src/elements/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import classnames from 'classnames'
import { useMemo, type MouseEvent, type ButtonHTMLAttributes, type FunctionComponent, useCallback } from 'react'
import styled from 'styled-components'

import { PrimaryButton, SecondaryButton } from './Button'
import { interpolatePrimaryButtonThemedCss, interpolateSecondaryButtonThemedCss } from './Button/utils'
import { Accent, Size } from '../constants'
import { type IconProps } from '../types/definitions'
import { stopMouseEventPropagation } from '../utils/stopMouseEventPropagation'
Expand Down Expand Up @@ -64,14 +64,14 @@ export function IconButton({
[color, Icon, iconSize, size]
)

const buttonProps = useMemo(
const buttonProps: BaseButtonProps = useMemo(
() => ({
$isCompact: isCompact,
$size: size,
children: commonChildren,
className:
badgeNumber === undefined ? classnames('Element-IconButton', className) : classnames('Element-IconButton'),
isCompact,
onClick: handleClick,
size,
style: badgeNumber === undefined ? style : undefined,
type,
...nativeProps
Expand All @@ -84,13 +84,13 @@ export function IconButton({
return (
<>
{badgeNumber === undefined ? (
<SecondaryButton as={StyledButton} {...buttonProps} />
<SecondaryButton {...buttonProps} />
) : (
<Wrapper className={className} style={style}>
<BadgeNumber backgroundColor={badgeBackgroundColor} color={badgeColor} size={size}>
<BadgeNumber $backgroundColor={badgeBackgroundColor} $color={badgeColor} $size={size}>
{badgeNumber}
</BadgeNumber>
<SecondaryButton as={StyledButton} {...buttonProps} />
<SecondaryButton {...buttonProps} />
</Wrapper>
)}
</>
Expand All @@ -100,13 +100,13 @@ export function IconButton({
return (
<>
{badgeNumber === undefined ? (
<TertiaryButton as={StyledButton} {...buttonProps} />
<TertiaryButton {...buttonProps} />
) : (
<Wrapper className={className} style={style}>
<BadgeNumber backgroundColor={badgeBackgroundColor} color={badgeColor} size={size}>
<BadgeNumber $backgroundColor={badgeBackgroundColor} $color={badgeColor} $size={size}>
{badgeNumber}
</BadgeNumber>
<TertiaryButton as={StyledButton} {...buttonProps} />
<TertiaryButton {...buttonProps} />
</Wrapper>
)}
</>
Expand All @@ -116,13 +116,13 @@ export function IconButton({
return (
<>
{badgeNumber === undefined ? (
<PrimaryButton as={StyledButton} {...buttonProps} />
<PrimaryButton as={BaseButton} {...buttonProps} />
) : (
<Wrapper className={className} style={style}>
<BadgeNumber backgroundColor={badgeBackgroundColor} color={badgeColor} size={size}>
<BadgeNumber $backgroundColor={badgeBackgroundColor} $color={badgeColor} $size={size}>
{badgeNumber}
</BadgeNumber>
<PrimaryButton as={StyledButton} {...buttonProps} />
<PrimaryButton as={BaseButton} {...buttonProps} />
</Wrapper>
)}
</>
Expand All @@ -147,9 +147,9 @@ const LEFT_MARGIN: Record<Size, number> = {
}

const BadgeNumber = styled.div<{
backgroundColor: string | undefined
color: string | undefined
size: Size
$backgroundColor: string | undefined
$color: string | undefined
$size: Size
}>`
display: inline-block;
position: absolute;
Expand All @@ -159,27 +159,34 @@ const BadgeNumber = styled.div<{
border-radius: 10px;
top: -5px;
line-height: 14px;
left: ${p => (p.size ? LEFT_MARGIN[p.size] : 25)}px;
background: ${p => (p.backgroundColor ? p.backgroundColor : p.theme.color.maximumRed)};
color: ${p => (p.color ? p.color : p.theme.color.white)};
left: ${p => (p.$size ? LEFT_MARGIN[p.$size] : 25)}px;
background: ${p => (p.$backgroundColor ? p.$backgroundColor : p.theme.color.maximumRed)};
color: ${p => (p.$color ? p.$color : p.theme.color.white)};
font-size: 12px;
letter-spacing: 0px;
font-weight: 700;
`

// We can't use $-prefixed props here for some reason (maybe because the `as` prop exclude them?).
const StyledButton = styled.button<{
isCompact: boolean | undefined
size: Size
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
$isCompact: boolean | undefined
$size: Size
}
const BaseButton = styled.button<{
$isCompact: boolean | undefined
$size: Size
}>`
align-items: center;
border-style: solid;
border-width: ${p => (p.isCompact ? 0 : 1)}px;
border-width: ${p => (p.$isCompact ? 0 : 1)}px;
display: flex;
justify-content: center;
padding: ${p => (p.isCompact ? 0 : PADDING[p.size])};
padding: ${p => (p.$isCompact ? 0 : PADDING[p.$size])};
`

const PrimaryButton = styled(BaseButton)(interpolatePrimaryButtonThemedCss)

const SecondaryButton = styled(BaseButton)(interpolateSecondaryButtonThemedCss)

const TertiaryButton = styled.button`
background-color: transparent;
border-color: transparent;
Expand Down

0 comments on commit 708db85

Please sign in to comment.