Fix sketch default color in dark mode (#2488)

Co-authored-by: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com>
This commit is contained in:
Ghxst
2026-05-21 19:18:32 +08:00
committed by GitHub
co-authored by Ghxst
parent 3a33a7b475
commit 93036afa2e
4 changed files with 112 additions and 1 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useT } from '../i18n';
import { readDefaultSketchToolColor } from './sketch-colors';
import type { SketchItem } from './sketch-model';
export type Tool = 'select' | 'pen' | 'text' | 'rect' | 'arrow' | 'eraser';
@@ -34,7 +35,7 @@ export function SketchEditor({
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const wrapRef = useRef<HTMLDivElement | null>(null);
const [tool, setTool] = useState<Tool>('pen');
const [color, setColor] = useState('#1c1b1a');
const [color, setColor] = useState(() => readDefaultSketchToolColor());
const [size, setSize] = useState(2);
const drawingRef = useRef<SketchItem | null>(null);
const [, force] = useState(0);
+18
View File
@@ -0,0 +1,18 @@
export const DEFAULT_SKETCH_LIGHT_TOOL_COLOR = '#1c1b1a';
export const DEFAULT_SKETCH_DARK_TOOL_COLOR = '#ffffff';
export function resolveDefaultSketchToolColor(
theme: string | null,
prefersDark: boolean,
): string {
if (theme === 'dark') return DEFAULT_SKETCH_DARK_TOOL_COLOR;
if (theme === 'light') return DEFAULT_SKETCH_LIGHT_TOOL_COLOR;
return prefersDark ? DEFAULT_SKETCH_DARK_TOOL_COLOR : DEFAULT_SKETCH_LIGHT_TOOL_COLOR;
}
export function readDefaultSketchToolColor(): string {
if (typeof document === 'undefined') return DEFAULT_SKETCH_LIGHT_TOOL_COLOR;
const theme = document.documentElement.getAttribute('data-theme');
const prefersDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches === true;
return resolveDefaultSketchToolColor(theme, prefersDark);
}
@@ -0,0 +1,68 @@
// @vitest-environment jsdom
import { cleanup, render } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { SketchEditor } from '../../src/components/SketchEditor';
import { I18nProvider } from '../../src/i18n';
class ResizeObserverMock {
observe() {}
disconnect() {}
}
function renderEditor() {
return render(
<I18nProvider initial="en">
<SketchEditor
items={[]}
onItemsChange={vi.fn()}
onSave={vi.fn()}
fileName="scratch.sketch.json"
/>
</I18nProvider>,
);
}
describe('SketchEditor default color', () => {
beforeEach(() => {
vi.stubGlobal('ResizeObserver', ResizeObserverMock);
vi.spyOn(HTMLCanvasElement.prototype, 'getContext').mockReturnValue({
setTransform: vi.fn(),
clearRect: vi.fn(),
save: vi.fn(),
fillRect: vi.fn(),
restore: vi.fn(),
beginPath: vi.fn(),
moveTo: vi.fn(),
lineTo: vi.fn(),
stroke: vi.fn(),
strokeRect: vi.fn(),
fillText: vi.fn(),
} as unknown as CanvasRenderingContext2D);
});
afterEach(() => {
cleanup();
document.documentElement.removeAttribute('data-theme');
vi.restoreAllMocks();
vi.unstubAllGlobals();
});
it('starts with a light pen color under the dark theme', () => {
document.documentElement.setAttribute('data-theme', 'dark');
const { container } = renderEditor();
const colorInput = container.querySelector<HTMLInputElement>('input[type="color"]');
expect(colorInput?.value).toBe('#ffffff');
});
it('keeps the existing default pen color under the light theme', () => {
document.documentElement.setAttribute('data-theme', 'light');
const { container } = renderEditor();
const colorInput = container.querySelector<HTMLInputElement>('input[type="color"]');
expect(colorInput?.value).toBe('#1c1b1a');
});
});
@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest';
import {
DEFAULT_SKETCH_DARK_TOOL_COLOR,
DEFAULT_SKETCH_LIGHT_TOOL_COLOR,
resolveDefaultSketchToolColor,
} from '../../src/components/sketch-colors';
describe('sketch-colors', () => {
it('uses a light tool color for an explicit dark theme', () => {
expect(resolveDefaultSketchToolColor('dark', false)).toBe(DEFAULT_SKETCH_DARK_TOOL_COLOR);
});
it('keeps the existing dark tool color for an explicit light theme', () => {
expect(resolveDefaultSketchToolColor('light', true)).toBe(DEFAULT_SKETCH_LIGHT_TOOL_COLOR);
});
it('follows the system dark preference when no explicit theme is set', () => {
expect(resolveDefaultSketchToolColor(null, true)).toBe(DEFAULT_SKETCH_DARK_TOOL_COLOR);
});
it('keeps the light-mode default when system mode is not dark', () => {
expect(resolveDefaultSketchToolColor(null, false)).toBe(DEFAULT_SKETCH_LIGHT_TOOL_COLOR);
});
});