Add tabbed layout for study page on mobile to reduce scrolling
On screens below sm (640px), a horizontal tab bar replaces the stacked-scroll layout: Scripture | Notes | Refs | Words | Commentary | Script. Each tab shows only one section at a time via max-sm:hidden on the others. The chunk sidebar and split-view toggle are also hidden on mobile since Prev/Next navigation in the header is sufficient there. Desktop stacked and split-view layouts are unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+39
-12
@@ -1277,6 +1277,7 @@ const App = () => {
|
|||||||
const [activeStudyTab, setActiveStudyTab] = useState(
|
const [activeStudyTab, setActiveStudyTab] = useState(
|
||||||
() => localStorage.getItem('activeStudyTab') || 'notes',
|
() => localStorage.getItem('activeStudyTab') || 'notes',
|
||||||
);
|
);
|
||||||
|
const [mobileStudyTab, setMobileStudyTab] = useState('scripture');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('studyLayout', studyLayout);
|
localStorage.setItem('studyLayout', studyLayout);
|
||||||
@@ -5494,7 +5495,7 @@ const deleteProject = (id) => {
|
|||||||
<main className="mx-auto max-w-7xl px-4 py-4 sm:py-8 sm:px-6 lg:px-8">
|
<main className="mx-auto max-w-7xl px-4 py-4 sm:py-8 sm:px-6 lg:px-8">
|
||||||
<section className={`grid min-w-0 gap-6 ${studyLayout === 'split' ? '' : 'lg:grid-cols-[260px_1fr]'}`}>
|
<section className={`grid min-w-0 gap-6 ${studyLayout === 'split' ? '' : 'lg:grid-cols-[260px_1fr]'}`}>
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<aside className={`min-w-0 rounded-3xl border border-slate-200 bg-white p-4 sm:p-6 shadow-panel ${studyLayout === 'split' ? 'hidden' : ''}`}>
|
<aside className={`min-w-0 rounded-3xl border border-slate-200 bg-white p-4 sm:p-6 shadow-panel max-sm:hidden ${studyLayout === 'split' ? 'hidden' : ''}`}>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-sm font-medium text-slate-500">Chunk Navigation</p>
|
<p className="text-sm font-medium text-slate-500">Chunk Navigation</p>
|
||||||
<h2 className="mt-2 text-xl font-semibold text-slate-900">{allChunks.length} chunks</h2>
|
<h2 className="mt-2 text-xl font-semibold text-slate-900">{allChunks.length} chunks</h2>
|
||||||
@@ -5611,7 +5612,7 @@ const deleteProject = (id) => {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setStudyLayout((m) => (m === 'split' ? 'stacked' : 'split'))}
|
onClick={() => setStudyLayout((m) => (m === 'split' ? 'stacked' : 'split'))}
|
||||||
className="rounded-2xl border border-slate-300 bg-white px-3 py-2 text-sm font-semibold text-slate-700 transition hover:border-slate-400"
|
className="max-sm:hidden rounded-2xl border border-slate-300 bg-white px-3 py-2 text-sm font-semibold text-slate-700 transition hover:border-slate-400"
|
||||||
title="Toggle two-pane study layout"
|
title="Toggle two-pane study layout"
|
||||||
>
|
>
|
||||||
{studyLayout === 'split' ? '☰ Stacked View' : '◫ Split View'}
|
{studyLayout === 'split' ? '☰ Stacked View' : '◫ Split View'}
|
||||||
@@ -5619,11 +5620,36 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile tab bar — shown only below sm, replaces the stacked-scroll layout */}
|
||||||
|
<div className="sm:hidden -mx-4 mt-4 flex overflow-x-auto border-b border-slate-200">
|
||||||
|
{[
|
||||||
|
{ id: 'scripture', label: 'Scripture' },
|
||||||
|
{ id: 'notes', label: 'Notes' },
|
||||||
|
{ id: 'crossRefs', label: 'Refs' },
|
||||||
|
{ id: 'wordStudy', label: 'Words' },
|
||||||
|
{ id: 'commentary', label: 'Commentary' },
|
||||||
|
{ id: 'script', label: 'Script' },
|
||||||
|
].map((tab) => (
|
||||||
|
<button
|
||||||
|
key={tab.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setMobileStudyTab(tab.id)}
|
||||||
|
className={`shrink-0 border-b-2 px-4 py-2.5 text-sm font-semibold transition ${
|
||||||
|
mobileStudyTab === tab.id
|
||||||
|
? 'border-slate-900 text-slate-900'
|
||||||
|
: 'border-transparent text-slate-500 hover:text-slate-700'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
{selectedChunk ? (
|
{selectedChunk ? (
|
||||||
<div className="mt-6 space-y-6">
|
<div className="mt-6 space-y-6">
|
||||||
<div className={`space-y-6 ${studyLayout === 'split' ? 'lg:flex lg:items-start lg:gap-6 lg:space-y-0' : ''}`}>
|
<div className={`space-y-6 ${studyLayout === 'split' ? 'lg:flex lg:items-start lg:gap-6 lg:space-y-0' : ''}`}>
|
||||||
{/* Scripture */}
|
{/* Scripture */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' ? 'lg:sticky lg:top-6 lg:flex-1 lg:basis-0 lg:min-w-0 lg:self-start' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'scripture' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' ? 'lg:sticky lg:top-6 lg:flex-1 lg:basis-0 lg:min-w-0 lg:self-start' : ''}`}>
|
||||||
<div className="mb-4 flex items-center justify-between gap-3">
|
<div className="mb-4 flex items-center justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold text-slate-700">Scripture</p>
|
<p className="text-sm font-semibold text-slate-700">Scripture</p>
|
||||||
@@ -5705,7 +5731,7 @@ const deleteProject = (id) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Session metadata — optional, used to label this chunk within a series */}
|
{/* Session metadata — optional, used to label this chunk within a series */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'notes' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
||||||
<h3 className="text-sm font-semibold text-slate-900">Session Info</h3>
|
<h3 className="text-sm font-semibold text-slate-900">Session Info</h3>
|
||||||
<p className="text-xs text-slate-500">
|
<p className="text-xs text-slate-500">
|
||||||
Optional — only fill this in if this chunk is part of a numbered series (a podcast episode,
|
Optional — only fill this in if this chunk is part of a numbered series (a podcast episode,
|
||||||
@@ -5730,7 +5756,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Background / general notes — unique per chunk */}
|
{/* Background / general notes — unique per chunk */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'notes' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, generalNotes: !c.generalNotes }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, generalNotes: !c.generalNotes }))}
|
||||||
@@ -5754,7 +5780,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* OIA Notes */}
|
{/* OIA Notes */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 space-y-4 ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 space-y-4 ${mobileStudyTab !== 'notes' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, oia: !c.oia }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, oia: !c.oia }))}
|
||||||
@@ -5799,7 +5825,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'notes' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'notes' ? 'hidden' : ''}`}>
|
||||||
<h3 className="text-sm font-semibold text-slate-900">Tags</h3>
|
<h3 className="text-sm font-semibold text-slate-900">Tags</h3>
|
||||||
<p className="mb-3 text-xs text-slate-500">Label this chunk by topic so you can search across studies later.</p>
|
<p className="mb-3 text-xs text-slate-500">Label this chunk by topic so you can search across studies later.</p>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
@@ -5871,7 +5897,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Cross-references */}
|
{/* Cross-references */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'crossRefs' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'crossRefs' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'crossRefs' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, crossRefs: !c.crossRefs }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, crossRefs: !c.crossRefs }))}
|
||||||
@@ -5936,7 +5962,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Greek words */}
|
{/* Greek words */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'wordStudy' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'wordStudy' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'wordStudy' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, greek: !c.greek }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, greek: !c.greek }))}
|
||||||
@@ -6150,7 +6176,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Commentary */}
|
{/* Commentary */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'commentary' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'commentary' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'commentary' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, commentary: !c.commentary }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, commentary: !c.commentary }))}
|
||||||
@@ -6212,7 +6238,7 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Final episode script archive */}
|
{/* Final episode script archive */}
|
||||||
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${studyLayout === 'split' && activeStudyTab !== 'script' ? 'hidden' : ''}`}>
|
<div className={`rounded-3xl border border-slate-200 bg-slate-50 p-5 ${mobileStudyTab !== 'script' ? 'max-sm:hidden' : ''} ${studyLayout === 'split' && activeStudyTab !== 'script' ? 'hidden' : ''}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCollapsedSections((c) => ({ ...c, finalScript: !c.finalScript }))}
|
onClick={() => setCollapsedSections((c) => ({ ...c, finalScript: !c.finalScript }))}
|
||||||
@@ -6278,7 +6304,8 @@ const deleteProject = (id) => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-6 rounded-3xl border border-slate-200 bg-slate-50 p-8 text-center text-slate-500">
|
<div className="mt-6 rounded-3xl border border-slate-200 bg-slate-50 p-8 text-center text-slate-500">
|
||||||
Select a chunk from the left panel to edit its notes and Greek studies.
|
<span className="sm:hidden">Use ‹ Prev / Next › above to pick a chunk.</span>
|
||||||
|
<span className="hidden sm:inline">Select a chunk from the left panel to edit its notes and Greek studies.</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user