Skip to content

Instantly share code, notes, and snippets.

@lucapette
Created March 30, 2026 12:54
Show Gist options
  • Select an option

  • Save lucapette/18296931c9dce9df9d5dc905ee73719b to your computer and use it in GitHub Desktop.

Select an option

Save lucapette/18296931c9dce9df9d5dc905ee73719b to your computer and use it in GitHub Desktop.

Revisions

  1. lucapette created this gist Mar 30, 2026.
    88 changes: 88 additions & 0 deletions live-preview-proposal.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    # Live Preview Mode for Markdown Editing

    ## Problem

    Current markdown file viewing requires toggling between "read" mode and "source text" mode, causing disorienting context loss. When editing a file, the view switches modes and scrolls to a different position.

    ## Proposed Solution

    Implement a live preview mode that displays rendered markdown while allowing inline editing, similar to Obsidian's live preview feature.

    ## Current State

    In `FileViewer.tsx`, there are **two mutually exclusive modes**:

    | Mode | Markdown Preview | Monaco Editor |
    |------|-----------------|---------------|
    | `preview` | Visible | Invisible |
    | `source` | Invisible | Visible |

    The toggle at line 776-779 switches between these two modes.

    ## Proposed Three-Mode Design

    | Mode | Markdown Preview | Monaco Editor | Use Case |
    |------|-----------------|---------------|----------|
    | `preview` | Visible | Invisible | Reading |
    | `source` | Invisible | Visible (normal) | Pure editing |
    | `livePreview` | Visible | Visible (transparent bg) | **Inline editing while reading** |

    ## Key Changes Required

    ### 1. `FileViewer.tsx`

    **State management (lines 237-242):**
    ```typescript
    type ViewMode = 'preview' | 'source' | 'livePreview'
    const previewModes = useRef(new Map<string, ViewMode>())
    ```

    **Editor styling for live preview:**
    - Monaco editor needs transparent background
    - Editor text matches markdown styling

    **Click handling in live preview:**
    - Map click coordinates to cursor position in Monaco
    - Pass clicks through to editor for editing

    ### 2. `FileViewerToolbar.tsx`

    Add third toggle state:
    - **Cycle button**: Preview → LivePreview → Source → Preview
    - Or **two toggles**: "Preview" + "Live Preview"

    Icon suggestions:
    - `Eye` for preview
    - `Code2` for source
    - New icon for live preview mode

    ## Implementation Phases

    ### Phase 1 - Core
    1. Add `ViewMode` type and update `previewModes` ref
    2. Make Monaco editor transparent in live preview mode
    3. Make markdown preview layer pass clicks through to editor
    4. Add click-to-cursor-position mapping

    ### Phase 2 - Polish
    5. Update toolbar with new toggle
    6. Sync scroll positions between preview and source
    7. Handle cursor visibility

    ## Files to Modify

    | File | Lines | Purpose |
    |------|-------|---------|
    | `src/renderer/components/shared/FileViewer.tsx` | 237-242 | State management |
    | `src/renderer/components/shared/FileViewer.tsx` | 776-779 | Toggle handler |
    | `src/renderer/components/shared/FileViewer.tsx` | 1000-1028 | Preview/editor visibility |
    | `src/renderer/components/shared/file-viewer/FileViewerToolbar.tsx` | 39-51 | Toggle button UI |

    ## Complexity Note

    The trickiest part is **click-to-cursor-position mapping**. The current `findSelectionLineRange()` maps selected text back to source lines. For live preview, we need to map click coordinates to cursor position.

    Options:
    1. Use Monaco's coordinate conversion APIs
    2. Pre-calculate line positions in rendered markdown
    3. Simplified heuristic based on character offset