feat(ui): add search history and shuffle buttons
- Implement persistent search history with 'Clear All' functionality - Add shuffle buttons for album and artist headers with robust logic - Fix repeat mode incorrectly defaulting to ON on startup - Adjust CSV progress bar position to avoid control overlap - Remove obsolete 'Inline Buttons' track action setting - Fix search history dropdown stacking and icon selector specificity
This commit is contained in:
parent
601262b70f
commit
c34d3a7db6
7 changed files with 2182 additions and 2730 deletions
4617
index.html
4617
index.html
File diff suppressed because one or more lines are too long
71
js/app.js
71
js/app.js
|
|
@ -464,21 +464,67 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const btn = e.target.closest('#play-album-btn');
|
const btn = e.target.closest('#play-album-btn');
|
||||||
if (btn.disabled) return;
|
if (btn.disabled) return;
|
||||||
|
|
||||||
const albumId = window.location.pathname.split('/')[2];
|
const pathParts = window.location.pathname.split('/');
|
||||||
|
const albumIndex = pathParts.indexOf('album');
|
||||||
|
const albumId = albumIndex !== -1 ? pathParts[albumIndex + 1] : null;
|
||||||
|
|
||||||
if (!albumId) return;
|
if (!albumId) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { tracks } = await api.getAlbum(albumId);
|
const { tracks } = await api.getAlbum(albumId);
|
||||||
if (tracks.length > 0) {
|
if (tracks && tracks.length > 0) {
|
||||||
player.setQueue(tracks, 0);
|
// Sort tracks by disc and track number for consistent playback
|
||||||
document.getElementById('shuffle-btn').classList.remove('active');
|
const sortedTracks = [...tracks].sort((a, b) => {
|
||||||
|
const discA = a.volumeNumber ?? a.discNumber ?? 1;
|
||||||
|
const discB = b.volumeNumber ?? b.discNumber ?? 1;
|
||||||
|
if (discA !== discB) return discA - discB;
|
||||||
|
return a.trackNumber - b.trackNumber;
|
||||||
|
});
|
||||||
|
|
||||||
|
player.setQueue(sortedTracks, 0);
|
||||||
|
const shuffleBtn = document.getElementById('shuffle-btn');
|
||||||
|
if (shuffleBtn) shuffleBtn.classList.remove('active');
|
||||||
|
player.shuffleActive = false;
|
||||||
player.playTrackFromQueue();
|
player.playTrackFromQueue();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to play album:', error);
|
console.error('Failed to play album:', error);
|
||||||
alert('Failed to play album: ' + error.message);
|
showNotification('Failed to play album');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.target.closest('#shuffle-album-btn')) {
|
||||||
|
const btn = e.target.closest('#shuffle-album-btn');
|
||||||
|
if (btn.disabled) return;
|
||||||
|
|
||||||
|
const pathParts = window.location.pathname.split('/');
|
||||||
|
const albumIndex = pathParts.indexOf('album');
|
||||||
|
const albumId = albumIndex !== -1 ? pathParts[albumIndex + 1] : null;
|
||||||
|
|
||||||
|
if (!albumId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { tracks } = await api.getAlbum(albumId);
|
||||||
|
if (tracks && tracks.length > 0) {
|
||||||
|
const shuffledTracks = [...tracks].sort(() => Math.random() - 0.5);
|
||||||
|
player.setQueue(shuffledTracks, 0);
|
||||||
|
const shuffleBtn = document.getElementById('shuffle-btn');
|
||||||
|
if (shuffleBtn) shuffleBtn.classList.remove('active');
|
||||||
|
player.shuffleActive = false;
|
||||||
|
player.playTrackFromQueue();
|
||||||
|
showNotification('Shuffling album');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to shuffle album:', error);
|
||||||
|
showNotification('Failed to shuffle album');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.target.closest('#shuffle-artist-btn')) {
|
||||||
|
const btn = e.target.closest('#shuffle-artist-btn');
|
||||||
|
if (btn.disabled) return;
|
||||||
|
document.getElementById('play-artist-radio-btn')?.click();
|
||||||
|
}
|
||||||
if (e.target.closest('#download-mix-btn')) {
|
if (e.target.closest('#download-mix-btn')) {
|
||||||
const btn = e.target.closest('#download-mix-btn');
|
const btn = e.target.closest('#download-mix-btn');
|
||||||
if (btn.disabled) return;
|
if (btn.disabled) return;
|
||||||
|
|
@ -1180,6 +1226,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|
||||||
const performSearch = debounce((query) => {
|
const performSearch = debounce((query) => {
|
||||||
if (query) {
|
if (query) {
|
||||||
|
ui.addToSearchHistory(query);
|
||||||
navigate(`/search/${encodeURIComponent(query)}`);
|
navigate(`/search/${encodeURIComponent(query)}`);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
@ -1191,11 +1238,25 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
searchInput.addEventListener('focus', () => {
|
||||||
|
ui.renderSearchHistory();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!e.target.closest('.search-bar')) {
|
||||||
|
const historyEl = document.getElementById('search-history');
|
||||||
|
if (historyEl) historyEl.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
searchForm.addEventListener('submit', (e) => {
|
searchForm.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const query = searchInput.value.trim();
|
const query = searchInput.value.trim();
|
||||||
if (query) {
|
if (query) {
|
||||||
|
ui.addToSearchHistory(query);
|
||||||
navigate(`/search/${encodeURIComponent(query)}`);
|
navigate(`/search/${encodeURIComponent(query)}`);
|
||||||
|
const historyEl = document.getElementById('search-history');
|
||||||
|
if (historyEl) historyEl.style.display = 'none';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
21
js/events.js
21
js/events.js
|
|
@ -40,7 +40,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
shuffleBtn.classList.add('active');
|
shuffleBtn.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.repeatMode !== REPEAT_MODE.OFF) {
|
if (player.repeatMode && player.repeatMode !== REPEAT_MODE.OFF) {
|
||||||
repeatBtn.classList.add('active');
|
repeatBtn.classList.add('active');
|
||||||
if (player.repeatMode === REPEAT_MODE.ONE) {
|
if (player.repeatMode === REPEAT_MODE.ONE) {
|
||||||
repeatBtn.classList.add('repeat-one');
|
repeatBtn.classList.add('repeat-one');
|
||||||
|
|
@ -808,10 +808,9 @@ export async function handleTrackAction(
|
||||||
return `
|
return `
|
||||||
<div class="modal-option ${alreadyContains ? 'already-contains' : ''}" data-id="${p.id}">
|
<div class="modal-option ${alreadyContains ? 'already-contains' : ''}" data-id="${p.id}">
|
||||||
<span>${p.name}</span>
|
<span>${p.name}</span>
|
||||||
${
|
${alreadyContains
|
||||||
alreadyContains
|
? `<button class="remove-from-playlist-btn-modal" title="Remove from playlist" style="background: transparent; border: none; color: inherit; cursor: pointer; padding: 4px; display: flex; align-items: center;">${SVG_BIN}</button>`
|
||||||
? `<button class="remove-from-playlist-btn-modal" title="Remove from playlist" style="background: transparent; border: none; color: inherit; cursor: pointer; padding: 4px; display: flex; align-items: center;">${SVG_BIN}</button>`
|
: ''
|
||||||
: ''
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
@ -1109,12 +1108,12 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
|
||||||
const type = card.dataset.albumId
|
const type = card.dataset.albumId
|
||||||
? 'album'
|
? 'album'
|
||||||
: card.dataset.playlistId
|
: card.dataset.playlistId
|
||||||
? 'playlist'
|
? 'playlist'
|
||||||
: card.dataset.mixId
|
: card.dataset.mixId
|
||||||
? 'mix'
|
? 'mix'
|
||||||
: card.dataset.href
|
: card.dataset.href
|
||||||
? card.dataset.href.split('/')[1]
|
? card.dataset.href.split('/')[1]
|
||||||
: 'item';
|
: 'item';
|
||||||
const id = card.dataset.albumId || card.dataset.playlistId || card.dataset.mixId;
|
const id = card.dataset.albumId || card.dataset.playlistId || card.dataset.mixId;
|
||||||
|
|
||||||
const item = trackDataStore.get(card) || {
|
const item = trackDataStore.get(card) || {
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ export class Player {
|
||||||
this.originalQueueBeforeShuffle = savedState.originalQueueBeforeShuffle || [];
|
this.originalQueueBeforeShuffle = savedState.originalQueueBeforeShuffle || [];
|
||||||
this.currentQueueIndex = savedState.currentQueueIndex ?? -1;
|
this.currentQueueIndex = savedState.currentQueueIndex ?? -1;
|
||||||
this.shuffleActive = savedState.shuffleActive || false;
|
this.shuffleActive = savedState.shuffleActive || false;
|
||||||
this.repeatMode = savedState.repeatMode || REPEAT_MODE.OFF;
|
this.repeatMode = savedState.repeatMode !== undefined ? savedState.repeatMode : REPEAT_MODE.OFF;
|
||||||
|
|
||||||
// Restore current track if queue exists and index is valid
|
// Restore current track if queue exists and index is valid
|
||||||
const currentQueue = this.shuffleActive ? this.shuffledQueue : this.queue;
|
const currentQueue = this.shuffleActive ? this.shuffledQueue : this.queue;
|
||||||
|
|
@ -244,7 +244,7 @@ export class Player {
|
||||||
// Warm connection/cache
|
// Warm connection/cache
|
||||||
// For Blob URLs (DASH), this head request is not needed and can cause errors.
|
// For Blob URLs (DASH), this head request is not needed and can cause errors.
|
||||||
if (!streamUrl.startsWith('blob:')) {
|
if (!streamUrl.startsWith('blob:')) {
|
||||||
fetch(streamUrl, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch(() => {});
|
fetch(streamUrl, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch(() => { });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name !== 'AbortError') {
|
if (error.name !== 'AbortError') {
|
||||||
|
|
|
||||||
|
|
@ -466,7 +466,8 @@ export const trackListSettings = {
|
||||||
|
|
||||||
getMode() {
|
getMode() {
|
||||||
try {
|
try {
|
||||||
const mode = localStorage.getItem(this.STORAGE_KEY) || 'dropdown';
|
let mode = localStorage.getItem(this.STORAGE_KEY) || 'dropdown';
|
||||||
|
if (mode === 'inline') mode = 'dropdown';
|
||||||
document.documentElement.setAttribute('data-track-actions-mode', mode);
|
document.documentElement.setAttribute('data-track-actions-mode', mode);
|
||||||
return mode;
|
return mode;
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
||||||
93
js/ui.js
93
js/ui.js
|
|
@ -1533,10 +1533,10 @@ export class UIRenderer {
|
||||||
dateDisplay =
|
dateDisplay =
|
||||||
window.innerWidth > 768
|
window.innerWidth > 768
|
||||||
? releaseDate.toLocaleDateString('en-US', {
|
? releaseDate.toLocaleDateString('en-US', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
})
|
})
|
||||||
: year;
|
: year;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2268,9 +2268,9 @@ export class UIRenderer {
|
||||||
<span>${artist.popularity}% popularity</span>
|
<span>${artist.popularity}% popularity</span>
|
||||||
<div class="artist-tags">
|
<div class="artist-tags">
|
||||||
${(artist.artistRoles || [])
|
${(artist.artistRoles || [])
|
||||||
.filter((role) => role.category)
|
.filter((role) => role.category)
|
||||||
.map((role) => `<span class="artist-tag">${role.category}</span>`)
|
.map((role) => `<span class="artist-tag">${role.category}</span>`)
|
||||||
.join('')}
|
.join('')}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
@ -2854,4 +2854,83 @@ export class UIRenderer {
|
||||||
artistEl.textContent = e.message || 'Track not found or unavailable';
|
artistEl.textContent = e.message || 'Track not found or unavailable';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSearchHistory() {
|
||||||
|
const historyEl = document.getElementById('search-history');
|
||||||
|
if (!historyEl) return;
|
||||||
|
|
||||||
|
const history = JSON.parse(localStorage.getItem('search-history') || '[]');
|
||||||
|
if (history.length === 0) {
|
||||||
|
historyEl.style.display = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
historyEl.innerHTML = history
|
||||||
|
.map(
|
||||||
|
(query) => `
|
||||||
|
<div class="search-history-item" data-query="${escapeHtml(query)}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="history-icon">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<polyline points="12 6 12 12 16 14"></polyline>
|
||||||
|
</svg>
|
||||||
|
<span class="query-text">${escapeHtml(query)}</span>
|
||||||
|
<span class="delete-history-btn" title="Remove from history">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.join('') +
|
||||||
|
`
|
||||||
|
<div class="search-history-clear-all" id="clear-search-history">
|
||||||
|
Clear all history
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
historyEl.style.display = 'block';
|
||||||
|
|
||||||
|
// Add event listeners
|
||||||
|
historyEl.querySelectorAll('.search-history-item').forEach((item) => {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
if (e.target.closest('.delete-history-btn')) {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.removeFromSearchHistory(item.dataset.query);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const query = item.dataset.query;
|
||||||
|
const searchInput = document.getElementById('search-input');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.value = query;
|
||||||
|
searchInput.dispatchEvent(new Event('input'));
|
||||||
|
historyEl.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const clearBtn = document.getElementById('clear-search-history');
|
||||||
|
if (clearBtn) {
|
||||||
|
clearBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
localStorage.removeItem('search-history');
|
||||||
|
this.renderSearchHistory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFromSearchHistory(query) {
|
||||||
|
let history = JSON.parse(localStorage.getItem('search-history') || '[]');
|
||||||
|
history = history.filter((q) => q !== query);
|
||||||
|
localStorage.setItem('search-history', JSON.stringify(history));
|
||||||
|
this.renderSearchHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
addToSearchHistory(query) {
|
||||||
|
if (!query || query.trim().length === 0) return;
|
||||||
|
let history = JSON.parse(localStorage.getItem('search-history') || '[]');
|
||||||
|
history = history.filter((q) => q !== query);
|
||||||
|
history.unshift(query);
|
||||||
|
history = history.slice(0, 10);
|
||||||
|
localStorage.setItem('search-history', JSON.stringify(history));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
styles.css
103
styles.css
|
|
@ -343,7 +343,11 @@ kbd {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure content sits on top of background */
|
/* Ensure content sits on top of background */
|
||||||
.main-header,
|
.main-header {
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
@ -450,7 +454,7 @@ kbd {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bar svg {
|
.search-bar svg.search-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0.75rem;
|
left: 0.75rem;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|
@ -493,6 +497,7 @@ kbd {
|
||||||
margin-bottom: var(--spacing-xl);
|
margin-bottom: var(--spacing-xl);
|
||||||
gap: var(--spacing-md);
|
gap: var(--spacing-md);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-controls {
|
.navigation-controls {
|
||||||
|
|
@ -573,6 +578,83 @@ body.has-page-background .track-item:hover {
|
||||||
background-color: var(--track-hover-bg, var(--secondary));
|
background-color: var(--track-hover-bg, var(--secondary));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-history {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: var(--card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-top: none;
|
||||||
|
border-radius: 0 0 var(--radius) var(--radius);
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 9999;
|
||||||
|
box-shadow: var(--shadow-xl);
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item:hover {
|
||||||
|
background: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item .history-icon {
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
opacity: 0.5;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item .query-text {
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item .delete-history-btn {
|
||||||
|
padding: 4px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity var(--transition);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-item .delete-history-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-clear-all {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--primary);
|
||||||
|
cursor: pointer;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
transition: background var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-clear-all:hover {
|
||||||
|
background: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="search"]::-webkit-search-cancel-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -637,6 +719,7 @@ body.has-page-background .track-item:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
|
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
@ -955,6 +1038,7 @@ body.has-page-background .track-item:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1100px) {
|
@media (max-width: 1100px) {
|
||||||
|
|
||||||
#home-recommended-songs,
|
#home-recommended-songs,
|
||||||
#artist-detail-tracks,
|
#artist-detail-tracks,
|
||||||
#playlist-detail-recommended {
|
#playlist-detail-recommended {
|
||||||
|
|
@ -1080,7 +1164,8 @@ body.has-page-background .track-item:hover {
|
||||||
|
|
||||||
.track-item.dragging {
|
.track-item.dragging {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
z-index: 1000;
|
z-index: 2000;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-number {
|
.track-number {
|
||||||
|
|
@ -1553,11 +1638,11 @@ body.has-page-background .track-item:hover {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked + .slider {
|
input:checked+.slider {
|
||||||
background-color: var(--primary);
|
background-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked + .slider::before {
|
input:checked+.slider::before {
|
||||||
transform: translateX(16px);
|
transform: translateX(16px);
|
||||||
background-color: var(--primary-foreground);
|
background-color: var(--primary-foreground);
|
||||||
}
|
}
|
||||||
|
|
@ -3362,8 +3447,8 @@ img[src=''] {
|
||||||
/* fuck this chud ass shit bro */
|
/* fuck this chud ass shit bro */
|
||||||
.csv-import-progress {
|
.csv-import-progress {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 20px;
|
bottom: 120px;
|
||||||
right: 20px;
|
right: 3%;
|
||||||
background: var(--card);
|
background: var(--card);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
|
@ -4049,7 +4134,7 @@ img[src=''] {
|
||||||
}
|
}
|
||||||
|
|
||||||
.csv-import-progress {
|
.csv-import-progress {
|
||||||
bottom: 10px;
|
bottom: 145px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
|
|
@ -4708,4 +4793,4 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue