Skip to content

Commit 704e182

Browse files
authored
chore: Merge PR #49 from feat/light-mode-toggle
2 parents e38d0e0 + df14363 commit 704e182

File tree

13 files changed

+128
-72
lines changed

13 files changed

+128
-72
lines changed

apps/expo/app.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"githubUrl": "https://github.com/codinsonn/codinsonn.dev",
1313
"scheme": "codinsonn",
1414
"backgroundColor": "#111827",
15+
"userInterfaceStyle": "dark",
1516
"splash": {
1617
"image": "../next/public/splash.png",
1718
"resizeMode": "contain",

apps/expo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"expo-linking": "5.0.2",
3535
"expo-router": "^2.0.0",
3636
"expo-status-bar": "~1.6.0",
37+
"expo-system-ui": "~2.4.0",
3738
"expo-updates": "~0.18.10",
3839
"expo-web-browser": "12.3.2",
3940
"react": "18.2.0",

features/app-core/twrnc.theme.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ const textColorUtilities = {
5252
'text-warning': 'text-yellow-500 dark:text-yellow-400',
5353
'text-danger': 'text-red-500 dark:text-red-400',
5454
'text-info': 'text-blue-500 dark:text-blue-400',
55+
'text-grayscale-900': 'text-neutral-100 dark:text-neutral-900',
56+
'text-grayscale-800': 'text-neutral-200 dark:text-neutral-800',
57+
'text-grayscale-700': 'text-neutral-300 dark:text-neutral-700',
58+
'text-grayscale-600': 'text-neutral-400 dark:text-neutral-600',
59+
'text-grayscale-500': 'text-neutral-500 dark:text-neutral-500',
60+
'text-grayscale-400': 'text-neutral-600 dark:text-neutral-400',
61+
'text-grayscale-300': 'text-neutral-700 dark:text-neutral-300',
62+
'text-grayscale-200': 'text-neutral-800 dark:text-neutral-200',
63+
'text-grayscale-100': 'text-neutral-900 dark:text-neutral-100',
5564
'text-on-primary-bg': 'text-white dark:text-gray-900',
5665
'text-on-secondary-bg': 'text-gray-700 dark:text-gray-300',
5766
'text-on-tertiary-bg': 'text-gray-600 dark:text-gray-400',
@@ -85,7 +94,7 @@ const buttonColorUtilities = {
8594
}
8695

8796
const borderColorUtilities = {
88-
'border-primary': 'border-white dark:border-white',
97+
'border-primary': 'border-white dark:border-gray-900',
8998
'border-secondary': 'border-gray-300 dark:border-gray-700',
9099
'border-tertiary': 'border-gray-400 dark:border-gray-600',
91100
}

features/cv-page/components/ResumeContactSection.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { H2 } from 'aetherspace/html-elements'
1010
// Components
1111
import { AetherIcon } from 'aetherspace/components'
1212
// Styles
13-
import { twStyled } from 'aetherspace/styles'
13+
import { twStyled, useTailwindStyles } from 'aetherspace/styles'
1414
// Utils
1515
import { isEmpty, uppercaseFirstChar } from 'aetherspace/utils'
1616
// Mocks
@@ -30,6 +30,10 @@ export const ResumeContactSection = (props: AetherProps<typeof ResumeContactSect
3030
// Props
3131
const { contactLinks } = props
3232

33+
// Styles
34+
const textSecondaryStyle = useTailwindStyles('text-secondary')
35+
const iconFill = (textSecondaryStyle?.color as string) || '#FFFFFF'
36+
3337
// -- Loading --
3438

3539
if (isEmpty(contactLinks)) return null
@@ -38,19 +42,21 @@ export const ResumeContactSection = (props: AetherProps<typeof ResumeContactSect
3842

3943
return (
4044
<StContactLinksContainer>
41-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Contact</H2>
45+
<H2 className="mb-1 body-sm-regular leading-6 text-grayscale-900">Contact</H2>
4246
{contactLinks?.map(({ id, socialLinkType, linkUrl, platformUsername, linkTitle }) => (
4347
<View key={id} tw="flex flex-row mt-5">
4448
<View tw="min-w-[100px] md:min-w-[110px] pt-[1px]">
45-
<Text tw="text-neutral-400 body-sm-regular">{uppercaseFirstChar(socialLinkType!)}</Text>
49+
<Text tw="text-grayscale-600 body-sm-regular">
50+
{uppercaseFirstChar(socialLinkType!)}
51+
</Text>
4652
</View>
4753
{linkUrl ? (
4854
<Link href={linkUrl} tw="flex flex-row">
4955
<Text tw="text-secondary body-sm-regular">
5056
<Text tw="text-secondary body-sm-regular">{platformUsername || linkTitle}</Text>
5157
{` `}
5258
<Text>
53-
<AetherIcon name="link-thin" size={14} fill="#FFFFFF" />
59+
<AetherIcon name="link-thin" size={14} fill={iconFill} />
5460
</Text>
5561
</Text>
5662
</Link>

features/cv-page/components/ResumeEntry.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { P } from 'aetherspace/html-elements'
99
// Components
1010
import { AetherIcon } from 'aetherspace/components'
1111
// Styles
12-
import { twStyled } from 'aetherspace/styles'
12+
import { twStyled, useTailwindStyles } from 'aetherspace/styles'
1313

1414
/* --- Schemas --------------------------------------------------------------------------------- */
1515

@@ -27,11 +27,15 @@ export const ResumeEntry = (props: AetherProps<typeof ResumeEntryProps>) => {
2727
// Props
2828
const { sideLabel, title, subTitle, linkUrl, description } = props
2929

30+
// Styles
31+
const textSecondaryStyle = useTailwindStyles('text-secondary')
32+
const iconFill = (textSecondaryStyle?.color as string) || '#FFFFFF'
33+
3034
// Render
3135
return (
3236
<StResumeEntry>
3337
<StResumeEntrySideLabel>
34-
<Text tw="text-neutral-400 font-primary-regular">{sideLabel}</Text>
38+
<Text tw="text-grayscale-600 font-primary-regular">{sideLabel}</Text>
3539
</StResumeEntrySideLabel>
3640
<StResumeEntryData>
3741
{/* Title */}
@@ -41,7 +45,7 @@ export const ResumeEntry = (props: AetherProps<typeof ResumeEntryProps>) => {
4145
<Text tw="text-secondary body-sm-regular leading-6 my-0">{title}</Text>
4246
{` `}
4347
<Text>
44-
<AetherIcon name="link-thin" size={14} fill="#FFFFFF" />
48+
<AetherIcon name="link-thin" size={14} fill={iconFill} />
4549
</Text>
4650
</Text>
4751
</Link>

features/cv-page/components/ResumeIntroCard.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const ResumeIntroCard = (props: AetherProps<typeof ResumeCardData>) => {
3333
<Image
3434
src={profileImgUrl}
3535
alt="Picture of the applicant"
36-
tw="w-22 h-22 mt-0 overflow-hidden bg-slate-100 rounded-full"
36+
tw="w-22 h-22 mt-0 overflow-hidden bg-slate-100 dark:bg-slate-900 rounded-full"
3737
/>
3838
</Link>
3939
</View>
@@ -42,7 +42,7 @@ export const ResumeIntroCard = (props: AetherProps<typeof ResumeCardData>) => {
4242
<H1 className="text-xl font-primary-regular text-primary my-0">{displayName}</H1>
4343
</View>
4444
<View className="flex flex-row">
45-
<P className="text-neutral-200 font-primary-regular my-0">
45+
<P className="text-secondary font-primary-regular my-0">
4646
{[`${functionTitle} in ${location}`, pronouns].filter(Boolean).join(', ')}
4747
</P>
4848
</View>
@@ -64,8 +64,8 @@ export const ResumeIntroCard = (props: AetherProps<typeof ResumeCardData>) => {
6464
<>
6565
<Spacing tw="h-8" />
6666
<StAboutSection>
67-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">About</H2>
68-
<P className="p-0 m-0 body-sm-regular leading-6 text-neutral-300">{about}</P>
67+
<H2 className="mb-1 body-sm-regular leading-6 text-grayscale-900">About</H2>
68+
<P className="p-0 m-0 body-sm-regular leading-6 text-grayscale-700">{about}</P>
6969
</StAboutSection>
7070
</>
7171
)}

features/cv-page/screens/ResumeScreen.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
344344
<>
345345
<Spacing tw="h-12" />
346346
<StResumeSection>
347-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Projects</H2>
347+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Projects</H2>
348348
{projects.map(({ title, year, linkUrl, client, description }) => (
349349
<ResumeEntry
350350
key={title}
@@ -362,7 +362,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
362362
<>
363363
<Spacing tw="h-12" />
364364
<StResumeSection>
365-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Side Projects</H2>
365+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Side Projects</H2>
366366
{sideProjects.map(({ title, year, linkUrl, client, description }) => (
367367
<ResumeEntry
368368
key={title}
@@ -380,7 +380,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
380380
<>
381381
<Spacing tw="h-12" />
382382
<StResumeSection>
383-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Writing</H2>
383+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Writing</H2>
384384
{writing.map(({ title, year, linkUrl, publisher, description }) => (
385385
<ResumeEntry
386386
key={title}
@@ -398,7 +398,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
398398
<>
399399
<Spacing tw="h-12" />
400400
<StResumeSection>
401-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Speaking</H2>
401+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Speaking</H2>
402402
{speaking.map(({ title, year, linkUrl, event, location, description }) => (
403403
<ResumeEntry
404404
key={title}
@@ -417,7 +417,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
417417
<>
418418
<Spacing tw="h-12" />
419419
<StResumeSection>
420-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Awards</H2>
420+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Awards</H2>
421421
{awards.map(({ title, year, linkUrl, presentedBy, description }) => (
422422
<ResumeEntry
423423
key={title}
@@ -435,7 +435,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
435435
<>
436436
<Spacing tw="h-12" />
437437
<StResumeSection>
438-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Work Experience</H2>
438+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Work Experience</H2>
439439
{workExperience.map(
440440
({ title, from, to, linkUrl, company, location, description }) => (
441441
<ResumeEntry
@@ -456,7 +456,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
456456
<>
457457
<Spacing tw="h-12" />
458458
<StResumeSection>
459-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Volunteering</H2>
459+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Volunteering</H2>
460460
{volunteering.map(({ title, from, to, linkUrl, company, location, description }) => (
461461
<ResumeEntry
462462
key={title}
@@ -475,7 +475,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
475475
<>
476476
<Spacing tw="h-12" />
477477
<StResumeSection>
478-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">Education</H2>
478+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">Education</H2>
479479
{education.map(({ title, from, to, linkUrl, institute, location, description }) => (
480480
<ResumeEntry
481481
key={title}
@@ -494,9 +494,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
494494
<>
495495
<Spacing tw="h-12" />
496496
<StResumeSection>
497-
<H2 className="mb-1 body-sm-regular leading-6 text-neutral-100">
498-
{ctaSection.title}
499-
</H2>
497+
<H2 className="mb-1 body-sm-regular leading-6 text-secondary">{ctaSection.title}</H2>
500498
{ctaSection.ctaLinks.map(({ socialLinkType, linkTitle, linkUrl }) => (
501499
<ResumeEntry
502500
key={linkTitle}
@@ -515,7 +513,7 @@ export const ResumeScreen = (props: TResumeScreenProps) => {
515513

516514
/* --- Styles ---------------------------------------------------------------------------------- */
517515

518-
const StScreenContainer = twStyled.View`w-full items-center px-4`
516+
const StScreenContainer = twStyled.View`w-full min-h-full items-center px-4 bg-primary`
519517

520518
const StResumeContainer = twStyled.Article`w-full md:max-w-[550px] py-16 flex-col`
521519

features/links-page/screens/BioScreen.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react'
22
// Navigation
33
import { Link, useAetherRoute, fetchAetherProps, useAetherNav } from 'aetherspace/navigation'
4+
// Context
5+
import { useAetherContext } from '../../../packages/@aetherspace/context'
46
// Schemas
57
import { z, aetherSchema, AetherParams, AetherProps } from 'aetherspace/schemas'
68
import { TUserBio, UserBio } from '../schemas'
@@ -14,6 +16,8 @@ import { H1 } from 'aetherspace/html-elements'
1416
import { BioSkeleton } from '../components/BioSkeleton'
1517
import BioLink from '../components/BioLink'
1618
import { AetherIcon } from 'aetherspace/components'
19+
// Hooks
20+
import { useTailwindStyles } from 'aetherspace/styles'
1721
// Utils
1822
import { isEmpty } from 'aetherspace/utils'
1923
// Mocks
@@ -108,14 +112,20 @@ export const BioScreen = (props: BioScreenProps) => {
108112
// Data
109113
const [bioData, { error }] = useAetherRoute(props, screenConfig)
110114
const { pathname } = useAetherNav()
115+
const { colorScheme, toggleColorScheme } = useAetherContext()
111116

112117
// Vars
113-
const ICON_COLOR = '#FFFFFF'
114118
const ICON_SIZE = 27
115119

116120
// Flags
117121
const isCustomBio = pathname?.includes('/bio/')
118122

123+
// -- Styles --
124+
125+
const primaryTextStyles = useTailwindStyles('text-primary')
126+
127+
const ICON_COLOR = (primaryTextStyles.color as string) ?? '#FFFFFF'
128+
119129
// -- Guards --
120130

121131
if (error) {
@@ -167,7 +177,9 @@ export const BioScreen = (props: BioScreenProps) => {
167177
))}
168178
</View>
169179

170-
<H1 tw="text-primary body-lg-bold mb-6">Featured Links</H1>
180+
<H1 tw="text-primary body-lg-bold mb-6" onPress={toggleColorScheme}>
181+
{`Featured Links`}
182+
</H1>
171183
<View tw="max-w-[620px] w-full lg:w-3/4 xl:w-2/4 px-5">
172184
<View tw="flex relative overflow-hidden gap-y-6">
173185
{bioData.linksInBio?.map((bioLink) => (
@@ -188,10 +200,10 @@ export const BioScreen = (props: BioScreenProps) => {
188200
</View>
189201

190202
<View tw="max-w-[600px] w-full lg:w-3/4 xl:w-2/4 mt-8 px-5 items-center">
191-
<Text tw="font-primary-light text-slate-200 text-center text-sm sm:text-base">
203+
<Text tw="font-primary-light text-secondary text-center text-sm sm:text-base">
192204
Ready for <Text tw="font-primary-regular">Organic leads</Text> from the Web,
193205
</Text>
194-
<Text tw="font-primary-light text-slate-200 text-center text-sm sm:text-base">
206+
<Text tw="font-primary-light text-secondary text-center text-sm sm:text-base">
195207
*and* <Text tw="font-primary-regular">Higher conversions</Text> on Mobile?
196208
</Text>
197209
<View tw="h-3" />

packages/@aetherspace/context/AetherContextManager/AetherContextManager.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
/* eslint-disable react-hooks/exhaustive-deps */
22
import React, { useState, useMemo, useEffect, useId } from 'react'
33
import { View, Platform, Dimensions } from 'react-native'
4-
import tailwind, { create as createTailwindWithConfig } from 'twrnc'
4+
import tailwind, {
5+
create as createTailwindWithConfig,
6+
useDeviceContext,
7+
useAppColorScheme,
8+
} from 'twrnc'
59
// Context
610
import { AetherContext, DEFAULT_AETHER_CONTEXT, AetherContextType } from './aetherContext'
711
// Hooks
@@ -36,6 +40,12 @@ const AetherContextManager = (props: AetherContextType) => {
3640
// Context ID
3741
const aetherContextID = useId()
3842

43+
// -- TWRNC Dark Mode --
44+
45+
useDeviceContext(tailwindFn, { withDeviceColorScheme: false })
46+
47+
const [colorScheme, toggleColorScheme, setColorScheme] = useAppColorScheme(tailwindFn)
48+
3949
// -- DidMount --
4050

4151
useEffect(() => {
@@ -44,7 +54,7 @@ const AetherContextManager = (props: AetherContextType) => {
4454
setGlobal('tailwindFn', tailwindFn)
4555
setRemountKey((prev) => prev + 1)
4656
}
47-
}, [])
57+
}, [colorScheme])
4858

4959
// -- ContextValue --
5060

@@ -125,16 +135,19 @@ const AetherContextManager = (props: AetherContextType) => {
125135
appWidth,
126136
appHeight,
127137
tailwind: tailwindFn,
138+
colorScheme,
139+
toggleColorScheme,
140+
setColorScheme,
128141
importSchema: props.importSchema,
129142
}
130-
}, [Platform.OS, appWidth, typeof window === 'undefined'])
143+
}, [Platform.OS, appWidth, typeof window === 'undefined', colorScheme])
131144

132145
// -- Render --
133146

134147
return (
135148
<AetherContext.Provider key={`mount-provider-${remountKey}`} value={contextValue}>
136149
<View
137-
key={`mount-view-${remountKey}`}
150+
key={`mount-view-${remountKey}-${colorScheme}`}
138151
style={{
139152
...props.style,
140153
...contextValue.tailwind`${['flex min-h-full min-w-full', props.tw].filter(Boolean).join(' ')}`, // prettier-ignore

packages/@aetherspace/context/AetherContextManager/aetherContext.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { GraphQLSchema } from 'graphql'
33
import { createContext, FC } from 'react'
44
import { TextProps } from 'react-native'
5-
import tailwind, { TwConfig, TailwindFn } from 'twrnc'
5+
import tailwind, { TwConfig, TailwindFn, RnColorScheme } from 'twrnc'
66

77
/* --- Types ----------------------------------------------------------------------------------- */
88

@@ -78,6 +78,9 @@ export interface AetherContextType {
7878
children?: any | any[]
7979
tailwind?: TailwindFn
8080
twConfig?: TwConfig
81+
colorScheme?: RnColorScheme
82+
toggleColorScheme?: () => void
83+
setColorScheme?: (scheme: RnColorScheme) => void
8184
importSchema?: () => Promise<GraphQLSchema>
8285
}
8386

0 commit comments

Comments
 (0)