Status: Resolved
Version: v0.2.5 (deferred widget commits); v0.3.x session integration
Fixed the cursor focus loss issue when editing table cells in Rendered and Split view modes. Table cells buffer edits and only commit changes to the source when focus leaves the table, preventing the re-parsing loop that caused focus loss.
Session model (v0.3.x): Leaving a table for a non-table block (heading, paragraph, etc.) is handled by RenderedEditSession — commit_session_block for BlockRef::TableCell sets a one-shot signal_table_force_commit, and the table widget flushes on its next frame. Intra-table Tab/Enter navigation still defers commit until focus leaves the grid entirely.
When editing table cells in Rendered or Split mode:
- Cell text changes →
output.changed = trueimmediately - Source markdown was updated on every keystroke
- Document was re-parsed on next frame
- New AST created new widget IDs
- Previous TextEdit widget was gone, focus was lost
This made table editing in WYSIWYG modes frustrating as users had to click back into cells after each keystroke.
Table cells now track modifications separately from change signaling:
pub struct TableEditState {
pub focused_cell: Option<(usize, usize)>,
pub pending_focus: Option<(usize, usize)>,
pub had_focus_last_frame: bool, // Track focus across frames
pub content_modified: bool, // Track if edits were made
}Changes are only committed when focus leaves the table entirely:
// Detect focus loss: had focus last frame but not this frame
let focus_lost = edit_state.had_focus_last_frame && !any_cell_has_focus;
if focus_lost && edit_state.content_modified {
changed = true; // Now signal the change
edit_state.content_modified = false;
}Switched from ui.add(TextEdit...) to TextEdit::show(ui) for better cursor state management, matching how other working editable widgets (headings) are implemented.
- While editing a cell: Type freely, cursor stays in position, source is NOT updated
- Click outside the table: Focus leaves, changes are committed to source
- Tab/Enter navigation: Focus moves to another cell (still in table), changes NOT committed yet
- Escape: Clears focus, changes are committed
- Add/Remove row/column buttons: Changes committed immediately (structural actions)
| File | Changes |
|---|---|
src/markdown/widgets.rs |
Added had_focus_last_frame and content_modified to TableEditState, deferred change detection, switched to TextEdit::show() |
The table supports full keyboard navigation:
| Key | Action |
|---|---|
| Tab | Move to next cell (right, then wrap to next row) |
| Shift+Tab | Move to previous cell (left, then wrap to previous row) |
| Enter | Move to next row (same column) |
| Escape | Exit table editing (commits changes) |
- Open a markdown file with a table in Split or Rendered mode
- Click on a table cell
- Type text - cursor should stay in position
- Tab between cells - focus should move correctly
- Click outside the table - changes should appear in raw source
- Verify undo/redo works for table edits
The deferred update approach means:
- Pro: Smooth editing experience without focus loss
- Pro: Cursor positioning works correctly on click
- Con: Preview/raw view doesn't update until you click away from the table
This matches the behavior of other click-to-edit widgets (paragraphs, list items) and provides a consistent editing experience.
- Editable Tables - Full table widget documentation
- Rendered edit session (tables) - Session + force-commit on cross-block leave
- Rendered edit session (overview) - Architecture hub
- Split View - Split view mode documentation
- WYSIWYG Editor - Overall editor architecture