UI consistency (buttons 1/N): add shared .btn primitive; migrate config-modal
Start of the button-consolidation pass (kettui's #1). The app had ~236 button classes / ~8-10 distinct looks with heavy near-duplication. Introduce a canonical .btn design-system primitive (base + .btn--primary / .btn--secondary / .btn--danger), modeled on the dominant existing look (accent-gradient primary, translucent ghost, semantic danger) and built on the accent CSS vars. New markup and the React pages should use this; existing per-page button classes will migrate onto it family by family. First family migrated: the config/settings modal buttons (.config-modal-btn*, 4 static uses, no JS refs) -> .btn .btn--primary / .btn--secondary. Removed the now-dead .config-modal-btn* rules and re-scoped its mobile full-width override to `.config-modal-actions .btn`. Visible change is minor by design (padding 28->24px, gradient direction normalized). Proof step for sign-off on the .btn look before rolling wider.
This commit is contained in:
parent
44faf44fca
commit
eebc58d3ff
2 changed files with 64 additions and 47 deletions
|
|
@ -7467,11 +7467,11 @@
|
||||||
|
|
||||||
<div class="watchlist-artist-config-footer">
|
<div class="watchlist-artist-config-footer">
|
||||||
<div class="config-modal-actions">
|
<div class="config-modal-actions">
|
||||||
<button class="config-modal-btn config-modal-btn-secondary"
|
<button class="btn btn--secondary"
|
||||||
onclick="closeWatchlistArtistConfigModal()">
|
onclick="closeWatchlistArtistConfigModal()">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button class="config-modal-btn config-modal-btn-primary" id="save-artist-config-btn">
|
<button class="btn btn--primary" id="save-artist-config-btn">
|
||||||
Save Preferences
|
Save Preferences
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -7651,11 +7651,11 @@
|
||||||
|
|
||||||
<div class="watchlist-artist-config-footer">
|
<div class="watchlist-artist-config-footer">
|
||||||
<div class="config-modal-actions">
|
<div class="config-modal-actions">
|
||||||
<button class="config-modal-btn config-modal-btn-secondary"
|
<button class="btn btn--secondary"
|
||||||
onclick="closeWatchlistGlobalSettingsModal()">
|
onclick="closeWatchlistGlobalSettingsModal()">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button class="config-modal-btn config-modal-btn-primary" id="save-global-config-btn"
|
<button class="btn btn--primary" id="save-global-config-btn"
|
||||||
onclick="saveWatchlistGlobalConfig()">
|
onclick="saveWatchlistGlobalConfig()">
|
||||||
Save Global Settings
|
Save Global Settings
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -7990,6 +7990,64 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
||||||
/* ======================================================= */
|
/* ======================================================= */
|
||||||
|
|
||||||
/* Main Dashboard Layout */
|
/* Main Dashboard Layout */
|
||||||
|
/* ── Shared button primitive ────────────────────────────────────────
|
||||||
|
The canonical button design system. New markup (and the React pages)
|
||||||
|
should use `.btn` + a modifier; existing per-page button classes are being
|
||||||
|
migrated onto it family by family. Values reflect the dominant existing
|
||||||
|
look (accent-gradient primary, translucent ghost, semantic danger/warning).
|
||||||
|
Filter "pills" / tab buttons are a separate primitive (see .tab below). */
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
|
||||||
|
|
||||||
|
.btn--primary {
|
||||||
|
background: linear-gradient(135deg, rgb(var(--accent-rgb)), rgb(var(--accent-light-rgb)));
|
||||||
|
color: #000;
|
||||||
|
font-weight: 700;
|
||||||
|
box-shadow: 0 4px 16px rgba(var(--accent-rgb), 0.3);
|
||||||
|
}
|
||||||
|
.btn--primary:hover:not(:disabled) {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.4);
|
||||||
|
}
|
||||||
|
.btn--primary:active:not(:disabled) { transform: translateY(0); }
|
||||||
|
|
||||||
|
.btn--secondary {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
.btn--secondary:hover:not(:disabled) {
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
border-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn--danger {
|
||||||
|
background: linear-gradient(135deg, #dc2626, #ef4444);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 700;
|
||||||
|
box-shadow: 0 4px 16px rgba(220, 38, 38, 0.3);
|
||||||
|
}
|
||||||
|
.btn--danger:hover:not(:disabled) {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 6px 20px rgba(220, 38, 38, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ── Shared page shell ──────────────────────────────────────────────
|
/* ── Shared page shell ──────────────────────────────────────────────
|
||||||
The canonical page card (the dashboard / stats look). Adopted by the
|
The canonical page card (the dashboard / stats look). Adopted by the
|
||||||
dashboard, tools, watchlist and wishlist pages — and intended for reuse
|
dashboard, tools, watchlist and wishlist pages — and intended for reuse
|
||||||
|
|
@ -20880,48 +20938,7 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-modal-btn {
|
/* .config-modal-btn* migrated to the shared .btn / .btn--primary / .btn--secondary primitive. */
|
||||||
padding: 12px 28px;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-primary {
|
|
||||||
background: linear-gradient(135deg, rgb(var(--accent-light-rgb)), rgb(var(--accent-rgb)));
|
|
||||||
color: #000;
|
|
||||||
box-shadow: 0 4px 16px rgba(var(--accent-rgb), 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-primary:hover {
|
|
||||||
background: linear-gradient(135deg, #1fdf64, rgb(var(--accent-light-rgb)));
|
|
||||||
box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.4);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-primary:active {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-primary:disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-secondary {
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
color: #ffffff;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-modal-btn-secondary:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.12);
|
|
||||||
border-color: rgba(255, 255, 255, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Linked Provider Artist */
|
/* Linked Provider Artist */
|
||||||
/* Per-source linked rows */
|
/* Per-source linked rows */
|
||||||
|
|
@ -21159,7 +21176,7 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-modal-btn {
|
.config-modal-actions .btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue