Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dark/light mode switch buttons in Options menu #1950

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 252 additions & 41 deletions frontend/css/style.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* Default (light) theme if no system override is detected, or system is light */
:root {
color-scheme: light;

/* Fonts */
--font-family: "Fira Sans", sans-serif;
--font-family-monospaced: "Fira Mono", monospace;
Expand Down Expand Up @@ -107,11 +110,12 @@
--help-sidebar-border: #eaeaea;
}

/* If user has no manual selection (no data-theme) AND system is dark, use these */
@media (prefers-color-scheme: dark) {
:root {
:root:not([data-theme]) {
color-scheme: dark;

/* Base colors */
/* Base colors (dark) */
--heading-color: #d7dce2;
--text-color: hsl(0deg 0% 75%);
--text-color-darker: hsl(0deg 0% 25%);
Expand Down Expand Up @@ -167,7 +171,7 @@
/* Query Editor */
--bql-keywords: #c678dd;
--bql-values: #98c379;
--bql-string: #ee5e5e; /* #e5c07b; */
--bql-string: #ee5e5e;
--bql-errors: var(--text-color-lighter);

/* Misc */
Expand All @@ -186,6 +190,164 @@
}
}

/* Explicit Light Mode (when data-theme="light") */
:root[data-theme="light"] {
color-scheme: light;

/* Base colors */
--heading-color: #333;
--text-color: hsl(0deg 0% 27%);
--text-color-lighter: hsl(0deg 0% 33%);
--text-color-lightest: hsl(0deg 0% 47%);
--link-color: hsl(203deg 100% 32%);
--link-hover-color: hsl(0deg 0% 33%);
--code-background: hsl(0deg 0% 97%);
--background: #fff;
--background-darker: hsl(0deg 0% 85%);
--border: hsl(0deg 0% 85%);
--border-darker: hsl(0deg 0% 80%);

/* Box shadows */
--box-shadow-button: 0 0 5px hsl(0deg 0% 50% / 50%);
--box-shadow-dropdown: 3px 3px 3px hsl(0deg 0% 50% / 50%);
--box-shadow-kbd: inset 0 -1px 0 var(--border-darker);
--box-shadow-overlay: 0 0 20px var(--overlay-wrapper-background);

/* Sidebar */
--sidebar-color: #444;
--sidebar-hover-color: var(--link-color);
--sidebar-background: hsl(0deg 0% 96%);
--sidebar-border: hsl(0deg 0% 87%);

/* Details */
--summary-background: hsl(0deg 0% 95%);
--summary-background-darker: hsl(0deg 0% 90%);

/* Header */
--header-color: #fff;
--header-background: hsl(203deg 100% 32%);
--header-placeholder-color: hsl(203deg 47% 66%);
--header-placeholder-background: hsl(203deg 56% 45%);

/* Tables */
--table-header-text: hsl(0deg 0% 40%);
--table-header-background: hsl(0deg 0% 90%);
--table-border: hsl(0deg 0% 90%);
--table-background-even: hsl(0deg 0% 95%);

/* Editor elements. */
--editor-activeline: #cef4;
--editor-selectionmatch: hsl(105deg 100% 73% / 50%);
--editor-account: var(--link-color);
--editor-class: #b84;
--editor-comment: #998;
--editor-constant: #008080;
--editor-currencies: #708;
--editor-date: #099;
--editor-directive: #333;
--editor-invalid-background: rgb(255 199 199 / 50%);
--editor-invalid: #333;
--editor-label-name: #221198;
--editor-number: #116543;
--editor-string: #a91111;

/* Query Editor */
--bql-keywords: #708;
--bql-values: #085;
--bql-string: #a11;
--bql-errors: #000;

/* Misc */
--placeholder-color: var(--text-color-lightest);
--placeholder-background: var(--background);
--mobile-button-text: #000;
--overlay-wrapper-background: rgb(0 0 0 / 50%);

/* Help pages */
--help-sidebar-background: #f8f8f8;
--help-sidebar-border: #eaeaea;
}

/* Explicit Dark Mode (when data-theme="dark") */
:root[data-theme="dark"] {
color-scheme: dark;

/* Base colors */
--heading-color: #d7dce2;
--text-color: hsl(0deg 0% 75%);
--text-color-darker: hsl(0deg 0% 25%);
--text-color-lighter: hsl(0deg 0% 85%);
--link-color: hsl(203deg 100% 70%);
--link-hover-color: hsl(0deg 0% 45%);
--code-background: hsl(0deg 0% 25%);
--background: hsl(200deg 6% 15%);
--background-darker: hsl(200deg 5% 30%);
--border: hsl(0deg 0% 35%);
--border-darker: hsl(0deg 0% 30%);

/* Box shadows */
--box-shadow-dropdown: 3px 3px 3px hsl(0deg 0% 25% / 50%);

/* Sidebar */
--sidebar-background: hsl(200deg 5% 18%);
--sidebar-color: hsl(0deg 0% 73%);
--sidebar-border: hsl(200deg 5% 25%);

/* Details */
--summary-background: hsl(0deg 0% 25%);
--summary-background-darker: hsl(0deg 0% 20%);

/* Header */
--header-color: #fff;
--header-background: hsl(203deg 100% 25%);

/* Tables */
--table-header-text: hsl(0deg 0% 80%);
--table-header-background: var(--sidebar-background);
--table-border: var(--sidebar-border);
--table-background-even: hsl(0deg 0% 18%);

/* Editor elements. */
--editor-activeline: #44535b44;
--editor-selectionmatch: hsl(105deg 100% 30% / 50%);
--editor-account: var(--link-color);
--editor-class: #e1a759;
--editor-comment: #998;
--editor-constant: #02a0a0;
--editor-currencies: #cd00e8;
--editor-date: #0ad3d3;
--editor-directive: #c6c6c6;
--editor-invalid-background: rgb(176 82 82 / 50%);
--editor-invalid: #d5c5c5;
--editor-label-name: #9c90f6;
--editor-number: #00b672;
--editor-string: #e87f7f;

/* Query Editor */
--bql-keywords: #c678dd;
--bql-values: #98c379;
--bql-string: #ee5e5e;
--bql-errors: var(--text-color-lighter);

/* Misc */
--placeholder-color: var(--text-color-lighter);
--placeholder-background: hsl(222deg 7% 29%);
--mobile-button-text: #cacaca;
--overlay-wrapper-background: rgb(0 0 0 / 50%);

/* Help pages */
--help-sidebar-background: #3b3b3b;
--help-sidebar-border: #2a2a2a;

input,
textarea {
background: var(--placeholder-background);
}
}

/* ----------------------------------------------------------------------------
Journal classes for default or light mode
-------------------------------------------------------------------------- */
.journal .balance {
--entry-background: hsl(120deg 100% 90%);
}
Expand Down Expand Up @@ -240,55 +402,104 @@
--journal-hover-highlight: hsl(0deg 0% 90% / 60%);
}

