Skip to content

Commit

Permalink
feat(components): add helix product typography (#15459)
Browse files Browse the repository at this point in the history
This PR implements the new helix product typography system. You can find
it here:
https://www.figma.com/design/1ot18My22DALIcjdLl5LJh/Helix-Design-System?node-id=3571-46578&t=B4pPbtL9mapki2Jg-4

The Product type system is distinct from at least the Web type system,
which will have different styles for readability in a different context.
It is currently only defined for places other than the ODD.

This ended up being a big PR because our usage of the `StyledText` atom
had to be changed somewhat.

The change was necessary because the helix product styles do not and are
not intended to align with the semantic styling presented by the
`StyledText` component - there is no direct alignment that "when you're
making a `<p>`, you use this style". Instead, the intent is that higher
level components will use the style by the name it has in helix, without
an explicit semantic link outside of the designs. That makes the way the
old styled text works kind of nonsense.

In addition, there are no helix product styles for the ODD, and there is
no current map and possibly no intention to have a future map between
the semantic styles of the ODD and Desktop. That means that having a
`StyledText` component that maps from a single semantic element to a set
of appropriate styles just doesn't really make sense.

So, `StyledText` is renamed to `LegacyStyledText` including at all
callsites. The new `StyledText` requires you to specify styles
separately for ODD and Desktop, though it gives you a handy type system
integrated hint towards which styles should be allowed. Well, not quite
required, more like you have no way to specify both in one prop.

 You can view it commit by commit:

-
07dae4b
adds the actual data for the helix product typography styling, and
stories for viewing them as design components (and for viewing the old
typography styles). This is more or less the only commit there was
during the initial review, though it didn't then have the stories for
the old typography
-
a36f501
is a repo-wide find and replace to change `StyledText` to
`LegacyStyledText`
-
acec934
implements the new `StyledText`.

Stories here:
https://s3-us-west-2.amazonaws.com/opentrons-components/EXEC-566-add-helix-product-typography/index.html?path=/docs/design-tokens-typography--docs

Closes EXEC-566
  • Loading branch information
sfoster1 authored Jun 21, 2024
1 parent f81bab0 commit fec1a98
Show file tree
Hide file tree
Showing 462 changed files with 3,850 additions and 2,697 deletions.
10 changes: 5 additions & 5 deletions app/src/App/DesktopAppFallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
DIRECTION_COLUMN,
Flex,
SPACING,
StyledText,
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'

Expand Down Expand Up @@ -45,12 +45,12 @@ export function DesktopAppFallback({ error }: FallbackProps): JSX.Element {
>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
<StyledText as="p">
<LegacyStyledText as="p">
{t('error_boundary_desktop_app_description')}
</StyledText>
<StyledText as="p" fontWeight={TYPOGRAPHY.fontWeightSemiBold}>
</LegacyStyledText>
<LegacyStyledText as="p" fontWeight={TYPOGRAPHY.fontWeightSemiBold}>
{error.message}
</StyledText>
</LegacyStyledText>
</Flex>
<AlertPrimaryButton
alignSelf={ALIGN_FLEX_END}
Expand Down
6 changes: 3 additions & 3 deletions app/src/App/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
Link,
SIZE_2,
SPACING,
StyledText,
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'

Expand Down Expand Up @@ -134,12 +134,12 @@ export function Navbar({ routes }: { routes: RouteProps[] }): JSX.Element {
/>
{navRoutes.map(({ name, navLinkTo }: RouteProps) => (
<NavbarLink key={name} to={navLinkTo as string}>
<StyledText
<LegacyStyledText
as="h3"
margin={`${SPACING.spacing8} 0 ${SPACING.spacing8} ${SPACING.spacing12}`}
>
{name}
</StyledText>
</LegacyStyledText>
</NavbarLink>
))}
</Flex>
Expand Down
6 changes: 3 additions & 3 deletions app/src/App/OnDeviceDisplayAppFallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
Flex,
JUSTIFY_CENTER,
SPACING,
StyledText,
LegacyStyledText,
} from '@opentrons/components'

import { MediumButton } from '../atoms/buttons'
Expand Down Expand Up @@ -59,9 +59,9 @@ export function OnDeviceDisplayAppFallback({
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
>
<StyledText as="p">
<LegacyStyledText as="p">
{t('branded:error_boundary_description')}
</StyledText>
</LegacyStyledText>
<MediumButton
width="100%"
buttonType="alert"
Expand Down
6 changes: 3 additions & 3 deletions app/src/DesignTokens/BorderRadius/BorderRadius.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
DIRECTION_COLUMN,
Flex,
SPACING,
StyledText,
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'

Expand Down Expand Up @@ -46,9 +46,9 @@ const Template: Story<BorderRadiusStorybookProps> = args => {
width="100%"
height="6rem"
>
<StyledText as="h2" fontWeight={TYPOGRAPHY.fontWeightRegular}>
<LegacyStyledText as="h2" fontWeight={TYPOGRAPHY.fontWeightRegular}>
{`${br[0]}" ${br[1]}`}
</StyledText>
</LegacyStyledText>
<Box
width="10rem"
height="4rem"
Expand Down
10 changes: 5 additions & 5 deletions app/src/DesignTokens/Colors/Colors.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Flex,
JUSTIFY_SPACE_BETWEEN,
SPACING,
StyledText,
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'

Expand Down Expand Up @@ -78,20 +78,20 @@ const Template: Story<ColorsStorybookProps> = args => {
border: `1px solid ${COLORS.grey20}`,
}}
>
<StyledText
<LegacyStyledText
color={invertColor(color[1] as string)}
fontSize={TYPOGRAPHY.fontSizeP}
fontWeight={TYPOGRAPHY.fontWeightBold}
>
{color[0]}
</StyledText>
<StyledText
</LegacyStyledText>
<LegacyStyledText
fontSize={TYPOGRAPHY.fontSizeP}
color={invertColor(color[1] as string)}
fontWeight={TYPOGRAPHY.fontWeightRegular}
>
{color[1]}
</StyledText>
</LegacyStyledText>
</Flex>
))}
</Flex>
Expand Down
6 changes: 3 additions & 3 deletions app/src/DesignTokens/Spacing/Spacing.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
DIRECTION_COLUMN,
Flex,
SPACING,
StyledText,
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'

Expand Down Expand Up @@ -44,9 +44,9 @@ const Template: Story<SpacingsStorybookProps> = args => {
width="100%"
height="6rem"
>
<StyledText as="h2" fontWeight={TYPOGRAPHY.fontWeightRegular}>
<LegacyStyledText as="h2" fontWeight={TYPOGRAPHY.fontWeightRegular}>
{`${spacing[0]} - ${spacing[1]}: ${convertToPx(spacing[1])}`}
</StyledText>
</LegacyStyledText>
<Box
width={spacing[1]}
height="2rem"
Expand Down
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', 'SemiBold'],
['HeadingSmall', 'Regular'],
['HeadingSmall', 'Bold'],
['BodyLarge', 'SemiBold'],
['BodyLarge', 'Regular'],
['BodyDefault', 'SemiBold'],
['BodyDefault', 'Regular'],
['Caption', 'SemiBold'],
['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}`] as string
const fontSizeInPx = convertToPx(fontSize)
return `font-size: ${fontSize}/${fontSizeInPx}`
}
const lineHeightForPairForHelix = (style: string, weight: string): string => {
const lineHeight = PRODUCT.TYPOGRAPHY[`lineHeight${style}${weight}`] as string
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)',
}
9 changes: 6 additions & 3 deletions app/src/atoms/Banner/Banner.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import { StyledText, TYPOGRAPHY } from '@opentrons/components'
import { LegacyStyledText, TYPOGRAPHY } from '@opentrons/components'
import { Banner } from './index'
import type { Meta, StoryObj } from '@storybook/react'

Expand Down Expand Up @@ -35,9 +35,12 @@ export const OverriddenExitIcon: Story = {
console.log('close')
},
closeButton: (
<StyledText as="p" textDecoration={TYPOGRAPHY.textDecorationUnderline}>
<LegacyStyledText
as="p"
textDecoration={TYPOGRAPHY.textDecorationUnderline}
>
{'Exit'}
</StyledText>
</LegacyStyledText>
),
},
}
Loading

0 comments on commit fec1a98

Please sign in to comment.