Skip to content
File

Blob: src/client/components/canvas/styles/canvas-theme.css

css118 lines
1/* Scope Excalidraw's customizable CSS variables to bland's canvas surface.
2 * Upstream API: https://docs.excalidraw.com/docs/@excalidraw/excalidraw/customizing-styles
3 * Stable selectors: .excalidraw and .excalidraw.theme--dark.
4 *
5 * The outer `.bland-canvas` wrapper keeps our overrides scoped so we never
6 * leak into any other Excalidraw instance a page might embed later. */
7 
8/* Hide the entire top-right chrome.
9 * Excalidraw renders three things there:
10 * 1. DefaultSidebar.Trigger (the "Library" button — we don't use its
11 * stock-shape library; pages are the unit of content in bland)
12 * 2. Collaborator UserList (bland already renders its own AvatarStack
13 * in the page chrome — duplicating it here is noise)
14 * 3. whatever `renderTopRightUI` returns (we return null)
15 * `renderTopRightUI` does not replace the other two, it only appends, so
16 * CSS is the cleanest way to drop the whole cluster. */
17.bland-canvas .excalidraw .layer-ui__wrapper__top-right {
18 display: none;
19}
20 
21/* UI chrome font — keep Excalidraw's own Excalifont/Cascadia on canvas
22 * content (part of the hand-drawn character), but make floating islands,
23 * menus, and dialogs read as bland surfaces. Excalidraw sets `Assistant` on
24 * several widget elements directly (burger button, help icon, zoom label,
25 * zen toggle), so a single rule on `.excalidraw` gets overridden by their
26 * own specificity. Descendant selector covers the whole subtree — the
27 * inline `<canvas>` element renders its own text, unaffected by this. */
28.bland-canvas .excalidraw,
29.bland-canvas .excalidraw * {
30 font-family: var(--font-sans);
31}
32 
33/* Font-size / weight consistency across menus.
34 * Excalidraw's right-click context menu defaults to 16px / weight 450
35 * while its dropdown MainMenu defaults to 14px / weight 400 — visibly
36 * different sizes. Normalize both to 14px / 450 (matches bland's sidebar
37 * menu language and the astigmatism-comfort "heavier weights" guidance
38 * in PRODUCT.md). */
39.bland-canvas .excalidraw .context-menu-item,
40.bland-canvas .excalidraw .dropdown-menu-item-base {
41 font-size: 14px;
42 font-weight: 450;
43}
44 
45.bland-canvas .excalidraw,
46.bland-canvas .excalidraw.theme--dark {
47 /* Brand accent — warm amethyst ramp. Drives selection handles, active
48 * tool state, and focus rings. */
49 --color-primary: var(--color-accent-500);
50 --color-primary-darker: var(--color-accent-600);
51 --color-primary-darkest: var(--color-accent-700);
52 --color-primary-light: color-mix(in oklab, var(--color-accent-500) 22%, transparent);
53 --color-primary-light-darker: color-mix(in oklab, var(--color-accent-500) 32%, transparent);
54 --color-primary-hover: var(--color-accent-400);
55 --color-primary-contrast-offset: var(--color-accent-400);
56 
57 /* Link color inside dialogs + hints. */
58 --link-color: var(--color-accent-400);
59 --link-color-hover: var(--color-accent-300);
60}
61 
62.bland-canvas .excalidraw.theme--dark {
63 /* Inset surface — slightly darker than the page body (#221f21) so the
64 * canvas reads as a recessed panel. Uses bland's warmed zinc-950. */
65 --default-bg-color: var(--color-zinc-950);
66 
67 /* Floating tool islands (top toolbar, properties panel) — one step up
68 * from the canvas so they lift off the surface. */
69 --island-bg-color: var(--color-zinc-800);
70 --island-bg-color-alt: var(--color-zinc-900);
71 --overlay-bg-color: color-mix(in oklab, var(--color-zinc-950) 80%, transparent);
72 
73 /* Popups (color picker, context menu, dropdowns) — match bland's
74 * overlay-surface token. */
75 --popup-bg-color: var(--color-zinc-800);
76 --popup-secondary-bg-color: var(--color-zinc-700);
77 --popup-text-color: var(--color-zinc-100);
78 
79 /* Sidebar (we hide Library, but dialogs + sheets still use this). */
80 --sidebar-bg-color: var(--color-zinc-900);
81 --sidebar-border-color: var(--color-zinc-800);
82 
83 /* Borders — subtle, avoid hairline contrast against the lifted dark. */
84 --default-border-color: var(--color-zinc-700);
85 --dialog-border-color: var(--color-zinc-700);
86 
87 /* Shadows — match the soft-lift feel of bland's own popovers. */
88 --shadow-island: 0 1px 2px rgba(0, 0, 0, 0.28), 0 8px 24px rgba(0, 0, 0, 0.32);
89 --shadow-island-stronger: 0 2px 4px rgba(0, 0, 0, 0.36), 0 12px 32px rgba(0, 0, 0, 0.4);
90 --modal-shadow: 0 4px 8px rgba(0, 0, 0, 0.4), 0 24px 48px rgba(0, 0, 0, 0.5);
91 --sidebar-shadow: 0 0 0 1px var(--color-zinc-800);
92 
93 /* Text — lifted off pure white per the astigmatism guidance in
94 * PRODUCT.md. Keep the contrast comfortable, not maximal. */
95 --text-primary-color: var(--color-zinc-100);
96 
97 /* Icons on chrome — same lifted tone as text. */
98 --icon-fill-color: var(--color-zinc-300);
99 
100 /* Buttons — bland's quiet-hover pattern. */
101 --button-hover-bg: color-mix(in srgb, var(--color-zinc-700) 60%, transparent);
102 --button-active-bg: color-mix(in srgb, var(--color-accent-500) 20%, transparent);
103 --button-active-border: var(--color-accent-500);
104 --button-gray-1: var(--color-zinc-800);
105 --button-gray-2: var(--color-zinc-700);
106 --button-gray-3: var(--color-zinc-600);
107 
108 /* Inputs inside dialogs. */
109 --input-bg-color: var(--color-zinc-900);
110 --input-border-color: var(--color-zinc-700);
111 --input-hover-bg-color: var(--color-zinc-800);
112 --input-label-color: var(--color-zinc-400);
113 
114 /* Selection highlight on canvas handles. */
115 --color-selection: var(--color-accent-500);
116 --focus-highlight-color: color-mix(in oklab, var(--color-accent-500) 50%, transparent);
117}