Skip to content

Commit

Permalink
feat(components): add helix product typography
Browse files Browse the repository at this point in the history
- Adds the new sizes for type in the helix product system
- Adds a dummy component under "Design Tokens" in storybook so you can
  view all the text

Closes EXEC-566

Make the storybook display all the stories
  • Loading branch information
sfoster1 committed Jun 20, 2024
1 parent f8d7d64 commit 07dae4b
Show file tree
Hide file tree
Showing 4 changed files with 373 additions and 0 deletions.
230 changes: 230 additions & 0 deletions app/src/DesignTokens/Typography/Typography.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import * as React from 'react'
import { css } from 'styled-components'
import type { FlattenSimpleInterpolation } from 'styled-components'
import {
ALIGN_CENTER,
Box,
DIRECTION_COLUMN,
Flex,
SPACING,
Text,
PRODUCT,
TYPOGRAPHY,
} from '@opentrons/components'

import type { Story, Meta } from '@storybook/react'

const fontStyles = {
'Helix Product (Desktop)': [
['Display', 'Bold'],
['HeadingLarge', 'Regular'],
['HeadingLarge', 'Bold'],
['HeadingMedium', 'Medium'],
['HeadingSmall', 'Regular'],
['HeadingSmall', 'Bold'],
['BodyLarge', 'Medium'],
['BodyLarge', 'Regular'],
['BodyDefault', 'Medium'],
['BodyDefault', 'Regular'],
['Caption', 'Medium'],
['Caption', 'Regular'],
['Code', 'Regular'],
],
ODD: [
['level1Header', ''],
['level2Header', 'Bold'],
['level2Header', 'SemiBold'],
['level2Header', 'Regular'],
['level3Header', 'Bold'],
['level3Header', 'SemiBold'],
['level3Header', 'Regular'],
['level4Header', 'Bold'],
['level4Header', 'SemiBold'],
['level4Header', 'Regular'],
['bodyText', 'Bold'],
['bodyText', 'SemiBold'],
['bodyText', 'Regular'],
['smallBodyText', 'Bold'],
['smallBodyText', 'SemiBold'],
['smallBodyText', 'Regular'],
],
'Legacy Desktop': [
['h1', 'Default'],
['h2', 'Regular'],
['h2', 'SemiBold'],
['h3', 'Regular'],
['h3', 'SemiBold'],
['h6', 'Default'],
['h6', 'SemiBold'],
['p', 'Regular'],
['p', 'SemiBold'],
['label', 'Regular'],
['label', 'SemiBold'],
['linkP', 'SemiBold'],
],
}

type TypographyStandard = keyof typeof fontStyles

export default {
title: 'Design Tokens/Typography',
argTypes: {
text: {
type: 'text',
},
styles: {
control: {
type: 'select',
},
options: Object.keys(fontStyles),
},
},
} as Meta

interface TypographyStorybookProps {
text: string
styles: TypographyStandard
}

const convertToPx = (remFormat: string): string => {
const pxVal = Number(remFormat.replace('rem', '')) * 16
return `${pxVal}px`
}
const styleForPairForHelix = (style: string, weight: string): string => {
const fontPayload = PRODUCT.TYPOGRAPHY[`fontStyle${style}${weight}`]
return css`
font: ${fontPayload};
`
}
const fontSizeForPairForHelix = (style: string, weight: string): string => {
const fontSize = PRODUCT.TYPOGRAPHY[`fontSize${style}${weight}`]
const fontSizeInPx = convertToPx(fontSize)
return `font-size: ${fontSize}/${fontSizeInPx}`
}
const lineHeightForPairForHelix = (style: string, weight: string): string => {
const lineHeight = PRODUCT.TYPOGRAPHY[`lineHeight${style}${weight}`]
const lineHeightInPx = convertToPx(lineHeight)
return `line-height: ${lineHeight}/${lineHeightInPx}`
}
const fontWeightForPairForHelix = (style: string, weight: string): string => {
const fontWeight = PRODUCT.TYPOGRAPHY[`fontWeight${style}${weight}`]
return `font-weight: ${fontWeight}`
}

