You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Preview Tab — Document Viewer/Editor in the Side Panel
Important
Problem: AI-modified .md files are only accessible through the Modified Files diff view, which shows raw unified diffs — unreadable for documentation-heavy workflows. There is no way to preview rendered documents or make quick edits without leaving the session.
Approach: Add a new "Preview" tab to the side panel (peer of Modified Files and Context) that lists AI-modified markdown files from the current session. Selecting a file renders it as a formatted document. A per-file toggle switches between rendered preview and a raw textarea for direct editing. Replace the existing "+" button with an extensible dropdown menu for opening panel types.
Approaches Considered:
(A) New side panel tab + menu launcher (chosen) — clean separation of concerns; document authoring is a distinct activity from code review; follows the established tab-registration pattern (Context tab precedent); the menu makes all openable panels discoverable and extensible.
(B) Extend the existing Review tab with a render mode — the original Preview Tab — Document Viewer/Editor in the Side Panel #162 design; smaller blast radius but conflates two purposes (code review vs document reading/editing) into one tab, making the UX ambiguous.
(C) Dedicated editor panel (separate from side panel) — maximum screen real estate but breaks the side-panel mental model and requires new panel infrastructure.
Scope:.md files modified by the AI in the current session. Preview mode renders documents; raw mode enables direct editing with auto-save. The "+" button is replaced with a panel-type menu. LaTeX (.tex) is a follow-up — full-document LaTeX rendering in the browser is a hard problem.
Assumptions: The existing Markdown component handles GFM rendering (headings, code blocks, LaTeX math, tables, links, images) and is stable/performant for file-sized documents.
Acceptance Criteria
Preview tab
A new "Preview" tab appears in the side panel alongside Modified Files and Context
The tab lists all .md files the AI modified in the current session
Each file in the list shows an A (added) or M (modified) badge
Clicking a file replaces the list with the rendered content (back button returns to list)
.md files render through the existing Markdown component (full GFM: headings, bold/italic, code blocks with syntax highlighting, tables, links, images, LaTeX math, task lists)
A per-file toggle switches between Preview (rendered) and Raw (editable textarea) modes
Raw mode shows a monospace textarea with the file source
Edits in raw mode auto-save with ~1s debounce
Cmd+S (Ctrl+S on Linux) triggers an immediate save in raw mode
Saves write to disk via the existing file-write mechanism
The tab only appears when at least one .md file has been AI-modified in the session (no empty state)
Non-.md files never appear in this tab
The Modified Files tab and Context tab are completely unaffected
Panel menu (replaces the "+" button)
The existing "+" button in the tab bar is replaced with a "+" button that opens a dropdown menu
The menu lists available panel types: "Context", "Preview"
Clicking a menu item opens that tab (same as if it were already open and you clicked its trigger)
The SESSION_OPEN_FILE_TAB ("open-file") tab is removed — no more inline file browser
The old-layout dialog-based file open behavior is also removed
The menu is the single extensible seam for adding future panel types
Menu items that are already open could be visually indicated (dimmed or checkmarked)
Key Decisions
Tab registration pattern
Follow the Context tab precedent:
Add "preview" constant to layout-tabs.ts
Filter from sortable file-tabs in createSessionTabs (helpers.ts)
Add to the active-tab priority chain
Add trigger + content in session-side-panel.tsx (both v1 and v2 code paths)
Panel menu replaces "+" button
The current "+" button has two implementations:
Old layout: lazy-imports DialogSelectFile and shows a modal file picker
V2 layout: calls openFileBrowser() which opens SESSION_OPEN_FILE_TAB inline
Both are replaced with a single dropdown menu (a Popover or DropdownMenu from the UI kit). The menu is a static list of panel types — initially "Context" and "Preview". Each item calls the same tabs().open("context") / tabs().open("preview") + tabs().setActive(...) pattern. This becomes the canonical extensibility point for future panels (e.g., "Outline", "References", "Terminal").
The SESSION_OPEN_FILE_TAB constant and all code paths that reference it are removed.
File list — flat, with change badges
A flat file list (not a tree) showing basename + relative directory, with A/M badges sourced from the session file-change set. Same visual density as the Modified Files list. Click navigates to the content view; a back/breadcrumb button returns to the list.
Content view — two modes
Mode
Behavior
Preview (default)
Rendered markdown via the existing Markdown component. Read-only.
Raw
Monospace textarea. Editable. Auto-save on debounce + Cmd+S for immediate flush.
The toggle is per-file — each file remembers its mode independently within the session.
Save mechanism
Raw-mode edits auto-save via a debounced (~1s) write to disk using the same file-write channel the agent uses. Cmd+S bypasses the debounce for an immediate write. The file remains in the Preview tab list (it was AI-modified; user edits don't remove it).
Data contract
// File entry in the Preview tab listinterfacePreviewFileEntry{path: string// absolute file pathrelativePath: string// relative to workspace rootbasename: string// file nameextension: ".md"changeType: "added"|"modified"}// Per-file view stateinterfacePreviewFileState{mode: "preview"|"raw"scrollPosition?: number// restore scroll on mode toggleunsavedContent?: string// buffer for debounced save}// Panel menu item (extensible registry)interfacePanelMenuItem{id: string// tab value, e.g. "context", "preview"label: string// display nameicon: string// icon name from the icon setavailable: ()=>boolean// whether to show (e.g. preview only when .md files exist)}
Constraints & Invariants
The existing Markdown component must not be forked — extend via props/composition only
No changes to the Modified Files tab behavior or the Context tab
No new panel layout types — the Preview tab lives inside the existing side panel tab system
CSS custom properties from the existing theme — no hardcoded colors
The tab is hidden when no .md files have been AI-modified in the session (no empty state)
File writes from raw mode use the same permissions/mechanism as agent file writes
The panel menu is the ONLY way to open non-file tabs going forward (replaces all "+" button behaviors)
Replace "+" button with PanelMenu; add Preview tab trigger + content (both v1 and v2 paths); remove SESSION_OPEN_FILE_TAB content/references
packages/app/src/components/session/index.ts
Export new components
Removed
File / Export
Reason
SESSION_OPEN_FILE_TAB constant
No longer used — panel menu replaces the file browser tab
DialogSelectFile lazy import in side panel
Replaced by panel menu
openFileBrowser() function
Replaced by panel menu
Prior Art
Context tab (session-context-tab.tsx) — the pattern for registering a non-file tab in the side panel
Modified Files / Review tab — the UX precedent for listing session-changed files with badges
Markdown component (packages/session-ui/src/components/markdown.tsx) — full GFM + LaTeX math + streaming + syntax highlighting via shiki
Obsidian / Notion — the reading-mode vs editing-mode toggle UX precedent
VS Code "..." menu in panel headers — precedent for a menu that opens different panel types
Follow-up: LaTeX (.tex) support
Full-document LaTeX rendering in the browser is hard. The options:
Option
Trade-off
KaTeX "document mode" (hand-rolled parser)
KaTeX is a math renderer, not a document renderer. You would be writing a LaTeX parser.
LaTeX.js
Covers a subset. Breaks on tikz, pgfplots, biblatex, custom macros.
WASM TeX engine (SwiftLaTeX)
30-100MB binary, multi-second compile, no arbitrary packages.
Server-side compilation
Requires TeX Live, compilation service, sandboxing. Way out of scope.
The most pragmatic future path: detect .tex files, show syntax-highlighted source with inline math blocks rendered via KaTeX (i.e., "raw mode with math sprinkled in"). Not a full Overleaf-style preview, but useful. Separate issue when the need is clear.
Source
Revised from the original #162 spec (2026-08-10). Pivoted from "rendered markdown diffs in the Review tab" to a standalone Preview tab. Scoped to .md only after honest assessment of LaTeX rendering feasibility. Panel menu added to replace the single-purpose "+" button with an extensible launcher.
type: spec
date: 2026-08-11
status: draft
priority: p2
platform: opencode
tags: [spec, ui, markdown, side-panel, preview, authoring]
linked_plan: null
Preview Tab — Document Viewer/Editor in the Side Panel
Important
Problem: AI-modified
.mdfiles are only accessible through the Modified Files diff view, which shows raw unified diffs — unreadable for documentation-heavy workflows. There is no way to preview rendered documents or make quick edits without leaving the session.Approach: Add a new "Preview" tab to the side panel (peer of Modified Files and Context) that lists AI-modified markdown files from the current session. Selecting a file renders it as a formatted document. A per-file toggle switches between rendered preview and a raw textarea for direct editing. Replace the existing "+" button with an extensible dropdown menu for opening panel types.
Approaches Considered:
Scope:
.mdfiles modified by the AI in the current session. Preview mode renders documents; raw mode enables direct editing with auto-save. The "+" button is replaced with a panel-type menu. LaTeX (.tex) is a follow-up — full-document LaTeX rendering in the browser is a hard problem.Assumptions: The existing
Markdowncomponent handles GFM rendering (headings, code blocks, LaTeX math, tables, links, images) and is stable/performant for file-sized documents.Acceptance Criteria
Preview tab
.mdfiles the AI modified in the current session.mdfiles render through the existingMarkdowncomponent (full GFM: headings, bold/italic, code blocks with syntax highlighting, tables, links, images, LaTeX math, task lists).mdfile has been AI-modified in the session (no empty state).mdfiles never appear in this tabPanel menu (replaces the "+" button)
SESSION_OPEN_FILE_TAB("open-file") tab is removed — no more inline file browserKey Decisions
Tab registration pattern
Follow the Context tab precedent:
"preview"constant tolayout-tabs.tscreateSessionTabs(helpers.ts)session-side-panel.tsx(both v1 and v2 code paths)Panel menu replaces "+" button
The current "+" button has two implementations:
DialogSelectFileand shows a modal file pickeropenFileBrowser()which opensSESSION_OPEN_FILE_TABinlineBoth are replaced with a single dropdown menu (a
PopoverorDropdownMenufrom the UI kit). The menu is a static list of panel types — initially "Context" and "Preview". Each item calls the sametabs().open("context")/tabs().open("preview")+tabs().setActive(...)pattern. This becomes the canonical extensibility point for future panels (e.g., "Outline", "References", "Terminal").The
SESSION_OPEN_FILE_TABconstant and all code paths that reference it are removed.File list — flat, with change badges
A flat file list (not a tree) showing basename + relative directory, with A/M badges sourced from the session file-change set. Same visual density as the Modified Files list. Click navigates to the content view; a back/breadcrumb button returns to the list.
Content view — two modes
Markdowncomponent. Read-only.The toggle is per-file — each file remembers its mode independently within the session.
Save mechanism
Raw-mode edits auto-save via a debounced (~1s) write to disk using the same file-write channel the agent uses. Cmd+S bypasses the debounce for an immediate write. The file remains in the Preview tab list (it was AI-modified; user edits don't remove it).
Data contract
Constraints & Invariants
Markdowncomponent must not be forked — extend via props/composition only.mdfiles have been AI-modified in the session (no empty state)File Changes
New files
packages/app/src/components/session/session-preview-tab.tsxpackages/app/src/components/session/preview-file-list.tsxpackages/app/src/components/session/preview-content.tsxpackages/app/src/components/session/raw-editor.tsxpackages/app/src/components/session/panel-menu.tsxModified files
packages/app/src/context/layout-tabs.ts"preview"tab constant; removeSESSION_OPEN_FILE_TABpackages/app/src/pages/session/helpers.tspreviewOpensignal, filter from sortable tabs, add to priority chain; remove open-file tab logicpackages/app/src/pages/session/session-side-panel.tsxPanelMenu; add Preview tab trigger + content (both v1 and v2 paths); removeSESSION_OPEN_FILE_TABcontent/referencespackages/app/src/components/session/index.tsRemoved
SESSION_OPEN_FILE_TABconstantDialogSelectFilelazy import in side panelopenFileBrowser()functionPrior Art
session-context-tab.tsx) — the pattern for registering a non-file tab in the side panelMarkdowncomponent (packages/session-ui/src/components/markdown.tsx) — full GFM + LaTeX math + streaming + syntax highlighting via shikiFollow-up: LaTeX (
.tex) supportFull-document LaTeX rendering in the browser is hard. The options:
The most pragmatic future path: detect
.texfiles, show syntax-highlighted source with inline math blocks rendered via KaTeX (i.e., "raw mode with math sprinkled in"). Not a full Overleaf-style preview, but useful. Separate issue when the need is clear.Source
Revised from the original #162 spec (2026-08-10). Pivoted from "rendered markdown diffs in the Review tab" to a standalone Preview tab. Scoped to
.mdonly after honest assessment of LaTeX rendering feasibility. Panel menu added to replace the single-purpose "+" button with an extensible launcher.