/* Fallback for system dark (no data-theme) - override journal colors */
@media (prefers-color-scheme: dark) {
:root {
.journal .balance {
--entry-background: hsl(120deg 50% 15%);
}
:root:not([data-theme]) .journal .balance {
--entry-background: hsl(120deg 50% 15%);
}

.journal .close {
--entry-background: hsl(0deg 0% 15%);
}
:root:not([data-theme]) .journal .close {
--entry-background: hsl(0deg 0% 15%);
}

.journal .custom {
--entry-background: hsl(52deg 100% 15%);
}
:root:not([data-theme]) .journal .custom {
--entry-background: hsl(52deg 100% 15%);
}

.journal .document {
--entry-background: hsl(300deg 45% 25%);
}
:root:not([data-theme]) .journal .document {
--entry-background: hsl(300deg 45% 25%);
}

.journal .note {
--entry-background: hsl(212deg 43% 25%);
}
:root:not([data-theme]) .journal .note {
--entry-background: hsl(212deg 43% 25%);
}

.journal .open {
--entry-background: hsl(0deg 0% 20%);
}
:root:not([data-theme]) .journal .open {
--entry-background: hsl(0deg 0% 20%);
}

.journal .other {
--entry-background: hsl(180deg 100% 25%);
}
:root:not([data-theme]) .journal .other {
--entry-background: hsl(180deg 100% 25%);
}

.journal .pad {
--entry-background: hsl(180deg 100% 15%);
}
:root:not([data-theme]) .journal .pad {
--entry-background: hsl(180deg 100% 15%);
}

.journal .pending {
--entry-background: hsl(343deg 60% 20%);
}
:root:not([data-theme]) .journal .pending {
--entry-background: hsl(343deg 60% 20%);
}

.journal .query {
--entry-background: hsl(213deg 100% 25%);
}
:root:not([data-theme]) .journal .query {
--entry-background: hsl(213deg 100% 25%);
}

.journal .budget {
--entry-background: hsl(35deg 100% 20%);
}
:root:not([data-theme]) .journal .budget {
--entry-background: hsl(35deg 100% 20%);
}

.journal {
--journal-postings: hsl(0deg 0% 10%);
--journal-hover-highlight: hsl(0deg 0% 20% / 60%);
}
:root:not([data-theme]) .journal {
--journal-postings: hsl(0deg 0% 10%);
--journal-hover-highlight: hsl(0deg 0% 20% / 60%);
}
}

/* Explicit dark mode overrides for journal classes */
:root[data-theme="dark"] .journal .balance {
--entry-background: hsl(120deg 50% 15%);
}

:root[data-theme="dark"] .journal .close {
--entry-background: hsl(0deg 0% 15%);
}

:root[data-theme="dark"] .journal .custom {
--entry-background: hsl(52deg 100% 15%);
}

:root[data-theme="dark"] .journal .document {
--entry-background: hsl(300deg 45% 25%);
}

:root[data-theme="dark"] .journal .note {
--entry-background: hsl(212deg 43% 25%);
}

:root[data-theme="dark"] .journal .open {
--entry-background: hsl(0deg 0% 20%);
}

:root[data-theme="dark"] .journal .other {
--entry-background: hsl(180deg 100% 25%);
}

:root[data-theme="dark"] .journal .pad {
--entry-background: hsl(180deg 100% 15%);
}

:root[data-theme="dark"] .journal .pending {
--entry-background: hsl(343deg 60% 20%);
}

:root[data-theme="dark"] .journal .query {
--entry-background: hsl(213deg 100% 25%);
}

:root[data-theme="dark"] .journal .budget {
--entry-background: hsl(35deg 100% 20%);
}

:root[data-theme="dark"] .journal {
--journal-postings: hsl(0deg 0% 10%);
--journal-hover-highlight: hsl(0deg 0% 20% / 60%);
}
8 changes: 8 additions & 0 deletions frontend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ function init(): void {
});

router.trigger("page-loaded");


const storedTheme = localStorage.getItem("theme") ?? "auto";
if (storedTheme === "auto") {
document.documentElement.removeAttribute("data-theme");
} else {
document.documentElement.setAttribute("data-theme", storedTheme);
}
}

init();
6 changes: 6 additions & 0 deletions frontend/src/reports/options/Options.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
import { urlFor } from "../../helpers";
import { _ } from "../../i18n";
import OptionsTable from "./OptionsTable.svelte";
import ThemeToggle from "./ThemeToggle.svelte";

export let fava_options: Record<string, string>;
export let beancount_options: Record<string, string>;
</script>

<h2>
{_("Theme style")}
</h2>
<ThemeToggle />

<h2>
{_("Fava options")}
<a href={$urlFor("help/options")}>({_("help")})</a>
Expand Down
Loading
Loading