const styleForPairForLegacy = (style: string, weight: string): string => {
return TYPOGRAPHY[`${style}${weight}`]
}

const fontSizeForPairForLegacy = (style: string, weight: string): string => {
const stylePayload = styleForPairForLegacy(style, weight)
const sizeStr = valueFromFlattenedInterp(stylePayload, 'font-size:')
const sizeInPx = convertToPx(sizeStr)

return `font-size: ${sizeStr}/${sizeInPx}`
}

const lineHeightForPairForLegacy = (style: string, weight: string): string => {
const stylePayload = styleForPairForLegacy(style, weight)
const sizeStr = valueFromFlattenedInterp(stylePayload, 'line-height:')
const sizeInPx = convertToPx(sizeStr)
return `line-height: ${sizeStr}/${sizeInPx}`
}

const fontWeightForPairForLegacy = (style: string, weight: string): string => {
const stylePayload = styleForPairForLegacy(style, weight)
const fontWeight = valueFromFlattenedInterp(stylePayload, 'font-weight:')
return `font-weight: ${fontWeight}`
}

const valueFromFlattenedInterp = (
style: FlattenSimpleInterpolation,
valueName: str
): string => {
return style.reduce(
([sawKey, value]: [boolean, null | string], el) => {
const thisEl = el.trim()
if (sawKey && value == null) {
return [sawKey, el]
}
if (sawKey && value != null) {
return [sawKey, value]
}
if (thisEl.includes(valueName)) {
return [true, null]
}
return [false, null]
},
[false, null]
)[1]
}

const styleForPair = (
style: string,
weight: string,
which: TypographyStandard
): string =>
which === 'Helix Product (Desktop)'
? styleForPairForHelix(style, weight)
: styleForPairForLegacy(style, weight)

const fontSizeForPair = (
style: string,
weight: string,
which: TypographyStandard
): string =>
which === 'Helix Product (Desktop)'
? fontSizeForPairForHelix(style, weight)
: fontSizeForPairForLegacy(style, weight)

const lineHeightForPair = (
style: string,
weight: string,
which: TypographyStandard
): string =>
which === 'Helix Product (Desktop)'
? lineHeightForPairForHelix(style, weight)
: lineHeightForPairForLegacy(style, weight)

const fontWeightForPair = (
style: string,
weight: string,
which: TypographyStandard
): string =>
which === 'Helix Product (Desktop)'
? fontWeightForPairForHelix(style, weight)
: fontWeightForPairForLegacy(style, weight)

const Template: Story<TypographyStorybookProps> = args => {
const fonts = fontStyles[args.styles]
return (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing8}
padding={SPACING.spacing24}
>
{fonts.map(([style, weight]) => (
<Box key={`${style}_${weight}`} alignItems={ALIGN_CENTER}>
<Text css={styleForPair(style, weight, args.styles)}>
{`${style} ${weight} (${fontWeightForPair(
style,
weight,
args.styles
)}, ${fontSizeForPair(
style,
weight,
args.styles
)}, ${lineHeightForPair(style, weight, args.styles)}): ${
args.text
}`}
</Text>
</Box>
))}
</Flex>
)
}

export const AllTypographyStyles = Template.bind({})
AllTypographyStyles.args = {
text: 'The quick brown fox jumped over the lazy dog.',
styles: 'Helix Product (Desktop)',
}
1 change: 1 addition & 0 deletions components/src/helix-design-system/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * as COLORS from './colors'
export * as BORDERS from './borders'
export * as PRODUCT from './product'
1 change: 1 addition & 0 deletions components/src/helix-design-system/product/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as TYPOGRAPHY from './typography'
141 changes: 141 additions & 0 deletions components/src/helix-design-system/product/typography.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* Note: these values are only currently correct for desktop and should not be used on ODD.
*/

// Valid for most typography styles
export const fontFamily = 'Public Sans'

export const fontWeightRegular = '400'
export const fontWeightSemiBold = '600'
export const fontWeightBold = '700'

// Display styles
const fontFamilyDisplay = fontFamily
const fontSizeDisplay = '2.4375rem' // 39px
const lineHeightDisplay = '3rem' // 48px

