feat(reader): implement full appearance customization panel with themes, fonts, margins, line-height, and localStorage persistence

This commit is contained in:
2026-10-05 16:15:20 +03:00
parent c0fdcd776b
commit 84e9be614e
4 changed files with 589 additions and 37 deletions
+281 -9
View File
@@ -2822,6 +2822,22 @@ body {
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
.reader-settings-panel {
position: fixed !important;
top: auto !important;
bottom: calc(58px + env(safe-area-inset-bottom, 0px)) !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-height: calc(85dvh - 60px) !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch !important;
border-radius: 20px !important;
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.55) !important;
z-index: 10006 !important;
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
@keyframes slideUpSheet {
from {
transform: translateY(100%);
@@ -3127,22 +3143,278 @@ body {
display: flex;
align-items: center;
gap: 4px;
}
.reader-scroll-area {
padding: 36px 24px 60px;
max-width: 780px;
margin: 0 auto;
--reader-font-size: 18px;
--reader-line-height: 1.65;
--reader-font-family: 'Literata', 'Merriweather', 'Georgia', 'Cambria', serif;
--reader-max-width: 760px;
--reader-padding-h: 24px;
--reader-text-align: left;
--reader-bg: var(--bg-surface);
--reader-text: var(--text-main);
background-color: var(--reader-bg);
min-height: 60vh;
padding: 0;
transition: background-color 0.2s ease, color 0.2s ease;
}
.reader-content-body {
font-family: Georgia, 'Times New Roman', serif;
font-size: 19px;
line-height: 1.85;
color: var(--text-main);
max-width: var(--reader-max-width);
margin: 0 auto;
padding: 32px var(--reader-padding-h) 80px;
font-family: var(--reader-font-family);
font-size: var(--reader-font-size);
line-height: var(--reader-line-height);
text-align: var(--reader-text-align);
color: var(--reader-text);
word-break: break-word;
user-select: text;
transition: font-size 0.15s ease, line-height 0.15s ease, max-width 0.2s ease, padding 0.2s ease;
}
/* Reader Appearance Themes */
.reader-scroll-area.reader-theme-sepia {
--reader-bg: #fbf0d9;
--reader-text: #433422;
}
.reader-scroll-area.reader-theme-sepia .reader-word:hover {
background-color: rgba(217, 119, 6, 0.25);
color: #92400e;
}
.reader-scroll-area.reader-theme-sepia blockquote {
background-color: #f4e4c1;
border-color: #d6bc97;
color: #5f4b32;
}
.reader-scroll-area.reader-theme-sepia .reader-inline-code,
.reader-scroll-area.reader-theme-sepia .reader-code-wrap pre {
background-color: #efe0bc;
color: #433422;
border-color: #dec89f;
}
.reader-scroll-area.reader-theme-sepia .reader-table th,
.reader-scroll-area.reader-theme-sepia .reader-table td {
border-color: #dec89f;
}
.reader-scroll-area.reader-theme-light {
--reader-bg: #ffffff;
--reader-text: #1e293b;
}
.reader-scroll-area.reader-theme-light blockquote {
background-color: #f8fafc;
border-color: #cbd5e1;
color: #334155;
}
.reader-scroll-area.reader-theme-light .reader-inline-code,
.reader-scroll-area.reader-theme-light .reader-code-wrap pre {
background-color: #f1f5f9;
color: #0f172a;
border-color: #e2e8f0;
}
.reader-scroll-area.reader-theme-light .reader-word:hover {
background-color: rgba(2, 132, 199, 0.15);
color: #0284c7;
}
.reader-scroll-area.reader-theme-oled {
--reader-bg: #000000;
--reader-text: #d8e2ec;
}
.reader-scroll-area.reader-theme-oled blockquote {
background-color: #0a0e17;
border-color: #1e293b;
}
.reader-scroll-area.reader-theme-oled .reader-inline-code,
.reader-scroll-area.reader-theme-oled .reader-code-wrap pre {
background-color: #0a0e17;
border-color: #1e293b;
}
.reader-scroll-area.reader-theme-dark {
--reader-bg: var(--bg-surface);
--reader-text: var(--text-main);
}
/* Reader Font Families */
.reader-scroll-area.reader-font-sans {
--reader-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
.reader-scroll-area.reader-font-serif {
--reader-font-family: 'Literata', 'Merriweather', 'Georgia', 'Cambria', 'Times New Roman', serif;
}
.reader-scroll-area.reader-font-mono {
--reader-font-family: 'JetBrains Mono', 'Fira Code', 'Menlo', 'Consolas', monospace;
}
/* Reader Margin & Width Variants */
.reader-scroll-area.reader-margins-narrow {
--reader-max-width: 940px;
--reader-padding-h: 12px;
}
.reader-scroll-area.reader-margins-normal {
--reader-max-width: 760px;
--reader-padding-h: 24px;
}
.reader-scroll-area.reader-margins-wide {
--reader-max-width: 600px;
--reader-padding-h: 36px;
}
/* Reader Text Alignment */
.reader-scroll-area.reader-align-left {
--reader-text-align: left;
}
.reader-scroll-area.reader-align-justify {
--reader-text-align: justify;
hyphens: auto;
}
/* Reader Appearance Settings Panel / Sheet */
.reader-settings-panel {
position: fixed;
top: 64px;
right: 28px;
width: 320px;
background-color: var(--bg-surface);
border: 1px solid var(--border-focus);
border-radius: var(--radius-lg);
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.45);
z-index: 10002;
padding: 16px;
animation: fadeIn 0.15s ease-out;
}
.reader-settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid var(--border-color);
}
.reader-settings-header h4 {
font-size: 15px;
font-weight: 700;
color: var(--text-main);
}
.reader-settings-body {
display: flex;
flex-direction: column;
gap: 12px;
}
.setting-row {
display: flex;
flex-direction: column;
gap: 6px;
}
.setting-label {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-muted);
}
.setting-segmented-control {
display: flex;
background-color: var(--bg-input);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
padding: 2px;
gap: 2px;
}
.seg-btn {
flex: 1;
padding: 6px 8px;
font-size: 12px;
font-weight: 600;
background: transparent;
border: none;
border-radius: 4px;
color: var(--text-muted);
cursor: pointer;
transition: var(--transition);
text-align: center;
}
.seg-btn:hover {
color: var(--text-main);
}
.seg-btn.active {
background-color: var(--primary);
color: #0f172a;
}
.setting-stepper {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--bg-input);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
padding: 4px 6px;
}
.step-btn {
background: var(--bg-surface-hover);
border: 1px solid var(--border-color);
border-radius: 4px;
color: var(--text-main);
font-size: 13px;
font-weight: 700;
width: 38px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.step-val {
font-size: 14px;
font-weight: 700;
color: var(--primary);
}
.theme-palette {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
}
.theme-chip {
padding: 7px 10px;
font-size: 12px;
font-weight: 600;
border-radius: var(--radius-sm);
border: 2px solid transparent;
cursor: pointer;
text-align: center;
transition: var(--transition);
}
.theme-chip-dark { background: #1e293b; color: #f8fafc; border-color: #334155; }
.theme-chip-sepia { background: #fbf0d9; color: #433422; border-color: #d6bc97; }
.theme-chip-light { background: #ffffff; color: #0f172a; border-color: #cbd5e1; }
.theme-chip-oled { background: #000000; color: #e2e8f0; border-color: #334155; }
.theme-chip.active {
border-color: var(--primary) !important;
box-shadow: 0 0 0 2px var(--primary-dim);
}
.reader-settings-btn {
display: inline-flex;
align-items: center;
gap: 4px;
}
.reader-content-body h1,