mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Auto-hide toolbar in Reviewer (#2262)
* Give webviews a slide-in animation if reduced motion isn't set. * Auto-hide toolbar in review mode moving the mouse above the main webview expands the toolbar. When the mouse leaves the toolbar, it will collapse after a delay of 2s. * Save some space on bottom toolbars * Use props for all hard-coded transition durations and decrease most commonly used duration (200ms) to 150ms. * Move auto-hide logic into ToolbarWebView and handle auto-hide specific events in the respective webview subclasses. * Fix typing issues * Fix flickering issue * Add auto_hide_toolbar opt-in to preferences * Rename hide_toolbar to collapse_toolbar to better describe the dock-like behaviour. * Rename setting to minimize_distractions * Reduce calls to pm in eventFilter * Run formatter * Revert setting title to something more specific * Increase default animation time to 180ms * Inset toolbar in review mode when auto-hide is not enabled. * Use card background on toolbar and add glass effect * Use flatten/elevate over inset/outset * Use flatten/elevate over inset/outset * Update toolbar.py * Fix toolbar background delay * Tweak styles * Use "collapse" instead of "auto-hide" * Fix background misalignment in collapse mode * Do not collapse toolbar when pointer is outside MainWebView * Reduce hide_timer interval to 1000ms * Use CSS to hide toolbar instead of setting webview height * Add guard to prevent backdrop-filter: blur on Qt 5.14 * Apply transition to body instead of toolbar to not complicate things for #2301. * Fix Qt 5.14 and apply guard globally * Fix background image scaling difference * Tweak preference wording (dae)
This commit is contained in:
parent
afca2f52ce
commit
9f8667fb47
29 changed files with 236 additions and 59 deletions
|
@ -48,3 +48,4 @@ preferences-monthly-backups = Monthly backups to keep:
|
|||
preferences-minutes-between-backups = Minutes between automatic backups:
|
||||
preferences-reduce-motion = Reduce motion
|
||||
preferences-reduce-motion-tooltip = Disable various animations and transitions of the user interface
|
||||
preferences-collapse-toolbar = Hide top bar during review
|
||||
|
|
|
@ -15,7 +15,9 @@ table {
|
|||
&:hover {
|
||||
@include elevation(2);
|
||||
}
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
transition: box-shadow var(--transition) ease-in-out;
|
||||
background: var(--canvas-glass);
|
||||
backdrop-filter: blur(var(--blur));
|
||||
}
|
||||
|
||||
a.deck {
|
||||
|
|
|
@ -18,10 +18,6 @@ body {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
#innertable {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#middle td[align="center"] {
|
||||
padding-top: 10px;
|
||||
position: relative;
|
||||
|
@ -30,7 +26,7 @@ body {
|
|||
button {
|
||||
min-width: 60px;
|
||||
white-space: nowrap;
|
||||
margin: 0.5em;
|
||||
margin: 9px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
@ -51,10 +47,6 @@ button {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
#ansbut {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
:focus {
|
||||
border-color: color(border-focus);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#header {
|
||||
border-bottom: 0;
|
||||
margin-bottom: 6px;
|
||||
margin-top: 0;
|
||||
padding: 9px;
|
||||
}
|
||||
|
|
|
@ -6,25 +6,27 @@
|
|||
@use "sass/elevation" as *;
|
||||
@use "sass/button-mixins" as button;
|
||||
|
||||
#header {
|
||||
padding-bottom: 4px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.tdcenter {
|
||||
.toolbar {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
border-radius: prop(border-radius);
|
||||
overflow: hidden;
|
||||
border-bottom-left-radius: prop(border-radius-large);
|
||||
border-bottom-right-radius: prop(border-radius-large);
|
||||
@include button.base($with-hover: false, $with-active: false);
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
@include elevation(1, $opacity-boost: -0.1);
|
||||
|
||||
@include elevation(1, $opacity-boost: -0.08);
|
||||
&:hover {
|
||||
@include elevation(2);
|
||||
// elevated state (deck browser, overview)
|
||||
body:not(.flat) & {
|
||||
background: var(--canvas-elevated);
|
||||
@include elevation(1);
|
||||
&:hover {
|
||||
@include elevation(2);
|
||||
}
|
||||
}
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
// glass effect
|
||||
background: var(--canvas-glass);backdrop-filter: unset;
|
||||
backdrop-filter: blur(var(--blur));
|
||||
|
||||
transition: all var(--transition) ease-in-out;
|
||||
}
|
||||
|
||||
body {
|
||||
|
@ -32,6 +34,11 @@ body {
|
|||
padding: 0;
|
||||
-webkit-user-select: none;
|
||||
overflow: hidden;
|
||||
|
||||
&.collapsed {
|
||||
transform: translateY(-100vh);
|
||||
}
|
||||
transition: transform var(--transition) ease-in-out;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -40,12 +47,16 @@ body {
|
|||
|
||||
.hitem {
|
||||
font-weight: bold;
|
||||
padding: 8px 14px;
|
||||
padding: 6px 12px 8px;
|
||||
text-decoration: none;
|
||||
color: color(fg);
|
||||
display: inline-block;
|
||||
@include button.base;
|
||||
border: none;
|
||||
|
||||
body:not(.flat) &,
|
||||
&:hover {
|
||||
@include button.base($border: false);
|
||||
background: var(--canvas-elevated);
|
||||
}
|
||||
&:first-child {
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
@ -75,7 +86,7 @@ body {
|
|||
display: inline-block;
|
||||
visibility: visible !important;
|
||||
animation-timing-function: linear;
|
||||
transition: all 0.2s ease-in;
|
||||
transition: all var(--transition) ease-in;
|
||||
}
|
||||
|
||||
#sync-spinner {
|
||||
|
|
|
@ -15,13 +15,21 @@
|
|||
body {
|
||||
color: var(--fg);
|
||||
background: var(--canvas);
|
||||
transition: opacity 0.5s ease-out;
|
||||
transition: opacity var(--transition-medium) ease-out;
|
||||
margin: 2em;
|
||||
overscroll-behavior: none;
|
||||
&:not(.isMac),
|
||||
&:not(.isMac) * {
|
||||
@include scrollbar.custom;
|
||||
}
|
||||
&.reduced-motion,
|
||||
&.reduced-motion * {
|
||||
transition: none !important;
|
||||
animation: none !important;
|
||||
}
|
||||
&.no-blur * {
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>640</width>
|
||||
<height>640</height>
|
||||
<height>660</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -113,6 +113,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="collapse_toolbar">
|
||||
<property name="text">
|
||||
<string>preferences_collapse_toolbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="useCurrent">
|
||||
<item>
|
||||
|
@ -666,7 +673,7 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignCenter">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>preferences_some_settings_will_take_effect_after</string>
|
||||
|
@ -696,6 +703,7 @@
|
|||
<tabstop>ignore_accents_in_search</tabstop>
|
||||
<tabstop>legacy_import_export</tabstop>
|
||||
<tabstop>reduce_motion</tabstop>
|
||||
<tabstop>collapse_toolbar</tabstop>
|
||||
<tabstop>useCurrent</tabstop>
|
||||
<tabstop>default_search_text</tabstop>
|
||||
<tabstop>uiScale</tabstop>
|
||||
|
|
|
@ -66,6 +66,7 @@ from aqt.qt import sip
|
|||
from aqt.sync import sync_collection, sync_login
|
||||
from aqt.taskman import TaskManager
|
||||
from aqt.theme import Theme, theme_manager
|
||||
from aqt.toolbar import Toolbar, ToolbarWebView
|
||||
from aqt.undo import UndoActionsInfo
|
||||
from aqt.utils import (
|
||||
HelpPage,
|
||||
|
@ -143,6 +144,27 @@ class MainWebView(AnkiWebView):
|
|||
# currently safe for us to import more than one file at once
|
||||
return
|
||||
|
||||
# Main webview specific event handling
|
||||
def eventFilter(self, obj, evt):
|
||||
if handled := super().eventFilter(obj, evt):
|
||||
return handled
|
||||
|
||||
if evt.type() == QEvent.Type.Leave:
|
||||
if self.mw.pm.collapse_toolbar():
|
||||
# Expand toolbar when mouse moves above main webview
|
||||
# and automatically collapse it with delay after mouse leaves
|
||||
if self.mapFromGlobal(QCursor.pos()).y() < self.geometry().y():
|
||||
if self.mw.toolbarWeb.collapsed:
|
||||
self.mw.toolbarWeb.expand()
|
||||
return True
|
||||
|
||||
if evt.type() == QEvent.Type.Enter:
|
||||
if self.mw.pm.collapse_toolbar():
|
||||
self.mw.toolbarWeb.hide_timer.start()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AnkiQt(QMainWindow):
|
||||
col: Collection
|
||||
|
@ -707,10 +729,16 @@ class AnkiQt(QMainWindow):
|
|||
|
||||
def _reviewState(self, oldState: MainWindowState) -> None:
|
||||
self.reviewer.show()
|
||||
if self.pm.collapse_toolbar():
|
||||
self.toolbarWeb.collapse()
|
||||
else:
|
||||
self.toolbarWeb.flatten()
|
||||
|
||||
def _reviewCleanup(self, newState: MainWindowState) -> None:
|
||||
if newState != "resetRequired" and newState != "review":
|
||||
self.reviewer.cleanup()
|
||||
self.toolbarWeb.elevate()
|
||||
self.toolbarWeb.expand()
|
||||
|
||||
# Resetting state
|
||||
##########################################################################
|
||||
|
@ -844,10 +872,8 @@ title="{}" {}>{}</button>""".format(
|
|||
self.form = aqt.forms.main.Ui_MainWindow()
|
||||
self.form.setupUi(self)
|
||||
# toolbar
|
||||
tweb = self.toolbarWeb = AnkiWebView(title="top toolbar")
|
||||
tweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
||||
tweb.disable_zoom()
|
||||
self.toolbar = aqt.toolbar.Toolbar(self, tweb)
|
||||
tweb = self.toolbarWeb = ToolbarWebView(self, title="top toolbar")
|
||||
self.toolbar = Toolbar(self, tweb)
|
||||
# main area
|
||||
self.web = MainWebView(self)
|
||||
# bottom area
|
||||
|
@ -1332,6 +1358,10 @@ title="{}" {}>{}</button>""".format(
|
|||
window.windowState() ^ Qt.WindowState.WindowFullScreen
|
||||
)
|
||||
|
||||
def collapse_toolbar_if_allowed(self) -> None:
|
||||
if self.pm.collapse_toolbar() and self.state == "review":
|
||||
self.toolbarWeb.collapse()
|
||||
|
||||
# Auto update
|
||||
##########################################################################
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ class Preferences(QDialog):
|
|||
def setup_global(self) -> None:
|
||||
"Setup options global to all profiles."
|
||||
self.form.reduce_motion.setChecked(self.mw.pm.reduced_motion())
|
||||
self.form.collapse_toolbar.setChecked(self.mw.pm.collapse_toolbar())
|
||||
self.form.uiScale.setValue(int(self.mw.pm.uiScale() * 100))
|
||||
themes = [
|
||||
tr.preferences_theme_label(theme=theme)
|
||||
|
@ -238,7 +239,7 @@ class Preferences(QDialog):
|
|||
restart_required = True
|
||||
|
||||
self.mw.pm.set_reduced_motion(self.form.reduce_motion.isChecked())
|
||||
|
||||
self.mw.pm.set_collapse_toolbar(self.form.collapse_toolbar.isChecked())
|
||||
self.mw.pm.set_legacy_import_export(self.form.legacy_import_export.isChecked())
|
||||
|
||||
if restart_required:
|
||||
|
|
|
@ -524,6 +524,12 @@ create table if not exists profiles
|
|||
def set_reduced_motion(self, on: bool) -> None:
|
||||
self.meta["reduced_motion"] = on
|
||||
|
||||
def collapse_toolbar(self) -> bool:
|
||||
return self.meta.get("collapse_toolbar", False)
|
||||
|
||||
def set_collapse_toolbar(self, on: bool) -> None:
|
||||
self.meta["collapse_toolbar"] = on
|
||||
|
||||
def last_addon_update_check(self) -> int:
|
||||
return self.meta.get("last_addon_update_check", 0)
|
||||
|
||||
|
|
|
@ -543,6 +543,8 @@ class Reviewer:
|
|||
self.showContextMenu()
|
||||
elif url.startswith("play:"):
|
||||
play_clicked_audio(url, self.card)
|
||||
elif url.startswith("updateToolbar"):
|
||||
self.mw.toolbarWeb.update_background_image()
|
||||
else:
|
||||
print("unrecognized anki link:", url)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from typing import cast
|
||||
|
||||
from aqt import colors
|
||||
from aqt import colors, props
|
||||
from aqt.qt import *
|
||||
from aqt.theme import theme_manager
|
||||
|
||||
|
@ -173,7 +173,7 @@ class Switch(QAbstractButton):
|
|||
|
||||
def _animate_toggle(self) -> None:
|
||||
animation = QPropertyAnimation(self, cast(QByteArray, b"position"), self)
|
||||
animation.setDuration(100)
|
||||
animation.setDuration(int(theme_manager.var(props.TRANSITION)))
|
||||
animation.setStartValue(self.start_position)
|
||||
animation.setEndValue(self.end_position)
|
||||
# hide label during animation
|
||||
|
|
|
@ -25,6 +25,7 @@ from aqt.qt import (
|
|||
QStyleFactory,
|
||||
Qt,
|
||||
qtmajor,
|
||||
qtminor,
|
||||
)
|
||||
|
||||
|
||||
|
@ -169,6 +170,8 @@ class ThemeManager:
|
|||
classes.append("macos-dark-mode")
|
||||
if aqt.mw.pm.reduced_motion():
|
||||
classes.append("reduced-motion")
|
||||
if qtmajor == 5 and qtminor < 15:
|
||||
classes.append("no-blur")
|
||||
return " ".join(classes)
|
||||
|
||||
def body_classes_for_card_ord(
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import re
|
||||
from typing import Any, Optional
|
||||
|
||||
import aqt
|
||||
from anki.sync import SyncStatus
|
||||
|
@ -25,6 +26,76 @@ class BottomToolbar:
|
|||
self.toolbar = toolbar
|
||||
|
||||
|
||||
class ToolbarWebView(AnkiWebView):
|
||||
def __init__(self, mw: aqt.AnkiQt, title: str) -> None:
|
||||
AnkiWebView.__init__(self, mw, title=title)
|
||||
self.mw = mw
|
||||
self.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
||||
self.disable_zoom()
|
||||
self.collapsed = False
|
||||
self.web_height = 0
|
||||
# collapse timer
|
||||
self.hide_timer = QTimer()
|
||||
self.hide_timer.setSingleShot(True)
|
||||
self.hide_timer.setInterval(1000)
|
||||
qconnect(self.hide_timer.timeout, self.mw.collapse_toolbar_if_allowed)
|
||||
|
||||
def eventFilter(self, obj, evt):
|
||||
if handled := super().eventFilter(obj, evt):
|
||||
return handled
|
||||
|
||||
# prevent collapse if pointer inside
|
||||
if evt.type() == QEvent.Type.Enter:
|
||||
self.hide_timer.stop()
|
||||
self.hide_timer.setInterval(1000)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _onHeight(self, qvar: Optional[int]) -> None:
|
||||
super()._onHeight(qvar)
|
||||
self.web_height = int(qvar)
|
||||
|
||||
def collapse(self) -> None:
|
||||
self.collapsed = True
|
||||
self.eval("""document.body.classList.add("collapsed"); """)
|
||||
|
||||
def expand(self) -> None:
|
||||
self.collapsed = False
|
||||
self.eval("""document.body.classList.remove("collapsed"); """)
|
||||
|
||||
def flatten(self) -> None:
|
||||
self.eval("document.body.classList.add('flat'); ")
|
||||
|
||||
def elevate(self) -> None:
|
||||
self.eval(
|
||||
"""
|
||||
document.body.classList.remove("flat");
|
||||
document.body.style.removeProperty("background");
|
||||
"""
|
||||
)
|
||||
|
||||
def update_background_image(self) -> None:
|
||||
def set_background(val: str) -> None:
|
||||
# remove offset from copy
|
||||
background = re.sub(r"-\d+px ", "0%", val)
|
||||
# change computedStyle px value back to 100vw
|
||||
background = re.sub(r"\d+px", "100vw", background)
|
||||
|
||||
self.eval(
|
||||
f"""document.body.style.setProperty("background", '{background}'); """
|
||||
)
|
||||
# offset reviewer background by toolbar height
|
||||
self.mw.web.eval(
|
||||
f"""document.body.style.setProperty("background-position-y", "-{self.web_height}px"); """
|
||||
)
|
||||
|
||||
self.mw.web.evalWithCallback(
|
||||
"""window.getComputedStyle(document.body).background; """,
|
||||
set_background,
|
||||
)
|
||||
|
||||
|
||||
class Toolbar:
|
||||
def __init__(self, mw: aqt.AnkiQt, web: AnkiWebView) -> None:
|
||||
self.mw = mw
|
||||
|
@ -32,7 +103,6 @@ class Toolbar:
|
|||
self.link_handlers: dict[str, Callable] = {
|
||||
"study": self._studyLinkHandler,
|
||||
}
|
||||
self.web.setFixedHeight(30)
|
||||
self.web.requiresCol = False
|
||||
|
||||
def draw(
|
||||
|
@ -195,11 +265,10 @@ class Toolbar:
|
|||
######################################################################
|
||||
|
||||
_body = """
|
||||
<center id=outer>
|
||||
<table id=header>
|
||||
<tr>
|
||||
<td class=tdcenter align=center>%s</td>
|
||||
</tr></table>
|
||||
<center id="outer">
|
||||
<div id="header">
|
||||
<div class="toolbar">%s<div>
|
||||
</div>
|
||||
</center>
|
||||
"""
|
||||
|
||||
|
|
|
@ -634,7 +634,6 @@ html {{ {font} }}
|
|||
from aqt import mw
|
||||
|
||||
if qvar is None:
|
||||
|
||||
mw.progress.single_shot(1000, mw.reset)
|
||||
return
|
||||
|
||||
|
|
|
@ -47,10 +47,14 @@ for line in re.split(r"[;\{\}]|\*\/", data):
|
|||
print("failed to match", line)
|
||||
continue
|
||||
|
||||
# convert variable names to Qt style
|
||||
var = m.group(1).replace("-", "_").upper()
|
||||
val = m.group(2)
|
||||
|
||||
if reached_props:
|
||||
# remove trailing ms from time props
|
||||
val = re.sub(r"^(\d+)ms$", r"\1", val)
|
||||
|
||||
if not var in props:
|
||||
props.setdefault(var, {})["comment"] = comment
|
||||
props[var]["light"] = val
|
||||
|
|
|
@ -32,6 +32,34 @@ $vars: (
|
|||
),
|
||||
),
|
||||
),
|
||||
transition: (
|
||||
default: (
|
||||
"Default duration of transitions in milliseconds",
|
||||
(
|
||||
default: 180ms,
|
||||
),
|
||||
),
|
||||
medium: (
|
||||
"Slightly longer transition duration in milliseconds",
|
||||
(
|
||||
default: 500ms,
|
||||
),
|
||||
),
|
||||
slow: (
|
||||
"Long transition duration in milliseconds",
|
||||
(
|
||||
default: 1000ms,
|
||||
),
|
||||
),
|
||||
),
|
||||
blur: (
|
||||
default: (
|
||||
"Default background blur value",
|
||||
(
|
||||
default: 20px,
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
colors: (
|
||||
fg: (
|
||||
|
@ -107,6 +135,13 @@ $vars: (
|
|||
dark: palette(darkgray, 6),
|
||||
),
|
||||
),
|
||||
glass: (
|
||||
"Transparent background for surfaces containing text",
|
||||
(
|
||||
light: color.scale(white, $alpha: -60%),
|
||||
dark: color.scale(palette(darkgray, 4), $alpha: -60%),
|
||||
),
|
||||
),
|
||||
),
|
||||
border: (
|
||||
default: (
|
||||
|
|
|
@ -45,7 +45,7 @@ html {
|
|||
|
||||
button {
|
||||
/* override transition for instant hover response */
|
||||
transition: color 0.15s ease-in-out, box-shadow 0.15s ease-in-out !important;
|
||||
transition: color var(--transition) ease-in-out, box-shadow var(--transition) ease-in-out !important;
|
||||
border-radius: prop(border-radius);
|
||||
@include button.base;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,6 @@ button {
|
|||
@include elevation(1, $opacity-boost: -0.08);
|
||||
&:hover {
|
||||
@include elevation(2);
|
||||
transition: box-shadow 0.2s linear;
|
||||
transition: box-shadow var(--transition) linear;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ body {
|
|||
color: var(--fg);
|
||||
background: var(--canvas);
|
||||
margin: 1em;
|
||||
transition: opacity 0.5s ease-out;
|
||||
transition: opacity var(--transition-medium) ease-out;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
z-index: 4;
|
||||
height: var(--client-height);
|
||||
box-shadow: var(--box-shadow);
|
||||
transition: box-shadow 0.1s ease-in-out;
|
||||
transition: box-shadow var(--transition) ease-in-out;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -63,7 +63,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
@include elevation(4);
|
||||
}
|
||||
}
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
transition: box-shadow var(--transition) ease-in-out;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
h1 {
|
||||
|
@ -73,7 +73,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
right: 0;
|
||||
bottom: 4px;
|
||||
color: var(--fg-faint);
|
||||
transition: color 0.2s linear;
|
||||
transition: color var(--transition) linear;
|
||||
&:hover {
|
||||
transition: none;
|
||||
color: var(--fg);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "sass/base";
|
||||
|
||||
// override Bootstrap transition duration
|
||||
$carousel-transition: 0.2s;
|
||||
$carousel-transition: var(--transition);
|
||||
|
||||
@import "bootstrap/scss/buttons";
|
||||
@import "bootstrap/scss/button-group";
|
||||
|
|
|
@ -18,7 +18,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
.collapse-badge {
|
||||
display: inline-block;
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.2s ease-in-out, transform 80ms ease-in;
|
||||
transition: opacity var(--transition) ease-in-out,
|
||||
transform var(--transition) ease-in;
|
||||
&.highlighted {
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
<style lang="scss">
|
||||
svg {
|
||||
transition: opacity 1s;
|
||||
transition: opacity var(--transition-slow);
|
||||
}
|
||||
|
||||
.counts-outer {
|
||||
|
|
|
@ -148,7 +148,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
&.loading {
|
||||
opacity: 0.5;
|
||||
transition: opacity 1s;
|
||||
transition: opacity var(--transition-slow);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
font-size: 15px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s;
|
||||
transition: opacity var(--transition);
|
||||
color: var(--fg);
|
||||
background: var(--canvas-overlay);
|
||||
|
||||
|
|
|
@ -145,6 +145,9 @@ export async function _updateQA(
|
|||
|
||||
await _runHook(onUpdateHook);
|
||||
|
||||
// dynamic toolbar background
|
||||
bridgeCommand("updateToolbar");
|
||||
|
||||
// wait for mathjax to ready
|
||||
await MathJax.startup.promise
|
||||
.then(() => {
|
||||
|
|
|
@ -10,7 +10,10 @@ hr {
|
|||
body {
|
||||
margin: 20px;
|
||||
overflow-wrap: break-word;
|
||||
background-color: var(--canvas);
|
||||
// default background setting to fit with toolbar
|
||||
background-size: 100vw;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
// explicit nightMode definition required
|
||||
|
|
Loading…
Reference in a new issue