Skip to content

Make dark-theme canvas rendering match light where the drag artifact lives - #324

Merged
dovvnloading merged 1 commit into
mainfrom
fix/dark-render-parity
Aug 14, 2026
Merged

Make dark-theme canvas rendering match light where the drag artifact lives#324
dovvnloading merged 1 commit into
mainfrom
fix/dark-render-parity

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Problem

Dragging a node slowly makes its connection line visibly step out of sync with the node - but only in the dark theme. A full audit of every difference between the two themes (design tokens, the entire stylesheet, all application code, the canvas library's internals, the desktop shell, and external reports of the same symptom) established two things. First, no code executes differently by theme: the lag mechanism - the node moving on the graphics processor's fast path while the connection line is redrawn each frame - exists identically in both themes. Second, exactly three rendering differences make dark display that lag while light hides it:

  1. The connection line in dark was a bright stroke on a near-black canvas at roughly 2.07:1 contrast, versus light's soft 1.68:1 gray-on-gray. At a width of 1.5 pixels the line also falls into the renderer's thin-line smoothing regime below about 67 percent zoom, whose stepping is measurably harsher for a light line on a dark background than the reverse. Same misstep, dramatically different visibility.
  2. Dark's card shadows were 2.2 times denser than light's - the only structural asymmetry in the whole theme palette - giving the dragged card a much crisper silhouette to judge the line against.
  3. The page root had no background of its own, so anything shown before content paints resolved to the window's backdrop rather than the theme's canvas color.

The audit also found that the composition change in #323 never took effect: the window library passes its own feature-disabling switch, duplicate switches resolve last-one-wins, and the flag was silently discarded.

Change

  • New per-theme connection stroke token: dark gets #444444, which reproduces light's contrast ratio on the dark canvas; light keeps its current appearance. Stroke width goes from 1.5 to 2 to stay out of the thin-line smoothing regime at working zoom levels, with high-quality smoothing pinned explicitly.
  • Dark's shadow values now equal light's, removing the palette's only structural asymmetry.
  • The page root paints the theme's window color opaquely in both themes.
  • The launcher now merges both feature names into a single switch so the composition setting actually reaches the browser regardless of which argument list wins.

Test plan

  • Full frontend check passes: schema, types, lint (0 errors), 1927/1927 tests including the token parity and contrast guards, production build, bundle size
  • Launcher passes a syntax check
  • On the affected machine, dark theme: relaunch the desktop app and drag a connected node slowly - the reporter's reproduction, requiring visual confirmation

…lives

A full audit of every difference between the two themes established that
no code executes differently by theme - the connection-lag-while-
dragging artifact is present in both, and dark merely renders it
visibly. Three rendering-relevant asymmetries did that, and this change
removes each:

1. Connection stroke: dark painted a bright line on a near-black canvas
   at roughly 2.07:1 contrast, versus light's soft 1.68:1 - and at
   stroke-width 1.5 the line falls into the renderer's hairline
   anti-aliasing regime below about 67 percent zoom, whose stepping is
   visibly harsher for light-on-dark than dark-on-light. A dedicated
   per-theme stroke token now reproduces light's contrast ratio on the
   dark canvas (dark #444444; light keeps its #AFAFAF appearance),
   stroke-width goes to 2 to stay out of hairline mode, and
   geometricPrecision pins high-quality anti-aliasing.

2. Shadows: dark's alphas (0.40/0.45/0.55) were 2.2x denser than
   light's (0.18/0.203/0.248) - the only structural asymmetry in the
   entire token palette - crisping the dragged card's silhouette and
   amplifying any visible misstep. Dark now uses light's values.

3. Page root background: html/body/#root had no background of their
   own, so pre-paint clears resolved to the embedding window's backdrop
   instead of the theme's canvas color. The root now paints the theme's
   window color opaquely in both themes.

Also corrects the #323 composition flag, which the audit found never
reached the browser: pywebview's Windows backend passes its own
--disable-features switch and duplicate switches resolve last-one-wins,
so the flag was silently discarded. Both feature names now travel in
one merged list, so whichever list wins carries both.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit 701e7bf into main Aug 14, 2026
dovvnloading added a commit that referenced this pull request Aug 14, 2026
These three changes were attempts at the drag artifact that were not
confirmed to work before shipping, and the most recent one made things
worse: with #324 in place the connection lag became visible in the light
theme as well, where it had previously been unnoticeable.

The most likely cause of that regression is the composition flag. The
audit behind #324 established that the flag added in #323 never reached
the browser, because the window library passes a conflicting switch and
duplicate switches resolve last-one-wins. #324 corrected the delivery,
so disabling delegated composition took effect for the first time - and
it applies to both themes equally, which matches the report exactly. The
stroke width increase and the explicit high-quality smoothing hint in
the same change also affect both themes and cannot be ruled out.

This restores graphlink_desktop.py, styles.css and gl-vars-dev.css to
their state as of #321. The measured performance fixes in #319, #320 and
#321 are untouched.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@dovvnloading
dovvnloading deleted the fix/dark-render-parity branch August 15, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant