diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db54a61..848c30b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -265,6 +265,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +### Themes β consistent focus borders on inputs and dropdowns + +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1052](https://github.com/Psychotoxical/psysonic/pull/1052)** + +* Text fields no longer draw a double border when focused β they now show a single clean ring across every theme. The colour-blind-safe themes keep their stronger high-contrast focus ring on every field, including the header search. +* Dropdown and popover borders now follow the active theme in all themes (a couple of themes previously rendered them with an unthemed colour). + + + ## [1.47.0] > **π Thank you to our amazing Discord community.** This release would not have been possible without your tireless support, quality checks, bug reports and all-round collaboration. Every report, every repro and every bit of feedback shaped what shipped here β thank you. Come join us: [discord.gg/AMnDRErm4u](https://discord.gg/AMnDRErm4u) diff --git a/src/styles/components/context-menu-submenu.css b/src/styles/components/context-menu-submenu.css index db10bf82..5e09e136 100644 --- a/src/styles/components/context-menu-submenu.css +++ b/src/styles/components/context-menu-submenu.css @@ -46,12 +46,18 @@ flex: 1; min-width: 0; background: var(--input-bg); - border: 1px solid var(--accent); + border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-primary); font-size: 12px; padding: 3px 7px; outline: none; + transition: border-color var(--transition-fast), box-shadow var(--transition-fast); +} + +.context-submenu-input:focus { + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-dim); } .context-submenu-input::placeholder { diff --git a/src/styles/components/orbit-session-top-strip.css b/src/styles/components/orbit-session-top-strip.css index 33fbcfc4..14a190a8 100644 --- a/src/styles/components/orbit-session-top-strip.css +++ b/src/styles/components/orbit-session-top-strip.css @@ -817,9 +817,11 @@ font-size: 14px; box-sizing: border-box; outline: none; + transition: border-color var(--transition-fast), box-shadow var(--transition-fast); } .orbit-start-modal__input:focus { border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-dim); } .orbit-start-modal__reshuffle { diff --git a/src/styles/components/playback-delay-sleep-delayed-start-modal.css b/src/styles/components/playback-delay-sleep-delayed-start-modal.css index 3e5b63bb..698771ad 100644 --- a/src/styles/components/playback-delay-sleep-delayed-start-modal.css +++ b/src/styles/components/playback-delay-sleep-delayed-start-modal.css @@ -469,6 +469,6 @@ .playback-delay-custom__input:focus { outline: none; border-color: var(--accent); - box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); + box-shadow: 0 0 0 3px var(--accent-dim); } diff --git a/src/styles/components/playlists-page.css b/src/styles/components/playlists-page.css index 92f11a26..818bb150 100644 --- a/src/styles/components/playlists-page.css +++ b/src/styles/components/playlists-page.css @@ -20,11 +20,12 @@ padding: 6px 12px; width: 220px; outline: none; - transition: border-color 0.15s; + transition: border-color var(--transition-fast), box-shadow var(--transition-fast); } .playlist-filter-input:focus { border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-dim); } .playlist-filter-input::placeholder { diff --git a/src/styles/components/ui-scale-slider.css b/src/styles/components/ui-scale-slider.css index 53b2552a..92c3065f 100644 --- a/src/styles/components/ui-scale-slider.css +++ b/src/styles/components/ui-scale-slider.css @@ -165,8 +165,8 @@ .folder-col-filter-input:focus { outline: none; - border-color: color-mix(in srgb, var(--accent) 70%, var(--border-subtle)); - box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent); + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-dim); } .folder-col.folder-col--compact .folder-col-filter { diff --git a/src/styles/themes/focus.css b/src/styles/themes/focus.css index 01315349..f7b914b2 100644 --- a/src/styles/themes/focus.css +++ b/src/styles/themes/focus.css @@ -15,3 +15,26 @@ outline-offset: var(--focus-ring-offset); } +/* Text inputs draw their OWN focus ring (border + box-shadow), so the global + outline above stacks a second ring outside it β the "double border". Drop it + for them. Specificity is deliberate: `inputβ¦:focus-visible` is (0,1,1), which + beats the global :focus-visible (0,1,0) but LOSES to the colour-blind-safe + themes' `[data-theme] *:focus-visible` (0,2,0) β so those themes keep their + stronger AAA ring on every field (incl. inputs) by design. The `:where()` + type-exclusion stays weightless so non-text controls (range/checkbox/β¦) keep + the outline everywhere. */ +input:not(:where([type='button'], [type='submit'], [type='reset'], [type='checkbox'], [type='radio'], [type='range'], [type='color'], [type='file'], [type='image'])):focus-visible, +textarea:focus-visible { + outline: none; +} + +/* Under forced-colors the OS drops the box-shadow ring, so restore an outline + as the focus indicator for those same text inputs. */ +@media (forced-colors: active) { + input:not(:where([type='button'], [type='submit'], [type='reset'], [type='checkbox'], [type='radio'], [type='range'], [type='color'], [type='file'], [type='image'])):focus-visible, + textarea:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring-color); + outline-offset: var(--focus-ring-offset); + } +} + diff --git a/src/styles/themes/semantic-cascade.css b/src/styles/themes/semantic-cascade.css index bb5b6148..0f54ad82 100644 --- a/src/styles/themes/semantic-cascade.css +++ b/src/styles/themes/semantic-cascade.css @@ -55,6 +55,8 @@ --menu-item-hover: var(--bg-hover); --menu-item-active-text: var(--accent); --menu-divider: var(--border-subtle); + --border-dropdown: var(--border); + --shadow-dropdown: rgba(0, 0, 0, 0.5); --modal-bg: var(--bg-card); --modal-scrim: rgba(17, 17, 27, 0.85); diff --git a/src/styles/themes/vision-dark-component-level-overrides.css b/src/styles/themes/vision-dark-component-level-overrides.css index cf7c79d4..605209b3 100644 --- a/src/styles/themes/vision-dark-component-level-overrides.css +++ b/src/styles/themes/vision-dark-component-level-overrides.css @@ -35,6 +35,18 @@ outline-offset: 2px; } +/* The header search wraps its input in a cluster