From aab093121bb741e07883ace0d4cbffa217abf385 Mon Sep 17 00:00:00 2001 From: callumalpass Date: Wed, 7 Oct 2026 05:51:23 +1100 Subject: [PATCH] Drop the sidebar's second panel One panel at a time reads more cleanly; the rail remains for a hidden sidebar, and the outline's counts already tie the tabs together. --- README.md | 4 +-- apps/writer/src/styles.css | 10 -------- apps/writer/src/ui/WorkspaceView.tsx | 37 ++++++---------------------- apps/writer/src/ui/icons.tsx | 2 -- apps/writer/src/ui/layout.ts | 5 +--- 5 files changed, 10 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 751a1e51..5a3b5241 100644 --- a/README.md +++ b/README.md @@ -134,9 +134,7 @@ margin, hovering a passage shows who said what, and **F7** steps to the next com **Comments** panel lists every thread, with what others wrote since you last opened the manuscript marked as new, and can be filtered to one person's comments or your own. -The sidebar's tabs can be opened side by side: the split button beside them shows a second -panel beneath, so the outline and comments can be read together. Hiding the sidebar leaves a -rail of its tabs. +Hiding the sidebar leaves a rail of its tabs. Click a block in the preview to jump to the corresponding text. The preview also follows the editor's cursor. **Problems** in the top bar lists unknown citekeys, missing labels, unavailable diff --git a/apps/writer/src/styles.css b/apps/writer/src/styles.css index 895cb2d9..0d850a2a 100644 --- a/apps/writer/src/styles.css +++ b/apps/writer/src/styles.css @@ -253,16 +253,6 @@ kbd { font-family: var(--mono); font-size: 11.5px; padding: 1px 5px; border: 1px .sidebar-tabs button:focus-visible { outline-offset: -2px; } .tab-count { font-size: 11px; font-weight: 400; color: var(--faint); font-variant-numeric: tabular-nums; } .sidebar-panel { min-height: 0; overflow: auto; padding: 0.5rem 0.5rem 1.5rem; scrollbar-gutter: stable; } -/* A second panel beneath the first, with its own small tabs. */ -.outline.has-lower { grid-template-rows: auto minmax(0, 1fr) minmax(0, 1fr); } -.sidebar-lower { display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; border-top: 1px solid var(--line); } -.sidebar-lower-tabs { display: flex; align-items: center; gap: 0.9rem; min-height: 32px; padding: 0 0.5rem 0 1rem; border-bottom: 1px solid var(--line); } -.sidebar-lower-tabs > [role="tab"] { padding: 0; border: 0; background: none; color: var(--muted); font-size: 12px; cursor: pointer; } -.sidebar-lower-tabs > [role="tab"]:hover { color: var(--ink); } -.sidebar-lower-tabs > [role="tab"][aria-selected="true"] { color: var(--ink); font-weight: 700; } -.sidebar-lower-tabs > .mdbase-icon-button { margin-left: auto; } -.sidebar-split { margin-left: auto; align-self: center; color: var(--muted); } -.sidebar-split[aria-pressed="true"] { color: var(--ink); } /* The sidebar hidden leaves a rail of its tabs. */ .sidebar-rail { grid-area: rail; display: grid; align-content: start; justify-items: center; gap: 0.25rem; padding: 0.5rem 0; border-right: 1px solid var(--line); background: var(--canvas); } .rail-button { position: relative; display: grid; place-items: center; width: 32px; height: 32px; border: 0; border-radius: 6px; background: none; color: var(--muted); cursor: pointer; } diff --git a/apps/writer/src/ui/WorkspaceView.tsx b/apps/writer/src/ui/WorkspaceView.tsx index a234ad15..87821ee6 100644 --- a/apps/writer/src/ui/WorkspaceView.tsx +++ b/apps/writer/src/ui/WorkspaceView.tsx @@ -39,7 +39,6 @@ import { PlusIcon, SidebarIcon, SplitIcon, - SplitVerticalIcon, } from "./icons.js"; import { readerSourceHref } from "../apps.js"; import { errorMessage } from "../async.js"; @@ -213,11 +212,8 @@ export function WorkspaceView({ workspace, since, onClose }: { workspace: Manusc const toggleLivePreview = useCallback(() => setLayout((l) => ({ ...l, livePreview: !l.livePreview })), [setLayout]); const setSidebarTab = useCallback((tab: SidebarTab) => { rememberedTabs.set(workspace.main, tab); - // The lower panel never repeats the upper: the two swap. - setLayout((l) => ({ ...l, tab, lowerTab: l.lowerTab === tab ? l.tab : l.lowerTab })); + setLayout((l) => ({ ...l, tab })); }, [setLayout, workspace.main]); - const setLowerTab = useCallback((lowerTab: SidebarTab | null) => setLayout((l) => ({ ...l, lowerTab: lowerTab === l.tab ? null : lowerTab })), [setLayout]); - const toggleLower = useCallback(() => setLayout((l) => ({ ...l, lowerTab: l.lowerTab ? null : l.tab === "comments" ? "outline" : "comments" })), [setLayout]); const order = useMemo(() => workspace.readingOrder(), [workspace, snap.records, snap.recordPaths, snap.annotationPaths]); const activeView = snap.records.get(active); @@ -282,7 +278,7 @@ export function WorkspaceView({ workspace, since, onClose }: { workspace: Manusc }, [placed, active]); const showComments = useCallback(() => { - setLayout((l) => (l.sidebar && (l.tab === "comments" || l.lowerTab === "comments") ? l : { ...l, sidebar: true, tab: "comments", lowerTab: l.lowerTab === "comments" ? l.tab : l.lowerTab })); + setLayout((l) => (l.sidebar && l.tab === "comments" ? l : { ...l, sidebar: true, tab: "comments" })); setPane("outline"); }, [setLayout]); @@ -742,9 +738,9 @@ export function WorkspaceView({ workspace, since, onClose }: { workspace: Manusc request={sourcesRequest} /> ); - /** A sidebar panel's contents (Sources in the upper slot is rendered by the sidebar itself, kept mounted). */ + /** The outline or comments panel (Sources is rendered by the sidebar itself, kept mounted). */ const panelFor = (tab: SidebarTab) => - tab === "sources" ? sourcesPanel : ( + tab === "sources" ? null : ( tab === "outline" ? ( <> -