-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
theme-switch.tsx
61 lines (55 loc) · 1.58 KB
/
theme-switch.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { useTheme } from 'next-themes'
import { useMounted } from 'nextra/hooks'
import { MoonIcon, SunIcon } from 'nextra/icons'
import type { ReactElement } from 'react'
import { z } from 'zod'
import { useConfig } from '../contexts'
import { Select } from './select'
type ThemeSwitchProps = {
lite?: boolean
className?: string
}
export const themeOptionsSchema = z.strictObject({
light: z.string(),
dark: z.string(),
system: z.string()
})
type ThemeOptions = z.infer<typeof themeOptionsSchema>
export function ThemeSwitch({
lite,
className
}: ThemeSwitchProps): ReactElement {
const { setTheme, resolvedTheme, theme = '' } = useTheme()
const mounted = useMounted()
const config = useConfig().themeSwitch
const IconToUse = mounted && resolvedTheme === 'dark' ? MoonIcon : SunIcon
const options: ThemeOptions =
typeof config.useOptions === 'function'
? config.useOptions()
: config.useOptions
return (
<Select
className={className}
title="Change theme"
options={[
{ key: 'light', name: options.light },
{ key: 'dark', name: options.dark },
{ key: 'system', name: options.system }
]}
onChange={option => {
setTheme(option.key)
}}
selected={{
key: theme,
name: (
<div className="nx-flex nx-items-center nx-gap-2 nx-capitalize">
<IconToUse />
<span className={lite ? 'md:nx-hidden' : ''}>
{mounted ? options[theme as keyof typeof options] : options.light}
</span>
</div>
)
}}
/>
)
}