mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 06:17:23 +00:00
Fix logo
This commit is contained in:
1 parent
6bc5467c08
commit
10dbca8177
2 files changed
+82
-1
No files matched your search
@@ -95,6 +95,11 @@ export function usePacedText(text: string, enabled: boolean): string {
|
||||
return enabled ? text.slice(0, Math.min(visibleLength, text.length)) : text;
|
||||
}
|
||||
|
||||
// Each useDarkTheme() caller holds its own state; a toggle broadcasts the new
|
||||
// value so every other caller (logo, Mermaid, code blocks) follows without a
|
||||
// reload.
|
||||
const THEME_CHANGE_EVENT = 'docsgpt:themechange';
|
||||
|
||||
export function useDarkTheme() {
|
||||
const getSystemThemePreference = () => {
|
||||
return (
|
||||
@@ -126,6 +131,15 @@ export function useDarkTheme() {
|
||||
return () => mediaQuery.removeListener(handleChange);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleThemeChange = (event: Event) => {
|
||||
setIsDarkTheme((event as CustomEvent<boolean>).detail);
|
||||
};
|
||||
window.addEventListener(THEME_CHANGE_EVENT, handleThemeChange);
|
||||
return () =>
|
||||
window.removeEventListener(THEME_CHANGE_EVENT, handleThemeChange);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('selectedTheme', isDarkTheme ? 'Dark' : 'Light');
|
||||
const action = isDarkTheme ? 'add' : 'remove';
|
||||
@@ -148,7 +162,11 @@ export function useDarkTheme() {
|
||||
}, [isDarkTheme]);
|
||||
|
||||
const toggleTheme = () => {
|
||||
setIsDarkTheme(!isDarkTheme);
|
||||
const next = !isDarkTheme;
|
||||
setIsDarkTheme(next);
|
||||
window.dispatchEvent(
|
||||
new CustomEvent<boolean>(THEME_CHANGE_EVENT, { detail: next }),
|
||||
);
|
||||
};
|
||||
|
||||
return [isDarkTheme, toggleTheme, componentMounted] as const;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { act } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useDarkTheme } from './index';
|
||||
|
||||
Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });
|
||||
|
||||
describe('useDarkTheme', () => {
|
||||
let container: HTMLDivElement;
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.setItem('selectedTheme', 'Light');
|
||||
vi.stubGlobal('matchMedia', (query: string) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
addListener: () => {},
|
||||
removeListener: () => {},
|
||||
}));
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
container.remove();
|
||||
localStorage.clear();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('updates every consumer when one of them toggles the theme', async () => {
|
||||
let toggle: (() => void) | undefined;
|
||||
let logoIsDark: boolean | undefined;
|
||||
|
||||
function Settings() {
|
||||
const [, toggleTheme] = useDarkTheme();
|
||||
toggle = toggleTheme;
|
||||
return null;
|
||||
}
|
||||
function Logo() {
|
||||
[logoIsDark] = useDarkTheme();
|
||||
return null;
|
||||
}
|
||||
|
||||
const root = createRoot(container);
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<>
|
||||
<Settings />
|
||||
<Logo />
|
||||
</>,
|
||||
);
|
||||
});
|
||||
expect(logoIsDark).toBe(false);
|
||||
|
||||
await act(async () => toggle?.());
|
||||
expect(logoIsDark).toBe(true);
|
||||
|
||||
await act(async () => toggle?.());
|
||||
expect(logoIsDark).toBe(false);
|
||||
|
||||
await act(async () => root.unmount());
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user