Skip to content

Commit ea0decd

Browse files
authored
add tailwind styling setup (#2047)
1 parent d74fca8 commit ea0decd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1488
-3387
lines changed

bun.lock

Lines changed: 57 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/styleguide.tsx

Lines changed: 29 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import * as HtmlElements from '@expo/html-elements';
22
import { type TextProps } from '@expo/html-elements/build/primitives/Text';
33
import Link from 'next/link';
4-
import {
5-
type ComponentType,
6-
type CSSProperties,
7-
type PropsWithChildren,
8-
useContext,
9-
useState,
10-
} from 'react';
4+
import { type ComponentType, type CSSProperties, type PropsWithChildren, useState } from 'react';
115
import {
126
StyleSheet,
137
type TextStyle,
@@ -17,93 +11,40 @@ import {
1711
type ViewStyle,
1812
} from 'react-native';
1913

20-
import CustomAppearanceContext from '../context/CustomAppearanceContext';
21-
22-
export const layout = {
23-
maxWidth: 1200,
24-
};
14+
import tw from '~/util/tailwind';
2515

2616
export function useLayout() {
2717
const { width } = useWindowDimensions();
2818
return {
2919
isSmallScreen: width < 800,
30-
isBelowMaxWidth: width < layout.maxWidth,
20+
isBelowMaxWidth: width < 1200,
3121
};
3222
}
3323

34-
export const colors = {
35-
primary: '#61DAFB',
36-
primaryLight: '#c1f4ff',
37-
primaryDark: '#39BEE2',
38-
primaryHover: '#61dafb16',
39-
sky: '#C6EEFB',
40-
powder: '#EEFAFE',
41-
pewter: '#BEC8CB',
42-
gray1: '#f9f9f9',
43-
gray2: '#ececec',
44-
gray3: '#CFCFD5',
45-
gray4: '#828898',
46-
gray5: '#505461',
47-
gray6: '#24262e',
48-
gray7: '#21232A',
49-
black: '#242424',
50-
white: '#ffffff',
51-
secondary: '#afb1af',
52-
warning: '#FBE679',
53-
warningLight: '#FEF7D6',
54-
warningDark: '#995e00',
55-
error: '#ff5555',
56-
success: '#4caf50',
57-
};
58-
59-
export const darkColors = {
60-
black: '#000',
61-
background: '#19191f',
62-
subHeader: '#14141a',
63-
border: '#2a2e36',
64-
veryDark: '#111114',
65-
dark: '#14141a',
66-
darkBright: '#1c1c21',
67-
powder: '#262a36',
68-
pewter: '#767C8E',
69-
secondary: '#a2a7ab',
70-
warningLight: '#2f2704',
71-
warning: '#9a810c',
72-
primaryDark: '#2e9ab8',
73-
};
74-
75-
const baseTextStyles = {
76-
color: colors.black,
77-
marginVertical: 0,
78-
fontWeight: '400' as const,
79-
fontFamily: 'inherit',
80-
};
81-
8224
const textStyles = StyleSheet.create({
83-
h1: { ...baseTextStyles, fontSize: 57.25, fontWeight: '600' as const },
84-
h2: { ...baseTextStyles, fontSize: 35.5, fontWeight: '600' as const },
85-
h3: { ...baseTextStyles, fontSize: 26.5, fontWeight: '600' as const },
86-
h4: { ...baseTextStyles, fontSize: 22 },
87-
h5: { ...baseTextStyles, fontSize: 20 },
88-
h6: { ...baseTextStyles, fontSize: 18 },
89-
headline: { ...baseTextStyles, fontSize: 16, fontWeight: '500' as const },
90-
p: { ...baseTextStyles, fontSize: 16 },
91-
caption: { ...baseTextStyles, fontSize: 15, lineHeight: 22 },
92-
label: { ...baseTextStyles, fontSize: 12, fontWeight: '500' as const },
25+
h1: tw`text-[57.25px] font-semibold`,
26+
h2: tw`text-[35.5px] font-semibold`,
27+
h3: tw`text-[26.5px] font-semibold`,
28+
h4: tw`text-[22px]`,
29+
h5: tw`text-[20px]`,
30+
h6: tw`text-[18px]`,
31+
headline: tw`text-[16px] font-medium`,
32+
p: tw`text-[16px]`,
33+
caption: tw`text-[15px] leading-[22px]`,
34+
label: tw`text-[12px] font-medium`,
9335
});
9436

95-
type TextStyles = TextStyle | TextStyle[];
96-
9737
type CustomTextProps = TextProps &
9838
PropsWithChildren<{
9939
id?: string;
10040
numberOfLines?: number;
10141
}>;
10242

103-
function createTextComponent(Element: ComponentType<TextProps>, textStyle?: TextStyles) {
43+
export function createTextComponent(
44+
Element: ComponentType<TextProps>,
45+
textStyle?: StyleProp<TextStyle>
46+
) {
10447
function TextComponent({ children, style, id, numberOfLines }: CustomTextProps) {
105-
const { isDark } = useContext(CustomAppearanceContext);
106-
10748
const elementStyle = Element?.displayName
10849
? StyleSheet.flatten(textStyles[Element.displayName as keyof typeof textStyles])
10950
: undefined;
@@ -112,7 +53,12 @@ function createTextComponent(Element: ComponentType<TextProps>, textStyle?: Text
11253
<Element
11354
id={id}
11455
numberOfLines={numberOfLines}
115-
style={[elementStyle, textStyle, { color: isDark ? colors.white : colors.black }, style]}>
56+
style={[
57+
tw`font-sans font-normal my-0 text-black dark:text-white`,
58+
elementStyle as StyleProp<TextStyle>,
59+
textStyle,
60+
style,
61+
]}>
11662
{children}
11763
</Element>
11864
);
@@ -139,15 +85,14 @@ type AProps = PropsWithChildren<{
13985
target?: string;
14086
href: string;
14187
hoverStyle?: StyleProp<TextStyle>;
142-
containerStyle?: CSSProperties | undefined;
88+
containerStyle?: CSSProperties;
14389
}>;
14490

14591
export function A({ href, target, children, style, hoverStyle, containerStyle, ...rest }: AProps) {
146-
const { isDark } = useContext(CustomAppearanceContext);
14792
const [isHovered, setIsHovered] = useState(false);
14893

149-
const linkStyles = getLinkStyles(isDark);
150-
const linkHoverStyles = getLinkHoverStyles();
94+
const linkStyles = tw`font-sans text-black underline decoration-pewter dark:text-white dark:decoration-palette-gray5`;
95+
const linkHoverStyles = tw`decoration-primary-dark`;
15196

15297
if ((target === '_self' && !href.startsWith('#')) || href.startsWith('/')) {
15398
const passedStyle = StyleSheet.flatten(style);
@@ -171,7 +116,7 @@ export function A({ href, target, children, style, hoverStyle, containerStyle, .
171116
<span
172117
onPointerEnter={() => setIsHovered(true)}
173118
onPointerLeave={() => setIsHovered(false)}
174-
style={{ display: 'contents', ...containerStyle }}>
119+
style={{ ...tw`contents`, ...containerStyle }}>
175120
<HtmlElements.A
176121
{...rest}
177122
href={href}
@@ -185,21 +130,6 @@ export function A({ href, target, children, style, hoverStyle, containerStyle, .
185130
);
186131
}
187132

188-
function getLinkStyles(isDark: boolean): TextStyle {
189-
return {
190-
color: isDark ? colors.white : colors.black,
191-
textDecorationColor: isDark ? colors.gray5 : colors.pewter,
192-
textDecorationLine: 'underline',
193-
fontFamily: 'inherit',
194-
};
195-
}
196-
197-
function getLinkHoverStyles(): TextStyle {
198-
return {
199-
textDecorationColor: colors.primaryDark,
200-
};
201-
}
202-
203133
type HoverEffectProps = PropsWithChildren<{ style?: StyleProp<ViewStyle> }>;
204134

205135
export function HoverEffect({ children, style }: HoverEffectProps) {
@@ -209,10 +139,9 @@ export function HoverEffect({ children, style }: HoverEffectProps) {
209139
return (
210140
<View
211141
style={[
212-
// @ts-expect-error Transition is a valid web style property
213142
{ transition: 'opacity 0.33s' },
214-
isHovered && { opacity: 0.75 },
215-
isActive && { opacity: 0.5 },
143+
isHovered && tw`opacity-75`,
144+
isActive && tw`opacity-50`,
216145
style,
217146
]}
218147
onPointerEnter={() => setIsHovered(true)}

components/Button.tsx

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { A } from '@expo/html-elements';
22
import { type PropsWithChildren } from 'react';
3-
import {
4-
StyleSheet,
5-
type TextStyle,
6-
Pressable,
7-
type StyleProp,
8-
type ViewStyle,
9-
} from 'react-native';
3+
import { type TextStyle, Pressable, type StyleProp, type ViewStyle } from 'react-native';
104

11-
import { darkColors, HoverEffect, P } from '~/common/styleguide';
5+
import { HoverEffect, P } from '~/common/styleguide';
6+
import tw from '~/util/tailwind';
127

138
type Props = PropsWithChildren & {
149
href?: string;
@@ -29,10 +24,7 @@ export function Button({
2924
}: Props) {
3025
const isLink = !!href;
3126
const buttonStyle = [
32-
styles.container,
33-
{
34-
backgroundColor: darkColors.primaryDark,
35-
},
27+
tw`justify-center items-center rounded outline-offset-1 select-none bg-primary-darker dark:bg-primary-dark`,
3628
style,
3729
];
3830

@@ -43,7 +35,7 @@ export function Button({
4335
{isLink ? (
4436
<A
4537
href={href}
46-
style={{ borderRadius: 4, fontFamily: 'inherit', fontSize: 'inherit' }}
38+
style={tw`rounded font-sans`}
4739
{...(openInNewTab ? { target: '_blank' } : {})}
4840
{...rest}>
4941
<Pressable focusable={false} style={buttonStyle} accessible={false}>
@@ -58,12 +50,3 @@ export function Button({
5850
</HoverEffect>
5951
);
6052
}
61-
62-
const styles = StyleSheet.create({
63-
container: {
64-
justifyContent: 'center',
65-
alignItems: 'center',
66-
borderRadius: 4,
67-
outlineOffset: 1,
68-
},
69-
});

components/CheckBox.tsx

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,26 @@
1-
import { useContext } from 'react';
2-
import { type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native';
1+
import { type StyleProp, View, type ViewStyle } from 'react-native';
32

4-
import { colors, darkColors } from '~/common/styleguide';
5-
import CustomAppearanceContext from '~/context/CustomAppearanceContext';
3+
import tw from '~/util/tailwind';
64

75
import { Check } from './Icons';
86

97
type Props = {
108
style?: StyleProp<ViewStyle>;
119
value?: boolean;
12-
color?: string;
1310
};
1411

15-
export default function CheckBox({ style, value, color }: Props) {
16-
const { isDark } = useContext(CustomAppearanceContext);
17-
12+
export default function CheckBox({ style, value }: Props) {
1813
return (
1914
<View
2015
style={[
21-
styles.container,
22-
{
23-
borderColor: value ? color : isDark ? darkColors.border : colors.gray4,
24-
backgroundColor: value ? color : isDark ? darkColors.dark : colors.white,
25-
},
16+
tw`size-[18px] items-center justify-center border-2 rounded-sm mr-2`,
17+
value
18+
? tw`border-primary-dark bg-primary-dark`
19+
: tw`border-palette-gray4 bg-white dark:border-default dark:bg-dark`,
20+
{ transition: 'border-color .33s, background-color .33s' },
2621
style,
2722
]}>
28-
{value ? (
29-
<Check width={14} height={10} fill={isDark ? darkColors.veryDark : colors.white} />
30-
) : null}
23+
{value ? <Check width={14} height={10} style={tw`text-white dark:text-black`} /> : null}
3124
</View>
3225
);
3326
}
34-
35-
const styles = StyleSheet.create({
36-
container: {
37-
height: 18,
38-
width: 18,
39-
justifyContent: 'center',
40-
alignItems: 'center',
41-
borderWidth: 2,
42-
borderStyle: 'solid',
43-
borderRadius: 2,
44-
marginRight: 8,
45-
},
46-
});

0 commit comments

Comments
 (0)