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:
@ -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 {
|
||||
|
@ -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 (
|
||||
|
@ -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 (
|
||||
|
@ -50,7 +50,7 @@ export const Header: React.FC<HeaderProps> = (props) => {
|
||||
cookiesStore={cookiesStore.toString()}
|
||||
/>
|
||||
) : null}
|
||||
<SwitchTheme />
|
||||
<SwitchTheme cookiesStore={cookiesStore.toString()} />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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>
|
||||
)
|
||||
}
|
@ -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>
|
||||
|
Reference in New Issue
Block a user