feat(editor): the dark scheme everywhere — the surface, documentation, mode buttons, program windows

The surface turns dark with light labels and cables and a faint light outline
round Java's icons; documentation rectangles become a tint of their colour and
texts are drawn towards light; the mode buttons use Java's pictures freed from
their grey ground (tools/dark-pictures/make.py); native controls follow
color-scheme; the desktop's program windows paint through Java-look tokens
whose light values are Java's own. The exported image and the report keep
Java's colours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-10 22:27:03 +00:00
co-authored by Claude Opus 5.5
parent 8c4e5049f6
commit ae10ee6c31
17 changed files with 536 additions and 127 deletions
+6 -3
View File
@@ -36,7 +36,7 @@ import { bounds, cablePath, deviceBox, ICONS, iconOf, JAVA_LABEL_FONT, type Devi
import { fitted, middle, shifted, spread, toScreen, toSurface, zoomedAt, zoomIn, zoomOut, type Point, type Size, type Viewport } from './viewport.js';
import { ZoomBar } from './ZoomBar.js';
import { gripPlace, handlePlace, HANDLES, menuPlace, NO_EDGE, shownHandles, TARGET, type Edges } from './handles.js';
import { EDGE_BAND, edgesAt, FOCUS_BAND, FOCUS_BORDER, fontFamily, holdFrame, rectangleBorder, rectangleFill, TEXT_BORDER, textColor, type Frame } from './documentationPaint.js';
import { darkRectangleBorder, darkRectangleFill, darkTextColor, EDGE_BAND, edgesAt, FOCUS_BAND, FOCUS_BORDER, fontFamily, holdFrame, rectangleBorder, rectangleFill, textColor, type Frame } from './documentationPaint.js';
/** How far a pointer moves before a press becomes a drag. */
export const DRAG_THRESHOLD = 4;
@@ -152,6 +152,8 @@ function Documentation({ item, documenting, focused }: { readonly item: Document
fill={rectangleFill(item.color, documenting)}
stroke={focused ? 'none' : rectangleBorder(item.color)}
strokeWidth={1}
// The dark scheme's paint (sheet.css takes it): Java's is for a white surface.
style={{ '--doc-fill-dark': darkRectangleFill(item.color, documenting), '--doc-stroke-dark': focused ? 'none' : darkRectangleBorder(item.color) } as CSSProperties}
/>
</g>
);
@@ -166,14 +168,15 @@ function Documentation({ item, documenting, focused }: { readonly item: Document
style={{
boxSizing: 'border-box',
padding: 1,
color: textColor(item.color),
// The words' colour, in the dark scheme drawn towards light (sheet.css).
...({ '--doc-ink': textColor(item.color), '--doc-ink-dark': darkTextColor(item.color) } as CSSProperties),
font: `${item.italic ? 'italic ' : ''}${item.bold ? 'bold ' : ''}${item.size}px ${fontFamily(item.font)}`,
whiteSpace: 'pre-wrap',
overflowWrap: 'break-word',
overflow: 'hidden',
width: '100%',
height: '100%',
border: documenting && !focused ? `1px solid ${TEXT_BORDER}` : undefined,
border: documenting && !focused ? '1px solid var(--doc-text-border)' : undefined,
visibility: focused ? 'hidden' : undefined,
}}
>
@@ -40,6 +40,24 @@ export function textColor(color: Color): string {
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, ${color.alpha})`;
}
/**
* The editor's dark scheme (not Java's — it has none; the exported image and
* the report keep Java's paint): a rectangle's colour as a tint of the dark
* surface, stronger while documenting, its border the colour itself, faded.
*/
export function darkRectangleFill(color: Color, documenting: boolean): string {
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, ${documenting ? 0.28 : 0.2})`;
}
export function darkRectangleBorder(color: Color): string {
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, 0.7)`;
}
/** A text's colour on the dark surface: drawn towards the light text colour, so that Java's black reads as light and a red as a light red. */
export function darkTextColor(color: Color): string {
return `color-mix(in oklab, ${textColor(color)} 15%, var(--canvas-label))`;
}
/** Java's logical font names as the browser has them; any other a font of that name, else sans-serif. */
export function fontFamily(name: string): string {
switch (name.toLowerCase()) {