Skip to content

Add markdown source toggle#1263

Open
damselem wants to merge 4 commits into
getpaseo:mainfrom
damselem:codex/paseo-markdown-previewsource-toggle
Open

Add markdown source toggle#1263
damselem wants to merge 4 commits into
getpaseo:mainfrom
damselem:codex/paseo-markdown-previewsource-toggle

Conversation

@damselem
Copy link
Copy Markdown
Contributor

@damselem damselem commented May 31, 2026

Linked issue

Closes #1264

Type of change

  • Bug fix
  • New feature (with prior issue + design alignment)
  • Refactor / code improvement
  • Docs

What does this PR do

Markdown file tabs currently render the preview directly, with no way to inspect the raw Markdown from the same tab. This adds a tab-menu action for rendered Markdown files that toggles the tab between the rendered preview and the highlighted source view.

The tab state now stores an explicit file render mode: preview or source. Opening a file without a render mode still normalizes to preview, so existing open-file paths and older persisted file tabs keep their current behavior. The toggle is wired through the desktop tab menu, mobile tab menu, and split-pane tab rows, and it is intentionally hidden for line-targeted Markdown links because those already need the source/highlighted-line view.

The toggle uses distinct destination icons: Show source uses the code icon, and Show preview uses the eye icon.

Follow-up review feedback is also covered: reopening an already-open Markdown file without an explicit render mode preserves the user's current preview/source mode, while callers that explicitly request renderMode: "source" or renderMode: "preview" are still honored.

Markdown file tab menu with Show source image

How did you verify it

  • npx vitest run packages/app/src/workspace/file-open/index.test.ts packages/app/src/screens/workspace/workspace-tab-menu.test.ts packages/app/src/components/file-pane-render-mode.test.ts packages/app/src/screens/workspace/workspace-pane-state.test.ts packages/app/src/screens/workspace/workspace-tab-model.test.ts packages/app/src/screens/workspace/workspace-bulk-close.test.ts packages/app/src/utils/workspace-navigation.test.ts --bail=1
  • npx vitest run packages/app/src/stores/workspace-tabs-store/state.test.ts packages/app/src/stores/workspace-layout-store.test.ts --bail=1
  • npm run format
  • npm run lint
  • npm run typecheck
  • git diff --check
  • pre-commit hook reran format check, lint, and full typecheck successfully

workspace-tab-menu.test.ts also asserts the icon mapping: Show source uses code, and Show preview uses eye.

Visual QA is still needed before marking this ready: open a Markdown file tab on desktop/web and mobile, verify the menu shows Show source, toggle to the source view, verify the menu changes to Show preview, then toggle back.

Risk surface

This touches workspace tab target normalization and equality for file tabs. The intended behavior is still one tab per file path, with source/preview represented as mutable state on that tab rather than separate tabs.

The main UI risk is that one of the tab menu surfaces could fail to expose or refresh the action correctly after toggling. The main state risk is old persisted file tabs without renderMode; those are normalized to preview and covered by the file target tests. Reopen/focus behavior for existing file tabs is covered by reducer and split-layout store tests so omitted render mode preserves the current tab mode without blocking explicit render-mode requests.

Checklist

  • One focused change. Unrelated cleanups split out.
  • npm run typecheck passes
  • npm run lint passes
  • npm run format ran
  • UI changes include screenshots or video for every affected platform
  • Tests added or updated where it made sense

@damselem damselem changed the title [codex] Add markdown source toggle Add markdown source toggle May 31, 2026
@damselem damselem marked this pull request as ready for review May 31, 2026 23:43
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 31, 2026

Greptile Summary

This PR adds a per-tab renderMode: "preview" | "source" field to file tab targets, wiring a "Show source / Show preview" toggle through the desktop tab context menu, mobile tab switcher, and split-pane tab rows. A new WorkspaceTabTargetInput type separates inputs (where renderMode is optional) from the normalised WorkspaceTabTarget (where renderMode is always present), avoiding silent coercion in callers that navigate to a file without specifying a mode.

  • The preserveExistingFileRenderMode flag is threaded through both the tabs store (applyEnsureTab/buildNextTabsForEnsure) and the layout store (openTabInLayoutFocused/Background/updateExistingTabTarget), so navigating to an already-open source-mode file from the explorer leaves the tab's mode intact rather than silently resetting it to preview.
  • Persisted tabs lacking renderMode are migrated to \"preview\" in coerceWorkspaceTabTarget, preserving backward compatibility with existing workspaces.

