╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Auth/Logout.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │109 self.session.data.user_id = null; │ │110 // jump focus back to the users tab — the logout button is about to│ │111 // be hidden by the tab-label swap. │ │112 - try root_focus.setFocus(self.users_tab_id); │ │112 + root_focus.setFocus(self.users_tab_id); │ │113 } │ │114 │ │115 pub fn clearGrid(self: *View) void { │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Home.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │198 } │ │199 │ │200 if (index != current_index) { │ │201 - try root_focus.setFocus(self.box.children.keys()[index]);│ │201 + root_focus.setFocus(self.box.children.keys()[index]); │ │202 } │ │203 } │ │204 } │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Home/Header.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │163 else => {}, │ │164 } │ │165 if (new_tab != current_tab) { │ │166 - try root_focus.setFocus(self.tab_ids.keys()[new_tab]);│ │166 + root_focus.setFocus(self.tab_ids.keys()[new_tab]); │ │167 } │ │168 } │ │169 │ ╰───────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │300 } │ │301 │ │302 if (index != current_index) { │ │303 - try root_focus.setFocus(self.box.children.keys()[index]);│ │303 + root_focus.setFocus(self.box.children.keys()[index]); │ │304 } │ │305 } │ │306 } │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │366 errdefer diff_scroll.deinit(allocator); │ │367 var frame = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = .hidden, .direction = .vert }); │ │368 errdefer frame.deinit(allocator); │ │369 + // the frame's selected child is its scroll, so the focus chain │ │370 + // reaches a hunk (populateDiff points the scroll's inner box at │ │371 + // one), letting focus recovery descend into the diff pane after │ │372 + // it's laid out beside a too-narrow list. │ │373 + frame.getFocus().child_id = diff_scroll.getFocus().id; │ │374 try frame.children.put(allocator, diff_scroll.getFocus().id, .{ .widget = .{ .scroll = diff_scroll }, .rect = null, .min_size = null });│ │375 break :blk frame; │ │376 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │539 // the web bounds the layout to the browser viewport like the terminal; │ │540 // each Scroll's web-native mode hands its full content to a real │ │541 // scrollable element, so we no longer build unbounded here. │ │542 + // │ │543 + // crossing panes only re-selects the content box's child (focusDiff / │ │544 + // focusList); when the window is too narrow to show both, the pane that │ │545 + // held focus is dropped here. the framework recovers focus after the │ │546 + // top-level build by re-deriving it down the selected-child chain, so │ │547 + // there's nothing to fix up afterward. │ │548 try self.box.build(allocator, constraint, root_focus); │ │538 - │ │539 - // if the diff pane is selected but focus is still elsewhere in this view, │ │540 - // the pane was too narrow to lay out when focus crossed over. it's laid │ │541 - // out now, so focus its hunk. │ │542 - if (self.diffActive() and inner.children.count() > 0) { │ │543 - if (root_focus.grandchild_id) |g| { │ │544 - const in_view = self.box.getFocus().children.contains(g); │ │545 - const in_diff = inner.children.contains(g); │ │546 - if (in_view and !in_diff) │ │547 - try root_focus.setFocus(inner.getFocus().child_id orelse inner.children.keys()[0]);│ │548 - } │ │549 - } │ │549 } │ │550 │ │551 fn refreshDiff(self: *View, allocator: std.mem.Allocator) !void { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │574 try self.addHunkBox(allocator, inner, hunk.lines); │ │575 } │ │576 if (commit.has_more) try self.addNavLink(allocator, inner, "next →", commit.oid, commit.window_start + diff_page);│ │577 + │ │578 + // point the pane at its first row so focus recovery can land here. │ │579 + if (inner.children.count() > 0) inner.getFocus().child_id = inner.children.keys()[0]; │ │580 │ │581 // reset the scroll to the top for the newly-shown commit: directly on the │ │582 // terminal (the wasm offset), and via a version bump on the web (so the │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │665 │ │666 if (self.session.is_terminal) { │ │667 if (in_range and self.hunkVisible(@intCast(target))) {│ │666 - try root_focus.setFocus(keys[@intCast(target)]); │ │668 + root_focus.setFocus(keys[@intCast(target)]); │ │669 return; │ │670 } │ │671 │ ╰───────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │673 sc.y += delta * 5; // magnify because it's a line count│ │674 self.clampDiffScroll(); │ │675 if (in_range and self.hunkVisible(@intCast(target))) { │ │674 - try root_focus.setFocus(keys[@intCast(target)]); │ │676 + root_focus.setFocus(keys[@intCast(target)]); │ │677 } │ │678 } else { │ │679 if (in_range) { │ ╰────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │678 - try root_focus.setFocus(keys[@intCast(target)]);│ │680 + root_focus.setFocus(keys[@intCast(target)]); │ │681 } │ │682 } │ │683 } │ ╰─────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