migrate the majority of the sass vars to css variables

Allows add-ons to easily override the theme, and allows us to apply
styling to elements outside of the normal document flow (like applying
the normal background colour to a position: fixed element).
This commit is contained in:
Damien Elmes 2020-08-27 15:57:24 +10:00
parent ab32623dde
commit 2d26280dab
13 changed files with 177 additions and 138 deletions

View file

@ -52,7 +52,7 @@ all: check
./scripts/copy-qt-files) ./scripts/copy-qt-files)
@touch $@ @touch $@
TSDEPS := $(wildcard ts/src/*.ts) $(wildcard ts/scss/*.scss) TSDEPS := $(wildcard ts/src/*.ts) $(wildcard ts/scss/*.scss) $(wildcard ../ts/src/scss/*)
.build/js: $(TSDEPS) .build/js: $(TSDEPS)
(cd ts && make build) (cd ts && make build)

View file

@ -182,7 +182,7 @@ QTabWidget { background-color: %s; }
palette.setColor(QPalette.Window, window_bg) palette.setColor(QPalette.Window, window_bg)
palette.setColor(QPalette.AlternateBase, window_bg) palette.setColor(QPalette.AlternateBase, window_bg)
palette.setColor(QPalette.Button, QColor(colors.get("fusion-button-base-bg"))) palette.setColor(QPalette.Button, QColor("#454545"))
frame_bg = self.qcolor("frame-bg") frame_bg = self.qcolor("frame-bg")
palette.setColor(QPalette.Base, frame_bg) palette.setColor(QPalette.Base, frame_bg)

View file

@ -359,45 +359,28 @@ class AnkiWebView(QWebEngineView):
return QColor("#ececec") return QColor("#ececec")
return self.style().standardPalette().color(QPalette.Window) return self.style().standardPalette().color(QPalette.Window)
def stdHtml( def standard_css(self) -> str:
self,
body: str,
css: Optional[List[str]] = None,
js: Optional[List[str]] = None,
head: str = "",
context: Optional[Any] = None,
):
web_content = WebContent(
body=body,
head=head,
js=["webview.js"] + (["jquery.js"] if js is None else js),
css=["webview.css"] + ([] if css is None else css),
)
gui_hooks.webview_will_set_content(web_content, context)
palette = self.style().standardPalette() palette = self.style().standardPalette()
color_hl = palette.color(QPalette.Highlight).name() color_hl = palette.color(QPalette.Highlight).name()
if isWin: if isWin:
# T: include a font for your language on Windows, eg: "Segoe UI", "MS Mincho" # T: include a font for your language on Windows, eg: "Segoe UI", "MS Mincho"
family = _('"Segoe UI"') family = _('"Segoe UI"')
widgetspec = "button { font-family:%s; }" % family button_style = "button { font-family:%s; }" % family
widgetspec += "\n:focus { outline: 1px solid %s; }" % color_hl button_style += "\n:focus { outline: 1px solid %s; }" % color_hl
fontspec = "font-size:12px;font-family:%s;" % family font = "font-size:12px;font-family:%s;" % family
elif isMac: elif isMac:
family = "Helvetica" family = "Helvetica"
fontspec = 'font-size:15px;font-family:"%s";' % family font = 'font-size:15px;font-family:"%s";' % family
widgetspec = """ button_style = """
button { -webkit-appearance: none; background: #fff; border: 1px solid #ccc; button { -webkit-appearance: none; background: #fff; border: 1px solid #ccc;
border-radius:5px; font-family: Helvetica }""" border-radius:5px; font-family: Helvetica }"""
else: else:
family = self.font().family() family = self.font().family()
color_hl_txt = palette.color(QPalette.HighlightedText).name() color_hl_txt = palette.color(QPalette.HighlightedText).name()
color_btn = palette.color(QPalette.Button).name() color_btn = palette.color(QPalette.Button).name()
fontspec = 'font-size:14px;font-family:"%s";' % family font = 'font-size:14px;font-family:"%s";' % family
widgetspec = """ button_style = """
/* Buttons */ /* Buttons */
button{ button{
background-color: %(color_btn)s; background-color: %(color_btn)s;
@ -416,45 +399,70 @@ div[contenteditable="true"]:focus {
"color_hl_txt": color_hl_txt, "color_hl_txt": color_hl_txt,
} }
csstxt = "\n".join(self.bundledCSS(fname) for fname in web_content.css) zoom = self.zoomFactor()
jstxt = "\n".join(self.bundledScript(fname) for fname in web_content.js) background = self._getWindowColor().name()
from aqt import mw
head = mw.baseHTML() + csstxt + jstxt + web_content.head
body_class = theme_manager.body_class()
if is_rtl(anki.lang.currentLang): if is_rtl(anki.lang.currentLang):
lang_dir = "rtl" lang_dir = "rtl"
else: else:
lang_dir = "ltr" lang_dir = "ltr"
html = """ return f"""
<!doctype html> body {{ zoom: {zoom}; background: {background}; direction: {lang_dir}; {font} }}
<html><head> {button_style}
<title>{}</title> :root {{ --window-bg: {background} }}
"""
<style> def stdHtml(
body {{ zoom: {}; background: {}; direction: {}; {} }} self,
{} body: str,
</style> css: Optional[List[str]] = None,
js: Optional[List[str]] = None,
{} head: str = "",
context: Optional[Any] = None,
):
web_content = WebContent(
body=body,
head=head,
js=["webview.js"] + (["jquery.js"] if js is None else js),
css=["webview.css"] + ([] if css is None else css),
)
gui_hooks.webview_will_set_content(web_content, context)
csstxt = ""
if "webview.css" in web_content.css:
# we want our dynamic styling to override the defaults in
# webview.css, but come before user-provided stylesheets so that
# they can override us if necessary
web_content.css.remove("webview.css")
csstxt = self.bundledCSS("webview.css")
csstxt += f"<style>{self.standard_css()}</style>"
csstxt += "\n".join(self.bundledCSS(fname) for fname in web_content.css)
jstxt = "\n".join(self.bundledScript(fname) for fname in web_content.js)
from aqt import mw
head = mw.baseHTML() + csstxt + jstxt + web_content.head
body_class = theme_manager.body_class()
if theme_manager.night_mode:
doc_class = "night-mode"
else:
doc_class = ""
html = f"""
<!doctype html>
<html class="{doc_class}">
<head>
<title>{self.title}</title>
{head}
</head> </head>
<body class="{}">{}</body> <body class="{body_class}">{web_content.body}</body>
</html>""".format( </html>"""
self.title,
self.zoomFactor(),
self._getWindowColor().name(),
lang_dir,
fontspec,
widgetspec,
head,
body_class,
web_content.body,
)
# print(html) # print(html)
self.setHtml(html) self.setHtml(html)

View file

@ -1,4 +1,10 @@
@use 'vars'; /* night-mode-specific colours */
$fusion-button-gradient-start: #555555;
$fusion-button-gradient-end: #656565;
$fusion-button-outline: #222222;
$fusion-button-hover-bg: #656565;
$fusion-button-border: #646464;
$fusion-button-base-bg: #454545;
.isWin { .isWin {
button { button {
@ -19,21 +25,21 @@
-webkit-appearance: none; -webkit-appearance: none;
border-radius: 3px; border-radius: 3px;
padding: 5px; padding: 5px;
border: 1px solid vars.$day-border; border: 1px solid var(--border);
} }
} }
.nightMode { .nightMode {
button { button {
-webkit-appearance: none; -webkit-appearance: none;
color: vars.$night-text-fg; color: var(--text-fg);
/* match the fusion button gradient */ /* match the fusion button gradient */
background: linear-gradient(0deg, background: linear-gradient(0deg,
vars.$fusion-button-gradient-start 0%, $fusion-button-gradient-start 0%,
vars.$fusion-button-gradient-end 100%); $fusion-button-gradient-end 100%);
box-shadow: 0 0 3px vars.$fusion-button-outline; box-shadow: 0 0 3px $fusion-button-outline;
border: 1px solid vars.$fusion-button-border; border: 1px solid $fusion-button-border;
border-radius: 2px; border-radius: 2px;
padding: 10px; padding: 10px;
@ -42,7 +48,7 @@
} }
button:hover { button:hover {
background: vars.$fusion-button-hover-bg; background: $fusion-button-hover-bg;
} }
} }

View file

@ -1,36 +1,34 @@
@use 'vars';
.review-count { .review-count {
color: vars.$day-review-count; color: var(--review-count);
} }
.new-count { .new-count {
color: vars.$day-new-count; color: var(--new-count);
} }
.learn-count { .learn-count {
color: vars.$day-learn-count; color: var(--learn-count);
} }
.zero-count { .zero-count {
color: vars.$day-zero-count; color: var(--zero-count);
} }
.nightMode { .nightMode {
.review-count { .review-count {
color: vars.$night-review-count; color: var(--review-count);
} }
.new-count { .new-count {
color: vars.$night-new-count; color: var(--new-count);
} }
.learn-count { .learn-count {
color: vars.$night-learn-count; color: var(--learn-count);
} }
.zero-count { .zero-count {
color: vars.$night-zero-count; color: var(--zero-count);
} }
} }

View file

@ -1,11 +1,10 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
@use 'card_counts'; @use 'card_counts';
a.deck { a.deck {
color: vars.$day-text-fg; color: var(--text-fg);
text-decoration: none; text-decoration: none;
min-width: 5em; min-width: 5em;
display: inline-block; display: inline-block;
@ -16,7 +15,7 @@ a.deck:hover {
} }
tr.deck td { tr.deck td {
border-bottom: 1px solid vars.$day-faint-border; border-bottom: 1px solid var(--faint-border);
} }
tr.top-level-drag-row td { tr.top-level-drag-row td {
@ -28,7 +27,7 @@ td {
} }
tr.drag-hover td { tr.drag-hover td {
border-bottom: 1px solid vars.$day-border; border-bottom: 1px solid var(--border);
} }
body { body {
@ -37,7 +36,7 @@ body {
} }
.current { .current {
background-color: vars.$day-faint-border; background-color: var(--faint-border);
} }
.decktd { .decktd {
@ -54,14 +53,14 @@ body {
} }
.collapse { .collapse {
color: vars.$day-text-fg; color: var(--text-fg);
text-decoration: none; text-decoration: none;
display: inline-block; display: inline-block;
width: 1em; width: 1em;
} }
.filtered { .filtered {
color: vars.$day-link !important; color: var(--link) !important;
} }
.gears { .gears {
@ -73,23 +72,23 @@ body {
.nightMode { .nightMode {
a.deck { a.deck {
color: vars.$night-text-fg; color: var(--text-fg);
} }
tr.deck td { tr.deck td {
border-bottom-color: vars.$night-faint-border; border-bottom-color: var(--faint-border);
} }
tr.drag-hover td { tr.drag-hover td {
border-bottom-color: vars.$night-border; border-bottom-color: var(--border);
} }
.current { .current {
background-color: vars.$night-faint-border; background-color: var(--faint-border);
} }
.collapse { .collapse {
color: vars.$night-text-fg; color: var(--text-fg);
} }
.gears { .gears {
@ -97,7 +96,7 @@ body {
} }
.filtered { .filtered {
color: vars.$night-link !important; color: var(--link) !important;
} }
} }

View file

@ -1,12 +1,10 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
.field { .field {
border: 1px solid vars.$day-border; border: 1px solid var(--border);
background: vars.$day-frame-bg; background: var(--frame-bg);
color: vars.$day-text-fg; color: var(--text-fg);
padding: 5px; padding: 5px;
overflow-wrap: break-word; overflow-wrap: break-word;
overflow: auto; overflow: auto;
@ -75,14 +73,14 @@ button.highlighted {
} }
.dupe { .dupe {
background: vars.$day-flag1-bg; background: var(--flag1-bg);
} }
.nightMode { .nightMode {
.field { .field {
border-color: vars.$night-border; border-color: var(--border);
background: vars.$night-frame-bg; background: var(--frame-bg);
color: vars.$night-text-fg; color: var(--text-fg);
} }
button.linkb > img { button.linkb > img {
@ -90,11 +88,11 @@ button.highlighted {
} }
.dupe { .dupe {
background: vars.$night-flag1-bg; background: var(--flag1-bg);
} }
#dupes a { #dupes a {
color: vars.$night-link; color: var(--link);
} }
} }

View file

@ -1,7 +1,6 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
@use 'card_counts'; @use 'card_counts';
.smallLink { .smallLink {
@ -14,7 +13,7 @@ h3 {
.descfont { .descfont {
padding: 1em; padding: 1em;
color: vars.$day-slightly-grey-text; color: var(--slightly-grey-text);
} }
.description { .description {
@ -37,6 +36,6 @@ h3 {
.nightMode { .nightMode {
.descfont { .descfont {
color: vars.$night-slightly-grey-text; color: var(--slightly-grey-text);
} }
} }

View file

@ -1,7 +1,6 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
@use 'card_counts'; @use 'card_counts';
body { body {
@ -51,7 +50,7 @@ button {
} }
#outer { #outer {
border-top: 1px solid vars.$day-border; border-top: 1px solid var(--border);
} }
#innertable { #innertable {
@ -60,6 +59,6 @@ button {
.nightMode { .nightMode {
#outer { #outer {
border-top-color: vars.$night-faint-border; border-top-color: var(--faint-border);
} }
} }

View file

@ -1,8 +1,6 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
hr { hr {
background-color: #ccc; background-color: #ccc;
} }
@ -13,8 +11,8 @@ body {
} }
body.nightMode { body.nightMode {
background-color: vars.$night-window-bg; background-color: var(--window-bg);
color: vars.$night-text-fg; color: var(--text-fg);
} }
img { img {

View file

@ -1,12 +1,10 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use 'vars';
#header { #header {
padding: 3px; padding: 3px;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid vars.$day-border; border-bottom: 1px solid var(--border);
} }
.tdcenter { .tdcenter {
@ -28,7 +26,7 @@ body {
padding-right: 12px; padding-right: 12px;
padding-left: 12px; padding-left: 12px;
text-decoration: none; text-decoration: none;
color: vars.$day-text-fg; color: var(--text-fg);
} }
.hitem:hover { .hitem:hover {
@ -39,24 +37,24 @@ body {
.nightMode { .nightMode {
.hitem { .hitem {
color: vars.$night-text-fg; color: var(--text-fg);
} }
#header { #header {
border-bottom-color: vars.$night-faint-border; border-bottom-color: var(--faint-border);
} }
.normal-sync { .normal-sync {
color: vars.$night-new-count; color: var(--new-count);
} }
.full-sync { .full-sync {
color: vars.$night-learn-count; color: var(--learn-count);
} }
} }
.isMac.nightMode #header { .isMac.nightMode #header {
border-bottom-color: vars.$night-frame-bg; border-bottom-color: var(--frame-bg);
} }
@keyframes spin { @keyframes spin {
@ -81,11 +79,11 @@ body {
} }
.normal-sync { .normal-sync {
color: vars.$day-new-count; color: var(--new-count);
} }
.full-sync { .full-sync {
color: vars.$day-learn-count; color: var(--learn-count);
} }

View file

@ -6,11 +6,8 @@
body { body {
margin: 2em; margin: 2em;
color: vars.$day-text-fg; color: var(--text-fg);
background: var(--window-bg);
// currently this is injected via webview.py to try to match the
// system background color
// background: vars.$day-window-bg;
} }
h1 { h1 {
@ -18,16 +15,16 @@ h1 {
} }
a { a {
color: vars.$day-link; color: var(--link);
} }
body.nightMode { body.nightMode {
color: vars.$night-text-fg; color: var(--text-fg);
background: vars.$night-window-bg; background: var(--window-bg);
} }
body.nightMode::-webkit-scrollbar { body.nightMode::-webkit-scrollbar {
background: vars.$night-window-bg; background: var(--window-bg);
} }
body.nightMode::-webkit-scrollbar:horizontal { body.nightMode::-webkit-scrollbar:horizontal {
@ -39,7 +36,7 @@ body.nightMode::-webkit-scrollbar:vertical {
} }
body.nightMode::-webkit-scrollbar-thumb { body.nightMode::-webkit-scrollbar-thumb {
background: vars.$fusion-button-hover-bg; background: buttons.$fusion-button-hover-bg;
border-radius: 8px; border-radius: 8px;
} }
@ -53,7 +50,7 @@ body.nightMode::-webkit-scrollbar-thumb:vertical {
.nightMode { .nightMode {
a { a {
color: vars.$night-link; color: var(--link);
} }
} }

View file

@ -40,10 +40,49 @@ $night-flag4-bg: #3581a9;
$night-suspended-bg: #aaaa33; $night-suspended-bg: #aaaa33;
$night-marked-bg: #77c; $night-marked-bg: #77c;
/* night-mode-specific colours */
$fusion-button-gradient-start: #555555; :root {
$fusion-button-gradient-end: #656565; --text-fg: #{$day-text-fg};
$fusion-button-outline: #222222; --window-bg: #{$day-window-bg};
$fusion-button-hover-bg: #656565; --frame-bg: #{$day-frame-bg};
$fusion-button-border: #646464; --border: #{$day-border};
$fusion-button-base-bg: #454545; --faint-border: #{$day-faint-border};
--link: #{$day-link};
--review-count: #{$day-review-count};
--new-count: #{$day-new-count};
--learn-count: #{$day-learn-count};
--zero-count: #{$day-zero-count};
--slightly-grey-text: #{$day-slightly-grey-text};
--highlight-bg: #{$day-highlight-bg};
--highlight-fg: #{$day-highlight-fg};
--disabled: #{$day-disabled};
--flag1-bg: #{$day-flag1-bg};
--flag2-bg: #{$day-flag2-bg};
--flag3-bg: #{$day-flag3-bg};
--flag4-bg: #{$day-flag4-bg};
--suspended-bg: #{$day-suspended-bg};
--marked-bg: #{$day-marked-bg};
}
:root[class*="night-mode"] {
--text-fg: #{$night-text-fg};
--window-bg: #{$night-window-bg};
--frame-bg: #{$night-frame-bg};
--border: #{$night-border};
--faint-border: #{$night-faint-border};
--link: #{$night-link};
--review-count: #{$night-review-count};
--new-count: #{$night-new-count};
--learn-count: #{$night-learn-count};
--zero-count: #{$night-zero-count};
--slightly-grey-text: #{$night-slightly-grey-text};
--highlight-bg: #{$night-highlight-bg};
--highlight-fg: #{$night-highlight-fg};
--disabled: #{$night-disabled};
--flag1-bg: #{$night-flag1-bg};
--flag2-bg: #{$night-flag2-bg};
--flag3-bg: #{$night-flag3-bg};
--flag4-bg: #{$night-flag4-bg};
--suspended-bg: #{$night-suspended-bg};
--marked-bg: #{$night-marked-bg};
}