You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In apps/desktop/src/theme.rs:150-181, the OKLab to sRGB conversion uses approximate hardcoded coefficients that produce visibly incorrect colors:
let red = linear_srgb_to_srgb(4.076_741_7* l - 3.307_711_6* m + 0.230_969_94* s);let green = linear_srgb_to_srgb(-1.268_438* l + 2.609_757_4* m - 0.341_319_4* s);let blue = linear_srgb_to_srgb(-0.004_196_086_3* l - 0.703_418_6* m + 1.707_614_7* s);
These are simplified approximations of the OKLab inverse transform. For a video editor, color accuracy is critical - these inaccuracies will compound across the rendering pipeline.
Additionally, light theme chart colors are all grayscale (chroma=0):
chart_1: oklch(0.87,0.0,0.0),// All chart_1 through chart_5 have chroma=0chart_2: oklch(0.556,0.0,0.0),
chart_3:oklch(0.439,0.0,0.0),
chart_4:oklch(0.371,0.0,0.0),
chart_5:oklch(0.269,0.0,0.0),
This makes charts unusable in light mode - all bars/lines render as identical gray.
Expected Behavior
Use the exact OKLab inverse transform matrix from the specification (Björn Ottosson's paper)
Light theme chart colors should have distinct hues (chroma > 0)
Steps To Reproduce
Run desktop app in light mode
Observe chart components - all colors are identical gray
Compare rendered colors against reference OKLab implementation
Recurrence Probability
Always - deterministic color math error
Additional Context
For a video editor, color fidelity is a core requirement. Consider using a vetted color space library like palette or oklab crate instead of hand-rolled approximations. The current implementation deviates from the OKLab spec.
Updated chart_1 through chart_5 tokens in both desktop Theme::light/Theme::dark and web styles.css from monochrome gray (chroma=0) to distinct chromatic palettes matching standard shadcn OKLCH tokens.
Added unit tests in apps/desktop/src/theme.rs ensuring chart colors across light and dark modes have distinct hues.
Part 1 of this issue doesn't hold up — part 2 does, and it's broader
I checked the OKLab math before acting on this, and half of it is based on a misreading of the code. Recording it so nobody spends time "fixing" correct color code.
The inverse transform matrix is the spec matrix
The constants in apps/desktop/src/theme.rs:163-165 are not an approximation. They're the published OKLab inverse matrix from the CSS Color 4 spec / Björn Ottosson's paper, written to 7 significant figures:
repo value
canonical value
R
4.076_741_7
4.076_741_6621
G
2.609_757_4
2.609_757_4011
B
1.707_614_7
1.707_614_7010
I compiled the repo's oklch_with_alpha alongside a reference implementation using the full-precision constants, and compared outputs across six colors spanning both axes:
oklch(0.5, 0.1, 30): repo=[0.579200,0.294419,0.251104] ref=[0.579200,0.294419,0.251104] delta=0.00e0
oklch(0.87, 0.15, 200): repo=[0.000000,0.945209,0.983945] ref=[0.000000,0.945209,0.983945] delta=0.00e0
oklch(0.269, 0.2, 90): repo=[0.289957,0.064028,0.000000] ref=[0.289957,0.064028,0.000000] delta=0.00e0
oklch(0.6, 0.05, 320): repo=[0.556399,0.466118,0.576902] ref=[0.556399,0.466118,0.576902] delta=0.00e0
max delta vs canonical spec = 0.000e0
one 8-bit color step (1/255) = 3.922e-3
Delta is exactly zero — the 7-significant-figure constants round to identical f32 values, so the two implementations are bit-for-bit the same. There is no color error here, and for a video editor that's the reassuring outcome.
So I would not swap in palette/oklab here. Adopting a crate would work, but it would be churn against correct code, and the current version already has unit tests covering the neutral endpoints. (One genuinely minor note, far below the threshold of a bug: linear_srgb_to_srgb applies the transfer function before clamping to gamut, where the spec clamps linear values first. The difference only shows at the very edges of out-of-gamut colors, and the final clamp catches it.)
Part 2 is real, and it affects both themes
chroma = 0.0 makes the hue argument mathematically irrelevant — a and b both collapse to zero, so r == g == b exactly:
The issue scopes this to the light theme, but chart_1 through chart_5 are all chroma: 0.0 in both blocks — lines 82-86 and 121-125. So dark mode is equally colorless.
For reference, shadcn/ui's default theme uses distinct hues for these (oklch(0.646 0.222 41.116) and friends), so the grayscale values look like a deliberate placeholder rather than an oversight.
Why I stopped here
I don't think I should push a specific palette. No chart component is rendered in the desktop app yet, so there are no pixels to validate a choice against, and picking hues is a design decision rather than a bug fix — which is exactly the kind of thing the current contribution freeze is about.
If you want the charts functional, the useful next step is a short decision on which values to use (shadcn defaults, a brand-derived set, or the brand/ directory if those colors are meant to carry through). Happy to implement whatever you pick.
Activity
killer1panda commentedon Sep 8, 2026
I've resolved the grayscale chart colors on my fork:
fix/desktop-theme-chart-colorsefc0440Changes
chart_1throughchart_5tokens in both desktopTheme::light/Theme::darkand webstyles.cssfrom monochrome gray (chroma=0) to distinct chromatic palettes matching standard shadcn OKLCH tokens.apps/desktop/src/theme.rsensuring chart colors across light and dark modes have distinct hues.rollroyces commentedon Oct 23, 2026
Part 1 of this issue doesn't hold up — part 2 does, and it's broader
I checked the OKLab math before acting on this, and half of it is based on a misreading of the code. Recording it so nobody spends time "fixing" correct color code.
The inverse transform matrix is the spec matrix
The constants in
apps/desktop/src/theme.rs:163-165are not an approximation. They're the published OKLab inverse matrix from the CSS Color 4 spec / Björn Ottosson's paper, written to 7 significant figures:4.076_741_74.076_741_66212.609_757_42.609_757_40111.707_614_71.707_614_7010I compiled the repo's
oklch_with_alphaalongside a reference implementation using the full-precision constants, and compared outputs across six colors spanning both axes:Delta is exactly zero — the 7-significant-figure constants round to identical
f32values, so the two implementations are bit-for-bit the same. There is no color error here, and for a video editor that's the reassuring outcome.So I would not swap in
palette/oklabhere. Adopting a crate would work, but it would be churn against correct code, and the current version already has unit tests covering the neutral endpoints. (One genuinely minor note, far below the threshold of a bug:linear_srgb_to_srgbapplies the transfer function before clamping to gamut, where the spec clamps linear values first. The difference only shows at the very edges of out-of-gamut colors, and the final clamp catches it.)Part 2 is real, and it affects both themes
chroma = 0.0makes the hue argument mathematically irrelevant —aandbboth collapse to zero, sor == g == bexactly:The issue scopes this to the light theme, but
chart_1throughchart_5are allchroma: 0.0in both blocks — lines 82-86 and 121-125. So dark mode is equally colorless.For reference, shadcn/ui's default theme uses distinct hues for these (
oklch(0.646 0.222 41.116)and friends), so the grayscale values look like a deliberate placeholder rather than an oversight.Why I stopped here
I don't think I should push a specific palette. No chart component is rendered in the desktop app yet, so there are no pixels to validate a choice against, and picking hues is a design decision rather than a bug fix — which is exactly the kind of thing the current contribution freeze is about.
If you want the charts functional, the useful next step is a short decision on which values to use (shadcn defaults, a brand-derived set, or the
brand/directory if those colors are meant to carry through). Happy to implement whatever you pick.