Skip to content

Commit

Permalink
fix(DarkThemeToggle): should toggle the theme with usePreferences i…
Browse files Browse the repository at this point in the history
…s false (#417) (#424)

Closes: #417
  • Loading branch information
Xavier Chevalier authored Nov 5, 2022
1 parent 6ea90f1 commit 37244ff
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 42 deletions.
20 changes: 19 additions & 1 deletion src/lib/components/DarkThemeToggle/DarkThemeToggle.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest';
import { Flowbite } from '../Flowbite';
import { DarkThemeToggle } from './DarkThemeToggle';

describe.concurrent('Dark theme toggle', () => {
describe('Dark theme toggle', () => {
it('should toggle the theme when `Space` is pressed', async () => {
const user = userEvent.setup();
render(
Expand All @@ -19,4 +19,22 @@ describe.concurrent('Dark theme toggle', () => {
expect(screen.queryByLabelText('Currently light mode')).not.toBeInTheDocument();
expect(screen.queryByLabelText('Currently dark mode')).toBeInTheDocument();
});

it('should toggle the theme with `usePreferences` is false', async () => {
const user = userEvent.setup();
render(
<Flowbite theme={{ usePreferences: false }}>
<DarkThemeToggle />
</Flowbite>,
);

expect(screen.queryByLabelText('Currently light mode')).toBeInTheDocument();
expect(screen.queryByLabelText('Currently dark mode')).not.toBeInTheDocument();

await user.tab();
await user.keyboard('[Space]');

expect(screen.queryByLabelText('Currently light mode')).not.toBeInTheDocument();
expect(screen.queryByLabelText('Currently dark mode')).toBeInTheDocument();
});
});
62 changes: 21 additions & 41 deletions src/lib/components/Flowbite/ThemeContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import windowExists from '../../helpers/window-exists';
import defaultTheme from '../../theme/default';
import type { FlowbiteTheme } from './FlowbiteTheme';

export type Mode = string | undefined | 'light' | 'dark';
export type Mode = 'light' | 'dark';

interface ThemeContextProps {
theme: FlowbiteTheme;
Expand All @@ -32,54 +32,34 @@ export function useTheme(): ThemeContextProps {

export const useThemeMode = (
usePreferences: boolean,
): [Mode, React.Dispatch<React.SetStateAction<Mode>> | undefined, (() => void) | undefined] => {
if (!usePreferences) return [undefined, undefined, undefined];
const [mode, setMode] = useState<Mode>(undefined);

const savePreference = (m: string) => localStorage.setItem('theme', m);

): [Mode, React.Dispatch<React.SetStateAction<Mode>>, () => void] => {
const [mode, setModeState] = useState<Mode>('light');
const savePreference = (mode: Mode) => localStorage.setItem('theme', mode);
const getPreference = (): Mode => (localStorage.getItem('theme') as Mode) || getPrefersColorScheme();
const userPreferenceIsDark = () => window.matchMedia?.('(prefers-color-scheme: dark)').matches;
const getPrefersColorScheme = (): Mode => (userPreferenceIsDark() ? 'dark' : 'light');
const toggleMode = () => {
if (!mode) {
const newMode = mode === 'dark' ? 'light' : 'dark';
setMode(newMode);
setModeState(newMode);
};
const setMode = (mode: Mode) => {
savePreference(mode);
if (!windowExists()) {
return;
}

if (windowExists()) {
document.documentElement.classList.toggle('dark');
if (mode === 'dark') {
document.documentElement.classList.add('dark');
return;
}

savePreference(mode);
setMode(mode == 'dark' ? 'light' : 'dark');
document.documentElement.classList.remove('dark');
};

if (usePreferences) {
useEffect(() => {
const userPreference =
windowExists() && !!window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const userMode = localStorage.getItem('theme') || (userPreference ? 'dark' : 'light');

if (userMode) {
setMode(userMode);
}
}, []);

useEffect(() => {
if (!mode) {
return;
}

savePreference(mode);

if (!windowExists()) {
return;
}

if (mode != 'dark') {
document.documentElement.classList.remove('dark');
} else {
document.documentElement.classList.add('dark');
}
}, [mode]);
useEffect(() => setModeState(getPreference()), []);
useEffect(() => setMode(mode), [mode]);
}

return [mode, setMode, toggleMode];
return [mode, setModeState, toggleMode];
};

0 comments on commit 37244ff

Please sign in to comment.