fix: sync color scheme on loading state (#13878)
Before: https://github.com/user-attachments/assets/a769a2f8-554a-42f7-8adb-e8b4be92a4d1 Aftter: https://github.com/user-attachments/assets/9200967a-902f-4f8d-822d-827dda32bac2 --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@@ -60,14 +60,30 @@
|
||||
disableInputAutoZoom();
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
:root {
|
||||
/* THEME_DARK.background.tertiary */
|
||||
--theme-dark-background-tertiary: #1d1d1d;
|
||||
/* THEME_LIGHT.background.tertiary */
|
||||
--theme-light-background-tertiary: #f1f1f1;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html, body {
|
||||
background-color: var(--theme-dark-background-tertiary);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
html, body {
|
||||
background-color: var(--theme-light-background-tertiary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script
|
||||
type="module"
|
||||
src="/src/renderBodyOptimisticBackgroundBeforeAppBootstrap.ts"
|
||||
></script>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ThemeProvider } from '@emotion/react';
|
||||
import { createContext, useState } from 'react';
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { useSystemColorScheme } from '../hooks/useSystemColorScheme';
|
||||
import { persistedColorSchemeState } from '@/ui/theme/states/persistedColorSchemeState';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { type ColorScheme } from 'twenty-ui/input';
|
||||
import { THEME_DARK, THEME_LIGHT, ThemeContextProvider } from 'twenty-ui/theme';
|
||||
|
||||
@@ -14,16 +15,16 @@ export const ThemeSchemeContext = createContext<(theme: ColorScheme) => void>(
|
||||
);
|
||||
|
||||
export const BaseThemeProvider = ({ children }: BaseThemeProviderProps) => {
|
||||
const systemColorScheme = useSystemColorScheme();
|
||||
const [themeScheme, setThemeScheme] = useState(systemColorScheme);
|
||||
|
||||
const [persistedColorScheme, setPersistedColorScheme] = useRecoilState(
|
||||
persistedColorSchemeState,
|
||||
);
|
||||
document.documentElement.className =
|
||||
themeScheme === 'Dark' ? 'dark' : 'light';
|
||||
persistedColorScheme === 'Dark' ? 'dark' : 'light';
|
||||
|
||||
const theme = themeScheme === 'Dark' ? THEME_DARK : THEME_LIGHT;
|
||||
const theme = persistedColorScheme === 'Dark' ? THEME_DARK : THEME_LIGHT;
|
||||
|
||||
return (
|
||||
<ThemeSchemeContext.Provider value={setThemeScheme}>
|
||||
<ThemeSchemeContext.Provider value={setPersistedColorScheme}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ThemeContextProvider theme={theme}>{children}</ThemeContextProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useRecoilState } from 'recoil';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { persistedColorSchemeState } from '@/ui/theme/states/persistedColorSchemeState';
|
||||
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import {
|
||||
type IconComponent,
|
||||
@@ -20,6 +21,7 @@ export const useColorScheme = () => {
|
||||
const { updateOneRecord: updateOneWorkspaceMember } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
|
||||
});
|
||||
const [, setPersistedColorScheme] = useRecoilState(persistedColorSchemeState);
|
||||
|
||||
const colorScheme = currentWorkspaceMember?.colorScheme ?? 'System';
|
||||
|
||||
@@ -28,6 +30,7 @@ export const useColorScheme = () => {
|
||||
if (!currentWorkspaceMember) {
|
||||
return;
|
||||
}
|
||||
setPersistedColorScheme(value);
|
||||
setCurrentWorkspaceMember((current) => {
|
||||
if (!current) {
|
||||
return current;
|
||||
@@ -47,6 +50,7 @@ export const useColorScheme = () => {
|
||||
[
|
||||
currentWorkspaceMember,
|
||||
setCurrentWorkspaceMember,
|
||||
setPersistedColorScheme,
|
||||
updateOneWorkspaceMember,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { localStorageEffect } from '~/utils/recoil-effects';
|
||||
|
||||
export const persistedColorSchemeState = atom<ColorScheme>({
|
||||
key: 'persistedColorSchemeState',
|
||||
default: 'System',
|
||||
effects: [localStorageEffect()],
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
// TODO consume theme from twenty-ui after its migration as a package, at the moment the bunlde is too big
|
||||
// eslint-disable-next-line @nx/workspace-no-hardcoded-colors
|
||||
const THEME_LIGHT_BACKGROUND_TERTIARY = '#f1f1f1';
|
||||
// eslint-disable-next-line @nx/workspace-no-hardcoded-colors
|
||||
const THEME_DARK_BACKGROUND_TERTIARY = '#1d1d1d';
|
||||
|
||||
// TODO should search in local storage for user last session appearance preferences
|
||||
const renderBodyOptimisticBackgroundBeforeAppBootstrap = () => {
|
||||
const isDarkTheme =
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
if (isDarkTheme) {
|
||||
document.body.style.background = THEME_DARK_BACKGROUND_TERTIARY;
|
||||
} else {
|
||||
document.body.style.background = THEME_LIGHT_BACKGROUND_TERTIARY;
|
||||
}
|
||||
};
|
||||
renderBodyOptimisticBackgroundBeforeAppBootstrap();
|
||||
Reference in New Issue
Block a user