diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index ab28dbe5d..1a4f013cc 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -16,12 +16,18 @@ export const MEASUREMENT_PILL_HEIGHT = 18 export const MEASUREMENT_PILL_RADIUS = 3 export const MEASUREMENT_TEXT_BASELINE = 4 export const CANVAS_BG_COLOR = { r: 0.96, g: 0.96, b: 0.96, a: 1 } satisfies Color -export const CANVAS_BG_COLOR_DARK = { r: 0.173, g: 0.173, b: 0.173, a: 1 } satisfies Color // #2c2c2c, Figma-ish dark canvas +export const CANVAS_BG_COLOR_DARK = { r: 0.137, g: 0.145, b: 0.165, a: 1 } satisfies Color // #23252a, dark canvas default /** - * Returns the canvas background to initialize new pages with. Defers - * to the OS `prefers-color-scheme` so users on a dark desktop don't - * get a white flash every time they open a document. + * Returns the canvas background to initialize new pages with. + * + * The app/host theme wins over the OS preference: when the editor is embedded + * by w4c-quasar the host opens it with `?theme=dark|light` and its own UI can be + * dark while the OS is light — without this the app opened a bright #f5f5f5 + * canvas inside a dark host. Outside the embed we read the resolved app theme + * from `` (set by `src/app/shell/theme.ts`). The OS + * `prefers-color-scheme` remains the fallback so a dark desktop still avoids a + * light flash when the app theme is unknown. * * NOTE: this is deliberately the runtime/new-page path only. The * `.fig` serialization path continues to write the static light @@ -34,6 +40,15 @@ export function getDefaultCanvasBgColor(): Color { if ('env' in import.meta && import.meta.env.DEV && params.has('test')) { return CANVAS_BG_COLOR } + + // W4C fork delta: `?theme=` is injected by the host + // (w4c-quasar/src/config/openpencil.ts); `data-theme` is the resolved app + // theme. Prefer them over the OS preference so the canvas matches the UI. + const resolvedTheme = + typeof document !== 'undefined' ? document.documentElement.dataset.theme : undefined + const hostTheme = params.get('theme') ?? resolvedTheme + if (hostTheme === 'dark') return CANVAS_BG_COLOR_DARK + if (hostTheme === 'light') return CANVAS_BG_COLOR } if ( diff --git a/packages/core/src/editor/page-viewports.ts b/packages/core/src/editor/page-viewports.ts index 59a46e16e..add0120ce 100644 --- a/packages/core/src/editor/page-viewports.ts +++ b/packages/core/src/editor/page-viewports.ts @@ -1,6 +1,6 @@ import type { Color } from '@open-pencil/scene-graph/primitives' -import { CANVAS_BG_COLOR } from '#core/constants' +import { getDefaultCanvasBgColor } from '#core/constants' import type { EditorContext } from './types' @@ -36,7 +36,7 @@ export function createPageViewportStore(ctx: EditorContext) { ctx.state.panX = 0 ctx.state.panY = 0 ctx.state.zoom = 1 - ctx.state.pageColor = { ...CANVAS_BG_COLOR } + ctx.state.pageColor = { ...getDefaultCanvasBgColor() } } function deletePageViewport(pageId: string) { diff --git a/packages/core/src/editor/state/view.ts b/packages/core/src/editor/state/view.ts index 8f59597f0..3fa7b3b54 100644 --- a/packages/core/src/editor/state/view.ts +++ b/packages/core/src/editor/state/view.ts @@ -1,5 +1,5 @@ import { createGuideOverlayState } from '#core/canvas/guides/types' -import { CANVAS_BG_COLOR } from '#core/constants' +import { getDefaultCanvasBgColor } from '#core/constants' import type { EditorState, EditorViewState } from '#core/editor/types' export function createDefaultEditorViewState(pageId: string): EditorViewState { @@ -20,7 +20,7 @@ export function createDefaultEditorViewState(pageId: string): EditorViewState { penCursorY: null, autoLayoutHover: null, panX: 0, - pageColor: { ...CANVAS_BG_COLOR }, + pageColor: { ...getDefaultCanvasBgColor() }, panY: 0, zoom: 1, renderVersion: 0,