From 735e247477302cf21536cb76a1362203089fe8f5 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 12 Jul 2026 10:48:31 -0500 Subject: [PATCH] Add dark mode and compact chapter links --- package-lock.json | 4 +- package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- src/App.css | 220 ++++++++++++++++++++++++++++++++++++-- src/App.tsx | 33 ++++++ 7 files changed, 248 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c9a1b1..d0acdea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "libre-study", - "version": "0.1.17", + "version": "0.1.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "libre-study", - "version": "0.1.17", + "version": "0.1.18", "dependencies": { "@tauri-apps/api": "^2.11.1", "react": "^19.2.7", diff --git a/package.json b/package.json index f8a4727..e9c592d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "libre-study", "private": true, - "version": "0.1.17", + "version": "0.1.18", "type": "module", "scripts": { "dev": "vite --host 127.0.0.1", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8851a45..372564e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -77,7 +77,7 @@ checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "app" -version = "0.1.17" +version = "0.1.18" dependencies = [ "log", "rusqlite", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index be6089e..88d29bc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "app" -version = "0.1.17" +version = "0.1.18" description = "A Tauri App" authors = ["you"] license = "" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2838a42..1113aa8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "Libre Study", - "version": "0.1.17", + "version": "0.1.18", "identifier": "org.librestudy.desktop", "build": { "frontendDist": "../dist", diff --git a/src/App.css b/src/App.css index b018513..8e5cc3c 100644 --- a/src/App.css +++ b/src/App.css @@ -386,29 +386,37 @@ textarea:focus-visible { .chapter-tabs { display: flex; - flex-wrap: wrap; + flex-wrap: nowrap; justify-content: center; - gap: 3px; - max-height: 38px; + gap: 0; + max-width: 100%; + max-height: 18px; overflow: hidden; + white-space: nowrap; } .chapter-tabs button { - min-width: 22px; - min-height: 20px; - padding: 2px 5px; - border-color: #cfc4ad; - background: #f2ead8; - color: #4c422f; + min-width: 0; + min-height: 0; + padding: 0 3px; + border: 0; + border-radius: 0; + background: transparent; + color: #6f5a24; font-size: 10px; - line-height: 1; + line-height: 1.1; + text-decoration: none; + box-shadow: none; } .chapter-tabs button.active, .chapter-tabs button:hover, .chapter-tabs button:focus-visible { - background: #d6a84f; + background: transparent; color: #151510; + text-decoration: underline; + text-decoration-color: #d6a84f; + text-underline-offset: 2px; } .page-columns { @@ -1291,6 +1299,196 @@ textarea:focus-visible { width: auto; } +.segmented-control { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 4px; + padding: 3px; + border: 1px solid #d8cfbf; + border-radius: 7px; + background: #fffef8; +} + +.segmented-control button { + background: transparent; + color: #3f443d; +} + +.segmented-control button.active { + background: #2f6f5e; + color: #fffef8; +} + +.theme-dark { + background: #161a18; + color: #eee8d8; +} + +.theme-dark .reader { + background: #161a18; +} + +.theme-dark .page-system, +.theme-dark .notes-workspace, +.theme-dark .status-panel, +.theme-dark .bible-page, +.theme-dark .page-turner, +.theme-dark .footnote-strip, +.theme-dark .modal-panel, +.theme-dark .study-margin, +.theme-dark .study-top-tools, +.theme-dark .modal-section, +.theme-dark .note-helper, +.theme-dark .note-placeholder, +.theme-dark .segmented-control, +.theme-dark input, +.theme-dark select, +.theme-dark textarea { + border-color: #3f493f; + background: #222820; + color: #eee8d8; +} + +.theme-dark .bible-page, +.theme-dark .page-turner, +.theme-dark .footnote-strip { + background: #1d221c; +} + +.theme-dark .page-columns { + column-rule-color: #333b32; +} + +.theme-dark .page-verse { + color: #f2eadb; +} + +.theme-dark .page-verse.selected { + background: #3a3322; +} + +.theme-dark .page-verse sup, +.theme-dark .chapter-tabs button, +.theme-dark .footnote-list p span { + color: #ddb763; +} + +.theme-dark .chapter-tabs button.active, +.theme-dark .chapter-tabs button:hover, +.theme-dark .chapter-tabs button:focus-visible { + color: #fff7df; +} + +.theme-dark .original-language-verse, +.theme-dark .english-strong-line, +.theme-dark .resource-card { + border-color: #3f493f; + background: #20251f; +} + +.theme-dark .margin-section-header { + background: #2b332a; +} + +.theme-dark .margin-section-header:hover, +.theme-dark .margin-section-header:focus-visible { + background: #344031; +} + +.theme-dark .strong-focus { + border-color: #3b5a50; + background: #1f302b; +} + +.theme-dark .panel-header { + border-bottom-color: #3f493f; +} + +.theme-dark .panel-header span, +.theme-dark .margin-reference, +.theme-dark .translit, +.theme-dark .eyebrow, +.theme-dark .collapse-button, +.theme-dark .mini-settings, +.theme-dark .resource-disabled, +.theme-dark .commentary-list small, +.theme-dark .dictionary-list p strong, +.theme-dark .page-turner span, +.theme-dark .footnote-strip span, +.theme-dark .timeline-canvas time, +.theme-dark .timeline-canvas span, +.theme-dark .timeline-canvas small, +.theme-dark .note-helper small, +.theme-dark .note-placeholder small, +.theme-dark .session-facts dt, +.theme-dark .about-list dt, +.theme-dark .modal-section label, +.theme-dark .page-controls label { + color: #aaa996; +} + +.theme-dark .strong-focus h4, +.theme-dark .strong-focus p, +.theme-dark .commentary-list h3, +.theme-dark .dictionary-list h3, +.theme-dark .commentary-list p, +.theme-dark .dictionary-list p, +.theme-dark .linked-line-text, +.theme-dark .lemma-line-text, +.theme-dark .session-facts dd, +.theme-dark .about-list dd, +.theme-dark .about-modal p, +.theme-dark .resource-toggles label, +.theme-dark .checkbox-row, +.theme-dark .segmented-control button { + color: #eee8d8 !important; +} + +.theme-dark .segmented-control button.active, +.theme-dark .study-top-tools button, +.theme-dark .pin-notes, +.theme-dark .strong-focus button, +.theme-dark .about-links a { + background: #3a7a69; + color: #fffdf6 !important; +} + +.theme-dark .modal-backdrop { + background: rgba(5, 7, 5, 0.68); +} + +.theme-dark .close-button, +.theme-dark .tool-rail, +.theme-dark .notes-drawer-grip { + background: #111511; +} + +.theme-dark .book-tabs { + background: #161a18; +} + +.theme-dark .book-tabs button { + border-color: #4b422f; + background: #312c20; + color: #ddc17f; +} + +.theme-dark .book-tabs button:hover, +.theme-dark .book-tabs button:focus-visible, +.theme-dark .book-tabs button.active { + background: #c7963f; + color: #141510; +} + +.theme-dark .split-resizer { + background: linear-gradient(90deg, transparent, #4b5448 45%, #4b5448 55%, transparent); +} + +.theme-dark .split-resizer:hover, +.theme-dark .split-resizer:focus-visible { + background: #c7963f; +} + .about-modal p { margin: 0; color: #3f443d; diff --git a/src/App.tsx b/src/App.tsx index 2037341..da8eecf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,6 +19,7 @@ const timelineLimit = 200 type ViewMode = 'page' | 'study' | 'notes' | 'compare' type StrongDisplayMode = 'off' | 'highlight' | 'numbers' type PageMotion = 'idle' | 'turn-forward' | 'turn-back' +type ThemeMode = 'light' | 'dark' type TimelineEntryType = 'verse' | 'strong' | 'footnote' | 'search' | 'navigation' | 'view' | 'setting' type TimelineEntry = { @@ -223,6 +224,7 @@ function App() { const [pageMotion, setPageMotion] = useState('idle') const [viewMode, setViewMode] = useState('notes') const [query, setQuery] = useState('') + const [themeMode, setThemeMode] = useState('light') const [libraryVerses, setLibraryVerses] = useState([]) const [verses, setVerses] = useState([]) const [selectedId, setSelectedId] = useState(null) @@ -407,6 +409,7 @@ function App() { showDictionaryPanel: boolean splitPercent: number notesPinned: boolean + themeMode: ThemeMode }> setLemmaFontSize(parsed.lemmaFontSize ?? 17) setLinkedFontSize(parsed.linkedFontSize ?? 15) @@ -422,6 +425,7 @@ function App() { setShowDictionaryPanel(parsed.showDictionaryPanel ?? true) setSplitPercent(parsed.splitPercent ?? 50) setNotesPinned(parsed.notesPinned ?? false) + setThemeMode(parsed.themeMode ?? 'light') } catch { localStorage.removeItem(studySettingsStorageKey) } @@ -493,6 +497,7 @@ function App() { showDictionaryPanel, splitPercent, notesPinned, + themeMode, }), ) }, [ @@ -510,6 +515,7 @@ function App() { showLinkedLine, showOriginalLine, splitPercent, + themeMode, ]) useEffect(() => { @@ -782,6 +788,11 @@ function App() { }) } + function changeThemeMode(nextThemeMode: ThemeMode) { + setThemeMode(nextThemeMode) + recordDisplaySetting(`Theme: ${nextThemeMode}`) + } + function beginSplitResize(event: ReactMouseEvent) { event.preventDefault() const reader = readerRef.current @@ -1278,6 +1289,7 @@ function App() { key={chapter} type="button" className={chapter === selectedVerse?.chapter ? 'active' : ''} + style={{ fontSize: `${Math.max(8, Math.min(11, 13 - chapters.length / 20))}px` }} onClick={() => selectedVerse && jumpTo(selectedVerse.book, chapter, 1)} > {chapter} @@ -1733,6 +1745,26 @@ function App() {
+
+

Theme

+
+ + +
+
+

Original Language Line