Handle theme change

This commit is contained in:
Ben Grant 2023-05-24 19:48:29 +10:00
parent 6220e599cf
commit 90352503b3
2 changed files with 78 additions and 69 deletions

View file

@ -1,6 +1,6 @@
'use client' 'use client'
import { useCallback, useRef, useState } from 'react' import { useCallback, useEffect, useRef, useState } from 'react'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { maps } from 'hue-map' import { maps } from 'hue-map'
import { Settings as SettingsIcon } from 'lucide-react' import { Settings as SettingsIcon } from 'lucide-react'
@ -33,6 +33,12 @@ const Settings = () => {
} }
}, []) }, [])
// Use user theme preference
useEffect(() => {
document.body.classList.toggle('light', store?.theme === 'Light')
document.body.classList.toggle('dark', store?.theme === 'Dark')
}, [store?.theme])
return <> return <>
<button <button
type="button" type="button"
@ -50,79 +56,81 @@ const Settings = () => {
<div onClick={e => e.stopPropagation()}> <div onClick={e => e.stopPropagation()}>
<span className={styles.heading}>{t('options.name')}</span> <span className={styles.heading}>{t('options.name')}</span>
<ToggleField {store && <>
label={t('options.weekStart.label')} <ToggleField
name="weekStart" label={t('options.weekStart.label')}
options={{ name="weekStart"
'Sunday': t('options.weekStart.options.Sunday'), options={{
'Monday': t('options.weekStart.options.Monday'), 'Sunday': t('options.weekStart.options.Sunday'),
}} 'Monday': t('options.weekStart.options.Monday'),
value={store?.weekStart === 0 ? 'Sunday' : 'Monday'} }}
onChange={value => store?.setWeekStart(value === 'Sunday' ? 0 : 1)} value={store?.weekStart === 0 ? 'Sunday' : 'Monday'}
/> onChange={value => store?.setWeekStart(value === 'Sunday' ? 0 : 1)}
/>
<ToggleField <ToggleField
label={t('options.timeFormat.label')} label={t('options.timeFormat.label')}
name="timeFormat" name="timeFormat"
options={{ options={{
'12h': t('options.timeFormat.options.12h'), '12h': t('options.timeFormat.options.12h'),
'24h': t('options.timeFormat.options.24h'), '24h': t('options.timeFormat.options.24h'),
}} }}
value={store?.timeFormat ?? '12h'} value={store?.timeFormat ?? '12h'}
onChange={value => store?.setTimeFormat(value)} onChange={value => store?.setTimeFormat(value)}
/> />
<ToggleField <ToggleField
label={t('options.theme.label')} label={t('options.theme.label')}
name="theme" name="theme"
options={{ options={{
'System': t('options.theme.options.System'), 'System': t('options.theme.options.System'),
'Light': t('options.theme.options.Light'), 'Light': t('options.theme.options.Light'),
'Dark': t('options.theme.options.Dark'), 'Dark': t('options.theme.options.Dark'),
}} }}
value={store?.theme ?? 'System'} value={store?.theme ?? 'System'}
onChange={value => store?.setTheme(value)} onChange={value => store?.setTheme(value)}
/> />
<SelectField <SelectField
label={t('options.colormap.label')} label={t('options.colormap.label')}
name="colormap" name="colormap"
options={{ options={{
'crabfit': t('options.colormap.classic'), 'crabfit': t('options.colormap.classic'),
...Object.fromEntries(Object.keys(maps).sort().map(palette => [ ...Object.fromEntries(Object.keys(maps).sort().map(palette => [
palette, palette,
unhyphenate(palette) unhyphenate(palette)
])), ])),
}} }}
isSmall isSmall
value={store?.colormap} value={store?.colormap}
onChange={event => store?.setColormap(event.target.value)} onChange={event => store?.setColormap(event.target.value)}
/> />
<ToggleField <ToggleField
label={t('options.highlight.label')} label={t('options.highlight.label')}
name="highlight" name="highlight"
description={t('options.highlight.title')} description={t('options.highlight.title')}
options={{ options={{
'Off': t('options.highlight.options.Off'), 'Off': t('options.highlight.options.Off'),
'On': t('options.highlight.options.On'), 'On': t('options.highlight.options.On'),
}} }}
value={store?.highlight ? 'On' : 'Off'} value={store?.highlight ? 'On' : 'Off'}
onChange={value => store?.setHighlight(value === 'On')} onChange={value => store?.setHighlight(value === 'On')}
/> />
<SelectField <SelectField
label={t('options.language.label')} label={t('options.language.label')}
name="language" name="language"
id="language" id="language"
options={{ options={{
...Object.fromEntries(Object.entries(languageDetails).map(([id, details]) => [id, details.name])), ...Object.fromEntries(Object.entries(languageDetails).map(([id, details]) => [id, details.name])),
...process.env.NODE_ENV !== 'production' && { 'cimode': 'DEV' }, ...process.env.NODE_ENV !== 'production' && { 'cimode': 'DEV' },
}} }}
isSmall isSmall
value={i18n.language} value={i18n.language}
onChange={e => i18n.changeLanguage(e.target.value).then(() => router.refresh())} onChange={e => i18n.changeLanguage(e.target.value).then(() => router.refresh())}
/> />
</>}
</div> </div>
</dialog> </dialog>
</> </>

View file

@ -37,6 +37,7 @@ const ToggleField = <TValue extends string>({
id={`${name}-${key}`} id={`${name}-${key}`}
checked={value === key} checked={value === key}
onChange={() => onChange(key as TValue)} onChange={() => onChange(key as TValue)}
onClick={() => onChange(key as TValue)}
/> />
<label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label> <label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label>
</div> </div>