feat(web): add button size toggle (S/M/L) in header

Adds a size selector in the header bar that allows users to choose
between Small, Medium, and Large sound buttons. Choice persists
via localStorage. Responsive breakpoints also respect the setting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bot 2026-03-01 02:03:04 +01:00
parent ba8c07f347
commit e0bbe03851
2 changed files with 142 additions and 1 deletions

View file

@ -25,6 +25,12 @@ const THEMES = [
];
type Tab = 'all' | 'favorites' | 'recent';
type BtnSize = 'S' | 'M' | 'L';
const BTN_SIZES: { id: BtnSize; label: string }[] = [
{ id: 'S', label: 'S' },
{ id: 'M', label: 'M' },
{ id: 'L', label: 'L' },
];
export default function App() {
/* ── State ── */
@ -44,6 +50,7 @@ export default function App() {
const [volume, setVolume] = useState(1);
const [favs, setFavs] = useState<Record<string, boolean>>({});
const [theme, setTheme] = useState(() => localStorage.getItem('jb-theme') || 'midnight');
const [btnSize, setBtnSize] = useState<BtnSize>(() => (localStorage.getItem('jb-btn-size') as BtnSize) || 'M');
const [isAdmin, setIsAdmin] = useState(false);
const [showAdmin, setShowAdmin] = useState(false);
@ -91,6 +98,11 @@ export default function App() {
localStorage.setItem('jb-theme', theme);
}, [theme]);
/* ── Button Size ── */
useEffect(() => {
localStorage.setItem('jb-btn-size', btnSize);
}, [btnSize]);
/* ── SSE ── */
useEffect(() => {
const unsub = subscribeEvents((msg) => {
@ -230,7 +242,7 @@ export default function App() {
/* ── Render ── */
return (
<div className={`app-shell ${chaosMode ? 'party-active' : ''}`}>
<div className={`app-shell ${chaosMode ? 'party-active' : ''}`} data-btn-size={btnSize}>
{/* ════════ Header ════════ */}
<header className="header">
@ -256,6 +268,18 @@ export default function App() {
<strong>{total}</strong> Sounds
</div>
<div className="size-toggle" title="Button-Größe">
{BTN_SIZES.map(s => (
<button
key={s.id}
className={`size-opt ${btnSize === s.id ? 'active' : ''}`}
onClick={() => setBtnSize(s.id)}
>
{s.label}
</button>
))}
</div>
<select
className="select-clean"
value={theme}

View file

@ -378,6 +378,40 @@ input, select {
font-weight: 700;
}
/* ── Size Toggle (S / M / L) ── */
.size-toggle {
display: inline-flex;
background: var(--bg-surface-2);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
overflow: hidden;
flex-shrink: 0;
}
.size-opt {
padding: 4px 10px;
font-size: 11px;
font-weight: 700;
color: var(--text-muted);
transition: all 0.15s;
border-right: 1px solid var(--border);
line-height: 1;
}
.size-opt:last-child {
border-right: none;
}
.size-opt:hover {
color: var(--text-primary);
background: var(--bg-surface-3);
}
.size-opt.active {
color: var(--accent);
background: var(--accent-subtle);
}
/* Theme & Channel selects */
.select-clean {
appearance: none;
@ -677,6 +711,71 @@ input, select {
background: var(--warning);
}
/* ── Button Size Variants (S / M / L) ── */
/* S = default (36px) */
[data-btn-size="M"] .sound-btn {
height: 46px;
font-size: 13.5px;
max-width: 260px;
padding: 0 16px 0 0;
}
[data-btn-size="M"] .sound-btn .sound-label {
line-height: 46px;
padding: 0 12px;
}
[data-btn-size="M"] .sound-btn .cat-bar {
width: 4px;
}
[data-btn-size="M"] .sound-btn .fav-star {
right: 4px;
}
[data-btn-size="M"] .sound-btn .fav-star .material-icons {
font-size: 16px;
}
[data-btn-size="M"] .sound-btn .badge-dot {
width: 7px;
height: 7px;
top: 4px;
right: 4px;
}
[data-btn-size="L"] .sound-btn {
height: 58px;
font-size: 14.5px;
max-width: 300px;
padding: 0 20px 0 0;
}
[data-btn-size="L"] .sound-btn .sound-label {
line-height: 58px;
padding: 0 14px;
}
[data-btn-size="L"] .sound-btn .cat-bar {
width: 5px;
}
[data-btn-size="L"] .sound-btn .fav-star {
right: 6px;
}
[data-btn-size="L"] .sound-btn .fav-star .material-icons {
font-size: 18px;
}
[data-btn-size="L"] .sound-btn .badge-dot {
width: 8px;
height: 8px;
top: 5px;
right: 5px;
}
/*
Control Bar (Bottom)
*/
@ -1212,6 +1311,24 @@ input, select {
max-width: 180px;
}
[data-btn-size="M"] .sound-btn {
height: 40px;
font-size: 12.5px;
max-width: 220px;
}
[data-btn-size="M"] .sound-btn .sound-label {
line-height: 40px;
}
[data-btn-size="L"] .sound-btn {
height: 50px;
font-size: 13.5px;
max-width: 260px;
}
[data-btn-size="L"] .sound-btn .sound-label {
line-height: 50px;
}
.control-bar {
padding: 0 12px;
height: auto;