1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-29 22:37:44 +02:00

refactor: implement light/dark themes using cookies

This commit is contained in:
2023-08-01 14:11:46 +02:00
parent e82db952db
commit caa6a90418
21 changed files with 117 additions and 117 deletions

View File

@ -1,6 +1,6 @@
import Image from 'next/image'
import type { CookiesStore } from '@/i18n/i18n.client'
import type { CookiesStore } from '@/utils/constants'
import { useI18n } from '@/i18n/i18n.client'
export interface LocaleFlagProps {

View File

@ -3,8 +3,8 @@
import { useCallback, useEffect, useState, useRef } from 'react'
import classNames from 'clsx'
import { AVAILABLE_LOCALES } from '@/utils/constants'
import type { CookiesStore } from '@/i18n/i18n.client'
import type { Locale as LocaleType, CookiesStore } from '@/utils/constants'
import { LOCALES } from '@/utils/constants'
import { Arrow } from './Arrow'
import { LocaleFlag } from './LocaleFlag'
@ -43,7 +43,7 @@ export const Locales = (props: LocalesProps): JSX.Element => {
}
}, [])
const handleLocale = async (locale: string): Promise<void> => {
const handleLocale = async (locale: LocaleType): Promise<void> => {
const { setLocale } = await import('@/i18n/i18n.server')
setLocale(locale)
}
@ -70,7 +70,7 @@ export const Locales = (props: LocalesProps): JSX.Element => {
{ hidden: hiddenMenu }
)}
>
{AVAILABLE_LOCALES.filter((locale) => {
{LOCALES.filter((locale) => {
return locale !== currentLocale
}).map((locale) => {
return (

View File

@ -1,23 +1,22 @@
'use client'
import { useEffect, useState } from 'react'
import classNames from 'clsx'
import { useTheme } from 'next-themes'
export const SwitchTheme: React.FC = () => {
const [mounted, setMounted] = useState(false)
const { theme, setTheme } = useTheme()
import { useTheme } from '@/theme/theme.client'
import type { CookiesStore } from '@/utils/constants'
useEffect(() => {
setMounted(true)
}, [])
export interface SwitchThemeProps {
cookiesStore: CookiesStore
}
if (!mounted) {
return null
}
export const SwitchTheme = (props: SwitchThemeProps): JSX.Element => {
const { cookiesStore } = props
const theme = useTheme(cookiesStore)
const handleClick = (): void => {
setTheme(theme === 'dark' ? 'light' : 'dark')
const handleClick = async (): Promise<void> => {
const { setTheme } = await import('@/theme/theme.server')
const newTheme = theme === 'dark' ? 'light' : 'dark'
setTheme(newTheme)
}
return (

View File

@ -50,7 +50,7 @@ export const Header: React.FC<HeaderProps> = (props) => {
cookiesStore={cookiesStore.toString()}
/>
) : null}
<SwitchTheme />
<SwitchTheme cookiesStore={cookiesStore.toString()} />
</div>
</header>
)

View File

@ -2,9 +2,9 @@
import { useMemo } from 'react'
import type { CookiesStore } from '@/i18n/i18n.client'
import { useI18n } from '@/i18n/i18n.client'
import { BIRTH_DATE, BIRTH_DATE_STRING, getAge } from '@/utils/getAge'
import type { CookiesStore } from '@/utils/constants'
import { ProfileItem } from './ProfileItem'

View File

@ -1,15 +0,0 @@
'use client'
import { ThemeProvider } from 'next-themes'
type ProvidersProps = React.PropsWithChildren
export const Providers = (props: ProvidersProps): JSX.Element => {
const { children } = props
return (
<ThemeProvider attribute='class' defaultTheme='dark'>
{children}
</ThemeProvider>
)
}

View File

@ -1,9 +1,7 @@
'use client'
import { useState, useEffect, useMemo } from 'react'
import { useTheme } from 'next-themes'
import Image from 'next/image'
import { getTheme } from '@/theme/theme.server'
import type { SkillName } from './skills'
import { skills } from './skills'
@ -15,28 +13,17 @@ export const SkillComponent: React.FC<SkillComponentProps> = (props) => {
const { skill } = props
const skillProperties = skills[skill]
const [mounted, setMounted] = useState(false)
const { theme } = useTheme()
useEffect(() => {
setMounted(true)
}, [])
const theme = getTheme()
const image = useMemo(() => {
const getImage = (): string => {
if (typeof skillProperties.image === 'string') {
return skillProperties.image
}
if (!mounted) {
return skillProperties.image.dark
}
if (theme === 'light') {
return skillProperties.image.light
}
return skillProperties.image.dark
}, [skillProperties, theme, mounted])
if (!mounted) {
return null
}
return (
@ -53,7 +40,7 @@ export const SkillComponent: React.FC<SkillComponentProps> = (props) => {
width={64}
height={64}
alt={skill}
src={image}
src={getImage()}
/>
<p className='mt-1'>{skill}</p>
</div>