Skip to content

Commit

Permalink
fix: Issue with typing of ‘size’ props (#493)
Browse files Browse the repository at this point in the history
  • Loading branch information
dogmar authored Jun 8, 2023
1 parent f5752c9 commit d79b6e7
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 119 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"firebase:start": "yarn build:storybook && npx firebase emulators:start"
},
"engines": {
"node": "18.12.1"
"node": "18.16.0"
},
"dependencies": {
"@floating-ui/react-dom-interactions": "0.13.3",
Expand Down
98 changes: 52 additions & 46 deletions src/components/AppIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,100 @@ import PropTypes from 'prop-types'
import { type ReactNode, type Ref, forwardRef } from 'react'
import { last } from 'lodash-es'

import { styledTheme as theme } from '../theme'
import { type DefaultTheme, useTheme } from 'styled-components'

import { type CSSObject } from '../types'
import { type styledTheme as theme } from '../theme'

import { type FillLevel, useFillLevel } from './contexts/FillLevelContext'

type Hue = 'default' | 'lighter' | 'lightest'
type Size = 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'

type AppIconProps = DivProps & {
size?: Size
spacing?: 'none' | 'padding' | string
hue?: 'default' | 'lighter' | 'lightest'
const HUES = ['default', 'lighter', 'lightest'] as const
const SIZES = [
'xxsmall',
'xsmall',
'small',
'medium',
'large',
'xlarge',
] as const
const SPACINGS = ['none', 'padding'] as const

type AppIconHue = (typeof HUES)[number]
type AppIconSize = (typeof SIZES)[number]
type AppIconSpacing = (typeof SPACINGS)[number]

type AppIconProps = Omit<DivProps, 'size'> & {
size?: AppIconSize
spacing?: AppIconSpacing
hue?: AppIconHue
clickable?: boolean
url?: string
icon?: ReactNode
alt?: string
name?: string
initials?: string
onClose?: () => void
[x: string]: unknown
}

const propTypes = {
size: PropTypes.oneOf([
'xxsmall',
'xsmall',
'small',
'medium',
'large',
'xlarge',
]),
spacing: PropTypes.oneOf(['none', 'padding']),
hue: PropTypes.oneOf(['default', 'lighter', 'lightest']),
size: PropTypes.oneOf(SIZES),
spacing: PropTypes.oneOf(SPACINGS),
hue: PropTypes.oneOf(HUES),
clickable: PropTypes.bool,
url: PropTypes.string,
IconComponent: PropTypes.elementType,
alt: PropTypes.string,
}
} as const

const parentFillLevelToHue: Record<FillLevel, Hue> = {
const parentFillLevelToHue = {
0: 'default',
1: 'lighter',
2: 'lightest',
3: 'lightest',
}
} as const satisfies Record<FillLevel, AppIconHue>

const sizeToWidth: Record<Size, number> = {
const sizeToWidth = {
xxsmall: 32,
xsmall: 48,
small: 64,
medium: 96,
large: 140,
xlarge: 160,
}
} as const satisfies Record<AppIconSize, number>

const sizeToIconWidth: Record<Size, number> = {
const sizeToIconWidth = {
xxsmall: 16,
xsmall: 32,
small: 48,
medium: 64,
large: 76,
xlarge: 96,
}
} as const satisfies Record<AppIconSize, number>

const hueToColor: Record<Hue, string> = {
const hueToColor = {
default: 'fill-one',
lighter: 'fill-two',
lightest: 'fill-three',
}
} as const satisfies Record<AppIconHue, string>

const hueToBorderColor: {
[key in 'default' | 'lighter' | 'lightest']: string
} = {
const hueToBorderColor = {
default: 'border',
lighter: 'border-fill-two',
lightest: 'border-fill-three',
}

const sizeToFont: Record<Size, CSSObject> = {
xxsmall: {
...theme.partials.text.body2Bold,
fontSize: 12,
},
xsmall: theme.partials.text.body2Bold,
small: theme.partials.text.subtitle2,
medium: theme.partials.text.subtitle1,
large: theme.partials.text.title2,
xlarge: theme.partials.text.title2,
}
} as const satisfies Record<AppIconHue, keyof typeof theme.colors>

const sizeToFont = (size: AppIconSize, theme: DefaultTheme) =>
({
xxsmall: {
...theme.partials.text.body2Bold,
fontSize: 12,
},
xsmall: theme.partials.text.body2Bold,
small: theme.partials.text.subtitle2,
medium: theme.partials.text.subtitle1,
large: theme.partials.text.title2,
xlarge: theme.partials.text.title2,
}[size])

export function toInitials(name: string) {
let initials = name
Expand Down Expand Up @@ -131,6 +136,7 @@ function AppIconRef(
const color = hueToColor[hue]
const borderColor = hueToBorderColor[hue]
const hasBorder = spacing === 'padding'
const theme = useTheme()

return (
<Flex
Expand Down Expand Up @@ -168,7 +174,7 @@ function AppIconRef(
justifyContent="center"
userSelect="none"
textTransform="uppercase"
{...sizeToFont[size]}
{...sizeToFont(size, theme)}
>
{initials || (name ? toInitials(name) : '')}
</Flex>
Expand All @@ -180,7 +186,7 @@ function AppIconRef(

const AppIcon = forwardRef(AppIconRef)

AppIcon.propTypes = propTypes as any
AppIcon.propTypes = propTypes

export default AppIcon
export type { AppIconProps }
8 changes: 5 additions & 3 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import {
type CornerSize = 'medium' | 'large'
type CardHue = 'default' | 'lighter' | 'lightest'

type CardProps = {
type BaseCardProps = {
hue?: CardHue // Deprecated, prefer fillLevel
fillLevel?: FillLevel
cornerSize?: CornerSize
clickable?: boolean
selected?: boolean
} & DivProps
}

type CardProps = DivProps & BaseCardProps

const fillLevelToBGColor: Record<FillLevel, string> = {
0: 'fill-one',
Expand Down Expand Up @@ -126,4 +128,4 @@ const Card = forwardRef<HTMLDivElement, CardProps>(
)

export default Card
export type { CardProps, CornerSize as CardSize, CardHue }
export type { BaseCardProps, CardProps, CornerSize as CardSize, CardHue }
88 changes: 45 additions & 43 deletions src/components/Chip.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,76 @@
import { Flex, type FlexProps, Spinner } from 'honorable'
import PropTypes from 'prop-types'
import { type ReactElement, type Ref, forwardRef } from 'react'
import styled from 'styled-components'
import styled, { type DefaultTheme } from 'styled-components'

import Card, { type CardProps } from './Card'
import Card, { type BaseCardProps } from './Card'
import { type FillLevel, useFillLevel } from './contexts/FillLevelContext'
import CloseIcon from './icons/CloseIcon'

type Hue = 'default' | 'lighter' | 'lightest'
type Size = 'small' | 'medium' | 'large'
type Severity =
| 'neutral'
| 'info'
| 'success'
| 'warning'
| 'error'
| 'critical'

export type ChipProps = FlexProps & {
size?: 'small' | 'medium' | 'large'
severity?: Severity
icon?: ReactElement
loading?: boolean
closeButton?: boolean
clickable?: boolean
} & CardProps

const parentFillLevelToHue: Record<FillLevel, Hue> = {
const HUES = ['default', 'lighter', 'lightest'] as const
const SIZES = ['small', 'medium', 'large'] as const
const SEVERITIES = [
'neutral',
'info',
'success',
'warning',
'error',
'critical',
] as const

type ChipHue = (typeof HUES)[number]
type ChipSize = (typeof SIZES)[number]
type ChipSeverity = (typeof SEVERITIES)[number]

export type ChipProps = Omit<FlexProps, 'size'> &
BaseCardProps & {
size?: ChipSize
severity?: ChipSeverity
icon?: ReactElement
loading?: boolean
closeButton?: boolean
clickable?: boolean
[x: string]: unknown
}

const propTypes = {
size: PropTypes.oneOf(SIZES),
severity: PropTypes.oneOf(SEVERITIES),
hue: PropTypes.oneOf(HUES),
icon: PropTypes.element,
loading: PropTypes.bool,
} as const

const parentFillLevelToHue = {
0: 'default',
1: 'lighter',
2: 'lightest',
3: 'lightest',
}
} as const satisfies Record<FillLevel, ChipHue>

const severityToColor: Record<Severity, string> = {
const severityToColor = {
neutral: 'text',
info: 'text-primary-accent',
success: 'text-success-light',
warning: 'text-warning-light',
error: 'text-danger-light',
critical: 'text-danger',
}
} as const satisfies Record<ChipSeverity, string>

const severityToIconColor: Record<Severity, string> = {
const severityToIconColor = {
neutral: 'icon-default',
info: 'icon-info',
success: 'icon-success',
warning: 'icon-warning',
error: 'icon-danger',
critical: 'icon-danger-critical',
}
} as const satisfies Record<ChipSeverity, keyof DefaultTheme['colors']>

const sizeToCloseHeight: Record<Size, number> = {
const sizeToCloseHeight = {
small: 8,
medium: 10,
large: 12,
}
} as const satisfies Record<ChipSize, number>

const ChipCard = styled(Card)(({ theme }) => ({
'.closeIcon': {
Expand Down Expand Up @@ -138,19 +153,6 @@ function ChipRef(

const Chip = forwardRef(ChipRef)

Chip.propTypes = {
size: PropTypes.oneOf(['small', 'medium', 'large']),
severity: PropTypes.oneOf([
'neutral',
'info',
'success',
'warning',
'error',
'critical',
]),
hue: PropTypes.oneOf(['default', 'lighter', 'lightest']),
icon: PropTypes.element,
loading: PropTypes.bool,
}
Chip.propTypes = propTypes

export default Chip
Loading

0 comments on commit d79b6e7

Please sign in to comment.