Refine rail and book tab layout

This commit is contained in:
2026-07-12 09:45:33 -05:00
parent ea22ffd2b9
commit 984db5b4dd
7 changed files with 91 additions and 55 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "libre-study",
"version": "0.1.9",
"version": "0.1.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "libre-study",
"version": "0.1.9",
"version": "0.1.10",
"dependencies": {
"@tauri-apps/api": "^2.11.1",
"react": "^19.2.7",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "libre-study",
"private": true,
"version": "0.1.9",
"version": "0.1.10",
"type": "module",
"scripts": {
"dev": "vite --host 127.0.0.1",
+1 -1
View File
@@ -77,7 +77,7 @@ checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
[[package]]
name = "app"
version = "0.1.9"
version = "0.1.10"
dependencies = [
"log",
"rusqlite",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "app"
version = "0.1.9"
version = "0.1.10"
description = "A Tauri App"
authors = ["you"]
license = ""
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
"productName": "Libre Study",
"version": "0.1.9",
"version": "0.1.10",
"identifier": "org.librestudy.desktop",
"build": {
"frontendDist": "../dist",
+49 -11
View File
@@ -7,7 +7,7 @@
}
.app-shell.menu-open .reader {
filter: brightness(0.72);
filter: blur(1.5px) brightness(0.62) saturate(0.72);
}
.tool-rail {
@@ -35,6 +35,7 @@
.brand-mark {
display: grid;
flex: 0 0 auto;
place-items: center;
width: 42px;
height: 42px;
@@ -67,6 +68,7 @@
.menu-button {
flex: 0 0 auto;
justify-content: center;
align-self: center;
}
.menu-button span {
@@ -82,6 +84,19 @@
gap: 4px;
}
.tool-rail:hover .menu-button,
.tool-rail:focus-within .menu-button {
width: 42px;
padding: 0;
}
.app-identity {
display: flex;
gap: 12px;
align-items: center;
min-height: 42px;
}
.rail-icon {
display: grid;
flex: 0 0 18px;
@@ -116,6 +131,23 @@
margin-top: auto;
}
.rail-description {
display: none;
margin: 0;
padding: 12px;
border: 1px solid #3c4239;
border-radius: 6px;
background: #252b25;
color: #d9ddd4;
font-size: 13px;
line-height: 1.45;
}
.tool-rail:hover .rail-description,
.tool-rail:focus-within .rail-description {
display: block;
}
.reader {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
@@ -266,13 +298,13 @@ textarea:focus-visible {
.bible-page {
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
grid-template-rows: auto minmax(0, 1fr);
min-height: 0;
padding: 26px 30px;
}
.bible-page header,
.bible-page footer {
.page-turner {
display: flex;
justify-content: space-between;
gap: 16px;
@@ -283,13 +315,15 @@ textarea:focus-visible {
text-transform: uppercase;
}
.bible-page footer {
padding-top: 16px;
.page-turner {
grid-column: 1 / -1;
padding: 14px 30px;
border-top: 1px solid #e8e2d4;
background: #fffef8;
text-transform: none;
}
.bible-page footer span {
.page-turner span {
color: #6b675d;
font-size: 13px;
font-weight: 700;
@@ -687,26 +721,30 @@ textarea:focus-visible {
}
.book-tabs {
display: flex;
display: grid;
grid-column: 1 / -1;
grid-template-columns: repeat(24, minmax(0, 1fr));
gap: 3px;
align-items: flex-start;
padding: 0 16px 10px;
overflow-x: auto;
overflow: hidden;
background: #ece9df;
}
.book-tabs button {
min-width: 44px;
min-width: 0;
height: 30px;
padding: 4px 7px;
padding: 4px 3px;
border-color: #c8bea9;
border-top: 0;
border-radius: 0 0 7px 7px;
background: #efe4c9;
color: #4c422f;
font-size: 11px;
font-size: 10px;
font-weight: 800;
line-height: 1.05;
white-space: normal;
overflow-wrap: anywhere;
box-shadow: 0 5px 10px rgba(44, 48, 42, 0.08);
}
+36 -38
View File
@@ -387,6 +387,16 @@ function App() {
() => Array.from(new Set(libraryVerses.map((verse) => verse.book))),
[libraryVerses],
)
const visibleBookTabs = useMemo(() => {
if (!selectedVerse || !books.length) return []
const visibleCount = 24
const selectedIndex = Math.max(0, books.indexOf(selectedVerse.book))
const halfWindow = Math.floor(visibleCount / 2)
const maxStart = Math.max(0, books.length - visibleCount)
const start = Math.min(Math.max(0, selectedIndex - halfWindow), maxStart)
return books.slice(start, start + visibleCount)
}, [books, selectedVerse])
const chapters = useMemo(() => {
if (!selectedVerse) return []
return Array.from(
@@ -512,17 +522,6 @@ function App() {
)
}
function setWorkspaceView(nextViewMode: ViewMode) {
setViewMode(nextViewMode)
recordTimeline(
{
type: 'view',
label: `View: ${nextViewMode}`,
},
{ viewMode: nextViewMode },
)
}
function setStrongDisplayMode(nextStrongDisplay: StrongDisplayMode) {
setStrongDisplay(nextStrongDisplay)
recordTimeline(
@@ -707,19 +706,24 @@ function App() {
</p>
))}
</div>
<footer>
<button type="button" onClick={() => shiftPage(-1)}>
Previous page
</button>
<span>{pageRange}</span>
<button type="button" onClick={() => shiftPage(1)}>
Next page
</button>
</footer>
</article>
)
}
function renderPageTurner() {
return (
<nav className="page-turner" aria-label="Page navigation">
<button type="button" onClick={() => shiftPage(-1)}>
Previous page
</button>
<span>{pageRange}</span>
<button type="button" onClick={() => shiftPage(1)}>
Next page
</button>
</nav>
)
}
function renderStudyMargin() {
if (!selectedVerse) return null
return (
@@ -814,7 +818,7 @@ function App() {
return (
<nav className="book-tabs" aria-label="Bible book tabs">
{books.map((book) => (
{visibleBookTabs.map((book) => (
<button
key={book}
type="button"
@@ -1039,23 +1043,16 @@ function App() {
<span />
<span />
</button>
<span className="brand-mark">LS</span>
<button type="button" title="Bible page" onClick={() => setWorkspaceView('page')}>
<span className="rail-icon">B</span>
<span className="rail-copy"><strong>Bible</strong><small>Page-only reading</small></span>
</button>
<button type="button" title="Study margin" onClick={() => setWorkspaceView('study')}>
<span className="rail-icon">M</span>
<span className="rail-copy"><strong>Margin</strong><small>References and linked words</small></span>
</button>
<button type="button" title="Notes workspace" onClick={() => setWorkspaceView('notes')}>
<span className="rail-icon">N</span>
<span className="rail-copy"><strong>Notes</strong><small>Study notes and timeline</small></span>
</button>
<button type="button" title="Compare translations" onClick={() => setWorkspaceView('compare')}>
<span className="rail-icon">C</span>
<span className="rail-copy"><strong>Compare</strong><small>Translation comparison</small></span>
</button>
<div className="app-identity" aria-label="Libre Study">
<span className="brand-mark">LS</span>
<span className="rail-copy">
<strong>Libre Study</strong>
<small>Free Bible study by Christ IT</small>
</span>
</div>
<p className="rail-description">
A readable Bible page, study margin, notes workspace, and linked public Bible data.
</p>
<button type="button" title="Session management" onClick={() => setSessionModalOpen(true)}>
<span className="rail-icon">S</span>
<span className="rail-copy"><strong>Sessions</strong><small>Save, export, and configure</small></span>
@@ -1188,6 +1185,7 @@ function App() {
{renderBiblePage('KJV')}
{viewMode !== 'page' ? renderStudyMargin() : null}
{renderFootnoteStrip()}
{renderPageTurner()}
{renderBookTabs()}
</div>
)}