diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index bef64a4f..6983f1c7 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -664,6 +664,12 @@ impl SlideApp { } } egui::Event::Key { key, pressed: true, modifiers, .. } => { + if key == egui::Key::Tab { + // The slide has the keyboard, so Tab is ours (indent, tab character, next + // shape). Left to egui it would also focus the first ribbon widget, and + // every key after it would go there instead of the slide (#78). + ctx.memory_mut(|m| m.move_focus(egui::FocusDirection::None)); + } let mods = Mods { shift: modifiers.shift, alt: modifiers.alt, cmd: modifiers.command || modifiers.ctrl }; if !self.session.tool.drawing_freeform() && menus::ui_shortcut(self, key, mods) { continue; @@ -932,6 +938,44 @@ mod tests { assert_eq!(harness.state().session.documents().len(), 2); } + /// #78: after Tab in a text box, typing and deleting no longer reached the text. + #[test] + fn typing_goes_on_after_tab_in_a_text_box() { + let mut harness = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state( + |ui, app: &mut SlideApp| { + app.logic(ui.ctx()); + app.ui(ui); + }, + SlideApp::new(Session::with_new(), Services::default()), + ); + harness.run_steps(2); + let title = harness.state().session.active().unwrap().doc.slides[0].shapes[0].id.0; + harness.state_mut().session.execute("text.edit", &json!({"id": title})).unwrap(); + harness.event(egui::Event::Text("ab".into())); + harness.run_steps(2); + harness.key_press(egui::Key::Tab); + harness.run_steps(2); + harness.event(egui::Event::Text("c".into())); + harness.run_steps(2); + assert_eq!(title_text(harness.state()), "ab\tc"); + harness.key_press(egui::Key::Backspace); + harness.run_steps(2); + assert_eq!(title_text(harness.state()), "ab\t"); + assert!(harness.state().session.active().unwrap().selection.text.is_some(), "still editing"); + // Tab at the start of a paragraph indents it, and typing goes on there too (#93). + harness.key_press(egui::Key::Enter); + harness.run_steps(2); + harness.key_press(egui::Key::Tab); + harness.run_steps(2); + harness.event(egui::Event::Text("d".into())); + harness.run_steps(2); + assert_eq!(title_text(harness.state()), "ab\t\nd"); + let level = |h: &egui_kittest::Harness| { + h.state().session.active().unwrap().doc.slides[0].shapes[0].text.as_ref().unwrap().paragraphs[1].level + }; + assert_eq!(level(&harness), 1); + } + #[test] fn home_needs_an_open_presentation() { let mut app = SlideApp::new(Session::new(), Services::default()); diff --git a/docs/gaps.md b/docs/gaps.md index 6ea4130a..fa303000 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -138,11 +138,6 @@ Detail in [file-format-parity.md](file-format-parity.md). - **Impact:** copy-paste of screenshots is a core workflow. - **Estimate:** 2โ€“4 h. **Beta blocker.** -### Tab inside a text box ends text entry (#78) -- **Evidence:** #78. -- **Impact:** tab stops and indented lists can't be typed. -- **Estimate:** 1โ€“2 h. - ### Charts: data grid, elements and the newer chart types - **Evidence:** checklist rows "Edit chart data" (P0, partial), "Chart elements" (partial), "Other chart types" (partial); `chartex` parts (waterfall, funnel, treemap, sunburst, histogram, box & @@ -247,5 +242,6 @@ Detail in [localization-parity.md](localization-parity.md). | Date | Change | Summary | |---|---|---| +| 2026-10-11 | minor | Removed "Tab inside a text box ends text entry" (#78, fixed) | | 2026-10-10 | minor | Noted that no gap blocks alpha (core-workflow gate passes) | | 2026-10-10 | major | Created: every gap from the 2026-10-10 re-measure and the 16 open GitHub issues, ranked, with beta blockers marked | diff --git a/docs/ui-parity.md b/docs/ui-parity.md index 5c7c50b9..8fe5e08d 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -48,7 +48,7 @@ AGENTS.md ยง2). Dimension score: **~60% ready** (estimated), **30โ€“50 h** to pa | Connector glue and rerouting | yes | yes | | Edit points on freeforms | yes | **no** | | Crop handles, crop to shape, aspect ratio | yes | partial | -| Text caret, selection, double/triple click, drag-select | yes | yes; Tab in text boxes ends editing (#78) | +| Text caret, selection, double/triple click, drag-select | yes | yes | | Exact size/position, lock aspect | yes | yes | | Rulers with indent markers and tab stops | yes | rulers yes; tab stops partial | | Context menus on shapes, slides, text, thumbnails | yes | yes, shorter | @@ -87,4 +87,5 @@ imitate Microsoft's. No pixel comparison against PowerPoint screenshots has been | Date | Change | Summary | |---|---|---| +| 2026-10-11 | minor | Tab in text boxes keeps editing (#78) | | 2026-10-10 | major | Created: shell, panes and dialogs, direct manipulation, shortcuts and visual fidelity against PowerPoint 16.113 |