feat(titlebar): selectable window button styles + minimize toggle (#1083)

* feat(titlebar): selectable window button styles + minimize toggle

Custom title bar (Linux) gains a window-button style picker, mirroring
the seekbar style picker pattern. Six form-named styles: dots, dotsGlyph,
flat, pill, outline, glyph. All buttons now carry minimize/maximize/close
glyphs for clear, colour-blind-friendly iconography; dots reveal glyphs on
hover, dotsGlyph always shows them.

- New authStore state windowButtonStyle (default dots) + showMinimizeButton,
  with rehydrate validation falling back to dots on unknown values.
- WindowButtonPreview reuses the real .titlebar-btn classes for WYSIWYG tiles.
- Picker + minimize toggle render under the Custom title bar setting, gated
  on the toggle being on.
- Monochrome styles use --text-primary glyphs and stronger borders for
  contrast on dark themes.
- Dev-build grey marker scoped to the real title bar so previews show true
  colours.
- i18n keys in all 9 locales; setter and rehydrate tests.

* docs(changelog): window button styles (#1083)
This commit is contained in:
Psychotoxical
2026-06-13 23:52:56 +02:00
committed by GitHub
parent be3f1dc299
commit 028eb65f7d
21 changed files with 386 additions and 47 deletions
+22 -10
View File
@@ -1,11 +1,15 @@
import React from 'react';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { Minus, Square, X } from 'lucide-react';
import { usePlayerStore } from '../store/playerStore';
import { useAuthStore } from '../store/authStore';
export default function TitleBar() {
const win = getCurrentWindow();
const currentTrack = usePlayerStore(s => s.currentTrack);
const isPlaying = usePlayerStore(s => s.isPlaying);
const windowButtonStyle = useAuthStore(s => s.windowButtonStyle);
const showMinimizeButton = useAuthStore(s => s.showMinimizeButton);
return (
<div className="titlebar" data-tauri-drag-region>
@@ -20,28 +24,36 @@ export default function TitleBar() {
)}
</div>
<div className="titlebar-controls">
<button
className="titlebar-btn titlebar-btn-minimize"
onClick={() => win.minimize()}
data-tooltip="Minimize"
data-tooltip-pos="bottom"
aria-label="Minimize"
/>
<div className="titlebar-controls" data-btnstyle={windowButtonStyle}>
{showMinimizeButton && (
<button
className="titlebar-btn titlebar-btn-minimize"
onClick={() => win.minimize()}
data-tooltip="Minimize"
data-tooltip-pos="bottom"
aria-label="Minimize"
>
<Minus size={10} strokeWidth={2.5} aria-hidden />
</button>
)}
<button
className="titlebar-btn titlebar-btn-maximize"
onClick={() => win.toggleMaximize()}
data-tooltip="Maximize"
data-tooltip-pos="bottom"
aria-label="Maximize"
/>
>
<Square size={9} strokeWidth={2.5} aria-hidden />
</button>
<button
className="titlebar-btn titlebar-btn-close"
onClick={() => win.close()}
data-tooltip="Close"
data-tooltip-pos="bottom"
aria-label="Close"
/>
>
<X size={10} strokeWidth={2.5} aria-hidden />
</button>
</div>
</div>
);