Add user preference for changing theme
This commit is contained in:
parent
98f4dcb1e0
commit
c9d59a634e
|
@ -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'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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'
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue