mirror of https://github.com/acid-info/lsd.git
feat: update design tokens
This commit is contained in:
parent
1749b02558
commit
e9cb00ea23
|
@ -14,7 +14,7 @@ export const parameters: Parameters = {
|
||||||
default: 'light',
|
default: 'light',
|
||||||
values: Object.entries(defaultThemes).map(([name, theme]) => ({
|
values: Object.entries(defaultThemes).map(([name, theme]) => ({
|
||||||
name,
|
name,
|
||||||
value: theme.palette.background.primary,
|
value: `rgb(${theme.palette.secondary})`,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
viewport: {
|
viewport: {
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
import { DecoratorFunction, useGlobals } from '@storybook/addons'
|
import { DecoratorFunction, useGlobals } from '@storybook/addons'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { defaultThemes, ThemeProvider } from '../src'
|
import { defaultThemes, Theme, ThemeProvider } from '../src'
|
||||||
|
|
||||||
export const withTheme: DecoratorFunction = (Story, context) => {
|
export const withTheme: DecoratorFunction = (Story, context) => {
|
||||||
const StoryComponent = Story as any as React.ComponentType
|
const StoryComponent = Story as any as React.ComponentType
|
||||||
|
|
||||||
const themeName = context.globals?.theme ?? 'light'
|
const themeName = context.globals?.theme ?? 'light'
|
||||||
const theme = defaultThemes[themeName]
|
const theme = defaultThemes[themeName] as Theme
|
||||||
|
|
||||||
const [globals, setGlobals] = useGlobals()
|
const [globals, setGlobals] = useGlobals()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGlobals({
|
const background = (context.parameters.backgrounds?.values ?? []).find(
|
||||||
...globals,
|
(value) => value.name === themeName,
|
||||||
backgrounds: {
|
)?.value
|
||||||
...(globals.background ?? {}),
|
|
||||||
value: theme.palette.background.primary,
|
globals.backgrounds?.value !== background &&
|
||||||
},
|
setGlobals({
|
||||||
})
|
...globals,
|
||||||
|
backgrounds: {
|
||||||
|
...(globals.background ?? {}),
|
||||||
|
value: background,
|
||||||
|
},
|
||||||
|
})
|
||||||
}, [theme])
|
}, [theme])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,47 +1,38 @@
|
||||||
import { css } from '@emotion/react'
|
import { css } from '@emotion/react'
|
||||||
import { withTheme } from '../Theme/withTheme'
|
|
||||||
import { buttonClasses } from './Button.classes'
|
import { buttonClasses } from './Button.classes'
|
||||||
|
|
||||||
export const ButtonStyles = withTheme(
|
export const ButtonStyles = css`
|
||||||
(theme) => css`
|
.${buttonClasses.root} {
|
||||||
.${buttonClasses.root} {
|
width: auto;
|
||||||
width: auto;
|
color: rgb(var(--lsd-text-primary));
|
||||||
color: var(--lsd-text-primary);
|
background: none;
|
||||||
background: none;
|
border: 1px solid rgb(var(--lsd-border-primary));
|
||||||
border: 1px solid var(--lsd-surface-primary);
|
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 6px 24px;
|
padding: 6px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: ${theme.breakpoints.lg.width}px) {
|
.${buttonClasses.disabled} {
|
||||||
color: red;
|
cursor: default;
|
||||||
border-color: red;
|
opacity: 0.34;
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.large} {
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.medium} {
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.small} {
|
||||||
|
padding: 6px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.root}:hover {
|
||||||
|
&:not(.${buttonClasses.disabled}) {
|
||||||
|
.${buttonClasses.text} {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.${buttonClasses.disabled} {
|
`
|
||||||
cursor: default;
|
|
||||||
color: var(--lsd-surface-disabled);
|
|
||||||
border-color: var(--lsd-surface-disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
.${buttonClasses.large} {
|
|
||||||
padding: 10px 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.${buttonClasses.medium} {
|
|
||||||
}
|
|
||||||
|
|
||||||
.${buttonClasses.small} {
|
|
||||||
padding: 6px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.${buttonClasses.root}:hover {
|
|
||||||
&:not(.${buttonClasses.disabled}) {
|
|
||||||
.${buttonClasses.text} {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import { Global } from '@emotion/react'
|
import { Global, SerializedStyles } from '@emotion/react'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { ButtonStyles } from '../Button/Button.styles'
|
import { ButtonStyles } from '../Button/Button.styles'
|
||||||
import { defaultThemes, Theme } from '../Theme'
|
import { defaultThemes, Theme, withTheme } from '../Theme'
|
||||||
|
|
||||||
|
const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
|
||||||
|
[ButtonStyles]
|
||||||
|
|
||||||
export const CSSBaseline: React.FC<{ theme?: Theme }> = ({
|
export const CSSBaseline: React.FC<{ theme?: Theme }> = ({
|
||||||
theme = defaultThemes.light,
|
theme = defaultThemes.light,
|
||||||
}) => {
|
}) => {
|
||||||
const styles = useMemo(
|
const styles = useMemo(
|
||||||
() =>
|
() =>
|
||||||
[ButtonStyles]
|
componentStyles
|
||||||
.map((style) => (typeof style === 'function' ? style(theme) : style))
|
.map((style) => (typeof style === 'function' ? style(theme) : style))
|
||||||
.map((style) => <Global key={style.name} styles={style} />),
|
.map((style) => <Global key={style.name} styles={style} />),
|
||||||
[theme],
|
[theme],
|
||||||
|
|
|
@ -7,173 +7,140 @@ export const baseTheme: Theme = {
|
||||||
xs: {
|
xs: {
|
||||||
width: 0,
|
width: 0,
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {},
|
display1: {},
|
||||||
headlineMd: {},
|
display2: {},
|
||||||
headlineStd: {},
|
h1: {},
|
||||||
headlineSm: {},
|
h2: {},
|
||||||
titleLg: {},
|
h3: {},
|
||||||
titleMd: {},
|
h4: {},
|
||||||
titleSm: {},
|
h5: {},
|
||||||
bodyLg: {},
|
h6: {},
|
||||||
bodyMd: {},
|
body1: {},
|
||||||
bodySm: {},
|
body2: {},
|
||||||
labelLg: {},
|
body3: {},
|
||||||
labelMd: {},
|
label1: {},
|
||||||
labelSm: {},
|
label2: {},
|
||||||
|
subtitle1: {},
|
||||||
|
subtitle2: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sm: {
|
sm: {
|
||||||
width: 400,
|
width: 400,
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {},
|
display1: {},
|
||||||
headlineMd: {},
|
display2: {},
|
||||||
headlineStd: {},
|
h1: {},
|
||||||
headlineSm: {},
|
h2: {},
|
||||||
titleLg: {},
|
h3: {},
|
||||||
titleMd: {},
|
h4: {},
|
||||||
titleSm: {},
|
h5: {},
|
||||||
bodyLg: {},
|
h6: {},
|
||||||
bodyMd: {},
|
body1: {},
|
||||||
bodySm: {},
|
body2: {},
|
||||||
labelLg: {},
|
body3: {},
|
||||||
labelMd: {},
|
label1: {},
|
||||||
labelSm: {},
|
label2: {},
|
||||||
|
subtitle1: {},
|
||||||
|
subtitle2: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
md: {
|
md: {
|
||||||
width: 768,
|
width: 768,
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {},
|
display1: {},
|
||||||
headlineMd: {},
|
display2: {},
|
||||||
headlineStd: {},
|
h1: {},
|
||||||
headlineSm: {},
|
h2: {},
|
||||||
titleLg: {},
|
h3: {},
|
||||||
titleMd: {},
|
h4: {},
|
||||||
titleSm: {},
|
h5: {},
|
||||||
bodyLg: {},
|
h6: {},
|
||||||
bodyMd: {},
|
body1: {},
|
||||||
bodySm: {},
|
body2: {},
|
||||||
labelLg: {},
|
body3: {},
|
||||||
labelMd: {},
|
label1: {},
|
||||||
labelSm: {},
|
label2: {},
|
||||||
|
subtitle1: {},
|
||||||
|
subtitle2: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
lg: {
|
lg: {
|
||||||
width: 1024,
|
width: 1024,
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {},
|
display1: {},
|
||||||
headlineMd: {},
|
display2: {},
|
||||||
headlineStd: {},
|
h1: {},
|
||||||
headlineSm: {},
|
h2: {},
|
||||||
titleLg: {},
|
h3: {},
|
||||||
titleMd: {},
|
h4: {},
|
||||||
titleSm: {},
|
h5: {},
|
||||||
bodyLg: {},
|
h6: {},
|
||||||
bodyMd: {},
|
body1: {},
|
||||||
bodySm: {},
|
body2: {},
|
||||||
labelLg: {},
|
body3: {},
|
||||||
labelMd: {},
|
label1: {},
|
||||||
labelSm: {},
|
label2: {},
|
||||||
|
subtitle1: {},
|
||||||
|
subtitle2: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
xl: {
|
xl: {
|
||||||
width: 1200,
|
width: 1200,
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {},
|
display1: {},
|
||||||
headlineMd: {},
|
display2: {},
|
||||||
headlineStd: {},
|
h1: {},
|
||||||
headlineSm: {},
|
h2: {},
|
||||||
titleLg: {},
|
h3: {},
|
||||||
titleMd: {},
|
h4: {},
|
||||||
titleSm: {},
|
h5: {},
|
||||||
bodyLg: {},
|
h6: {},
|
||||||
bodyMd: {},
|
body1: {},
|
||||||
bodySm: {},
|
body2: {},
|
||||||
labelLg: {},
|
body3: {},
|
||||||
labelMd: {},
|
label1: {},
|
||||||
labelSm: {},
|
label2: {},
|
||||||
|
subtitle1: {},
|
||||||
|
subtitle2: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
headlineLg: {
|
display1: { fontSize: '5.625rem', lineHeight: '6.125rem' },
|
||||||
fontSize: '2.875rem',
|
display2: { fontSize: '3.5625rem', lineHeight: '4rem' },
|
||||||
lineHeight: '3.25rem',
|
h1: { fontSize: '2.875rem', lineHeight: '3.25rem' },
|
||||||
},
|
h2: { fontSize: '2.25rem', lineHeight: '2.75rem' },
|
||||||
headlineMd: {
|
h3: { fontSize: '2rem', lineHeight: '2.5rem' },
|
||||||
fontSize: '1.75rem',
|
h4: { fontSize: '1.75rem', lineHeight: '2.25rem' },
|
||||||
lineHeight: '2.25rem',
|
h5: { fontSize: '1.5rem', lineHeight: '2rem' },
|
||||||
},
|
h6: { fontSize: '1.375rem', lineHeight: '1.75rem' },
|
||||||
headlineStd: {
|
subtitle1: { fontSize: '1rem', lineHeight: '1.5rem' },
|
||||||
fontSize: '2rem',
|
subtitle2: { fontSize: '0.875rem', lineHeight: '1.25rem' },
|
||||||
lineHeight: '2.5rem',
|
body1: { fontSize: '1rem', lineHeight: '1.5rem' },
|
||||||
},
|
body2: { fontSize: '0.875rem', lineHeight: '1.25rem' },
|
||||||
headlineSm: {
|
body3: { fontSize: '0.75rem', lineHeight: '1rem' },
|
||||||
fontSize: '1.5rem',
|
label1: { fontSize: '0.875rem', lineHeight: '1.25rem' },
|
||||||
lineHeight: '2rem',
|
label2: { fontSize: '0.75rem', lineHeight: '1rem' },
|
||||||
},
|
|
||||||
titleLg: {
|
|
||||||
fontSize: '1.375rem',
|
|
||||||
lineHeight: '1.75rem',
|
|
||||||
},
|
|
||||||
titleMd: {
|
|
||||||
fontSize: '1rem',
|
|
||||||
lineHeight: '1.5rem',
|
|
||||||
},
|
|
||||||
titleSm: {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
lineHeight: '1.25rem',
|
|
||||||
},
|
|
||||||
bodyLg: {
|
|
||||||
fontSize: '1rem',
|
|
||||||
lineHeight: '1.5rem',
|
|
||||||
},
|
|
||||||
bodyMd: {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
lineHeight: '1.25rem',
|
|
||||||
},
|
|
||||||
bodySm: {
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
lineHeight: '1rem',
|
|
||||||
},
|
|
||||||
labelLg: {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
lineHeight: '1.25rem',
|
|
||||||
},
|
|
||||||
labelMd: {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
lineHeight: '1.25rem',
|
|
||||||
},
|
|
||||||
labelSm: {
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
lineHeight: '1rem',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
palette: {
|
palette: {
|
||||||
background: {
|
primary: '0, 0, 0',
|
||||||
primary: 'rgba(255, 255, 255, 1)',
|
secondary: '255, 255, 255',
|
||||||
secondary: 'rgba(0, 0, 0, 1)',
|
|
||||||
},
|
|
||||||
border: {
|
|
||||||
primary: 'rgba(51, 51, 56, 1)',
|
|
||||||
secondary: 'rgba(255, 255, 255, 1)',
|
|
||||||
tertiary: 'rgba(223, 223, 226, 1)',
|
|
||||||
},
|
|
||||||
surface: {
|
surface: {
|
||||||
primary: 'rgba(0, 0, 0, 1)',
|
primary: '255, 255, 255',
|
||||||
secondary: 'rgba(0, 0, 0, 0.34)',
|
secondary: '0, 0, 0',
|
||||||
tertiary: 'rgba(0, 0, 0, 0.2)',
|
|
||||||
disabled: 'rgba(168, 168, 168, 1)',
|
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: 'rgba(0, 0, 0, 1)',
|
primary: '0, 0, 0',
|
||||||
secondary: 'rgba(0, 0, 0, 0.34)',
|
secondary: '255, 255, 255',
|
||||||
placeholder: 'rgba(0, 0, 0, 0.34)',
|
tertiary: '0, 0, 0, 0.34',
|
||||||
disabled: 'rgba(0, 0, 0, 0.34)',
|
|
||||||
},
|
},
|
||||||
icons: {
|
border: {
|
||||||
primary: 'rgba(0, 0, 0, 1)',
|
primary: '0, 0, 0',
|
||||||
disabled: 'rgba(0, 0, 0, 0.34)',
|
secondary: '255, 255, 255',
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
primary: '0, 0, 0',
|
||||||
|
secondary: '255, 255, 255',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
globalStyles: css``,
|
globalStyles: css``,
|
||||||
|
|
|
@ -10,21 +10,36 @@ export const LSD_NAMESPACE = 'lsd'
|
||||||
export const THEME_BREAKPOINTS = ['xs', 'sm', 'md', 'lg', 'xl'] as Breakpoints[]
|
export const THEME_BREAKPOINTS = ['xs', 'sm', 'md', 'lg', 'xl'] as Breakpoints[]
|
||||||
|
|
||||||
export const THEME_TYPOGRAPHY_VARIANTS = [
|
export const THEME_TYPOGRAPHY_VARIANTS = [
|
||||||
'headlineLg',
|
'display1',
|
||||||
'headlineStd',
|
'display2',
|
||||||
'headlineMd',
|
'h1',
|
||||||
'headlineSm',
|
'h2',
|
||||||
'titleLg',
|
'h3',
|
||||||
'titleMd',
|
'h4',
|
||||||
'titleSm',
|
'h5',
|
||||||
'bodySm',
|
'h6',
|
||||||
'bodyMd',
|
'subtitle1',
|
||||||
'bodyLg',
|
'subtitle2',
|
||||||
'labelLg',
|
'body1',
|
||||||
'labelMd',
|
'body2',
|
||||||
'labelSm',
|
'body3',
|
||||||
|
'label1',
|
||||||
|
'label2',
|
||||||
] as TypographyVariants[]
|
] as TypographyVariants[]
|
||||||
|
|
||||||
|
export const THEME_TYPOGRAPHY_ELEMENTS: Partial<
|
||||||
|
Record<TypographyVariants, string[]>
|
||||||
|
> = {
|
||||||
|
h1: ['h1'],
|
||||||
|
h2: ['h2'],
|
||||||
|
h3: ['h3'],
|
||||||
|
h4: ['h4'],
|
||||||
|
h5: ['h5'],
|
||||||
|
h6: ['h6'],
|
||||||
|
body1: ['body'],
|
||||||
|
label1: ['label'],
|
||||||
|
}
|
||||||
|
|
||||||
export const THEME_TYPOGRAPHY_PROPERTIES = [
|
export const THEME_TYPOGRAPHY_PROPERTIES = [
|
||||||
'fontSize',
|
'fontSize',
|
||||||
'lineHeight',
|
'lineHeight',
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { css } from '@emotion/react'
|
import { css } from '@emotion/react'
|
||||||
import defaultsDeep from 'lodash/defaultsDeep'
|
|
||||||
import { pairs } from '../../utils/object.utils'
|
import { pairs } from '../../utils/object.utils'
|
||||||
import { baseTheme } from './baseTheme'
|
import { baseTheme } from './baseTheme'
|
||||||
import { THEME_BREAKPOINTS, THEME_TYPOGRAPHY_VARIANTS } from './constants'
|
import { THEME_BREAKPOINTS, THEME_TYPOGRAPHY_VARIANTS } from './constants'
|
||||||
|
@ -9,6 +8,7 @@ import type {
|
||||||
CreateThemeProps,
|
CreateThemeProps,
|
||||||
Theme,
|
Theme,
|
||||||
ThemeBreakpoints,
|
ThemeBreakpoints,
|
||||||
|
ThemePalette,
|
||||||
TypographyVariants,
|
TypographyVariants,
|
||||||
VariantThemeProperties,
|
VariantThemeProperties,
|
||||||
} from './types'
|
} from './types'
|
||||||
|
@ -32,6 +32,9 @@ const createBreakpointStyle = (
|
||||||
...defaultTheme[key][variant],
|
...defaultTheme[key][variant],
|
||||||
...theme[key][variant],
|
...theme[key][variant],
|
||||||
...(all?.[index - 1]?.[key]?.[variant] ?? {}),
|
...(all?.[index - 1]?.[key]?.[variant] ?? {}),
|
||||||
|
...(defaultTheme.breakpoints?.[THEME_BREAKPOINTS[index]]?.[key]?.[
|
||||||
|
variant
|
||||||
|
] ?? {}),
|
||||||
...(theme.breakpoints?.[THEME_BREAKPOINTS[index]]?.[key]?.[variant] ??
|
...(theme.breakpoints?.[THEME_BREAKPOINTS[index]]?.[key]?.[variant] ??
|
||||||
{}),
|
{}),
|
||||||
}))
|
}))
|
||||||
|
@ -68,8 +71,34 @@ const createBreakpointStyles = (
|
||||||
).map((styles, index) => [THEME_BREAKPOINTS[index], styles]),
|
).map((styles, index) => [THEME_BREAKPOINTS[index], styles]),
|
||||||
) as ThemeBreakpoints
|
) as ThemeBreakpoints
|
||||||
|
|
||||||
const createPaletteStyles = (theme: CreateThemeProps, defaultTheme: Theme) =>
|
const createPaletteStyles = (theme: CreateThemeProps, defaultTheme: Theme) => {
|
||||||
defaultsDeep(theme.palette, defaultTheme.palette)
|
const primary = theme.palette.primary ?? defaultTheme.palette.primary
|
||||||
|
const secondary = theme.palette.secondary ?? defaultTheme.palette.secondary
|
||||||
|
|
||||||
|
const palette: ThemePalette = {
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
surface: {
|
||||||
|
primary: theme.palette.surface?.primary ?? secondary,
|
||||||
|
secondary: theme.palette.surface?.secondary ?? primary,
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
primary: theme.palette.border?.primary ?? primary,
|
||||||
|
secondary: theme.palette.border?.secondary ?? secondary,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
primary: theme.palette.icon?.primary ?? primary,
|
||||||
|
secondary: theme.palette.icon?.secondary ?? secondary,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: theme.palette.text?.primary ?? primary,
|
||||||
|
secondary: theme.palette.text?.secondary ?? secondary,
|
||||||
|
tertiary: theme.palette.text?.tertiary ?? `${primary}, 0.34`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return palette
|
||||||
|
}
|
||||||
|
|
||||||
export const createTheme = (
|
export const createTheme = (
|
||||||
props: CreateThemeProps,
|
props: CreateThemeProps,
|
||||||
|
|
|
@ -15,15 +15,8 @@ const darkTheme = createTheme(
|
||||||
breakpoints: {},
|
breakpoints: {},
|
||||||
typography: {},
|
typography: {},
|
||||||
palette: {
|
palette: {
|
||||||
background: {
|
primary: '255, 255, 255',
|
||||||
primary: '#000',
|
secondary: '0, 0, 0',
|
||||||
},
|
|
||||||
surface: {
|
|
||||||
primary: '#fff',
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
primary: 'rgb(255, 255, 255)',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
lightTheme,
|
lightTheme,
|
||||||
|
|
|
@ -1,109 +1,104 @@
|
||||||
import { css } from '@emotion/react'
|
import { css } from '@emotion/react'
|
||||||
import {
|
import {
|
||||||
LSD_NAMESPACE,
|
|
||||||
THEME_BREAKPOINTS,
|
THEME_BREAKPOINTS,
|
||||||
THEME_TYPOGRAPHY_PROPERTIES,
|
THEME_TYPOGRAPHY_PROPERTIES,
|
||||||
THEME_TYPOGRAPHY_VARIANTS,
|
THEME_TYPOGRAPHY_VARIANTS,
|
||||||
} from './constants'
|
} from './constants'
|
||||||
import { Breakpoints, Theme, TypographyVariants } from './types'
|
import { Theme, TypographyProperties, TypographyVariants } from './types'
|
||||||
|
import { withTheme } from './withTheme'
|
||||||
export const gs = {
|
|
||||||
breakpoint: (
|
|
||||||
theme: Theme,
|
|
||||||
breakpoint: Breakpoints,
|
|
||||||
content: string,
|
|
||||||
) => `@media (min-width: ${theme.breakpoints[breakpoint].width}px) {
|
|
||||||
${content}
|
|
||||||
}`,
|
|
||||||
|
|
||||||
|
const cssUtils = {
|
||||||
vars: {
|
vars: {
|
||||||
name: (...parts: string[]) => `--${[LSD_NAMESPACE, ...parts].join('-')}`,
|
lsd: (...seq: string[]) => `--${['lsd', ...seq].join('-')}`,
|
||||||
wrap: (v: string, wrap = true) => (!wrap ? v : `var(${v})`),
|
|
||||||
define: (name: string, value: any) => `${name}: ${value};`,
|
|
||||||
typography: (
|
typography: (
|
||||||
variant: TypographyVariants,
|
variant: TypographyVariants | string,
|
||||||
property: string,
|
property: TypographyProperties | string,
|
||||||
breakpoint?: Breakpoints | 'default',
|
) => cssUtils.vars.lsd(variant, property),
|
||||||
) => gs.vars.name(variant, property, ...(breakpoint ? [breakpoint] : [])),
|
color: (category: string, variant: string) =>
|
||||||
palette: (category: string, variant: string) =>
|
cssUtils.vars.lsd(category, variant),
|
||||||
gs.vars.name(category, variant),
|
wrap: (name: string) => `var(${name})`,
|
||||||
},
|
},
|
||||||
|
|
||||||
all: (theme: Theme) =>
|
define: (name: string, value: string) => `${name}: ${value};`,
|
||||||
[gs.typography.all(theme), gs.palette.all(theme)].join('\n'),
|
}
|
||||||
|
|
||||||
typography: {
|
const generateThemeGlobalStyles = withTheme((theme) => {
|
||||||
all: (theme: Theme) => [gs.typography.variants(theme)].join('\n'),
|
const vars: Array<string | string[]> = []
|
||||||
|
const styles: Array<string | string[]> = []
|
||||||
|
const breakpointStyles: string[][] = THEME_BREAKPOINTS.map(() => [])
|
||||||
|
const breakpointVars: string[][] = THEME_BREAKPOINTS.map(() => [])
|
||||||
|
|
||||||
variants: (theme: Theme) =>
|
{
|
||||||
[
|
THEME_TYPOGRAPHY_VARIANTS.forEach((variant) => {
|
||||||
...THEME_TYPOGRAPHY_VARIANTS.flatMap((variant) =>
|
THEME_TYPOGRAPHY_PROPERTIES.forEach((property) => {
|
||||||
THEME_TYPOGRAPHY_PROPERTIES.map((prop) =>
|
const value = theme.typography[variant][property]?.toString() ?? 'unset'
|
||||||
gs.vars.define(
|
vars.push(
|
||||||
gs.vars.typography(variant, prop),
|
cssUtils.define(cssUtils.vars.typography(variant, property), value),
|
||||||
theme.typography[variant][prop],
|
)
|
||||||
),
|
})
|
||||||
),
|
})
|
||||||
),
|
|
||||||
gs.typography.breakpoints(theme),
|
|
||||||
].join('\n'),
|
|
||||||
|
|
||||||
breakpoints: (theme: Theme) =>
|
THEME_BREAKPOINTS.forEach((breakpoint, breakpointIndex) => {
|
||||||
THEME_BREAKPOINTS.map((breakpoint, index) =>
|
THEME_TYPOGRAPHY_VARIANTS.forEach((variant) => {
|
||||||
gs.breakpoint(
|
THEME_TYPOGRAPHY_PROPERTIES.forEach((property) => {
|
||||||
theme,
|
const value =
|
||||||
breakpoint,
|
theme.breakpoints[breakpoint].typography[variant][property]
|
||||||
gs.typography.breakpoint(theme, breakpoint, index),
|
|
||||||
),
|
|
||||||
).join('\n'),
|
|
||||||
|
|
||||||
breakpoint: (
|
|
||||||
theme: Theme,
|
|
||||||
breakpoint: Breakpoints,
|
|
||||||
breakpointIndex: number,
|
|
||||||
) =>
|
|
||||||
THEME_TYPOGRAPHY_VARIANTS.flatMap((variant) =>
|
|
||||||
THEME_TYPOGRAPHY_PROPERTIES.map((prop) => {
|
|
||||||
const value = theme.breakpoints[breakpoint].typography[variant][prop]
|
|
||||||
const current =
|
const current =
|
||||||
breakpointIndex > 0
|
breakpointIndex > 0
|
||||||
? theme.breakpoints?.[THEME_BREAKPOINTS[breakpointIndex - 1]]
|
? theme.breakpoints?.[THEME_BREAKPOINTS[breakpointIndex - 1]]
|
||||||
?.typography?.[variant]?.[prop]
|
?.typography?.[variant]?.[property]
|
||||||
: theme.typography[variant][prop]
|
: theme.typography[variant][property]
|
||||||
|
|
||||||
return value !== current
|
if (value && value !== current) {
|
||||||
? gs.vars.define(gs.vars.typography(variant, prop), value)
|
breakpointVars[breakpointIndex].push(
|
||||||
: undefined
|
cssUtils.define(
|
||||||
}),
|
cssUtils.vars.typography(variant, property),
|
||||||
)
|
value.toString(),
|
||||||
.filter((value) => !!value)
|
),
|
||||||
.join('\n'),
|
)
|
||||||
},
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
palette: {
|
{
|
||||||
all: (theme: Theme) => {
|
const { primary, secondary, ...rest } = theme.palette
|
||||||
const palette = theme.palette as Record<string, Record<string, string>>
|
const palette = rest as Record<string, Record<string, string>>
|
||||||
|
|
||||||
return [
|
vars.push(
|
||||||
...Object.keys(palette).flatMap((name) =>
|
cssUtils.define(cssUtils.vars.color('theme', 'primary'), primary),
|
||||||
Object.keys(palette[name]).map((variant) =>
|
cssUtils.define(cssUtils.vars.color('theme', 'secondary'), secondary),
|
||||||
gs.palette.color(name, variant, palette[name][variant]),
|
...Object.keys(palette).flatMap((name) =>
|
||||||
|
Object.keys(palette[name]).map((variant) =>
|
||||||
|
cssUtils.define(
|
||||||
|
cssUtils.vars.color(name, variant),
|
||||||
|
palette[name][variant],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
`:root {
|
THEME_BREAKPOINTS.map((breakpoint, index) => {
|
||||||
html, body {
|
styles.push(`@media (min-width: ${theme.breakpoints[breakpoint].width}px) {
|
||||||
background-color: ${theme.palette.background.primary};
|
:root {
|
||||||
}
|
${breakpointVars[index]}
|
||||||
}
|
}
|
||||||
`,
|
|
||||||
].join('\n')
|
|
||||||
},
|
|
||||||
|
|
||||||
color: (name: string, variant: string, value: string) =>
|
${breakpointStyles[index]}
|
||||||
gs.vars.define(gs.vars.palette(name, variant), value),
|
}`)
|
||||||
},
|
})
|
||||||
}
|
|
||||||
|
return css`
|
||||||
|
:root {
|
||||||
|
${vars}
|
||||||
|
}
|
||||||
|
|
||||||
|
${styles}
|
||||||
|
`
|
||||||
|
})
|
||||||
|
|
||||||
export const createThemeGlobalStyles = (() => {
|
export const createThemeGlobalStyles = (() => {
|
||||||
return (theme: Theme) => {
|
return (theme: Theme) => {
|
||||||
|
@ -117,15 +112,8 @@ export const createThemeGlobalStyles = (() => {
|
||||||
)
|
)
|
||||||
return cache[key]
|
return cache[key]
|
||||||
|
|
||||||
const styles = globalStyles.all(theme)
|
cache[key] = generateThemeGlobalStyles(theme)
|
||||||
cache[key] = css`
|
|
||||||
:root {
|
|
||||||
${styles}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
return cache[key]
|
return cache[key]
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
||||||
export const globalStyles = gs
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ export {
|
||||||
} from './constants'
|
} from './constants'
|
||||||
export { createTheme } from './createTheme'
|
export { createTheme } from './createTheme'
|
||||||
export { defaultThemes } from './defaultThemes'
|
export { defaultThemes } from './defaultThemes'
|
||||||
export { createThemeGlobalStyles, globalStyles } from './globalStyles'
|
export { createThemeGlobalStyles } from './globalStyles'
|
||||||
export { ThemeProvider, type ThemeProviderProps } from './ThemeProvider'
|
export { ThemeProvider, type ThemeProviderProps } from './ThemeProvider'
|
||||||
export * from './types'
|
export * from './types'
|
||||||
export { useTheme } from './useTheme'
|
export { useTheme } from './useTheme'
|
||||||
|
|
|
@ -5,19 +5,21 @@ import { DeepPartial } from 'utility-types'
|
||||||
export type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
export type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
export type TypographyTypefaces = 'sans-serif' | 'serif' | 'mono'
|
export type TypographyTypefaces = 'sans-serif' | 'serif' | 'mono'
|
||||||
export type TypographyVariants =
|
export type TypographyVariants =
|
||||||
| 'headlineLg'
|
| 'display1'
|
||||||
| 'headlineStd'
|
| 'display2'
|
||||||
| 'headlineMd'
|
| 'h1'
|
||||||
| 'headlineSm'
|
| 'h2'
|
||||||
| 'titleLg'
|
| 'h3'
|
||||||
| 'titleMd'
|
| 'h4'
|
||||||
| 'titleSm'
|
| 'h5'
|
||||||
| 'bodyLg'
|
| 'h6'
|
||||||
| 'bodyMd'
|
| 'subtitle1'
|
||||||
| 'bodySm'
|
| 'subtitle2'
|
||||||
| 'labelLg'
|
| 'body1'
|
||||||
| 'labelMd'
|
| 'body2'
|
||||||
| 'labelSm'
|
| 'body3'
|
||||||
|
| 'label1'
|
||||||
|
| 'label2'
|
||||||
|
|
||||||
export type VariantThemeProperties = keyof Pick<Theme, 'typography'>
|
export type VariantThemeProperties = keyof Pick<Theme, 'typography'>
|
||||||
|
|
||||||
|
@ -28,30 +30,25 @@ export type ThemeTypography<T extends string = TypographyVariants> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ThemePalette = {
|
export type ThemePalette = {
|
||||||
background: {
|
primary: string
|
||||||
|
secondary: string
|
||||||
|
|
||||||
|
surface: {
|
||||||
primary: string
|
primary: string
|
||||||
secondary: string
|
secondary: string
|
||||||
}
|
}
|
||||||
border: {
|
border: {
|
||||||
primary: string
|
primary: string
|
||||||
secondary: string
|
secondary: string
|
||||||
tertiary: string
|
|
||||||
}
|
|
||||||
surface: {
|
|
||||||
primary: string
|
|
||||||
secondary: string
|
|
||||||
tertiary: string
|
|
||||||
disabled: string
|
|
||||||
}
|
}
|
||||||
text: {
|
text: {
|
||||||
primary: string
|
primary: string
|
||||||
secondary: string
|
secondary: string
|
||||||
placeholder: string
|
tertiary: string
|
||||||
disabled: string
|
|
||||||
}
|
}
|
||||||
icons: {
|
icon: {
|
||||||
primary: string
|
primary: string
|
||||||
disabled: string
|
secondary: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue