More complete pass at Tailwind naming

This commit is contained in:
Eric Bailey
2024-01-01 16:37:16 -06:00
parent 4f4a3efa18
commit c58a4d0d19
4 changed files with 201 additions and 285 deletions
+46 -5
View File
@@ -29,7 +29,7 @@ const lineHeight = Object.keys(tokens.lineHeight).reduce((acc, key) => {
const fontWeight = Object.keys(tokens.fontWeight).reduce((acc, key) => {
const k = key as tokens.FontWeight
acc[`font_${k}`] = {
fontWeight: tokens.fontWeight[k],
fontWeight: tokens.fontWeight[k] as TextStyle['fontWeight'],
}
return acc
}, {} as Record<`font_${tokens.FontWeight}`, {fontWeight: TextStyle['fontWeight']}>)
@@ -73,7 +73,16 @@ const padding = Object.keys(tokens.space).reduce(
},
}
},
{} as Record<`${'pa' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr'}_${tokens.Space}`, number>
{} as Record<
`${'p' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr'}_${tokens.Space}`,
{
padding?: number
paddingLeft?: number
paddingRight?: number
paddingTop?: number
paddingBottom?: number
}
>,
)
const margin = Object.keys(tokens.space).reduce(
@@ -107,7 +116,16 @@ const margin = Object.keys(tokens.space).reduce(
},
}
},
{} as Record<`${'pa' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr'}_${tokens.Space}`, number>
{} as Record<
`${'m' | 'mx' | 'my' | 'mt' | 'mb' | 'ml' | 'mr'}_${tokens.Space}`,
{
margin?: number
marginLeft?: number
marginRight?: number
marginTop?: number
marginBottom?: number
}
>,
)
export const atoms = {
@@ -154,6 +172,9 @@ export const atoms = {
* Flex
*/
...gap,
flex: {
display: 'flex',
},
flex_row: {
flexDirection: 'row',
},
@@ -163,6 +184,12 @@ export const atoms = {
flex_1: {
flex: 1,
},
flex_grow: {
flexGrow: 1,
},
flex_shrink: {
flexShrink: 1,
},
justify_center: {
justifyContent: 'center',
},
@@ -201,6 +228,20 @@ export const atoms = {
border: {
borderWidth: 1,
},
} as const
border_t: {
borderTopWidth: 1,
},
border_b: {
borderBottomWidth: 1,
},
const s = atoms.gap_md
/*
* Width
*/
w_full: {
width: '100%',
},
h_full: {
height: '100%',
},
} as const
+68 -60
View File
@@ -7,80 +7,88 @@ export type Palette = {
primary: string
positive: string
negative: string
l0: string
l1: string
l2: string
l3: string
l4: string
l5: string
l6: string
l7: string
}
export const lightPalette: Palette = {
primary: tokens.color.blue,
positive: tokens.color.green,
negative: tokens.color.red,
l0: tokens.color.white,
l1: tokens.color.gray1,
l2: tokens.color.gray2,
l3: tokens.color.gray3,
l4: tokens.color.gray4,
l5: tokens.color.gray5,
l6: tokens.color.gray6,
l7: tokens.color.black,
primary: tokens.color.blue_500,
positive: tokens.color.green_500,
negative: tokens.color.red_500,
} as const
export const darkPalette: Palette = {
primary: tokens.color.blue,
positive: tokens.color.green,
negative: tokens.color.red,
l0: tokens.color.black,
l1: tokens.color.gray6,
l2: tokens.color.gray5,
l3: tokens.color.gray4,
l4: tokens.color.gray3,
l5: tokens.color.gray2,
l6: tokens.color.gray1,
l7: tokens.color.white,
primary: tokens.color.blue_500,
positive: tokens.color.green_400,
negative: tokens.color.red_400,
} as const
export const light = {
palette: lightPalette,
atoms: {
...Object.keys(lightPalette).reduce((acc, key) => {
const k = key as keyof Palette
acc[`text_${k}`] = {
color: lightPalette[k],
}
return acc
}, {} as Record<`text_${keyof Palette}`, {color: string}>),
...Object.keys(lightPalette).reduce((acc, key) => {
const k = key as keyof Palette
acc[`bg_${k}`] = {
backgroundColor: lightPalette[k],
}
return acc
}, {} as Record<`bg_${keyof Palette}`, {backgroundColor: string}>),
text: {
color: tokens.color.gray_950,
},
text_contrast_700: {
color: tokens.color.gray_600,
},
text_contrast_500: {
color: tokens.color.gray_400,
},
text_inverted: {
color: tokens.color.white,
},
bg: {
backgroundColor: tokens.color.white,
},
bg_contrast_100: {
backgroundColor: tokens.color.gray_50,
},
bg_contrast_200: {
backgroundColor: tokens.color.gray_100,
},
bg_contrast_300: {
backgroundColor: tokens.color.gray_200,
},
border: {
borderColor: tokens.color.gray_100,
},
border_contrast_500: {
borderColor: tokens.color.gray_400,
},
},
} as const
}
export const dark: Theme = {
palette: darkPalette,
atoms: {
...Object.keys(darkPalette).reduce((acc, key) => {
const k = key as keyof Palette
acc[`text_${k}`] = {
color: darkPalette[k],
}
return acc
}, {} as Record<`text_${keyof Palette}`, {color: string}>),
...Object.keys(darkPalette).reduce((acc, key) => {
const k = key as keyof Palette
acc[`bg_${k}`] = {
backgroundColor: darkPalette[k],
}
return acc
}, {} as Record<`bg_${keyof Palette}`, {backgroundColor: string}>),
text: {
color: tokens.color.white,
},
text_contrast_700: {
color: tokens.color.gray_300,
},
text_contrast_500: {
color: tokens.color.gray_500,
},
text_inverted: {
color: tokens.color.gray_950,
},
bg: {
backgroundColor: tokens.color.gray_950,
},
bg_contrast_100: {
backgroundColor: tokens.color.gray_900,
},
bg_contrast_200: {
backgroundColor: tokens.color.gray_800,
},
bg_contrast_300: {
backgroundColor: tokens.color.gray_700,
},
border: {
borderColor: tokens.color.gray_800,
},
border_contrast_500: {
borderColor: tokens.color.gray_500,
},
},
} as const
}
+56 -23
View File
@@ -1,25 +1,57 @@
const BLUE_HUE = 210
const GRAYSCALE_SATURATION = 12
const BLUE_HUE = 211
const GRAYSCALE_SATURATION = 22
export const color = {
white: '#FFFFFF',
/**
* Mathematical scale of grays, from lightest to darkest, all based on the
* primary blue color
*/
gray1: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 95%)`,
gray2: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 85%)`,
gray3: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 75%)`,
gray4: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 30%)`,
gray5: `hsl(${BLUE_HUE} ${GRAYSCALE_SATURATION}%, 20%)`,
gray6: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 10%)`,
black: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 5%)`,
gray_50: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 95%)`,
gray_100: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 90%)`,
gray_200: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 80%)`,
gray_300: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 70%)`,
gray_400: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 60%)`,
gray_500: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 50%)`,
gray_600: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 40%)`,
gray_700: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 30%)`,
gray_800: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 20%)`,
gray_900: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 10%)`,
gray_950: `hsl(${BLUE_HUE}, ${GRAYSCALE_SATURATION}%, 5%)`,
blue: `hsl(${BLUE_HUE}, 100%, 53%)`,
green: '#54D469',
red: '#FB4566',
} as const
blue_50: `hsl(${BLUE_HUE}, 99%, 98%)`,
blue_100: `hsl(${BLUE_HUE}, 99%, 93%)`,
blue_200: `hsl(${BLUE_HUE}, 99%, 83%)`,
blue_300: `hsl(${BLUE_HUE}, 99%, 73%)`,
blue_400: `hsl(${BLUE_HUE}, 99%, 63%)`,
blue_500: `hsl(${BLUE_HUE}, 99%, 53%)`,
blue_600: `hsl(${BLUE_HUE}, 99%, 43%)`,
blue_700: `hsl(${BLUE_HUE}, 99%, 33%)`,
blue_800: `hsl(${BLUE_HUE}, 99%, 23%)`,
blue_900: `hsl(${BLUE_HUE}, 99%, 13%)`,
blue_950: `hsl(${BLUE_HUE}, 99%, 8%)`,
green_50: `hsl(130, 60%, 95%)`,
green_100: `hsl(130, 60%, 90%)`,
green_200: `hsl(130, 60%, 80%)`,
green_300: `hsl(130, 60%, 70%)`,
green_400: `hsl(130, 60%, 60%)`,
green_500: `hsl(130, 60%, 50%)`,
green_600: `hsl(130, 60%, 40%)`,
green_700: `hsl(130, 60%, 30%)`,
green_800: `hsl(130, 60%, 20%)`,
green_900: `hsl(130, 60%, 10%)`,
green_950: `hsl(130, 60%, 5%)`,
red_50: `hsl(349, 96%, 95%)`,
red_100: `hsl(349, 96%, 90%)`,
red_200: `hsl(349, 96%, 80%)`,
red_300: `hsl(349, 96%, 70%)`,
red_400: `hsl(349, 96%, 60%)`,
red_500: `hsl(349, 96%, 50%)`,
red_600: `hsl(349, 96%, 40%)`,
red_700: `hsl(349, 96%, 30%)`,
red_800: `hsl(349, 96%, 20%)`,
red_900: `hsl(349, 96%, 10%)`,
red_950: `hsl(349, 96%, 5%)`,
}
export const space = {
xxs: 2,
@@ -29,7 +61,7 @@ export const space = {
lg: 18,
xl: 24,
xxl: 32,
} as const
}
export const fontSize = {
xxs: 10,
@@ -39,26 +71,27 @@ export const fontSize = {
lg: 18,
xl: 22,
xxl: 26,
} as const
}
// TODO test
export const lineHeight = {
none: 1,
normal: 1.5,
relaxed: 1.625,
} as const
}
export const borderRadius = {
sm: 8,
md: 12,
xl: 36,
full: 999,
} as const
}
export const fontWeight = {
normal: '400',
semi: '600',
semibold: '600',
bold: '900',
} as const
}
export type Color = keyof typeof color
export type Space = keyof typeof space
+31 -197
View File
@@ -4,7 +4,7 @@ import {CenteredView, ScrollView} from '#/view/com/util/Views'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useSetColorMode} from '#/state/shell'
import {atoms, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf'
import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf'
import {Button, ButtonText} from '#/view/com/Button'
import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography'
@@ -12,7 +12,7 @@ function ThemeSelector() {
const setColorMode = useSetColorMode()
return (
<View style={[atoms.flex.row, atoms.flex.gap.m]}>
<View style={[a.flex_row, a.gap_md]}>
<Button
type="secondary"
size="small"
@@ -41,18 +41,14 @@ function BreakpointDebugger() {
return (
<View>
<H3 style={[atoms.padding.pb.m]}>Breakpoint Debugger</H3>
<Text style={[atoms.padding.pb.m]}>
<H3 style={[a.pb_md]}>Breakpoint Debugger</H3>
<Text style={[a.pb_md]}>
Current breakpoint: {!breakpoints.gtMobile && <Text>mobile</Text>}
{breakpoints.gtMobile && !breakpoints.gtTablet && <Text>tablet</Text>}
{breakpoints.gtTablet && <Text>desktop</Text>}
</Text>
<Text
style={[
atoms.padding.pa.m,
t.atoms.backgroundColor.l1,
{fontFamily: 'monospace'},
]}>
style={[a.p_md, t.atoms.bg_contrast_100, {fontFamily: 'monospace'}]}>
{JSON.stringify(breakpoints, null, 2)}
</Text>
</View>
@@ -63,35 +59,13 @@ function ThemedSection() {
const t = useTheme()
return (
<View style={[t.atoms.backgroundColor.l0, atoms.padding.pa.m]}>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>
<View style={[t.atoms.bg, a.p_md]}>
<H3 style={[a.pb_md, a.font_bold]}>
Colors (this theme is always light)
</H3>
<View style={[atoms.flex.row, atoms.flex.gap.m]}>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l0, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l1, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l2, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l3, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l4, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l5, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l6, {height: 60}]}
/>
<View
style={[atoms.flex.one, t.atoms.backgroundColor.l7, {height: 60}]}
/>
<View style={[a.flex_row, a.gap_md]}>
<View style={[a.flex_1, t.atoms.bg, {height: 60}]} />
<View style={[a.flex_1, t.atoms.bg_contrast_100, {height: 60}]} />
</View>
</View>
)
@@ -102,165 +76,34 @@ export function DebugScreen() {
return (
<ScrollView>
<CenteredView style={[t.atoms.backgroundColor.l0]}>
<View
style={[
atoms.padding.pa.xl,
atoms.flex.gap.xxl,
{paddingBottom: 200},
]}>
<CenteredView style={[t.atoms.bg]}>
<View style={[a.p_xl, a.gap_xxl, {paddingBottom: 200}]}>
<ThemeSelector />
<BreakpointDebugger />
<View>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>Colors</H3>
<View style={[atoms.flex.row, atoms.flex.gap.m]}>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l0,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l1,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l2,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l3,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l4,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l5,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l6,
{height: 60},
]}
/>
<View
style={[
atoms.flex.one,
t.atoms.backgroundColor.l7,
{height: 60},
]}
/>
<H3 style={[a.pb_md, a.font_bold]}>Colors</H3>
<View style={[a.flex_row, a.gap_md]}>
<View style={[a.flex_1, t.atoms.bg, {height: 60}]} />
</View>
</View>
<View>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>Spacing</H3>
<H3 style={[a.pb_md, a.font_bold]}>Spacing</H3>
<View style={[atoms.flex.gap.m]}>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<View style={[a.gap_md]}>
<View style={[a.flex_row, a.text_center]}>
<Text style={{width: 80}}>xxs (2px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.xxs,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>xs (4px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.xs,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>s (8px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.s,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>m (12px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.m,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>l (18px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.l,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>xl (24px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.xl,
t.atoms.backgroundColor.l3,
]}
/>
</View>
<View style={[atoms.flex.row, atoms.flex.alignCenter]}>
<Text style={{width: 80}}>xxl (32px)</Text>
<View
style={[
atoms.flex.one,
atoms.padding.pt.xxl,
t.atoms.backgroundColor.l3,
]}
/>
<View style={[a.flex_1, a.pt_xxs, t.atoms.bg_contrast_300]} />
</View>
</View>
</View>
<View>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>Typography</H3>
<H3 style={[a.p_md, a.font_bold]}>Typography</H3>
<View
style={[
atoms.flex.gap.m,
atoms.padding.pa.m,
t.atoms.backgroundColor.l1,
]}>
<View style={[a.gap_md, a.p_md, t.atoms.bg_contrast_100]}>
<H1>Heading 1</H1>
<H2>Heading 2</H2>
<H3>Heading 3</H3>
@@ -268,35 +111,26 @@ export function DebugScreen() {
<H5>Heading 5</H5>
<H6>Heading 6</H6>
<Text style={[atoms.font.xxl]}>H1 Size Text</Text>
<Text style={[atoms.font.xl]}>H2 Size Text</Text>
<Text style={[atoms.font.l]}>H3 Size Text</Text>
<Text style={[atoms.font.m]}>H4 Size Text</Text>
<Text style={[atoms.font.s]}>H5 Size Text</Text>
<Text style={[atoms.font.xs]}>H6 Size Text</Text>
<Text style={[atoms.font.xxs]}>Very Small Size Text</Text>
<Text style={[a.text_xxl]}>H1 Size Text</Text>
<Text style={[a.text_xl]}>H2 Size Text</Text>
<Text style={[a.text_lg]}>H3 Size Text</Text>
<Text style={[a.text_md]}>H4 Size Text</Text>
<Text style={[a.text_sm]}>H5 Size Text</Text>
<Text style={[a.text_xs]}>H6 Size Text</Text>
<Text style={[a.text_xxs]}>Very Small Size Text</Text>
</View>
</View>
<View>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>Breakpoints</H3>
</View>
<Alf theme="light">
<ThemedSection />
</Alf>
<View style={[atoms.flex.gap.m, atoms.flex.alignStart]}>
<H3 style={[atoms.padding.pb.m, atoms.font.bold]}>Buttons</H3>
<View style={[a.gap_md, a.align_start]}>
<H3 style={[a.pb_md, a.font_bold]}>Buttons</H3>
<Button>
{({state}) => (
<View
style={[
atoms.padding.pa.m,
atoms.radius.round,
t.atoms.backgroundColor.l2,
]}>
<View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}>
<Text>Unstyled button, state: {JSON.stringify(state)}</Text>
</View>
)}