// Display-Bold
export const fontSizeDisplayBold = fontSizeDisplay
export const lineHeightDisplayBold = lineHeightDisplay
export const fontFamilyDisplayBold = fontFamilyDisplay
export const fontWeightDisplayBold = fontWeightBold
export const fontStyleDisplayBold = `${fontWeightDisplayBold} ${fontSizeDisplayBold}/${lineHeightDisplayBold} ${fontFamilyDisplayBold}`

// Heading-Large
const fontSizeHeadingLarge = '1.625rem' // 26px
const lineHeightHeadingLarge = '2rem' // 32px
const fontFamilyHeadingLarge = fontFamily

// Heading-Large-Regular
export const fontFamilyHeadingLargeRegular = fontFamilyHeadingLarge
export const fontSizeHeadingLargeRegular = fontSizeHeadingLarge
export const lineHeightHeadingLargeRegular = lineHeightHeadingLarge
export const fontWeightHeadingLargeRegular = fontWeightRegular
export const fontStyleHeadingLargeRegular = `${fontWeightHeadingLargeRegular} ${fontSizeHeadingLargeRegular}/${lineHeightHeadingLargeRegular} ${fontFamilyHeadingLargeRegular}`

// Heading-Large-Bold
export const fontFamilyHeadingLargeBold = fontFamilyHeadingLarge
export const fontSizeHeadingLargeBold = fontSizeHeadingLarge
export const lineHeightHeadingLargeBold = lineHeightHeadingLarge
export const fontWeightHeadingLargeBold = fontWeightBold
export const fontStyleHeadingLargeBold = `${fontWeightHeadingLargeBold} ${fontSizeHeadingLargeBold}/${lineHeightHeadingLargeBold} ${fontFamilyHeadingLargeBold}`

// Heading-Medium
const fontSizeHeadingMedium = '1.4375rem' // 23px
const lineHeightHeadingMedium = '1.75rem' // 28px
const fontFamilyHeadingMedium = fontFamily

// Heading-Medium-Regular
export const fontSizeHeadingMediumMedium = fontSizeHeadingMedium
export const lineHeightHeadingMediumMedium = lineHeightHeadingMedium
export const fontFamilyHeadingMediumMedium = fontFamilyHeadingMedium
export const fontWeightHeadingMediumMedium = fontWeightSemiBold
export const fontStyleHeadingMediumMedium = `${fontWeightHeadingMediumMedium} ${fontSizeHeadingMediumMedium}/${lineHeightHeadingMediumMedium} ${fontFamilyHeadingMediumMedium}`

// Heading-Small
const fontSizeHeadingSmall = '1.125rem' // 18px
const lineHeightHeadingSmall = '1.5rem' // 24px
const fontFamilyHeadingSmall = fontFamily

// Heading-Small-Regular
export const fontSizeHeadingSmallRegular = fontSizeHeadingSmall
export const lineHeightHeadingSmallRegular = lineHeightHeadingSmall
export const fontFamilyHeadingSmallRegular = fontFamilyHeadingSmall
export const fontWeightHeadingSmallRegular = '600'
export const fontStyleHeadingSmallRegular = `${fontWeightHeadingSmallRegular} ${fontSizeHeadingSmallRegular}/${lineHeightHeadingSmallRegular} ${fontFamilyHeadingSmallRegular}`

// Heading-Small-Bold
export const fontSizeHeadingSmallBold = fontSizeHeadingSmall
export const lineHeightHeadingSmallBold = lineHeightHeadingSmall
export const fontFamilyHeadingSmallBold = fontFamilyHeadingSmall
export const fontWeightHeadingSmallBold = fontWeightBold
export const fontStyleHeadingSmallBold = `${fontWeightHeadingSmallBold} ${fontSizeHeadingSmallBold}/${lineHeightHeadingSmallBold} ${fontFamilyHeadingSmallBold}`

// Body-Large
const fontSizeBodyLarge = '1rem' // 16px
const lineHeightBodyLarge = '1.5rem' // 24px
const fontFamilyBodyLarge = fontFamily

// Body-Large-Medium
export const fontSizeBodyLargeMedium = fontSizeBodyLarge
export const lineHeightBodyLargeMedium = lineHeightBodyLarge
export const fontFamilyBodyLargeMedium = fontFamilyBodyLarge
export const fontWeightBodyLargeMedium = fontWeightSemiBold
export const fontStyleBodyLargeMedium = `${fontWeightBodyLargeMedium} ${fontSizeBodyLargeMedium}/${lineHeightBodyLargeMedium} ${fontFamilyBodyLargeMedium}`

// Body-Large-Regular
export const fontSizeBodyLargeRegular = fontSizeBodyLarge
export const lineHeightBodyLargeRegular = lineHeightBodyLarge
export const fontFamilyBodyLargeRegular = fontFamilyBodyLarge
export const fontWeightBodyLargeRegular = fontWeightRegular
export const fontStyleBodyLargeRegular = `${fontWeightBodyLargeRegular} ${fontSizeBodyLargeRegular}/${lineHeightBodyLargeRegular} ${fontFamilyBodyLargeRegular}`

// Body-Default
const fontSizeBodyDefault = '0.875rem' // 14px
const lineHeightBodyDefault = '1.25rem' // 20px
const fontFamilyBodyDefault = fontFamily

// Body-Default-Medium
export const fontSizeBodyDefaultMedium = fontSizeBodyDefault
export const lineHeightBodyDefaultMedium = lineHeightBodyDefault
export const fontFamilyBodyDefaultMedium = fontFamilyBodyDefault
export const fontWeightBodyDefaultMedium = fontWeightSemiBold
export const fontStyleBodyDefaultMedium = `${fontWeightBodyDefaultMedium} ${fontSizeBodyDefaultMedium}/${lineHeightBodyDefaultMedium} ${fontFamilyBodyDefaultMedium}`

// Body-Default-Regular
export const fontSizeBodyDefaultRegular = fontSizeBodyDefault
export const lineHeightBodyDefaultRegular = lineHeightBodyDefault
export const fontFamilyBodyDefaultRegular = fontFamilyBodyDefault
export const fontWeightBodyDefaultRegular = fontWeightRegular
export const fontStyleBodyDefaultRegular = `${fontWeightBodyDefaultRegular} ${fontSizeBodyDefaultRegular}/${lineHeightBodyDefaultRegular} ${fontFamilyBodyDefaultRegular}`

// Caption
const fontSizeCaption = '0.8125rem' // 13px
const lineHeightCaption = '1rem' // 16px
const fontFamilyCaption = 'Public Sans'

// Caption-Medium
export const fontSizeCaptionMedium = fontSizeCaption
export const lineHeightCaptionMedium = lineHeightCaption
export const fontFamilyCaptionMedium = fontFamilyCaption
export const fontWeightCaptionMedium = '500'
export const fontStyleCaptionMedium = `${fontWeightCaptionMedium} ${fontSizeCaptionMedium}/${lineHeightCaptionMedium} ${fontFamilyCaptionMedium}`

// Caption-Regular
export const fontSizeCaptionRegular = fontSizeCaption
export const lineHeightCaptionRegular = lineHeightCaption
export const fontFamilyCaptionRegular = fontFamilyCaption
export const fontWeightCaptionRegular = '400'
export const fontStyleCaptionRegular = `${fontWeightCaptionRegular} ${fontSizeCaptionRegular}/${lineHeightCaptionRegular} ${fontFamilyCaptionRegular}`

// Code
const fontSizeCode = '0.75rem' // 12px
const lineHeightCode = '1.25rem' // 20px
const fontFamilyCode = 'Reddit Mono'

// Code-Regular
export const fontSizeCodeRegular = fontSizeCode
export const lineHeightCodeRegular = lineHeightCode
export const fontFamilyCodeRegular = fontFamilyCode
export const fontWeightCodeRegular = fontWeightRegular
export const fontStyleCodeRegular = `${fontWeightCodeRegular} ${fontSizeCodeRegular}/${lineHeightCodeRegular} ${fontFamilyCodeRegular}`

0 comments on commit 07dae4b

Please sign in to comment.