Confidence Score: 5/5

Safe to merge. The renderMode clobbering regression flagged in the previous review is addressed, and the feature is well-tested across the affected state reducers and menu-builder paths.

The preservation logic is correct in both stores: when no renderMode is supplied, the existing tab's mode is kept; when an explicit renderMode is supplied (either via toggle or a line-targeted link), the tab is updated as expected. Serialisation/deserialisation handles old persisted tabs cleanly. Tests cover the preservation round-trip, explicit override, and the line-targeted exclusion for the menu toggle.

No files require special attention.

Important Files Changed

Filename Overview
packages/app/src/workspace/file-open/index.ts Adds WorkspaceFileRenderMode, WorkspaceFileTabTargetInput (optional renderMode), normalizeWorkspaceFileRenderMode, and workspaceFileTabTargetsEqual — the core type/normalization layer for this feature
packages/app/src/stores/workspace-tabs-store/state.ts Adds preserveExistingFileRenderMode flag and targetsShareFileLocation guard in buildNextTabsForEnsure to prevent clobbering source mode on re-navigation; coerces persisted tabs missing renderMode to "preview"
packages/app/src/stores/workspace-layout-actions.ts Threads preserveExistingFileRenderMode into updateExistingTabTarget so the layout store also skips retargeting source-mode tabs when no explicit renderMode is requested
packages/app/src/stores/workspace-layout-store.ts Adds shouldPreserveExistingFileRenderMode helper and passes the flag through all three open-tab actions (focused, child, background)
packages/app/src/workspace-tabs/identity.ts normalizeFileTabTarget now includes renderMode; workspaceTabTargetsEqual delegates to workspaceFileTabTargetsEqual so source vs preview are treated as distinct targets
packages/app/src/screens/workspace/workspace-tab-menu.ts Adds "Show source / Show preview" toggle entry with code/eye icons; correctly guarded by isRenderedMarkdownFile and absence of lineStart
packages/app/src/screens/workspace/workspace-screen.tsx Wires handleToggleMarkdownSource via retargetWorkspaceTab to all three tab-row surfaces (desktop tabs, mobile switcher, split container)
packages/app/src/components/file-pane.tsx location prop tightened to WorkspaceFileTabTarget; renderMode !== "source" guard added so markdown preview is suppressed in source mode
packages/app/src/screens/workspace/workspace-pane-state.ts preferredTarget and resolveSideFileOpenPlacement target widened to WorkspaceTabTargetInput; added defensive null-check after normalization in resolveSideFileOpenPlacement

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User navigates to file\ne.g. from file explorer] --> B{renderMode\nprovided?}
    B -- "No (undefined/null)" --> C[preserveExistingFileRenderMode = true\nnormalize → renderMode: preview]
    B -- "Yes (source/preview)" --> D[preserveExistingFileRenderMode = false\nnormalize → explicit renderMode]

    C --> E{Tab already open\nfor this file path?}
    D --> E

    E -- No --> F[Insert new tab\nwith normalized renderMode]

    E -- Yes --> G{preserveExistingFileRenderMode\n&& same file location?}
    G -- Yes --> H[Return currentTabs unchanged\n★ source mode preserved]
    G -- No\n(explicit renderMode request) --> I[Retarget tab to\nnew renderMode]

    J[Toggle button clicked] --> K[retargetWorkspaceTab with\nexplicit nextRenderMode]
    K --> D
Loading

Reviews (14): Last reviewed commit: "fix: use preview icon for markdown previ..." | Re-trigger Greptile

@damselem damselem force-pushed the codex/paseo-markdown-previewsource-toggle branch 10 times, most recently from 88b0b7a to 2fa83db Compare June 4, 2026 15:03
@damselem damselem force-pushed the codex/paseo-markdown-previewsource-toggle branch from 2fa83db to 4d22713 Compare June 5, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: show Markdown source from preview tabs

1 participant