From e1ff4385d6d37db0c140172142a0489304eead38 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Mon, 29 Jun 2026 06:48:26 +0200 Subject: [PATCH] feat(settings): add "Square Corners" appearance toggle (#1215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(settings): add "Square Corners" appearance toggle A Display toggle in Settings → Appearance → Visual Options that overrides the active theme to render cards and cover art with square (non-rounded) corners, for a sharper, boxy look. Covered surfaces: grid cards (album/playlist/artist/song/because) and their covers, detail-header heros (album/playlist/tracks), the Now Playing / Radio view, the fullscreen player, the cover lightbox, the queue panel cover, and the mini player. Persisted in themeStore and driven by an `html[data-square-corners]` attribute set in App.tsx — applied in both the main and mini-player webviews (the mini player rehydrates the theme store on the shared `storage` event). Strings added for all 12 locales. * docs(changelog): add Square Corners to 1.50.0 CHANGELOG and What's New --- CHANGELOG.md | 11 ++++ WHATS_NEW.md | 9 +++ src/App.tsx | 9 +++ src/components/settings/AppearanceTab.tsx | 7 +++ src/locales/de/settings.ts | 2 + src/locales/en/settings.ts | 2 + src/locales/es/settings.ts | 2 + src/locales/fr/settings.ts | 2 + src/locales/hu/settings.ts | 2 + src/locales/ja/settings.ts | 2 + src/locales/nb/settings.ts | 2 + src/locales/nl/settings.ts | 2 + src/locales/pl/settings.ts | 2 + src/locales/ro/settings.ts | 2 + src/locales/ru/settings.ts | 2 + src/locales/zh/settings.ts | 2 + src/store/themeStore.ts | 6 ++ src/styles/components/index.css | 1 + src/styles/components/square-corners.css | 70 +++++++++++++++++++++++ 19 files changed, 137 insertions(+) create mode 100644 src/styles/components/square-corners.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 271b0cca..431bbb47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > +## [1.50.0] + +## Added + +### Square corners — sharp-edged cards and covers + +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1215](https://github.com/Psychotoxical/psysonic/pull/1215)** + +* New **Square Corners** toggle under **Settings → Appearance → Visual Options → Display** overrides the active theme to render cards and cover art with square, non-rounded corners. Covers album, playlist, artist and song cards, detail-page cover art, the Now Playing / Radio and fullscreen views, the cover lightbox, the queue cover, and the mini player. Off by default; buttons, inputs and dialogs keep the theme's corners. + + ## [1.49.0] - 2026-06-29 ## Added diff --git a/WHATS_NEW.md b/WHATS_NEW.md index 844930ca..1d28ed1f 100644 --- a/WHATS_NEW.md +++ b/WHATS_NEW.md @@ -8,6 +8,15 @@ Within each section, order by **user impact** (most noticeable first) — not PR `CHANGELOG.md` keeps strict PR order inside Added / Changed / Fixed. +## [1.50.0] + +## Highlights + +### Square corners — a sharper, boxier look + +- New **Square Corners** toggle under **Settings → Appearance → Visual Options** strips the rounded corners off cards and cover art across the app — handy when a theme's rounding doesn't suit your album covers. Off by default; everything else stays the way your theme defines it. + + ## [1.49.0] ## Highlights diff --git a/src/App.tsx b/src/App.tsx index eae0b414..55819b8d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -86,6 +86,15 @@ export default function App() { document.documentElement.setAttribute('data-button-size', buttonSize); }, [buttonSize]); + // Strip rounded corners off grid cards when the user opts in — single CSS + // hook (`html[data-square-corners]`) overriding whatever radius the theme set. + const squareCorners = useThemeStore(s => s.squareCorners); + useEffect(() => { + const root = document.documentElement; + if (squareCorners) root.setAttribute('data-square-corners', ''); + else root.removeAttribute('data-square-corners'); + }, [squareCorners]); + // Hide all inline track-preview buttons when the user opts out — single // CSS hook (`html[data-track-previews="off"]`) instead of conditional // rendering in every tracklist. Per-location toggles use additional diff --git a/src/components/settings/AppearanceTab.tsx b/src/components/settings/AppearanceTab.tsx index 37b8bfea..2bebecb5 100644 --- a/src/components/settings/AppearanceTab.tsx +++ b/src/components/settings/AppearanceTab.tsx @@ -104,6 +104,13 @@ export function AppearanceTab() { onChange={theme.setFloatingPlayerBar} />
+ +
void; floatingPlayerBar: boolean; setFloatingPlayerBar: (v: boolean) => void; + /** Strip rounded corners off all grid cards (and their covers), overriding the + * active theme. Drives `html[data-square-corners]` in App.tsx. */ + squareCorners: boolean; + setSquareCorners: (v: boolean) => void; /** Master toggle for external artist artwork (fanart.tv). Off by default (§20). */ externalArtworkEnabled: boolean; setExternalArtworkEnabled: (v: boolean) => void; @@ -149,6 +153,8 @@ export const useThemeStore = create()( setExpandReplayGain: (v) => set({ expandReplayGain: v }), floatingPlayerBar: false, setFloatingPlayerBar: (v) => set({ floatingPlayerBar: v }), + squareCorners: false, + setSquareCorners: (v) => set({ squareCorners: v }), externalArtworkEnabled: false, setExternalArtworkEnabled: (v) => set({ externalArtworkEnabled: v }), externalArtworkByok: '', diff --git a/src/styles/components/index.css b/src/styles/components/index.css index 3738140f..4d1a851a 100644 --- a/src/styles/components/index.css +++ b/src/styles/components/index.css @@ -96,3 +96,4 @@ @import './back-to-top.css'; @import './error-boundary.css'; @import './backdrop-source-list.css'; +@import './square-corners.css'; diff --git a/src/styles/components/square-corners.css b/src/styles/components/square-corners.css new file mode 100644 index 00000000..45e8f163 --- /dev/null +++ b/src/styles/components/square-corners.css @@ -0,0 +1,70 @@ +/* ── Square Corners override ── + * + * Toggled by `html[data-square-corners]` (themeStore `squareCorners`, set in + * App.tsx). A global, theme-independent override that strips the rounded + * corners off the grid cards (album / playlist / artist / song / "because") + * and their cover artwork, for users who prefer a sharp, boxy look. + * + * Scope is deliberately limited to cards + their covers — buttons, inputs, + * dialogs and the player bar keep whatever radius the active theme defines. + * `!important` is required because some themes set card radii with their own + * `!important` (see e.g. `.artist-card-avatar-initial`). + * + * The fallback artist initials avatar (`.artist-card-avatar-initial`) stays a + * circle on purpose — it is an avatar placeholder, not a card corner. */ + +/* Grid cards + their covers. */ +html[data-square-corners] :is( + .card, + .album-card, + .artist-card, + .song-card, + .because-card, + .album-card-cover, + .because-card-cover-wrap, + .artist-card-avatar, + .album-card-cover img, + .artist-card-avatar img +) { + border-radius: 0 !important; +} + +/* Large cover art in the album / playlist / tracks detail headers (heros). */ +html[data-square-corners] :is( + .album-detail-cover, + .album-detail-cover-btn, + .hero-cover, + .playlist-hero-cover, + .tracks-hero-cover, + .tracks-hero-cover img +) { + border-radius: 0 !important; +} + +/* Now Playing / Radio full view cover art. */ +html[data-square-corners] :is( + .np-dash-hero-cover, + .np-cover +) { + border-radius: 0 !important; +} + +/* Fullscreen player, the cover lightbox, and the queue panel's current cover. */ +html[data-square-corners] :is( + .fsp-cover, + .cover-lightbox-img, + .queue-current-cover +) { + border-radius: 0 !important; +} + +/* Mini player cover. The mini player is a separate webview, but the + * `data-square-corners` attribute is applied in both window kinds (the App.tsx + * attribute effects run in each webview, and the mini player rehydrates the + * theme store on the shared-localStorage `storage` event). */ +html[data-square-corners] :is( + .mp-cover, + .mp-album-cover +) { + border-radius: 0 !important; +}