Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

[C-2890] Add first version of a typography component to web #3796

Merged
merged 1 commit into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions packages/web/src/components/typography/Text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { CSSProperties, ReactNode } from 'react'

import { getCurrentThemeColors, ThemeColor } from 'utils/theme/theme'

import { fontWeightMap, variantInfoMap, variantStrengthMap } from './constants'
import {
TextSizeInfo,
TextStrengthInfo,
TextVariant,
TextSize,
TextStrength
} from './types'

const defaultBodyInfo: TextSizeInfo & TextStrengthInfo = {
...variantInfoMap.body.M!,
...variantStrengthMap.body.default!
}

export type TextProps = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is wonderful

className?: string
children?: ReactNode
variant?: TextVariant
size?: TextSize
strength?: TextStrength
color?: ThemeColor
}

export const Text = (props: TextProps) => {
const {
className,
children,
variant = 'body',
strength = 'default',
size = 'M',
color = '--neutral',
...otherProps
} = props

const themeColors = getCurrentThemeColors()
const textColor = themeColors[color] ?? themeColors['--neutral']

const variantSizeInfo = variantInfoMap[variant][size] ?? {}
const variantStrengthInfo = variantStrengthMap[variant][strength] ?? {}

const {
tag: Tag,
fontSize,
lineHeight,
letterSpacing,
fontWeight,
textTransform
} = {
...defaultBodyInfo,
...variantSizeInfo,
...variantStrengthInfo
}

const styleObject: CSSProperties = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as a first implementation, using styleObject is okay, but long term i do think it makes sense to use classNames so we can get better performance and readability when inspecting elements

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea you're probably right here. using the styles like this will also make overwriting the styles more annoying. I'll update it in the future

fontWeight: fontWeightMap[fontWeight].toString(),
fontSize,
lineHeight,
letterSpacing,
textTransform,
color: textColor
}

return (
<Tag className={className} style={styleObject} {...otherProps}>
{children}
</Tag>
)
}
170 changes: 170 additions & 0 deletions packages/web/src/components/typography/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import {
FontWeight,
TextVariant,
TextVariantSizeInfo,
TextVariantStrengthInfo
} from './types'

export const fontWeightMap: Record<FontWeight, number> = {
heavy: 900,
bold: 700,
demiBold: 600,
medium: 500,
regular: 400,
light: 300,
thin: 200,
ultraLight: 100
}

export const variantInfoMap: Record<TextVariant, TextVariantSizeInfo> = {
display: {
XL: {
tag: 'h1',
fontSize: '96px',
lineHeight: '120px'
},
L: {
tag: 'h1',
fontSize: '72px',
lineHeight: '88px'
},
M: {
tag: 'h1',
fontSize: '56px',
lineHeight: '68px'
},
S: {
tag: 'h1',
fontSize: '42px',
lineHeight: '52px'
}
},
heading: {
XL: {
tag: 'h1',
fontSize: '36px',
lineHeight: '40px'
},
L: {
tag: 'h2',
fontSize: '28px',
lineHeight: '32px'
},
M: {
tag: 'h3',
fontSize: '24px',
lineHeight: '32px'
},
S: {
tag: 'h4',
fontSize: '20px',
lineHeight: '24px'
}
},
title: {
L: {
tag: 'p',
fontSize: '18px',
lineHeight: '24px'
},
M: {
tag: 'p',
fontSize: '16px',
lineHeight: '20px'
},
S: {
tag: 'p',
fontSize: '14px',
lineHeight: '16px'
},
XS: {
tag: 'p',
fontSize: '12px',
lineHeight: '16px'
}
},
label: {
XL: {
tag: 'label',
fontSize: '20px',
lineHeight: '24px',
letterSpacing: '0.5px',
textTransform: 'uppercase'
},
L: {
tag: 'label',
fontSize: '16px',
lineHeight: '16px',
letterSpacing: '0.5px',
textTransform: 'uppercase'
},
M: {
tag: 'label',
fontSize: '14px',
lineHeight: '16px',
letterSpacing: '0.5px',
textTransform: 'uppercase'
},
S: {
tag: 'label',
fontSize: '12px',
lineHeight: '12px',
letterSpacing: '0.5px',
textTransform: 'uppercase'
},
XS: {
tag: 'label',
fontSize: '10px',
lineHeight: '12px',
letterSpacing: '0.5px',
textTransform: 'uppercase'
}
},
body: {
L: {
tag: 'p',
fontSize: '18px',
lineHeight: '24px'
},
M: {
tag: 'p',
fontSize: '16px',
lineHeight: '20px'
},
S: {
tag: 'p',
fontSize: '14px',
lineHeight: '20px'
},
XS: {
tag: 'p',
fontSize: '12px',
lineHeight: '20px'
}
}
}

export const variantStrengthMap: Record<TextVariant, TextVariantStrengthInfo> =
{
display: {
default: { fontWeight: 'bold' },
strong: { fontWeight: 'heavy' }
},
heading: {
default: { fontWeight: 'bold' },
strong: { fontWeight: 'heavy' }
},
title: {
weak: { fontWeight: 'demiBold' },
default: { fontWeight: 'bold' },
strong: { fontWeight: 'heavy' }
},
label: {
default: { fontWeight: 'bold' },
strong: { fontWeight: 'heavy' }
},
body: {
default: { fontWeight: 'medium' },
strong: { fontWeight: 'demiBold' }
}
}
2 changes: 2 additions & 0 deletions packages/web/src/components/typography/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Text } from './Text'
export * from './types'
32 changes: 32 additions & 0 deletions packages/web/src/components/typography/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ElementType } from 'react'

export type FontWeight =
| 'heavy' // 900
| 'bold' // 700
| 'demiBold' // 600
| 'medium' // 500
| 'regular' // 400
| 'light' // 300
| 'thin' // 200
| 'ultraLight' // 100

export type TextStrength = 'weak' | 'default' | 'strong'
export type TextStrengthInfo = {
fontWeight: FontWeight
}
type TextTransformValue = 'uppercase' | 'lowercase' | 'capitalize' | 'inherit'

export type TextSize = 'XL' | 'L' | 'M' | 'S' | 'XS'
export type TextSizeInfo = {
tag: ElementType
fontSize: string | number
lineHeight: string | number
letterSpacing?: string | number
textTransform?: TextTransformValue
}

export type TextVariant = 'display' | 'heading' | 'title' | 'label' | 'body'
export type TextVariantSizeInfo = Partial<Record<TextSize, TextSizeInfo>>
export type TextVariantStrengthInfo = Partial<
Record<TextStrength, TextStrengthInfo>
>
Loading