refactor: centralize button styles in app.css
- Add global .btn, .btn-primary, .btn-secondary, .btn-danger, .btn-ghost classes - Add --danger color CSS variables for multi-theme support - Add .btn-sm and .btn-lg size modifiers - Refactor all modals and views to use global button classes - Remove 260+ lines of duplicated button CSS across components Files updated: - FavoritesEditModal, FolderEditModal, FolderSettingsModal - LocalLibraryTagEditorModal, MigrationModal, PlaylistImportModal - PlaylistModal, Sidebar, LocalLibraryView, PlaylistManagerView
This commit is contained in:
1 parent
1751a83499
commit
fcda0ddf36
11 files changed
+97
-357
No files matched your search
+85
@@ -16,6 +16,11 @@
|
||||
--accent-hover: #5a9bf4;
|
||||
--accent-active: #3275e4;
|
||||
|
||||
--danger: #ef4444;
|
||||
--danger-bg: rgba(239, 68, 68, 0.1);
|
||||
--danger-border: rgba(239, 68, 68, 0.3);
|
||||
--danger-hover: rgba(239, 68, 68, 0.2);
|
||||
|
||||
--border-subtle: #2a2a2a;
|
||||
--border-strong: #3a3a3a;
|
||||
|
||||
@@ -75,6 +80,11 @@
|
||||
--border-subtle: #e0e0e0;
|
||||
--border-strong: #cccccc;
|
||||
|
||||
--danger: #dc2626;
|
||||
--danger-bg: rgba(220, 38, 38, 0.1);
|
||||
--danger-border: rgba(220, 38, 38, 0.3);
|
||||
--danger-hover: rgba(220, 38, 38, 0.15);
|
||||
|
||||
/* Alpha overrides for light theme - use black-based */
|
||||
--alpha-4: rgba(0, 0, 0, 0.04);
|
||||
--alpha-5: rgba(0, 0, 0, 0.05);
|
||||
@@ -448,3 +458,78 @@ select {
|
||||
box-shadow: inset 0 0 0 1px var(--accent-primary);
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
/* ============ Standard Buttons ============ */
|
||||
/* Reusable button styles for modals, forms, and actions */
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 8px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
color: var(--bg-primary);
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-secondary);
|
||||
border-color: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: var(--danger-bg);
|
||||
border: 1px solid var(--danger-border);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.btn-danger:hover:not(:disabled) {
|
||||
background: var(--danger-hover);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.btn-ghost:hover:not(:disabled) {
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Button sizes */
|
||||
.btn-sm {
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
padding: 12px 28px;
|
||||
font-size: 15px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
@@ -550,39 +550,6 @@
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 20px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
color: var(--bg-primary);
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-custom-gradient {
|
||||
width: 100%;
|
||||
padding: 8px 16px;
|
||||
|
||||
@@ -429,47 +429,8 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 20px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
color: var(--bg-primary);
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
/* Layout-specific: push danger button to the left */
|
||||
.modal-actions :global(.btn-danger) {
|
||||
margin-right: auto;
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
border: 1px solid rgba(239, 68, 68, 0.3);
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.btn-danger:hover:not(:disabled) {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
@@ -689,42 +689,6 @@
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
.btn-primary {
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: transparent;
|
||||
border: 1px solid var(--text-muted);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
border-color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
|
||||
.btn-secondary:disabled,
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
|
||||
@@ -299,8 +299,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
<div class="footer-actions">
|
||||
<button class="secondary-btn" onclick={onClose} disabled={saving}>Cancel</button>
|
||||
<button class="primary-btn" onclick={handleSave} disabled={saving}>
|
||||
<button class="btn btn-secondary" onclick={onClose} disabled={saving}>Cancel</button>
|
||||
<button class="btn btn-primary" onclick={handleSave} disabled={saving}>
|
||||
{saving ? 'Saving...' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
@@ -520,11 +520,8 @@ input[type="number"] {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.footer-actions :global(.primary-btn),
|
||||
.footer-actions :global(.secondary-btn) {
|
||||
.footer-actions :global(.btn) {
|
||||
min-width: 96px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.select-inline {
|
||||
|
||||
@@ -327,37 +327,8 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
/* Layout-specific: equal width buttons */
|
||||
.modal-footer :global(.btn) {
|
||||
flex: 1;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: var(--accent-primary-hover);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
@@ -523,35 +523,6 @@
|
||||
border-top: 1px solid var(--bg-tertiary);
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
.btn-primary {
|
||||
padding: 10px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: transform 150ms ease, background 150ms ease, opacity 150ms ease;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: transparent;
|
||||
border: 1px solid var(--bg-tertiary);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.btn-primary:disabled,
|
||||
.btn-secondary:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
|
||||
@@ -777,42 +777,6 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
.btn-primary {
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: transparent;
|
||||
border: 1px solid var(--text-muted);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
border-color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
|
||||
.btn-secondary:disabled,
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.hidden-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1596,41 +1596,6 @@
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
.btn-primary {
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 150ms ease, opacity 150ms ease;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--alpha-10);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: var(--accent-secondary);
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.toggle-btn {
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
|
||||
@@ -2533,7 +2533,7 @@
|
||||
{/if}
|
||||
|
||||
<div class="settings-actions">
|
||||
<button class="secondary-btn" onclick={toggleHiddenAlbumsView}>
|
||||
<button class="btn btn-secondary" onclick={toggleHiddenAlbumsView}>
|
||||
<span>{showHiddenAlbums ? 'Show Active Albums' : 'View Hidden Albums'}</span>
|
||||
{#if hiddenAlbums.length > 0}
|
||||
<span class="count">({hiddenAlbums.length})</span>
|
||||
@@ -2541,7 +2541,7 @@
|
||||
</button>
|
||||
{#if hasDiscogsCredentials}
|
||||
<button
|
||||
class="secondary-btn"
|
||||
class="btn btn-secondary"
|
||||
onclick={handleFetchMissingArtwork}
|
||||
disabled={fetchingArtwork || isOffline}
|
||||
title={isOffline ? 'Artwork fetching unavailable offline' : ''}
|
||||
@@ -2645,7 +2645,7 @@
|
||||
<div class="albums-section">
|
||||
<div class="section-header">
|
||||
<h3>Hidden Albums ({hiddenAlbums.length})</h3>
|
||||
<button class="secondary-btn" onclick={toggleHiddenAlbumsView}>
|
||||
<button class="btn btn-secondary" onclick={toggleHiddenAlbumsView}>
|
||||
<span>Back to Active Albums</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -3281,10 +3281,10 @@
|
||||
</div>
|
||||
|
||||
<div class="footer-actions">
|
||||
<button class="secondary-btn" onclick={() => showAlbumEditModal = false}>
|
||||
<button class="btn btn-secondary" onclick={() => showAlbumEditModal = false}>
|
||||
Cancel
|
||||
</button>
|
||||
<button class="primary-btn" onclick={saveAlbumEdit}>
|
||||
<button class="btn btn-primary" onclick={saveAlbumEdit}>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
@@ -3707,30 +3707,6 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.secondary-btn:hover:not(:disabled) {
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--text-muted);
|
||||
}
|
||||
|
||||
.secondary-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.discogs-hint {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
@@ -5414,35 +5390,4 @@
|
||||
.footer-hint {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.secondary-btn,
|
||||
.primary-btn {
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
background: transparent;
|
||||
border: 1px solid var(--text-muted);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.secondary-btn:hover {
|
||||
border-color: var(--text-primary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.primary-btn:hover {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
</style>
|
||||
@@ -1534,56 +1534,6 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
.btn-primary,
|
||||
.btn-danger {
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: background-color 150ms ease, opacity 150ms ease;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--alpha-10);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-primary);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: var(--accent-secondary);
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: transparent;
|
||||
border: 1px solid var(--error);
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background: var(--error);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user