Fix: CSS Issues

This commit is contained in:
Youwes09
2026-04-02 22:46:55 -05:00
parent 15adb02be3
commit 11cd6ff870
6 changed files with 16 additions and 61 deletions
+6 -2
View File
@@ -27,7 +27,7 @@
{#if store.toasts.length}
<div class="toaster" aria-live="polite">
{#each store.toasts as t (t.id)}
<div
<button
class="toast toast-{t.kind}"
role="alert"
onclick={() => dismissToast(t.id)}
@@ -43,7 +43,7 @@
<p class="title">{t.title}</p>
{#if t.body}<p class="sub">{t.body}</p>{/if}
</div>
</div>
</button>
{/each}
</div>
{/if}
@@ -76,6 +76,10 @@
cursor: pointer;
animation: slideIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
transition: opacity 0.15s ease, transform 0.15s ease;
font-family: inherit;
font-size: inherit;
color: inherit;
text-align: left;
}
.toast:hover { opacity: 0.85; transform: translateX(-2px); }
+1 -1
View File
@@ -284,7 +284,7 @@
.header { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-4) var(--sp-6); border-bottom: 1px solid var(--border-dim); flex-shrink: 0; }
.header-right { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }
.heading { font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--weight-normal); color: var(--text-faint); letter-spacing: var(--tracking-wider); text-transform: uppercase; }
.header-actions { display: flex; gap: var(--sp-1); }
.icon-btn { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--radius-md); color: var(--text-muted); transition: color var(--t-base), background var(--t-base); }
.icon-btn:hover:not(:disabled) { color: var(--text-primary); background: var(--bg-raised); }
.icon-btn:disabled { opacity: 0.4; }
+3 -3
View File
@@ -921,9 +921,9 @@
</div>
{#if showResumeBanner}
<div class="resume-banner" class:fading={resumeFading} role="status" onclick={() => { resumeVisible = false; resumeFading = false; }}>
<button class="resume-banner" class:fading={resumeFading} onclick={() => { resumeVisible = false; resumeFading = false; }}>
<span>Bookmark at page {resumePage}</span>
</div>
</button>
{/if}
<div
@@ -1193,7 +1193,7 @@
.slider-tooltip { position: absolute; bottom: calc(100% + 2px); transform: translateX(-50%); background: var(--bg-raised); border: 1px solid var(--border-base); border-radius: var(--radius-sm); padding: 2px 6px; font-family: var(--font-ui); font-size: var(--text-2xs); color: var(--text-secondary); white-space: nowrap; pointer-events: none; z-index: 10; letter-spacing: var(--tracking-wide); }
.slider-wrap:hover .slider-track-bg, .slider-wrap.dragging .slider-track-bg { height: 5px; }
.resume-banner { position: fixed; top: 48px; left: 50%; display: flex; align-items: center; gap: var(--sp-2); background: var(--bg-raised); border: 1px solid var(--border-base); border-radius: var(--radius-lg); padding: 6px var(--sp-3); font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-secondary); z-index: 20; box-shadow: 0 4px 16px rgba(0,0,0,0.4); animation: bannerIn 0.2s cubic-bezier(0.16,1,0.3,1) both; white-space: nowrap; cursor: pointer; }
.resume-banner { position: fixed; top: 48px; left: 50%; display: flex; align-items: center; gap: var(--sp-2); background: var(--bg-raised); border: 1px solid var(--border-base); border-radius: var(--radius-lg); padding: 6px var(--sp-3); font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-secondary); z-index: 20; box-shadow: 0 4px 16px rgba(0,0,0,0.4); animation: bannerIn 0.2s cubic-bezier(0.16,1,0.3,1) both; white-space: nowrap; cursor: pointer; text-align: left; }
.resume-banner.fading { animation: bannerOut 1s ease forwards; }
@keyframes bannerIn { from { opacity: 0; transform: translateX(-50%) translateY(-6px) scale(0.97); } to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); } }
@keyframes bannerOut { from { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); } to { opacity: 0; transform: translateX(-50%) translateY(-4px) scale(0.97); } }
+2 -21
View File
@@ -12,8 +12,6 @@
let { editingId = $bindable(null), onClose }: Props = $props();
// ── Token group definitions ───────────────────────────────────────────────
const TOKEN_GROUPS: { label: string; tokens: (keyof ThemeTokens)[] }[] = [
{
label: "Backgrounds",
@@ -65,8 +63,6 @@
"color-info-bg": "Info background",
};
// ── State ─────────────────────────────────────────────────────────────────
function loadInitial(): { name: string; tokens: ThemeTokens } {
if (editingId) {
const existing = store.settings.customThemes.find(t => t.id === editingId);
@@ -81,13 +77,10 @@
let saveStatus: "idle" | "saved" = $state("idle");
let importError: string | null = $state(null);
// ── CSS vars helper ───────────────────────────────────────────────────────
function toCssVars(t: ThemeTokens): string {
return Object.entries(t).map(([k, v]) => `--${k}: ${v};`).join(" ");
}
// ── Actions ───────────────────────────────────────────────────────────────
function handleSave() {
const name = themeName.trim() || "Untitled Theme";
const id = editingId ?? `custom:${Math.random().toString(36).slice(2, 10)}`;
@@ -154,17 +147,15 @@
<svelte:window onkeydown={onKey} />
<!-- ── Main editor ────────────────────────────────────────────────────────────── -->
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div class="te-backdrop" onclick={onClose} role="presentation">
<div class="te-backdrop" tabindex="-1" onclick={onClose} onkeydown={(e) => e.key === "Escape" && onClose()}>
<div
class="te-shell"
role="dialog"
aria-label="Theme editor"
tabindex="0"
onclick={(e) => e.stopPropagation()}
>
<!-- ── Header ──────────────────────────────────────────────────────── -->
<header class="te-header">
<div class="te-header-left">
<button class="te-icon-btn" onclick={onClose} title="Close editor">
@@ -209,25 +200,17 @@
</div>
</header>
<!-- ── Body ───────────────────────────────────────────────────────── -->
<div class="te-body">
<!-- Left: live preview -->
<aside class="te-preview-pane">
<div class="te-pane-label">Live Preview</div>
<!--
FIX 1: toCssVars scoped only to this element, so only the
preview UI sees the draft tokens — not the editor shell.
-->
<div class="te-preview-ui" style={toCssVars(tokens)}>
<!-- Sidebar -->
<div class="prv-sidebar">
{#each [true, false, false, false] as active}
<div class="prv-sb-dot" class:active></div>
{/each}
</div>
<!-- Main -->
<div class="prv-main">
<div class="prv-titlebar">
<div class="prv-win-dots">
@@ -262,7 +245,6 @@
</div>
</div>
<!-- Swatch strip — scoped to draft tokens too -->
<div class="te-swatches" style={toCssVars(tokens)}>
{#each [
["bg-base","bg-base"],["bg-surface","bg-surface"],
@@ -279,7 +261,6 @@
</div>
</aside>
<!-- Right: token editor -->
<div class="te-editor-pane">
{#each TOKEN_GROUPS as group}
<div class="te-group">
+4 -16
View File
@@ -11,8 +11,6 @@
onClose: () => void;
} = $props();
// ── Prefs helpers ──────────────────────────────────────────────────────────
const mangaPrefs = $derived(
(store.settings.mangaPrefs?.[mangaId] ?? {}) as Partial<MangaPrefs>
);
@@ -30,15 +28,11 @@
});
}
// ── Scanlator list — derived from loaded chapters ──────────────────────────
const scanlators = $derived(
[...new Set(chapters.map(c => c.scanlator).filter((s): s is string => !!s?.trim()))]
.sort((a, b) => a.localeCompare(b))
);
// ── Options ────────────────────────────────────────────────────────────────
const DOWNLOAD_AHEAD_OPTIONS = [
{ value: 0, label: "Off" },
{ value: 2, label: "2" },
@@ -66,18 +60,14 @@
{ value: "manual", label: "Manual" },
];
// ── Backdrop close ─────────────────────────────────────────────────────────
function onBackdrop(e: MouseEvent) {
if (e.target === e.currentTarget) onClose();
}
</script>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div class="backdrop" onmousedown={onBackdrop}>
<div class="backdrop" role="presentation" tabindex="-1" onmousedown={onBackdrop}>
<div class="modal" role="dialog" aria-modal="true" aria-label="Automation">
<!-- Header -->
<div class="modal-header">
<div class="header-left">
<span class="modal-title">Automation</span>
@@ -86,10 +76,8 @@
<button class="close-btn" onclick={onClose} aria-label="Close"><X size={16} weight="light" /></button>
</div>
<!-- Body -->
<div class="modal-body">
<!-- ── Downloads ────────────────────────────────────────────────────── -->
<p class="section-label">Downloads</p>
<div class="auto-row">
@@ -100,6 +88,7 @@
<button
role="switch"
aria-checked={getPref("autoDownload")}
aria-label="Auto-download new chapters"
class="auto-toggle"
class:auto-toggle-on={getPref("autoDownload")}
onclick={() => setPref("autoDownload", !getPref("autoDownload"))}
@@ -140,7 +129,6 @@
<div class="divider"></div>
<!-- ── On Read ──────────────────────────────────────────────────────── -->
<p class="section-label">On Read</p>
<div class="auto-row">
@@ -151,6 +139,7 @@
<button
role="switch"
aria-checked={getPref("deleteOnRead")}
aria-label="Delete after reading"
class="auto-toggle"
class:auto-toggle-on={getPref("deleteOnRead")}
onclick={() => setPref("deleteOnRead", !getPref("deleteOnRead"))}
@@ -174,7 +163,6 @@
<div class="divider"></div>
<!-- ── Updates ─────────────────────────────────────────────────────── -->
<p class="section-label">Updates</p>
<div class="auto-row">
@@ -185,6 +173,7 @@
<button
role="switch"
aria-checked={getPref("pauseUpdates")}
aria-label="Pause updates"
class="auto-toggle"
class:auto-toggle-on={getPref("pauseUpdates")}
onclick={() => setPref("pauseUpdates", !getPref("pauseUpdates"))}
@@ -210,7 +199,6 @@
{#if scanlators.length > 1}
<div class="divider"></div>
<!-- ── Scanlator ──────────────────────────────────────────────────── -->
<p class="section-label">Scanlator</p>
<div class="auto-row auto-row-align-start">
@@ -19,8 +19,6 @@
onClose: () => void;
} = $props();
// ── State ──────────────────────────────────────────────────────────────────
type TabId = "records" | number;
let trackers: Tracker[] = $state([]);
@@ -39,8 +37,6 @@
let editingChapter: number | null = $state(null);
let chapterDraft: number = $state(0);
// ── Load ───────────────────────────────────────────────────────────────────
async function load() {
loading = true;
try {
@@ -61,7 +57,6 @@
$effect(() => { load(); });
// Auto-search with manga title when switching to a tracker tab
$effect(() => {
const tab = activeTab;
if (typeof tab !== "number") return;
@@ -71,14 +66,10 @@
doSearch(tab, mangaTitle);
});
// ── Helpers ────────────────────────────────────────────────────────────────
function trackerFor(id: number) { return trackers.find(t => t.id === id); }
function recordFor(trackerId: number){ return records.find(r => r.trackerId === trackerId); }
const loggedInTrackers = $derived(trackers.filter(t => t.isLoggedIn));
// ── Search ─────────────────────────────────────────────────────────────────
let searchTimer: ReturnType<typeof setTimeout>;
function onSearchInput() {
@@ -105,8 +96,6 @@
}
}
// ── Bind / Unbind ──────────────────────────────────────────────────────────
async function bind(result: TrackSearch) {
if (typeof activeTab !== "number") return;
binding = true;
@@ -137,8 +126,6 @@
}
}
// ── Update ─────────────────────────────────────────────────────────────────
async function updateStatus(record: TrackRecord, status: number) {
updatingRecord = record.id;
try {
@@ -234,7 +221,6 @@
>
<div class="modal" role="dialog" aria-label="Tracking">
<!-- ── Header ─────────────────────────────────────────────────────────── -->
<div class="modal-header">
<div class="header-left">
<span class="modal-title">Tracking</span>
@@ -256,7 +242,6 @@
</div>
{:else}
<!-- ── Tabs ──────────────────────────────────────────────────────────── -->
<div class="tabs">
<button
class="tab"
@@ -282,7 +267,6 @@
{/each}
</div>
<!-- ── My List tab ───────────────────────────────────────────────────── -->
{#if activeTab === "records"}
<div class="tab-body">
{#if records.length === 0}
@@ -434,7 +418,6 @@
{/if}
</div>
<!-- ── Tracker search tab ─────────────────────────────────────────────── -->
{:else}
{@const tracker = trackerFor(activeTab as number)}
{@const boundRecord = recordFor(activeTab as number)}
@@ -644,7 +627,6 @@
.result-bound { background: color-mix(in srgb, var(--accent) 8%, transparent) !important; }
.result-cover { width: 44px; height: 62px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border-dim); flex-shrink: 0; }
.result-cover-empty { background: var(--bg-raised); }
.hidden { display: none; }
.result-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); padding-top: 2px; }
.result-title { font-size: var(--text-sm); color: var(--text-secondary); line-height: var(--leading-snug); text-align: left; }
.result-meta { display: flex; flex-wrap: wrap; gap: var(--sp-1); }