Skip to content

feat(desktop): custom theme system — user-editable color variables, named themes, cross-device sync - #730

Draft
h4yfans wants to merge 10 commits into
mainfrom
custom-themes
Draft

feat(desktop): custom theme system — user-editable color variables, named themes, cross-device sync#730
h4yfans wants to merge 10 commits into
mainfrom
custom-themes

Conversation

@h4yfans

@h4yfans h4yfans commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

What

  • Custom themes: fork a built-in base (Warm/White/Dark), override any of ~65 theme color variables (surfaces, hover, text tones, sidebar, accent, graph, tasks, queue…) from Settings → Appearance with hex input + color picker, live preview, debounced autosave
  • Per-theme .memry/themes/<slug>.json in the vault + additive custom_themes table (migration 0035) as sync/clock source of truth
  • New theme sync item type (whole-item LWW per theme) + general.customThemeId synced field; theme stays at the base value so older clients render the base theme
  • FOUC-free startup via localStorage override cache read in preload

Notes

  • Sync-server must deploy before the desktop release that ships this (old servers filter record queries by their compiled-in type list)
  • Not yet verified live in Electron / two-profile sync; no E2E yet

@github-actions github-actions Bot added dependencies documentation Improvements or additions to documentation enhancement New feature or request test labels Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

React Doctor found 2 new issues in 1 file · 2 warnings · score 92 / 100 (Great) · 0 fixed · vs main

2 warnings

src/renderer/src/components/settings/custom-themes-section.tsx

  • ⚠️ L60 Missing effect dependencies exhaustive-deps
  • ⚠️ L148 Missing effect dependencies exhaustive-deps

Reviewed by React Doctor for commit f86844e. See inline comments for fixes.

clearCustomThemeVariables(root)

expect(root.style.getPropertyValue('--background')).toBe('')
expect(clearCustomThemeVariables(root)).toBeUndefined()
const fallback = useMemo(
() => computedVarValue(def.cssVar),
// Re-read the base value whenever the override toggles off.
[def.cssVar, override]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/exhaustive-deps (warning)

useMemo re-runs whenever override changes even though it never uses it.

Fix → Don't blindly add missing dependencies. Read the hook callback first.

Bad:
useEffect(() => {
setCount(count + 1);
}, [count]);

Better:
useEffect(() => {
setCount((currentCount) => currentCount + 1);
}, []);

If the missing value is recreated every render, move it inside the hook or stabilize it before adding it to deps.

Docs

useEffect(() => {
setName(theme.name)
setVariables(theme.variables)
}, [theme.id])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/exhaustive-deps (warning)

useEffect can run with a stale theme.name, theme.variables & show your users old data.

Fix → Don't blindly add missing dependencies. Read the hook callback first.

Bad:
useEffect(() => {
setCount(count + 1);
}, [count]);

Better:
useEffect(() => {
setCount((currentCount) => currentCount + 1);
}, []);

If the missing value is recreated every render, move it inside the hook or stabilize it before adding it to deps.

Docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies documentation Improvements or additions to documentation enhancement New feature or request test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant