diff --git a/ftl/core/preferences.ftl b/ftl/core/preferences.ftl
index 367ad74ba..089aa7d99 100644
--- a/ftl/core/preferences.ftl
+++ b/ftl/core/preferences.ftl
@@ -4,13 +4,13 @@ preferences-basic = Basic
preferences-change-deck-depending-on-note-type = Change deck depending on note type
preferences-changes-will-take-effect-when-you = Changes will take effect when you restart Anki.
preferences-hours-past-midnight = hours past midnight
-preferences-interface-language = Interface language:
+preferences-language = Language
preferences-interrupt-current-audio-when-answering = Interrupt current audio when answering
preferences-learn-ahead-limit = Learn ahead limit
preferences-mins = mins
preferences-network = Network
preferences-next-day-starts-at = Next day starts at
-preferences-note-media-is-not-backed-up = Note: Media is not backed up. Please create a periodic backup of your Anki folder to be safe.
+preferences-note-media-is-not-backed-up = Media is not backed up. Please create a periodic backup of your Anki folder to be safe.
preferences-on-next-sync-force-changes-in = On next sync, force changes in one direction
preferences-paste-clipboard-images-as-png = Paste clipboard images as PNG
preferences-paste-without-shift-key-strips-formatting = Paste without shift key strips formatting
@@ -21,19 +21,19 @@ preferences-scheduling = Scheduling
preferences-show-learning-cards-with-larger-steps = Show learning cards with larger steps before reviews
preferences-show-next-review-time-above-answer = Show next review time above answer buttons
preferences-show-play-buttons-on-cards-with = Show play buttons on cards with audio
-preferences-show-remaining-card-count-during-review = Show remaining card count during review
+preferences-show-remaining-card-count-during-review = Show remaining card count
preferences-some-settings-will-take-effect-after = Some settings will take effect after you restart Anki.
-preferences-synchronisation = Synchronisation
+preferences-synchronisation = Synchronisation
preferences-synchronizationnot-currently-enabled-click-the-sync = Synchronization
Not currently enabled; click the sync button in the main window to enable.
preferences-synchronize-audio-and-images-too = Synchronize audio and images too
preferences-timebox-time-limit = Timebox time limit
preferences-user-interface-size = User interface size
preferences-when-adding-default-to-current-deck = When adding, default to current deck
-preferences-you-can-restore-backups-via-fileswitch = You can restore backups via File>Switch Profile.
+preferences-you-can-restore-backups-via-fileswitch = You can restore backups via File > Switch Profile.
preferences-legacy-timezone-handling = Legacy timezone handling (buggy, but required for AnkiDroid <= 2.14)
preferences-default-search-text = Default search text
preferences-default-search-text-example = eg. 'deck:current '
-preferences-theme-label = Theme: { $theme }
+preferences-theme = Theme
preferences-theme-follow-system = Follow System
preferences-theme-light = Light
preferences-theme-dark = Dark
@@ -48,4 +48,21 @@ 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
+preferences-collapse-toolbar = Hide top bar
+preferences-appearance = Appearance
+preferences-general = General
+preferences-style = Style
+preferences-review = Review
+preferences-reviewer = Reviewer
+preferences-distractions = Distractions
+preferences-minimalist-mode = Minimalist mode
+preferences-editing = Editing
+preferences-browsing = Browsing
+preferences-default-deck = Default deck
+preferences-account = AnkiWeb Account
+preferences-media = Media
+preferences-note = Note
+preferences-limits = Limits
+preferences-scheduler = Scheduler
+preferences-user-interface = User Interface
+preferences-import-export = Import/Export
diff --git a/ftl/qt/preferences.ftl b/ftl/qt/preferences.ftl
index c417b9f1c..9f022cb6e 100644
--- a/ftl/qt/preferences.ftl
+++ b/ftl/qt/preferences.ftl
@@ -1,6 +1,6 @@
## Video drivers/hardware acceleration. Please avoid translating 'OpenGL' and 'ANGLE'.
-preferences-video-driver = Video driver: { $driver }
+preferences-video-driver = Video driver
preferences-video-driver-opengl-mac = OpenGL (recommended on Macs)
preferences-video-driver-software-mac = Software (not recommended)
preferences-video-driver-opengl-other = OpenGL (faster, may cause issues)
diff --git a/qt/aqt/__init__.py b/qt/aqt/__init__.py
index c5f54ae2b..af7980d1b 100644
--- a/qt/aqt/__init__.py
+++ b/qt/aqt/__init__.py
@@ -351,6 +351,7 @@ class AnkiApp(QApplication):
QCheckBox,
QRadioButton,
QMenu,
+ QSlider,
# classes with PyQt5 compatibility proxy
without_qt5_compat_wrapper(QToolButton),
without_qt5_compat_wrapper(QTabBar),
diff --git a/qt/aqt/data/web/css/deckbrowser.scss b/qt/aqt/data/web/css/deckbrowser.scss
index 21d349bb3..b191a278d 100644
--- a/qt/aqt/data/web/css/deckbrowser.scss
+++ b/qt/aqt/data/web/css/deckbrowser.scss
@@ -7,17 +7,19 @@
table {
padding: 1rem;
- background: var(--canvas-elevated);
- border: 1px solid var(--border-subtle);
- border-radius: var(--border-radius-large);
- @include elevation(1, $opacity-boost: -0.08);
- &:hover {
- @include elevation(2);
+ .fancy & {
+ border: 1px solid var(--border-subtle);
+ border-radius: var(--border-radius-medium);
+
+ @include elevation(1, $opacity-boost: -0.08);
+ &:hover {
+ @include elevation(2);
+ }
+ transition: box-shadow var(--transition) ease-in-out;
+ background: var(--canvas-glass);
+ backdrop-filter: blur(var(--blur));
}
- transition: box-shadow var(--transition) ease-in-out;
- background: var(--canvas-glass);
- backdrop-filter: blur(var(--blur));
}
a.deck {
@@ -37,7 +39,11 @@ th {
}
tr.deck td {
- padding: 4px 12px;
+ padding: 2px 12px;
+
+ .fancy & {
+ padding: 4px 12px;
+ }
}
tr.top-level-drag-row td {
diff --git a/qt/aqt/data/web/css/toolbar.scss b/qt/aqt/data/web/css/toolbar.scss
index b80cce550..f8f382d94 100644
--- a/qt/aqt/data/web/css/toolbar.scss
+++ b/qt/aqt/data/web/css/toolbar.scss
@@ -7,7 +7,6 @@
@use "sass/button-mixins" as button;
.header {
- height: 41px;
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: start;
@@ -31,65 +30,88 @@
}
.toolbar {
- height: 31px;
justify-self: center;
white-space: nowrap;
- overflow: hidden;
- border-bottom-left-radius: prop(border-radius-large);
- border-bottom-right-radius: prop(border-radius-large);
- @include elevation(1, $opacity-boost: -0.1);
-
- // elevated state (deck browser, overview)
- body:not(.flat) & {
- background: var(--canvas-elevated);
- @include elevation(1);
- &:hover {
- @include elevation(2);
- }
- }
- // glass effect
- background: var(--canvas-glass);backdrop-filter: unset;
- backdrop-filter: blur(var(--blur));
-
transition: all var(--transition) ease-in-out;
}
+.hitem {
+ font-weight: bold;
+ padding: 5px 12px;
+ color: color(fg);
+ display: inline-block;
+ &:hover {
+ text-decoration: underline;
+ }
+}
+
body {
margin: 0;
padding: 0;
-webkit-user-select: none;
overflow: hidden;
- &.collapsed {
- transform: translateY(-100vh);
+ &:not(.fancy).collapsed {
+ opacity: 0;
+ }
+ transition: opacity var(--transition) ease-in-out;
+
+ &.fancy {
+ &.collapsed {
+ transform: translateY(-100vh);
+ }
+ transition: transform var(--transition) ease-in-out;
+
+ .header {
+ height: 41px;
+ }
+ .toolbar {
+ height: 31px;
+
+ overflow: hidden;
+ border-bottom-left-radius: prop(border-radius-medium);
+ border-bottom-right-radius: prop(border-radius-medium);
+ @include elevation(1, $opacity-boost: -0.1);
+
+ // elevated state (deck browser, overview)
+ body:not(.flat) & {
+ background: var(--canvas-elevated);
+ @include elevation(1);
+ &:hover {
+ @include elevation(2);
+ }
+ }
+ // glass effect
+ background: var(--canvas-glass);
+ backdrop-filter: blur(var(--blur));
+ }
+
+ .hitem {
+ &:hover {
+ background: var(--canvas-inset);
+ text-decoration: none;
+ }
+ &:active {
+ @include button.base($border: false);
+ background: var(--canvas-elevated);
+ }
+ &:first-child {
+ padding-left: 18px;
+ }
+ &:last-child {
+ padding-right: 18px;
+ }
+ }
+ }
+ &:not(.fancy) {
+ border-bottom: 1px solid var(--border-subtle);
}
- transition: transform var(--transition) ease-in-out;
}
* {
-webkit-user-drag: none;
}
-.hitem {
- font-weight: bold;
- padding: 5px 12px;
- text-decoration: none;
- color: color(fg);
- display: inline-block;
-
- body:not(.flat) &,
- &:hover {
- @include button.base($border: false);
- background: var(--canvas-elevated);
- }
- &:first-child {
- padding-left: 18px;
- }
- &:last-child {
- padding-right: 18px;
- }
-}
-
.hitem:focus {
outline: 0;
}
diff --git a/qt/aqt/data/web/css/webview.scss b/qt/aqt/data/web/css/webview.scss
index 44e95d433..589387aaa 100644
--- a/qt/aqt/data/web/css/webview.scss
+++ b/qt/aqt/data/web/css/webview.scss
@@ -30,6 +30,11 @@ body {
&.no-blur * {
backdrop-filter: none !important;
}
+ &:not(.fancy),
+ &:not(.fancy) * {
+ box-shadow: none !important;
+ backdrop-filter: none !important;
+ }
}
a {
diff --git a/qt/aqt/forms/preferences.ui b/qt/aqt/forms/preferences.ui
index c550fd45e..af3ce2bb9 100644
--- a/qt/aqt/forms/preferences.ui
+++ b/qt/aqt/forms/preferences.ui
@@ -6,8 +6,8 @@
0
0
- 640
- 660
+ 604
+ 634
@@ -22,172 +22,404 @@
0
+
+
+ preferences_appearance
+
+
+ -
+
+
+ -
+
+
+ preferences_general
+
+
+
-
+
+
+ preferences_language
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QComboBox::AdjustToMinimumContentsLengthWithIcon
+
+
+
+ -
+
+
+ preferences_video_driver
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ preferences_user_interface
+
+
+
-
+
+
+ preferences_theme
+
+
+
+ -
+
+
+ -
+
+
+ preferences_style
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ %
+
+
+ 100
+
+
+ 200
+
+
+ 5
+
+
+
+ -
+
+
+ preferences_user_interface_size
+
+
+
+
+
+
+ -
+
+
+ preferences_reviewer
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ preferences_collapse_toolbar
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_show_play_buttons_on_cards_with
+
+
+
+
+
+
+ -
+
+
+ preferences_distractions
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ preferences_reduce_motion_tooltip
+
+
+ preferences_reduce_motion
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_minimalist_mode
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 20
+
+
+
+
+
+
preferences_basic
-
-
- 12
-
-
- 12
-
-
- 12
-
-
- 12
-
-
- 12
-
+
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- QComboBox::AdjustToMinimumContentsLengthWithIcon
+
+
+ preferences_editing
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ preferences_paste_clipboard_images_as_png
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_paste_without_shift_key_strips_formatting
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 10
+
+
+
+
+ -
+
+
-
+
+
+ preferences_default_deck
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
-
+
+ preferences_when_adding_default_to_current_deck
+
+
+ -
+
+ preferences_change_deck_depending_on_note_type
+
+
+
+
+
+
+
-
-
-
- -
-
-
- preferences_show_play_buttons_on_cards_with
-
-
-
- -
-
-
- preferences_interrupt_current_audio_when_answering
-
-
-
- -
-
-
- preferences_paste_clipboard_images_as_png
-
-
-
- -
-
-
- preferences_paste_without_shift_key_strips_formatting
-
-
-
- -
-
-
- preferences_ignore_accents_in_search
-
-
-
- -
-
-
- Legacy import/export handling
-
-
-
- -
-
-
- preferences_reduce_motion_tooltip
-
-
- preferences_reduce_motion
-
-
-
- -
-
-
- preferences_collapse_toolbar
+
+
+ preferences_browsing
+
+
-
+
+
-
+
+
+ preferences_default_search_text
+
+
+
+ -
+
+
+ preferences_default_search_text_example
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_ignore_accents_in_search
+
+
+
+
-
-
-
-
-
- preferences_when_adding_default_to_current_deck
-
-
- -
-
- preferences_change_deck_depending_on_note_type
-
-
-
-
- -
-
-
- preferences_default_search_text
+
+
+ preferences_review
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ preferences_show_next_review_time_above_answer
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_show_remaining_card_count_during_review
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_interrupt_current_audio_when_answering
+
+
+
+
-
-
-
- preferences_default_search_text_example
+
+
+ preferences_import_export
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Legacy import/export handling
+
+
+
+
- -
-
-
-
-
-
- preferences_user_interface_size
-
-
-
- -
-
-
- %
-
-
- 100
-
-
- 200
-
-
- 5
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
@@ -208,131 +440,169 @@
- preferences_scheduling
+ preferences_scheduler
- -
-
-
- preferences_show_next_review_time_above_answer
-
-
-
- -
-
-
- preferences_show_remaining_card_count_during_review
-
-
-
- -
-
-
- preferences_show_learning_cards_with_larger_steps
-
-
-
- -
-
-
- preferences_legacy_timezone_handling
-
-
-
- -
-
-
-
-
-
- preferences_v3_scheduler
+
-
+
+
+ preferences_scheduler
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ preferences_v3_scheduler
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_show_learning_cards_with_larger_steps
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_legacy_timezone_handling
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 10
+
+
+
+
+ -
+
+
+
-
-
-
- -
-
-
- 12
+
+
+ preferences_limits
-
-
-
-
- preferences_mins
-
-
-
- -
-
-
- 9999
-
-
-
- -
-
-
-
- 60
- 16777215
-
-
-
- 23
-
-
-
- -
-
-
- preferences_timebox_time_limit
-
-
-
- -
-
-
- preferences_hours_past_midnight
-
-
-
- -
-
-
- preferences_learn_ahead_limit
-
-
-
- -
-
-
- preferences_mins
-
-
-
- -
-
-
-
- 60
- 16777215
-
-
-
- 999
-
-
-
- -
-
-
- preferences_next_day_starts_at
-
-
-
-
+
+ -
+
+
+ 12
+
+
-
+
+
+
+ 60
+ 16777215
+
+
+
+ 999
+
+
+
+ -
+
+
+ preferences_mins
+
+
+
+ -
+
+
+ preferences_timebox_time_limit
+
+
+
+ -
+
+
+ preferences_hours_past_midnight
+
+
+
+ -
+
+
+
+ 60
+ 16777215
+
+
+
+ 23
+
+
+
+ -
+
+
+ preferences_learn_ahead_limit
+
+
+
+ -
+
+
+ preferences_next_day_starts_at
+
+
+
+ -
+
+
+ preferences_mins
+
+
+
+ -
+
+
+ 9999
+
+
+
+
+
+
+
-
@@ -370,114 +640,140 @@
12
-
-
-
- 10
+
+
+ preferences_synchronisation
-
-
-
-
-
-
-
- preferences_synchronisation
-
-
- true
-
-
- true
-
-
-
- -
-
-
- preferences_synchronize_audio_and_images_too
-
-
-
- -
-
-
- preferences_automatically_sync_on_profile_openclose
-
-
-
- -
-
-
- preferences_periodically_sync_media
-
-
-
- -
-
-
- preferences_on_next_sync_force_changes_in
-
-
-
- -
-
-
-
-
-
- LOGOUT
-
-
- false
-
-
-
- -
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 1
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_synchronize_audio_and_images_too
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_automatically_sync_on_profile_openclose
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_periodically_sync_media
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ preferences_on_next_sync_force_changes_in
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ preferences_account
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ LOGOUT
+
+
+ false
+
+
+
+
+
-
@@ -515,145 +811,175 @@
12
-
-
-
- preferences_backup_explanation
+
+
+
+ 0
+ 0
+
-
- true
+
+ preferences_backups
+
+
-
+
+
+ preferences_backup_explanation
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
-
+
+
+ 5
+
+
+ 9999
+
+
+
+ -
+
+
+ 9999
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ preferences_daily_backups
+
+
+
+ -
+
+
+ 9999
+
+
+
+ -
+
+
+ preferences_monthly_backups
+
+
+
+ -
+
+
+ preferences_weekly_backups
+
+
+
+ -
+
+
+ preferences_minutes_between_backups
+
+
+
+ -
+
+
+ 9999
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+ preferences_you_can_restore_backups_via_fileswitch
+
+
+
+
-
-
-
-
-
-
- 9999
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- 9999
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- preferences_daily_backups
-
-
-
- -
-
-
- preferences_monthly_backups
-
-
-
- -
-
-
- 9999
-
-
-
- -
-
-
- preferences_weekly_backups
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- preferences_minutes_between_backups
-
-
-
- -
-
-
- 5
-
-
- 9999
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- preferences_you_can_restore_backups_via_fileswitch
-
-
-
- -
-
-
- preferences_note_media_is_not_backed_up
-
-
- true
+
+
+ preferences_note
+
+
-
+
+
+ preferences_note_media_is_not_backed_up
+
+
+ true
+
+
+
+
-
@@ -674,10 +1000,13 @@
-
-
+
preferences_some_settings_will_take_effect_after
+
+ Qt::AlignCenter
+
-
@@ -693,25 +1022,27 @@
- theme
lang
video_driver
+ theme
+ styleComboBox
+ uiScale
+ collapse_toolbar
showPlayButtons
- interrupt_audio
+ reduce_motion
+ minimalist_mode
pastePNG
paste_strips_formatting
- ignore_accents_in_search
- legacy_import_export
- reduce_motion
- collapse_toolbar
useCurrent
default_search_text
- uiScale
+ ignore_accents_in_search
showEstimates
showProgress
+ interrupt_audio
+ legacy_import_export
+ sched2021
dayLearnFirst
legacy_timezone
- sched2021
newSpread
dayOffset
lrnCutoff
@@ -720,8 +1051,8 @@
syncOnProgramOpen
autoSyncMedia
fullSync
- syncDeauth
media_log
+ syncDeauth
minutes_between_backups
daily_backups
weekly_backups
diff --git a/qt/aqt/forms/setlang.ui b/qt/aqt/forms/setlang.ui
index 6f6fde77d..6f570d6d7 100644
--- a/qt/aqt/forms/setlang.ui
+++ b/qt/aqt/forms/setlang.ui
@@ -17,7 +17,7 @@
-
- preferences_interface_language
+ preferences_language
diff --git a/qt/aqt/forms/widgets.ui b/qt/aqt/forms/widgets.ui
index 491583083..a5c8d61f5 100644
--- a/qt/aqt/forms/widgets.ui
+++ b/qt/aqt/forms/widgets.ui
@@ -33,13 +33,6 @@
- -
-
-
- Force Style
-
-
-
-
diff --git a/qt/aqt/main.py b/qt/aqt/main.py
index 53660e6a7..31c1cffe7 100644
--- a/qt/aqt/main.py
+++ b/qt/aqt/main.py
@@ -1068,9 +1068,9 @@ title="{}" {}>{}""".format(
if is_lin:
# On Linux, the check requires invoking an external binary,
# which we don't want to be doing frequently
- interval_secs = 300
+ interval_secs = 10
else:
- interval_secs = 5
+ interval_secs = 2
self.progress.timer(
interval_secs * 1000,
theme_manager.apply_style_if_system_style_changed,
diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py
index 0b9048ff6..8e6ec1d11 100644
--- a/qt/aqt/preferences.py
+++ b/qt/aqt/preferences.py
@@ -13,7 +13,7 @@ from aqt import AnkiQt
from aqt.operations.collection import set_preferences
from aqt.profiles import VideoDriver
from aqt.qt import *
-from aqt.theme import Theme
+from aqt.theme import AnkiStyles, Theme
from aqt.utils import HelpPage, disable_help_button, openHelp, showInfo, showWarning, tr
@@ -207,20 +207,35 @@ 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.reduce_motion.setChecked(self.mw.pm.reduce_motion())
+ qconnect(self.form.reduce_motion.stateChanged, self.mw.pm.set_reduce_motion)
+
+ self.form.minimalist_mode.setChecked(self.mw.pm.minimalist_mode())
+ qconnect(self.form.minimalist_mode.stateChanged, self.mw.pm.set_minimalist_mode)
+
self.form.collapse_toolbar.setChecked(self.mw.pm.collapse_toolbar())
+ qconnect(
+ self.form.collapse_toolbar.stateChanged, self.mw.pm.set_collapse_toolbar
+ )
+
self.form.uiScale.setValue(int(self.mw.pm.uiScale() * 100))
themes = [
- tr.preferences_theme_label(theme=theme)
- for theme in (
- tr.preferences_theme_follow_system(),
- tr.preferences_theme_light(),
- tr.preferences_theme_dark(),
- )
+ tr.preferences_theme_follow_system(),
+ tr.preferences_theme_light(),
+ tr.preferences_theme_dark(),
]
self.form.theme.addItems(themes)
self.form.theme.setCurrentIndex(self.mw.pm.theme().value)
qconnect(self.form.theme.currentIndexChanged, self.on_theme_changed)
+
+ self.form.styleComboBox.addItems(
+ [member.name.lower().capitalize() for member in AnkiStyles]
+ )
+ self.form.styleComboBox.setCurrentIndex(self.mw.pm.get_widget_style())
+ qconnect(
+ self.form.styleComboBox.currentIndexChanged,
+ self.mw.pm.set_widget_style,
+ )
self.form.legacy_import_export.setChecked(self.mw.pm.legacy_import_export())
self.setup_language()
@@ -238,8 +253,6 @@ class Preferences(QDialog):
self.mw.pm.setUiScale(newScale)
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:
@@ -289,14 +302,12 @@ class Preferences(QDialog):
def setup_video_driver(self) -> None:
self.video_drivers = VideoDriver.all_for_platform()
- names = [
- tr.preferences_video_driver(driver=video_driver_name_for_platform(d))
- for d in self.video_drivers
- ]
+ names = [video_driver_name_for_platform(d) for d in self.video_drivers]
self.form.video_driver.addItems(names)
self.form.video_driver.setCurrentIndex(
self.video_drivers.index(self.mw.pm.video_driver())
)
+ self.form.video_driver_label.setVisible(qtmajor == 5)
self.form.video_driver.setVisible(qtmajor == 5)
def update_video_driver(self) -> None:
diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py
index 8621b22bb..01434c9b0 100644
--- a/qt/aqt/profiles.py
+++ b/qt/aqt/profiles.py
@@ -21,7 +21,7 @@ from anki.db import DB
from anki.lang import without_unicode_isolation
from anki.sync import SyncAuth
from anki.utils import int_time, is_mac, is_win, point_version
-from aqt import appHelpSite
+from aqt import appHelpSite, gui_hooks
from aqt.qt import *
from aqt.theme import AnkiStyles, Theme, theme_manager
from aqt.utils import disable_help_button, send_to_trash, showWarning, tr
@@ -523,12 +523,21 @@ create table if not exists profiles
def set_reduce_motion(self, on: bool) -> None:
self.meta["reduce_motion"] = on
+ gui_hooks.body_classes_need_update()
+
+ def minimalist_mode(self) -> bool:
+ return self.meta.get("tatsumoto_mode", False)
+
+ def set_minimalist_mode(self, on: bool) -> None:
+ self.meta["tatsumoto_mode"] = on
+ gui_hooks.body_classes_need_update()
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
+ gui_hooks.body_classes_need_update()
def last_addon_update_check(self) -> int:
return self.meta.get("last_addon_update_check", 0)
@@ -546,34 +555,14 @@ create table if not exists profiles
def set_theme(self, theme: Theme) -> None:
self.meta["theme"] = theme.value
- def set_forced_style(self, style: AnkiStyles | None) -> None:
- if style:
- self.meta[f"force_{AnkiStyles(style).name.lower()}_styles"] = True
-
- for member in AnkiStyles:
- if member != style:
- self.meta[f"force_{AnkiStyles(member).name.lower()}_styles"] = False
-
+ def set_widget_style(self, style: AnkiStyles) -> None:
+ self.meta["widget_style"] = style
theme_manager.apply_style()
- def has_forced_style(self) -> bool:
- for member in AnkiStyles:
- if self.meta[f"force_{AnkiStyles(member).name.lower()}_styles"]:
- return True
- return False
-
- # These getters are used by ThemeManager
- def unset_forced_styles(self) -> None:
- self.set_forced_style(None)
-
- def force_anki_styles(self) -> bool:
- return self.meta.get("force_anki_styles", False)
-
- def force_fusion_styles(self) -> bool:
- return self.meta.get("force_fusion_styles", False)
-
- def force_native_styles(self) -> bool:
- return self.meta.get("force_native_styles", False)
+ def get_widget_style(self) -> AnkiStyles:
+ return self.meta.get(
+ "widget_style", AnkiStyles.NATIVE if is_mac else AnkiStyles.ANKI
+ )
def browser_layout(self) -> BrowserLayout:
from aqt.browser.layout import BrowserLayout
diff --git a/qt/aqt/stylesheets.py b/qt/aqt/stylesheets.py
index 48ee06fdb..9eeace712 100644
--- a/qt/aqt/stylesheets.py
+++ b/qt/aqt/stylesheets.py
@@ -28,449 +28,564 @@ qlineargradient(
"""
-def general_styles(tm: ThemeManager) -> str:
- return f"""
-QFrame,
-QWidget {{
- background: none;
-}}
-QPushButton,
-QComboBox,
-QSpinBox,
-QLineEdit,
-QListWidget,
-QTreeWidget,
-QListView {{
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QLineEdit {{
- padding: 2px;
-}}
-QLineEdit:focus {{
- border-color: {tm.var(colors.BORDER_FOCUS)};
-}}
-QPushButton {{
- margin-top: 1px;
-}}
-QPushButton,
-QComboBox,
-QSpinBox {{
- padding: 2px 6px;
-}}
- """
+class CustomStyles:
+ def general(self, tm: ThemeManager) -> str:
+ return f"""
+ QFrame,
+ QWidget {{
+ background: none;
+ }}
+ QPushButton,
+ QComboBox,
+ QSpinBox,
+ QDateTimeEdit,
+ QLineEdit,
+ QListWidget,
+ QTreeWidget,
+ QListView,
+ QTextEdit,
+ QPlainTextEdit {{
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QLineEdit,
+ QTextEdit,
+ QPlainTextEdit,
+ QDateTimeEdit,
+ QListWidget,
+ QTreeWidget,
+ QListView {{
+ background: {tm.var(colors.CANVAS_CODE)};
+ }}
+ QLineEdit,
+ QTextEdit,
+ QPlainTextEdit,
+ QDateTimeEdit {{
+ padding: 2px;
+ }}
+ QSpinBox:focus,
+ QDateTimeEdit:focus,
+ QLineEdit:focus,
+ QTextEdit:editable:focus,
+ QPlainTextEdit:editable:focus,
+ QWidget:editable:focus {{
+ border-color: {tm.var(colors.BORDER_FOCUS)};
+ }}
+ QPushButton {{
+ margin-top: 1px;
+ }}
+ QPushButton,
+ QComboBox,
+ QSpinBox {{
+ padding: 2px 6px;
+ }}
+ QGroupBox {{
+ text-align: center;
+ font-weight: bold;
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ padding: 0.75em 0 0.75em 0;
+ background: {tm.var(colors.CANVAS_ELEVATED)};
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ margin-top: 10px;
+ }}
+ QGroupBox::title {{
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ margin: 0 2px;
+ left: 15px;
+ }}
+ """
+ def menu(self, tm: ThemeManager) -> str:
+ return f"""
+ QMenuBar {{
+ border-bottom: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ }}
+ QMenuBar::item {{
+ background-color: transparent;
+ padding: 2px 4px;
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QMenuBar::item:selected {{
+ background-color: {tm.var(colors.CANVAS_ELEVATED)};
+ }}
+ QMenu {{
+ background-color: {tm.var(colors.CANVAS_OVERLAY)};
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ padding: 4px;
+ }}
+ QMenu::item {{
+ background-color: transparent;
+ padding: 3px 14px;
+ margin-bottom: 4px;
+ }}
+ QMenu::item:selected {{
+ background-color: {tm.var(colors.HIGHLIGHT_BG)};
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QMenu::separator {{
+ height: 1px;
+ background: {tm.var(colors.BORDER_SUBTLE)};
+ margin: 0 8px 4px 8px;
+ }}
+ QMenu::indicator {{
+ border: 1px solid {tm.var(colors.BORDER)};
+ margin-{tm.left()}: 6px;
+ margin-{tm.right()}: -6px;
+ }}
+ """
-def menu_styles(tm: ThemeManager) -> str:
- return f"""
-QMenuBar {{
- border-bottom: 1px solid {tm.var(colors.BORDER_SUBTLE)};
-}}
-QMenuBar::item {{
- background-color: transparent;
- padding: 2px 4px;
- border-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QMenuBar::item:selected {{
- background-color: {tm.var(colors.CANVAS_ELEVATED)};
-}}
-QMenu {{
- background-color: {tm.var(colors.CANVAS_OVERLAY)};
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- padding: 4px;
-}}
-QMenu::item {{
- background-color: transparent;
- padding: 3px 14px;
- margin-bottom: 4px;
-}}
-QMenu::item:selected {{
- background-color: {tm.var(colors.HIGHLIGHT_BG)};
- border-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QMenu::separator {{
- height: 1px;
- background: {tm.var(colors.BORDER_SUBTLE)};
- margin: 0 8px 4px 8px;
-}}
-QMenu::indicator {{
- border: 1px solid {tm.var(colors.BORDER)};
- margin-{tm.left()}: 6px;
- margin-{tm.right()}: -6px;
-}}
- """
-
-
-def button_styles(tm: ThemeManager) -> str:
- # For some reason, Windows needs a larger padding to look the same
- button_pad = 25 if is_win else 15
- return f"""
-QPushButton {{ padding-left: {button_pad}px; padding-right: {button_pad}px; }}
-QPushButton,
-QTabBar::tab:!selected,
-QComboBox:!editable,
-QComboBox::drop-down:editable,
-QSpinBox::up-button,
-QSpinBox::down-button {{
- background: {tm.var(colors.BUTTON_BG)};
- border-bottom: 1px solid {tm.var(colors.SHADOW)};
-}}
-QPushButton:hover,
-QTabBar::tab:hover,
-QComboBox:!editable:hover,
-QSpinBox::up-button,
-QSpinBox::down-button {{
- background: {
- button_gradient(
- tm.var(colors.BUTTON_GRADIENT_START),
- tm.var(colors.BUTTON_GRADIENT_END),
- )
- };
-}}
-QPushButton:pressed,
-QSpinBox::up-button,
-QSpinBox::down-button {{
- background: {
- button_pressed_gradient(
- tm.var(colors.BUTTON_GRADIENT_START),
- tm.var(colors.BUTTON_GRADIENT_END),
- tm.var(colors.SHADOW)
- )
- };
-}}
- """
-
-
-def splitter_styles(tm: ThemeManager) -> str:
- return f"""
-QSplitter::handle,
-QMainWindow::separator {{
- height: 16px;
-}}
-QSplitter::handle:vertical,
-QMainWindow::separator:horizontal {{
- image: url({tm.themed_icon("mdi:drag-horizontal-FG_SUBTLE")});
-}}
-QSplitter::handle:horizontal,
-QMainWindow::separator:vertical {{
- image: url({tm.themed_icon("mdi:drag-vertical-FG_SUBTLE")});
-}}
-"""
-
-
-def combobox_styles(tm: ThemeManager) -> str:
- return f"""
-QComboBox {{
- padding: {"1px 6px 2px 4px" if tm.rtl() else "1px 4px 2px 6px"};
-}}
-QComboBox:focus {{
- border-color: {tm.var(colors.BORDER_FOCUS)};
-}}
-QComboBox:editable:on,
-QComboBox:editable:focus,
-QComboBox::drop-down:focus:editable,
-QComboBox::drop-down:pressed {{
- border-color: {tm.var(colors.BORDER_FOCUS)};
-}}
-QComboBox:on {{
- border-bottom: none;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}}
-QComboBox::item {{
- color: {tm.var(colors.FG)};
- background: {tm.var(colors.CANVAS_ELEVATED)};
-}}
-
-QComboBox::item:selected {{
- background: {tm.var(colors.HIGHLIGHT_BG)};
- color: {tm.var(colors.HIGHLIGHT_FG)};
-}}
-QComboBox::item::icon:selected {{
- position: absolute;
-}}
-QComboBox::drop-down {{
- subcontrol-origin: border;
- padding: 2px;
- padding-left: 4px;
- padding-right: 4px;
- width: 16px;
- subcontrol-position: top right;
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
- border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QComboBox::drop-down:!editable {{
- background: none;
- border-color: transparent;
-}}
-QComboBox::down-arrow {{
- image: url({tm.themed_icon("mdi:chevron-down")});
-}}
-QComboBox::drop-down:hover:editable {{
- background: {
- button_gradient(
- tm.var(colors.BUTTON_GRADIENT_START),
- tm.var(colors.BUTTON_GRADIENT_END),
- )
- };
-}}
- """
-
-
-def tabwidget_styles(tm: ThemeManager) -> str:
- return f"""
-QTabWidget {{
- border-radius: {tm.var(props.BORDER_RADIUS)};
- background: none;
-}}
-QTabWidget::pane {{
- top: -15px;
- padding-top: 1em;
- background: {tm.var(colors.CANVAS_ELEVATED)};
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QTabWidget::tab-bar {{
- alignment: center;
-}}
-QTabBar::tab {{
- background: none;
- padding: 4px 8px;
- min-width: 8ex;
-}}
-QTabBar::tab {{
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-bottom-color: {tm.var(colors.SHADOW)};
-}}
-QTabBar::tab:first {{
- border-top-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
- border-bottom-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QTabBar::tab:!first {{
- margin-{tm.left()}: -1px;
-}}
-QTabBar::tab:last {{
- border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
- border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QTabBar::tab:selected {{
- color: white;
- background: {tm.var(colors.BUTTON_PRIMARY_BG)};
-}}
-QTabBar::tab:selected:hover {{
- background: {
+ def button(self, tm: ThemeManager) -> str:
+ # For some reason, Windows needs a larger padding to look the same
+ button_pad = 25 if is_win else 15
+ return f"""
+ QPushButton {{ padding-left: {button_pad}px; padding-right: {button_pad}px; }}
+ QPushButton,
+ QTabBar::tab:!selected,
+ QComboBox:!editable,
+ QComboBox::drop-down:editable {{
+ background: {tm.var(colors.BUTTON_BG)};
+ border-bottom: 1px solid {tm.var(colors.SHADOW)};
+ }}
+ QPushButton:hover,
+ QTabBar::tab:hover,
+ QComboBox:!editable:hover,
+ QSpinBox::up-button:hover,
+ QSpinBox::down-button:hover,
+ QDateTimeEdit::up-button:hover,
+ QDateTimeEdit::down-button:hover {{
+ background: {
button_gradient(
- tm.var(colors.BUTTON_PRIMARY_GRADIENT_START),
- tm.var(colors.BUTTON_PRIMARY_GRADIENT_END),
- )
- };
-}}
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ )
+ };
+ }}
+ QPushButton:pressed,
+ QSpinBox::up-button:pressed,
+ QSpinBox::down-button:pressed,
+ QDateTimeEdit::up-button:pressed,
+ QDateTimeEdit::down-button:pressed {{
+ background: {
+ button_pressed_gradient(
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ tm.var(colors.SHADOW)
+ )
+ };
+ }}
+ """
+
+ def splitter(self, tm: ThemeManager) -> str:
+ return f"""
+ QSplitter::handle,
+ QMainWindow::separator {{
+ height: 16px;
+ }}
+ QSplitter::handle:vertical,
+ QMainWindow::separator:horizontal {{
+ image: url({tm.themed_icon("mdi:drag-horizontal-FG_SUBTLE")});
+ }}
+ QSplitter::handle:horizontal,
+ QMainWindow::separator:vertical {{
+ image: url({tm.themed_icon("mdi:drag-vertical-FG_SUBTLE")});
+ }}
"""
+ def combobox(self, tm: ThemeManager) -> str:
+ return f"""
+ QComboBox {{
+ padding: {"1px 6px 2px 4px" if tm.rtl() else "1px 4px 2px 6px"};
+ }}
+ QComboBox:focus {{
+ border-color: {tm.var(colors.BORDER_FOCUS)};
+ }}
+ QComboBox:editable:on,
+ QComboBox:editable:focus,
+ QComboBox::drop-down:focus:editable,
+ QComboBox::drop-down:pressed {{
+ border-color: {tm.var(colors.BORDER_FOCUS)};
+ }}
+ QComboBox:on {{
+ border-bottom: none;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ }}
+ QComboBox::item {{
+ color: {tm.var(colors.FG)};
+ background: {tm.var(colors.CANVAS_ELEVATED)};
+ }}
-def table_styles(tm: ThemeManager) -> str:
- return f"""
-QTableView {{
+ QComboBox::item:selected {{
+ background: {tm.var(colors.HIGHLIGHT_BG)};
+ color: {tm.var(colors.HIGHLIGHT_FG)};
+ }}
+ QComboBox::item::icon:selected {{
+ position: absolute;
+ }}
+ QComboBox::drop-down {{
+ subcontrol-origin: border;
+ padding: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
+ width: 16px;
+ subcontrol-position: top right;
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QComboBox::drop-down:!editable {{
+ background: none;
+ border-color: transparent;
+ }}
+ QComboBox::down-arrow {{
+ image: url({tm.themed_icon("mdi:chevron-down")});
+ }}
+ QComboBox::drop-down:hover:editable {{
+ background: {
+ button_gradient(
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ )
+ };
+ }}
+ """
+
+ def tabwidget(self, tm: ThemeManager) -> str:
+ return f"""
+ QTabWidget {{
border-radius: {tm.var(props.BORDER_RADIUS)};
- border-{tm.left()}: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-bottom: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- gridline-color: {tm.var(colors.BORDER_SUBTLE)};
- selection-background-color: {tm.var(colors.SELECTED_BG)};
- selection-color: {tm.var(colors.SELECTED_FG)};
-}}
-QHeaderView {{
- background: {tm.var(colors.CANVAS)};
-}}
-QHeaderView::section {{
- padding-{tm.left()}: 0px;
- padding-{tm.right()}: 15px;
- border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- background: {tm.var(colors.BUTTON_BG)};
-}}
-QHeaderView::section:first {{
- margin-left: -1px;
-}}
-QHeaderView::section:pressed,
-QHeaderView::section:pressed:!first {{
- background: {
- button_pressed_gradient(
- tm.var(colors.BUTTON_GRADIENT_START),
- tm.var(colors.BUTTON_GRADIENT_END),
- tm.var(colors.SHADOW)
- )
- }
-}}
-QHeaderView::section:hover {{
- background: {
- button_gradient(
- tm.var(colors.BUTTON_GRADIENT_START),
- tm.var(colors.BUTTON_GRADIENT_END),
- )
- };
-}}
-QHeaderView::section:first {{
- border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QHeaderView::section:!first {{
- border-left: none;
-}}
-QHeaderView::section:last {{
- border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QHeaderView::section:only-one {{
- border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
- border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
- border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QHeaderView::up-arrow,
-QHeaderView::down-arrow {{
- width: 20px;
- height: 20px;
- margin-{tm.left()}: -20px;
-}}
-QHeaderView::up-arrow {{
- image: url({tm.themed_icon("mdi:menu-up")});
-}}
-QHeaderView::down-arrow {{
- image: url({tm.themed_icon("mdi:menu-down")});
-}}
- """
-
-
-def spinbox_styles(tm: ThemeManager) -> str:
- return f"""
-QSpinBox::up-button,
-QSpinBox::down-button {{
- subcontrol-origin: border;
- width: 16px;
-}}
-QSpinBox::up-button {{
- margin-bottom: -1px;
- subcontrol-position: top right;
- border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QSpinBox::down-button {{
- margin-top: -1px;
- subcontrol-position: bottom right;
- border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
-}}
-QSpinBox::up-arrow {{
- image: url({tm.themed_icon("mdi:chevron-up")});
-}}
-QSpinBox::down-arrow {{
- image: url({tm.themed_icon("mdi:chevron-down")});
-}}
-QSpinBox::up-arrow,
-QSpinBox::down-arrow,
-QSpinBox::up-arrow:pressed,
-QSpinBox::down-arrow:pressed,
-QSpinBox::up-arrow:disabled:hover, QSpinBox::up-arrow:off:hover,
-QSpinBox::down-arrow:disabled:hover, QSpinBox::down-arrow:off:hover {{
- width: 16px;
- height: 16px;
-}}
-QSpinBox::up-arrow:hover,
-QSpinBox::down-arrow:hover {{
- width: 20px;
- height: 20px;
-}}
-QSpinBox::up-button:disabled, QSpinBox::up-button:off,
-QSpinBox::down-button:disabled, QSpinBox::down-button:off {{
- background: {tm.var(colors.BUTTON_DISABLED)};
-}}
-QSpinBox::up-arrow:off,
-QSpinBox::down-arrow:off {{
- image: url({tm.themed_icon("mdi:chevron-down-FG_DISABLED")});
-}}
- """
-
-
-def checkbox_styles(tm: ThemeManager) -> str:
- return f"""
-QCheckBox,
-QRadioButton {{
- spacing: 8px;
- margin: 2px 0;
-}}
-QCheckBox::indicator,
-QRadioButton::indicator,
-QMenu::indicator {{
- border: 1px solid {tm.var(colors.BORDER)};
- border-radius: {tm.var(props.BORDER_RADIUS)};
- background: {tm.var(colors.CANVAS_ELEVATED)};
- width: 16px;
- height: 16px;
-}}
-QRadioButton::indicator,
-QMenu::indicator:exclusive {{
- border-radius: 8px;
-}}
-QCheckBox::indicator:hover,
-QCheckBox::indicator:checked:hover,
-QRadioButton::indicator:hover,
-QRadioButton::indicator:checked:hover {{
- border: 2px solid {tm.var(colors.BORDER_STRONG)};
- width: 14px;
- height: 14px;
-}}
-QCheckBox::indicator:checked,
-QRadioButton::indicator:checked,
-QMenu::indicator:checked {{
- image: url({tm.themed_icon("mdi:check")});
-}}
-QRadioButton::indicator:checked {{
- image: url({tm.themed_icon("mdi:circle-medium")});
-}}
-QCheckBox::indicator:indeterminate {{
- image: url({tm.themed_icon("mdi:minus-thick")});
-}}
- """
-
-
-def scrollbar_styles(tm: ThemeManager) -> str:
- return f"""
-QAbstractScrollArea::corner {{
background: none;
- border: none;
-}}
-QScrollBar {{
- subcontrol-origin: content;
- background-color: transparent;
-}}
-QScrollBar::handle {{
+ }}
+ QTabWidget::pane {{
+ top: -15px;
+ padding-top: 1em;
+ background: {tm.var(colors.CANVAS_ELEVATED)};
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border-radius: {tm.var(props.BORDER_RADIUS)};
- background-color: {tm.var(colors.SCROLLBAR_BG)};
-}}
-QScrollBar::handle:hover {{
- background-color: {tm.var(colors.SCROLLBAR_BG_HOVER)};
-}}
-QScrollBar::handle:pressed {{
- background-color: {tm.var(colors.SCROLLBAR_BG_ACTIVE)};
-}}
-QScrollBar:horizontal {{
- height: 12px;
-}}
-QScrollBar::handle:horizontal {{
- min-width: 60px;
-}}
-QScrollBar:vertical {{
- width: 12px;
-}}
-QScrollBar::handle:vertical {{
- min-height: 60px;
-}}
-QScrollBar::add-line {{
- border: none;
- background: none;
-}}
-QScrollBar::sub-line {{
- border: none;
- background: none;
-}}
+ }}
+ QTabWidget::tab-bar {{
+ alignment: center;
+ }}
+ QTabBar::tab {{
+ background: none;
+ padding: 4px 8px;
+ min-width: 8ex;
+ }}
+ QTabBar::tab {{
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-bottom-color: {tm.var(colors.SHADOW)};
+ }}
+ QTabBar::tab:first {{
+ border-top-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
+ border-bottom-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QTabBar::tab:!first {{
+ margin-{tm.left()}: -1px;
+ }}
+ QTabBar::tab:last {{
+ border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QTabBar::tab:selected {{
+ color: white;
+ background: {tm.var(colors.BUTTON_PRIMARY_BG)};
+ }}
+ QTabBar::tab:selected:hover {{
+ background: {
+ button_gradient(
+ tm.var(colors.BUTTON_PRIMARY_GRADIENT_START),
+ tm.var(colors.BUTTON_PRIMARY_GRADIENT_END),
+ )
+ };
+ }}
+ QTabBar::tab:disabled,
+ QTabBar::tab:disabled:hover {{
+ background: {tm.var(colors.BUTTON_DISABLED)};
+ color: {tm.var(colors.FG_DISABLED)};
+ }}
+ QTabBar::tab:selected:disabled,
+ QTabBar::tab:selected:hover:disabled {{
+ background: {tm.var(colors.BUTTON_PRIMARY_DISABLED)};
+ }}
+ """
+
+ def table(self, tm: ThemeManager) -> str:
+ return f"""
+ QTableView {{
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ border-{tm.left()}: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-bottom: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ gridline-color: {tm.var(colors.BORDER_SUBTLE)};
+ selection-background-color: {tm.var(colors.SELECTED_BG)};
+ selection-color: {tm.var(colors.SELECTED_FG)};
+ background: {tm.var(colors.CANVAS_INSET)};
+ }}
+ QHeaderView {{
+ background: {tm.var(colors.CANVAS)};
+ }}
+ QHeaderView::section {{
+ padding-{tm.left()}: 0px;
+ padding-{tm.right()}: 15px;
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ background: {tm.var(colors.BUTTON_BG)};
+ }}
+ QHeaderView::section:first {{
+ margin-left: -1px;
+ }}
+ QHeaderView::section:pressed,
+ QHeaderView::section:pressed:!first {{
+ background: {
+ button_pressed_gradient(
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ tm.var(colors.SHADOW)
+ )
+ }
+ }}
+ QHeaderView::section:hover {{
+ background: {
+ button_gradient(
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ )
+ };
+ }}
+ QHeaderView::section:first {{
+ border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QHeaderView::section:!first {{
+ border-left: none;
+ }}
+ QHeaderView::section:last {{
+ border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QHeaderView::section:only-one {{
+ border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
+ border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QHeaderView::up-arrow,
+ QHeaderView::down-arrow {{
+ width: 20px;
+ height: 20px;
+ margin-{tm.left()}: -20px;
+ }}
+ QHeaderView::up-arrow {{
+ image: url({tm.themed_icon("mdi:menu-up")});
+ }}
+ QHeaderView::down-arrow {{
+ image: url({tm.themed_icon("mdi:menu-down")});
+ }}
+ """
+
+ def spinbox(self, tm: ThemeManager) -> str:
+ return f"""
+ QSpinBox::up-button,
+ QSpinBox::down-button,
+ QDateTimeEdit::up-button,
+ QDateTimeEdit::down-button {{
+ subcontrol-origin: border;
+ width: 16px;
+ margin: 1px;
+ }}
+ QSpinBox::up-button,
+ QDateTimeEdit::up-button {{
+ margin-bottom: -1px;
+ subcontrol-position: top right;
+ border-top-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QSpinBox::down-button,
+ QDateTimeEdit::down-button {{
+ margin-top: -1px;
+ subcontrol-position: bottom right;
+ border-bottom-{tm.right()}-radius: {tm.var(props.BORDER_RADIUS)};
+ }}
+ QSpinBox::up-arrow,
+ QDateTimeEdit::up-arrow {{
+ image: url({tm.themed_icon("mdi:chevron-up")});
+ }}
+ QSpinBox::down-arrow,
+ QDateTimeEdit::down-arrow {{
+ image: url({tm.themed_icon("mdi:chevron-down")});
+ }}
+ QSpinBox::up-arrow,
+ QSpinBox::down-arrow,
+ QSpinBox::up-arrow:pressed,
+ QSpinBox::down-arrow:pressed,
+ QSpinBox::up-arrow:disabled:hover, QSpinBox::up-arrow:off:hover,
+ QSpinBox::down-arrow:disabled:hover, QSpinBox::down-arrow:off:hover,
+ QDateTimeEdit::up-arrow,
+ QDateTimeEdit::down-arrow,
+ QDateTimeEdit::up-arrow:pressed,
+ QDateTimeEdit::down-arrow:pressed,
+ QDateTimeEdit::up-arrow:disabled:hover, QDateTimeEdit::up-arrow:off:hover,
+ QDateTimeEdit::down-arrow:disabled:hover, QDateTimeEdit::down-arrow:off:hover {{
+ width: 16px;
+ height: 16px;
+ }}
+ QSpinBox::up-arrow:hover,
+ QSpinBox::down-arrow:hover,
+ QDateTimeEdit::up-arrow:hover,
+ QDateTimeEdit::down-arrow:hover {{
+ width: 20px;
+ height: 20px;
+ }}
+ QSpinBox::up-button:disabled, QSpinBox::up-button:off,
+ QSpinBox::down-button:disabled, QSpinBox::down-button:off,
+ QDateTimeEdit::up-button:disabled, QDateTimeEdit::up-button:off,
+ QDateTimeEdit::down-button:disabled, QDateTimeEdit::down-button:off {{
+ background: {tm.var(colors.BUTTON_DISABLED)};
+ }}
+ QSpinBox::up-arrow:off,
+ QDateTimeEdit::up-arrow:off {{
+ image: url({tm.themed_icon("mdi:chevron-up-FG_DISABLED")});
+ }}
+ QSpinBox::down-arrow:off,
+ QDateTimeEdit::down-arrow:off {{
+ image: url({tm.themed_icon("mdi:chevron-down-FG_DISABLED")});
+ }}
+ """
+
+ def checkbox(self, tm: ThemeManager) -> str:
+ return f"""
+ QCheckBox,
+ QRadioButton {{
+ spacing: 8px;
+ margin: 2px 0;
+ }}
+ QCheckBox::indicator,
+ QRadioButton::indicator,
+ QMenu::indicator {{
+ border: 1px solid {tm.var(colors.BORDER)};
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ background: {tm.var(colors.CANVAS_ELEVATED)};
+ width: 16px;
+ height: 16px;
+ }}
+ QRadioButton::indicator,
+ QMenu::indicator:exclusive {{
+ border-radius: 8px;
+ }}
+ QCheckBox::indicator:hover,
+ QCheckBox::indicator:checked:hover,
+ QRadioButton::indicator:hover,
+ QRadioButton::indicator:checked:hover {{
+ border: 2px solid {tm.var(colors.BORDER_STRONG)};
+ width: 14px;
+ height: 14px;
+ }}
+ QCheckBox::indicator:checked,
+ QRadioButton::indicator:checked,
+ QMenu::indicator:checked {{
+ image: url({tm.themed_icon("mdi:check")});
+ }}
+ QRadioButton::indicator:checked {{
+ image: url({tm.themed_icon("mdi:circle-medium")});
+ }}
+ QCheckBox::indicator:indeterminate {{
+ image: url({tm.themed_icon("mdi:minus-thick")});
+ }}
+ """
+
+ def scrollbar(self, tm: ThemeManager) -> str:
+ return f"""
+ QAbstractScrollArea::corner {{
+ background: none;
+ border: none;
+ }}
+ QScrollBar {{
+ subcontrol-origin: content;
+ background-color: transparent;
+ }}
+ QScrollBar::handle {{
+ border-radius: {tm.var(props.BORDER_RADIUS)};
+ background-color: {tm.var(colors.SCROLLBAR_BG)};
+ }}
+ QScrollBar::handle:hover {{
+ background-color: {tm.var(colors.SCROLLBAR_BG_HOVER)};
+ }}
+ QScrollBar::handle:pressed {{
+ background-color: {tm.var(colors.SCROLLBAR_BG_ACTIVE)};
+ }}
+ QScrollBar:horizontal {{
+ height: 12px;
+ }}
+ QScrollBar::handle:horizontal {{
+ min-width: 60px;
+ }}
+ QScrollBar:vertical {{
+ width: 12px;
+ }}
+ QScrollBar::handle:vertical {{
+ min-height: 60px;
+ }}
+ QScrollBar::add-line {{
+ border: none;
+ background: none;
+ }}
+ QScrollBar::sub-line {{
+ border: none;
+ background: none;
+ }}
+ """
+
+ def slider(self, tm: ThemeManager) -> str:
+ return f"""
+ QSlider::horizontal {{
+ height: 20px;
+ }}
+ QSlider::vertical {{
+ width: 20px;
+ }}
+ QSlider::groove {{
+ border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
+ border-radius: 3px;
+ background: {tm.var(colors.CANVAS_ELEVATED)};
+ }}
+ QSlider::sub-page {{
+ background: {tm.var(colors.BUTTON_PRIMARY_GRADIENT_START)};
+ border-radius: 3px;
+ margin: 1px;
+ }}
+ QSlider::sub-page:disabled {{
+ background: {tm.var(colors.BUTTON_DISABLED)};
+ }}
+ QSlider::add-page {{
+ margin-{tm.right()}: 2px;
+ }}
+ QSlider::groove:vertical {{
+ width: 6px;
+ }}
+ QSlider::groove:horizontal {{
+ height: 6px;
+ }}
+ QSlider::handle {{
+ background: {tm.var(colors.BUTTON_BG)};
+ border: 1px solid {tm.var(colors.BORDER)};
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ border-bottom-color: {tm.var(colors.SHADOW)};
+ }}
+ QSlider::handle:vertical {{
+ margin: 0 -7px;
+ }}
+ QSlider::handle:horizontal {{
+ margin: -7px 0;
+ }}
+ QSlider::handle:hover {{
+ background: {button_gradient(
+ tm.var(colors.BUTTON_GRADIENT_START),
+ tm.var(colors.BUTTON_GRADIENT_END),
+ )}
+ }}
"""
+
+
+custom_styles = CustomStyles()
diff --git a/qt/aqt/theme.py b/qt/aqt/theme.py
index a3ed9f38f..91fd6db3f 100644
--- a/qt/aqt/theme.py
+++ b/qt/aqt/theme.py
@@ -46,8 +46,7 @@ class ColoredIcon:
class AnkiStyles(enum.IntEnum):
ANKI = 0
- FUSION = 1
- NATIVE = 2
+ NATIVE = 1
class Theme(enum.IntEnum):
@@ -176,6 +175,8 @@ class ThemeManager:
classes.append("macos-dark-mode")
if aqt.mw.pm.reduce_motion():
classes.append("reduce-motion")
+ if not aqt.mw.pm.minimalist_mode():
+ classes.append("fancy")
if qtmajor == 5 and qtminor < 15:
classes.append("no-blur")
return " ".join(classes)
@@ -237,36 +238,24 @@ class ThemeManager:
gui_hooks.theme_did_change()
def _apply_style(self, app: QApplication) -> None:
- from aqt.stylesheets import splitter_styles
+ buf = ""
- buf = splitter_styles(self) if not aqt.mw.pm.force_native_styles() else ""
-
- if aqt.mw.pm.force_anki_styles() or not (
- aqt.mw.pm.force_native_styles() or aqt.mw.pm.force_fusion_styles() or is_mac
- ):
- from aqt.stylesheets import (
- button_styles,
- checkbox_styles,
- combobox_styles,
- general_styles,
- menu_styles,
- scrollbar_styles,
- spinbox_styles,
- table_styles,
- tabwidget_styles,
- )
+ if aqt.mw.pm.get_widget_style() == AnkiStyles.ANKI:
+ from aqt.stylesheets import custom_styles
buf += "".join(
[
- general_styles(self),
- button_styles(self),
- checkbox_styles(self),
- menu_styles(self),
- combobox_styles(self),
- tabwidget_styles(self),
- table_styles(self),
- spinbox_styles(self),
- scrollbar_styles(self),
+ custom_styles.general(self),
+ custom_styles.button(self),
+ custom_styles.checkbox(self),
+ custom_styles.menu(self),
+ custom_styles.combobox(self),
+ custom_styles.tabwidget(self),
+ custom_styles.table(self),
+ custom_styles.spinbox(self),
+ custom_styles.scrollbar(self),
+ custom_styles.slider(self),
+ custom_styles.splitter(self),
]
)
@@ -278,19 +267,6 @@ class ThemeManager:
def _apply_palette(self, app: QApplication) -> None:
set_macos_dark_mode(self.night_mode)
- if aqt.mw.pm.force_native_styles() or (
- is_mac and not (qtmajor == 5 or aqt.mw.pm.force_anki_styles())
- ):
- app.setStyle(QStyleFactory.create(self._default_style)) # type: ignore
- self.default_palette.setColor(
- QPalette.ColorRole.Window, self.qcolor(colors.CANVAS)
- )
- self.default_palette.setColor(
- QPalette.ColorRole.AlternateBase, self.qcolor(colors.CANVAS)
- )
- app.setPalette(self.default_palette)
- return
-
app.setStyle(QStyleFactory.create("fusion")) # type: ignore
palette = QPalette()
diff --git a/qt/aqt/toolbar.py b/qt/aqt/toolbar.py
index 6e1bbd2b5..87e580107 100644
--- a/qt/aqt/toolbar.py
+++ b/qt/aqt/toolbar.py
@@ -52,6 +52,11 @@ class ToolbarWebView(AnkiWebView):
return False
+ def on_body_classes_need_update(self) -> None:
+ super().on_body_classes_need_update()
+ super().adjustHeightToFit()
+ self.expand()
+
def _onHeight(self, qvar: Optional[int]) -> None:
super()._onHeight(qvar)
self.web_height = int(qvar)
diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py
index 5bba81fc7..6a23d576b 100644
--- a/qt/aqt/webview.py
+++ b/qt/aqt/webview.py
@@ -248,6 +248,7 @@ class AnkiWebView(QWebEngineView):
self.resetHandlers()
self._filterSet = False
gui_hooks.theme_did_change.append(self.on_theme_did_change)
+ gui_hooks.body_classes_need_update.append(self.on_body_classes_need_update)
qconnect(self.loadFinished, self._on_load_finished)
@@ -706,6 +707,7 @@ html {{ {font} }}
return
gui_hooks.theme_did_change.remove(self.on_theme_did_change)
+ gui_hooks.body_classes_need_update.remove(self.on_body_classes_need_update)
mw.mediaServer.clear_page_html(id(self))
self._page.deleteLater()
@@ -733,6 +735,16 @@ html {{ {font} }}
"""
)
+ def on_body_classes_need_update(self) -> None:
+ from aqt import mw
+
+ self.eval(
+ f"""document.body.classList.toggle("fancy", {json.dumps(not mw.pm.minimalist_mode())}); """
+ )
+ self.eval(
+ f"""document.body.classList.toggle("reduce-motion", {json.dumps(mw.pm.minimalist_mode())}); """
+ )
+
@deprecated(info="use theme_manager.qcolor() instead")
def get_window_bg_color(self, night_mode: Optional[bool] = None) -> QColor:
return theme_manager.qcolor(colors.CANVAS)
diff --git a/qt/aqt/widgetgallery.py b/qt/aqt/widgetgallery.py
index 09b0bccd1..5b09eb9aa 100644
--- a/qt/aqt/widgetgallery.py
+++ b/qt/aqt/widgetgallery.py
@@ -5,7 +5,7 @@ import aqt
import aqt.main
from aqt.qt import QDialog, qconnect
from aqt.theme import AnkiStyles
-from aqt.utils import is_mac, restoreGeom, saveGeom
+from aqt.utils import restoreGeom, saveGeom
class WidgetGallery(QDialog):
@@ -29,23 +29,12 @@ class WidgetGallery(QDialog):
self.form.styleComboBox.addItems(
[member.name.lower().capitalize() for member in AnkiStyles]
)
- self.form.styleComboBox.setCurrentIndex(
- AnkiStyles.FUSION
- if self.mw.pm.force_fusion_styles()
- else AnkiStyles.NATIVE
- if self.mw.pm.force_native_styles() or is_mac
- else AnkiStyles.ANKI
- )
- self.form.forceCheckBox.setChecked(self.mw.pm.has_forced_style())
-
+ self.form.styleComboBox.setCurrentIndex(self.mw.pm.get_widget_style())
qconnect(
self.form.styleComboBox.currentIndexChanged,
- self.mw.pm.set_forced_style,
+ self.mw.pm.set_widget_style,
)
def reject(self) -> None:
super().reject()
- if not self.form.forceCheckBox.isChecked():
- self.mw.pm.unset_forced_styles()
-
saveGeom(self, "WidgetGallery")
diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py
index f4fda4d17..b43660a03 100644
--- a/qt/tools/genhooks_gui.py
+++ b/qt/tools/genhooks_gui.py
@@ -613,6 +613,10 @@ hooks = [
name="theme_did_change",
doc="Called after night mode is toggled.",
),
+ Hook(
+ name="body_classes_need_update",
+ doc="Called when a setting involving a webview body class is toggled.",
+ ),
# Webview
###################
Hook(
diff --git a/sass/base.scss b/sass/base.scss
index 09f689596..e093eaeac 100644
--- a/sass/base.scss
+++ b/sass/base.scss
@@ -1,6 +1,7 @@
@use "vars" as *;
@use "root-vars";
@use "button-mixins" as button;
+@use "sass/scrollbar";
$body-color: color(fg);
$body-bg: color(canvas);
@@ -43,6 +44,26 @@ html {
overscroll-behavior: none;
}
+body {
+ &:not(.isMac),
+ &:not(.isMac) * {
+ @include scrollbar.custom;
+ }
+ &.reduce-motion,
+ &.reduce-motion * {
+ transition: none !important;
+ animation: none !important;
+ }
+ &.no-blur * {
+ backdrop-filter: none !important;
+ }
+ &:not(.fancy),
+ &:not(.fancy) * {
+ box-shadow: none !important;
+ backdrop-filter: none !important;
+ }
+}
+
button {
/* override transition for instant hover response */
transition: color var(--transition) ease-in-out, box-shadow var(--transition) ease-in-out !important;
diff --git a/sass/buttons.scss b/sass/buttons.scss
index 215df2cce..070e0873f 100644
--- a/sass/buttons.scss
+++ b/sass/buttons.scss
@@ -24,15 +24,22 @@
button {
outline: none !important;
- @include button.base;
- border-radius: var(--border-radius-large);
- padding: 8px 10px;
+ border: none;
+ background: none;
+ &:hover {
+ background: var(--button-bg);
+ }
font-weight: 500;
+ padding: 8px 10px;
margin: 0 4px;
- @include elevation(1, $opacity-boost: -0.08);
- &:hover {
- @include elevation(2);
- transition: box-shadow var(--transition) linear;
+ .fancy & {
+ @include button.base;
+ border-radius: var(--border-radius-large);
+ @include elevation(1, $opacity-boost: -0.08);
+ &:hover {
+ @include elevation(2);
+ transition: box-shadow var(--transition) linear;
+ }
}
}
diff --git a/ts/components/TitledContainer.svelte b/ts/components/TitledContainer.svelte
index e653c1caf..7dc295696 100644
--- a/ts/components/TitledContainer.svelte
+++ b/ts/components/TitledContainer.svelte
@@ -36,9 +36,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
@use "sass/elevation" as *;
.container {
width: 100%;
- background: var(--canvas-elevated);
- border: 1px solid var(--border-subtle);
- border-radius: var(--border-radius-large, 10px);
+ :global(.fancy) & {
+ background: var(--canvas-elevated);
+ border: 1px solid var(--border-subtle);
+ border-radius: var(--border-radius-medium, 10px);
+
+ &.light {
+ @include elevation(2, $opacity-boost: -0.08);
+ &:hover,
+ &:focus-within {
+ @include elevation(3);
+ }
+ }
+ &.dark {
+ @include elevation(3, $opacity-boost: -0.08);
+ &:hover,
+ &:focus-within {
+ @include elevation(4);
+ }
+ }
+ }
padding: 1rem 1.75rem 0.75rem 1.25rem;
&.rtl {
padding: 1rem 1.25rem 0.75rem 1.75rem;
@@ -49,20 +66,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
color: var(--fg-subtle);
}
}
- &.light {
- @include elevation(2, $opacity-boost: -0.08);
- &:hover,
- &:focus-within {
- @include elevation(3);
- }
- }
- &.dark {
- @include elevation(3, $opacity-boost: -0.08);
- &:hover,
- &:focus-within {
- @include elevation(4);
- }
- }
transition: box-shadow var(--transition) ease-in-out;
page-break-inside: avoid;
}