Skip to content

Commit a7b2e01

Browse files
committed
feat: toggle color scheme
1 parent bb6be32 commit a7b2e01

File tree

4 files changed

+54
-10
lines changed

4 files changed

+54
-10
lines changed

app/src/components/environment.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import { Grid, Stars } from '@react-three/drei'
22
import { RigidBody } from '@react-three/rapier'
3-
import { isDarkMode } from '@react-three/uikit'
43
import { colors } from '@react-three/uikit-default'
54
import { IfInSessionMode } from '@react-three/xr'
5+
import { useEffect, useState } from 'react'
6+
7+
import { useIsDarkValue } from '~/hooks/use-is-dark'
68

79
export const Environment = () => {
8-
// const intensity = isDarkMode.value ? 0.5 : 1
9-
const intensity = 1
10+
const isDark = useIsDarkValue()
11+
const intensity = isDark ? 1 : 1.5
12+
13+
const [bg, setBg] = useState(colors.background.value)
14+
const [fg, setFg] = useState(colors.foreground.value)
15+
16+
// fix: listen signal update
17+
useEffect(() => {
18+
setBg(colors.background.value)
19+
setFg(colors.foreground.value)
20+
}, [isDark])
1021

1122
return (
1223
<>
@@ -22,7 +33,7 @@ export const Environment = () => {
2233
</RigidBody>
2334
<IfInSessionMode deny="immersive-ar">
2435
<Grid
25-
cellColor={colors.foreground.value}
36+
cellColor={fg}
2637
cellSize={1}
2738
cellThickness={1}
2839
fadeDistance={50}
@@ -31,8 +42,8 @@ export const Environment = () => {
3142
position={[0, 0, 0]}
3243
sectionSize={0}
3344
/>
34-
<color args={[colors.background.value]} attach="background" />
35-
{isDarkMode.value && <Stars count={99} depth={99} fade />}
45+
<color args={[bg]} attach="background" />
46+
{isDark && <Stars count={99} depth={99} fade />}
3647
</IfInSessionMode>
3748
</>
3849
)

app/src/components/ui/navbar.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ import {
44
Text,
55
} from '@react-three/uikit'
66
import { Button, Defaults, Input } from '@react-three/uikit-default'
7-
import { GithubIcon, SettingsIcon } from '@react-three/uikit-lucide'
7+
import { GithubIcon, MoonIcon, SettingsIcon, SunIcon } from '@react-three/uikit-lucide'
88
import { IfInSessionMode, useXRStore } from '@react-three/xr'
99

10+
import { useIsDarkValue, useToggleIsDark } from '~/hooks/use-is-dark'
1011
import { useNavigate } from '~/router'
1112

13+
const NavbarThemeIcon = ({ isDark }: { isDark: boolean }) => isDark
14+
? <SunIcon height={16} width={16} />
15+
: <MoonIcon height={16} width={16} />
16+
1217
export const Navbar = () => {
1318
const store = useXRStore()
1419
const navigate = useNavigate()
20+
const isDark = useIsDarkValue()
21+
const toggleIsDark = useToggleIsDark()
1522

1623
return (
1724
<IfInSessionMode deny={['immersive-ar', 'immersive-vr']}>
@@ -24,7 +31,7 @@ export const Navbar = () => {
2431
pointerEvents="listener"
2532
>
2633
<Container flexDirection="column" gap={8} lg={{ flexDirection: 'row' }}>
27-
<Input maxWidth={256} placeholder="Send message..." />
34+
<Input marginX="auto" maxWidth={288} placeholder="Send message..." />
2835
<Container gap={8} justifyContent="center">
2936
<Button
3037
data-test-id="enter-vr"
@@ -49,6 +56,14 @@ export const Navbar = () => {
4956
>
5057
<SettingsIcon height={16} width={16} />
5158
</Button>
59+
<Button
60+
data-test-id="toggle-color-scheme"
61+
onClick={() => toggleIsDark()}
62+
size="icon"
63+
variant="secondary"
64+
>
65+
<NavbarThemeIcon isDark={isDark} />
66+
</Button>
5267
<Button
5368
data-test-id="github"
5469
onClick={() => window.open('https://github.com/moeru-ai/n3p6', '_blank', 'noopener')}

app/src/hooks/use-is-dark.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createLocalStorageState } from 'foxact/create-local-storage-state'
2+
import { useCallback } from 'react'
3+
4+
const [useIsDark, useIsDarkValue] = createLocalStorageState(
5+
'n3p6/is-dark',
6+
window.matchMedia('(prefers-color-scheme: dark)').matches,
7+
)
8+
9+
const useToggleIsDark = () => {
10+
const [,setIsDark] = useIsDark()
11+
12+
return useCallback(() => setIsDark(prevIsDark => !prevIsDark), [setIsDark])
13+
}
14+
15+
export { useIsDark, useIsDarkValue, useToggleIsDark }

app/src/pages/_app.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { Canvas } from '@react-three/fiber'
22
import { setPreferredColorScheme } from '@react-three/uikit'
33
import { noEvents } from '@react-three/xr'
4+
import { useEffect } from 'react'
45
import { Outlet, useLocation } from 'react-router'
56

6-
// eslint-disable-next-line @masknet/no-top-level
7-
setPreferredColorScheme('system')
7+
import { useIsDarkValue } from '~/hooks/use-is-dark'
88

99
const AppLayout = () => {
1010
const { pathname } = useLocation()
1111
const events = pathname.includes('settings') ? undefined : noEvents
12+
const isDark = useIsDarkValue()
13+
14+
useEffect(() => setPreferredColorScheme(isDark ? 'dark' : 'light'), [isDark])
1215

1316
return (
1417
<Canvas

0 commit comments

Comments
 (0)