refactor(settings): SettingsSubCard primitives across all of Settings (#1182)

* feat(settings): add SettingsSubCard primitives for sub-section controls

Reusable wrappers (SettingsSubCard / SettingsField / SettingsRow /
SettingsValue / SettingsCallout) that encapsulate the settings-norm-* sub-card
styles. Per-mode and detail controls inside a settings section should use these
instead of hand-rolling the box with inline padding or one-off classes — the
lack of a shared primitive is what let recent additions drift off the pattern.

* refactor(settings): move the Audio tab onto the SettingsSubCard primitives

Normalization, Track transitions and Hi-Res now build their sub-cards from the
shared primitives instead of raw settings-norm-* markup. Track Previews, which
rendered its sub-options bare with inline styles and dividers, now uses the same
sub-card so the whole Audio tab is consistent. Behaviour and styling unchanged;
Track Previews' start/duration become labelled slider rows like Normalization.

* refactor(settings): move the remaining tabs onto SettingsSubCard

Apply the shared sub-card primitives across the rest of Settings so every tab
matches the Audio-tab reference look:

- Appearance: grid columns, window buttons, UI scale, font, seekbar
- Library: random-mix blacklist, rating-filter detail
- Input: in-app + global keybind lists
- Integrations: Discord templates, external-artwork BYOK
- System: language, Linux Wayland text render, clock format, logging
- Storage: media dir, hot-cache detail, downloads folder
- Backup: mode picker + per-mode export/import

Detail/per-mode controls now sit in the bordered sub-card; toggle groups stay on
SettingsToggle. Behaviour unchanged.

* refactor(settings): box the data-heavy and shared sections in SettingsSubCard

Bring the previously-skipped 'borderline' sections onto the sub-card too:

- Playback speed: wrap the settings-mode controls in a sub-card; the compact
  player-popup path is left untouched (shares the component via the compact flag)
- Theme scheduler: mode picker + theme/time selects move into the sub-card
- Cover-cache + analytics strategy: the per-server tables sit in a sub-card

Behaviour unchanged; the table layouts and the playback-rate-* internals stay as
they are, only the surrounding sub-card is added for visual consistency.
This commit is contained in:
Psychotoxical
2026-06-24 23:13:10 +02:00
committed by GitHub
parent 4e8f16b8ae
commit b6ac879b14
16 changed files with 700 additions and 624 deletions
+5
View File
@@ -6,6 +6,7 @@ import { useGlobalShortcutsStore, type GlobalAction, buildGlobalShortcut, format
import { useKeybindingsStore, type KeyAction, buildInAppBinding, formatBinding } from '../../store/keybindingsStore';
import SettingsSubSection from '../SettingsSubSection';
import { SettingsGroup } from './SettingsGroup';
import { SettingsSubCard } from './SettingsSubCard';
export function InputTab() {
const { t } = useTranslation();
@@ -34,6 +35,7 @@ export function InputTab() {
>
<div className="settings-card">
<SettingsGroup>
<SettingsSubCard>
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
{IN_APP_SHORTCUT_ACTIONS.map(({ id: action, getLabel }) => {
const label = getLabel(t);
@@ -97,6 +99,7 @@ export function InputTab() {
);
})}
</div>
</SettingsSubCard>
</SettingsGroup>
</div>
</SettingsSubSection>
@@ -120,6 +123,7 @@ export function InputTab() {
>
<div className="settings-card">
<SettingsGroup>
<SettingsSubCard>
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
{GLOBAL_SHORTCUT_ACTIONS.map(({ id: action, getLabel }) => {
const label = getLabel(t);
@@ -181,6 +185,7 @@ export function InputTab() {
);
})}
</div>
</SettingsSubCard>
</SettingsGroup>
</div>
</SettingsSubSection>