1
Fork 0

Add user preference for changing theme

This commit is contained in:
viktorstrate 2022-02-07 23:27:04 +01:00
parent 98f4dcb1e0
commit c9d59a634e
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
5 changed files with 84 additions and 6 deletions

View File

@ -18,7 +18,7 @@ export const SectionTitle = ({ children, nospace }: SectionTitleProps) => {
return ( return (
<h2 <h2
className={classNames( className={classNames(
'pb-1 border-b border-gray-200 text-xl mb-5', 'pb-1 border-b border-gray-200 dark:border-[#3B3B3B] text-xl mb-5',
!nospace && 'mt-6' !nospace && 'mt-6'
)} )}
> >

View File

@ -1,6 +1,6 @@
import { useMutation, useQuery } from '@apollo/client' import { useMutation, useQuery } from '@apollo/client'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import React, { useMemo } from 'react' import React, { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
import { LanguageTranslation } from '../../__generated__/globalTypes' import { LanguageTranslation } from '../../__generated__/globalTypes'
@ -16,6 +16,8 @@ import {
changeUserPreferencesVariables, changeUserPreferencesVariables,
} from './__generated__/changeUserPreferences' } from './__generated__/changeUserPreferences'
import { myUserPreferences } from './__generated__/myUserPreferences' import { myUserPreferences } from './__generated__/myUserPreferences'
import { TranslationFn } from '../../localization'
import { changeTheme, getTheme } from '../../theme'
const languagePreferences = [ const languagePreferences = [
{ key: 1, label: 'English', flag: 'uk', value: LanguageTranslation.English }, { key: 1, label: 'English', flag: 'uk', value: LanguageTranslation.English },
@ -47,6 +49,24 @@ const languagePreferences = [
}, },
] ]
const themePreferences = (t: TranslationFn) => [
{
key: 1,
label: t('settings.user_preferences.theme.auto.label', 'Same as system'),
value: 'auto',
},
{
key: 2,
label: t('settings.user_preferences.theme.light.label', 'Light'),
value: 'light',
},
{
key: 2,
label: t('settings.user_preferences.theme.dark.label', 'Dark'),
value: 'dark',
},
]
const CHANGE_USER_PREFERENCES = gql` const CHANGE_USER_PREFERENCES = gql`
mutation changeUserPreferences($language: String) { mutation changeUserPreferences($language: String) {
changeUserPreferences(language: $language) { changeUserPreferences(language: $language) {
@ -86,6 +106,12 @@ const UserPreferencesWrapper = styled.div`
const UserPreferences = () => { const UserPreferences = () => {
const { t } = useTranslation() const { t } = useTranslation()
const [theme, setTheme] = useState(getTheme())
const changeStateTheme = (value: string) => {
changeTheme(value)
setTheme(value)
}
const { data } = useQuery<myUserPreferences>(MY_USER_PREFERENCES) const { data } = useQuery<myUserPreferences>(MY_USER_PREFERENCES)
@ -109,7 +135,7 @@ const UserPreferences = () => {
{t('settings.user_preferences.title', 'User preferences')} {t('settings.user_preferences.title', 'User preferences')}
</SectionTitle> </SectionTitle>
<LogoutButton /> <LogoutButton />
<label id="user_pref_change_language_field"> <label htmlFor="user_pref_change_language_field">
<InputLabelTitle> <InputLabelTitle>
{t( {t(
'settings.user_preferences.change_language.label', 'settings.user_preferences.change_language.label',
@ -140,6 +166,23 @@ const UserPreferences = () => {
selected={data?.myUserPreferences.language || undefined} selected={data?.myUserPreferences.language || undefined}
disabled={loadingPrefs} disabled={loadingPrefs}
/> />
<label htmlFor="user_pref_change_theme_field">
<InputLabelTitle>
{t('settings.user_preferences.theme.title', 'Theme preferences')}
</InputLabelTitle>
<InputLabelDescription>
{t(
'settings.user_preferences.theme.description',
'Change the appearance of the website'
)}
</InputLabelDescription>
</label>
<Dropdown
id="user_pref_change_theme_field"
items={themePreferences(t)}
setSelected={changeStateTheme}
selected={theme}
/>
</UserPreferencesWrapper> </UserPreferencesWrapper>
) )
} }

View File

@ -12,7 +12,8 @@ html {
font-family: 'Source Sans Pro', sans-serif; font-family: 'Source Sans Pro', sans-serif;
} }
body.dark { body.dark,
html.dark {
@apply bg-dark-bg text-dark-text; @apply bg-dark-bg text-dark-text;
} }

View File

@ -7,11 +7,13 @@ import client from './apolloClient'
import { ApolloProvider } from '@apollo/client' import { ApolloProvider } from '@apollo/client'
import { BrowserRouter as Router } from 'react-router-dom' import { BrowserRouter as Router } from 'react-router-dom'
import { setupLocalization } from './localization' import { setupLocalization } from './localization'
import { updateTheme } from './theme'
import * as serviceWorkerRegistration from './serviceWorkerRegistration' import * as serviceWorkerRegistration from './serviceWorkerRegistration'
import './index.css' import './index.css'
import { SidebarProvider } from './components/sidebar/Sidebar' import { SidebarProvider } from './components/sidebar/Sidebar'
updateTheme()
setupLocalization() setupLocalization()
const Main = () => ( const Main = () => (
@ -24,8 +26,6 @@ const Main = () => (
</ApolloProvider> </ApolloProvider>
) )
document.getElementsByTagName('body')[0].classList.add('dark')
ReactDOM.render(<Main />, document.getElementById('root')) ReactDOM.render(<Main />, document.getElementById('root'))
serviceWorkerRegistration.register() serviceWorkerRegistration.register()

34
ui/src/theme.ts Normal file
View File

@ -0,0 +1,34 @@
export const updateTheme = () => {
if (
localStorage.theme === 'dark' ||
(!('theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}
export const changeTheme = (value: string) => {
if (value == 'light') {
localStorage.theme = 'light'
} else if (value == 'dark') {
localStorage.theme = 'dark'
} else {
// use OS preference
localStorage.removeItem('theme')
}
updateTheme()
}
export const getTheme = () => {
if (localStorage.theme == 'light') {
return 'light'
} else if (localStorage.theme == 'dark') {
return 'dark'
} else {
return 'auto'
}
}