╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │453 errdefer detail_scroll.deinit(allocator); │ │454 var frame = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = .hidden, .direction = .vert }); │ │455 errdefer frame.deinit(allocator); │ │456 + // the tool row sits above the scroll (populateDetail fills │ │457 + // it per issue) so it can't scroll out from under the web │ │458 + // overlay <form>, whose position doesn't track pane scrolling. │ │459 + { │ │460 + var row = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); │ │461 + errdefer row.deinit(allocator); │ │462 + try frame.children.put(allocator, row.getFocus().id, .{ .widget = .{ .box = row }, .rect = null, .min_size = null });│ │463 + } │ │464 // the frame's selected child is its scroll, so the focus chain │ │465 // reaches the description (populateDetail points the scroll's │ │466 // inner box at it), letting focus recovery descend into the pane. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │573 return &self.listScroll(index).child.box; │ │574 } │ │575 │ │576 + // the detail frame's children: the tool row above the scroll pane. │ │577 + const tool_row_index: usize = 0; │ │578 + const detail_scroll_index: usize = 1; │ │579 + │ │580 fn detailOuter(self: *View, index: usize) *wgt.Box(ui.Widget) { │ │581 return &self.resultsBox(index).children.values()[detail_index].widget.box; │ │582 + } │ │583 + │ │584 + fn toolRow(self: *View, index: usize) *wgt.Box(ui.Widget) { │ │585 + return &self.detailOuter(index).children.values()[tool_row_index].widget.box;│ │586 } │ │587 │ │588 fn detailScroll(self: *View, index: usize) *wgt.Scroll(ui.Widget) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │573 - return &self.detailOuter(index).children.values()[0].widget.scroll; │ │589 + return &self.detailOuter(index).children.values()[detail_scroll_index].widget.scroll;│ │590 } │ │591 │ │592 fn detailInner(self: *View, index: usize) *wgt.Box(ui.Widget) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │742 .open => "close", │ │743 .closed => "open", │ │744 }; │ │729 - var row = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz });│ │730 - errdefer row.deinit(allocator); │ │745 + const row = self.toolRow(index); │ │746 + for (row.children.values()) |*child| child.widget.deinit(allocator); │ │747 + row.children.clearAndFree(allocator); │ │748 const pa = self.session.page_arena.allocator(); │ │749 row.getFocus().kind = .{ .custom = if (self.data.identity.len == 0) │ │750 try std.fmt.allocPrint(pa, "form:/issues/{s}/{s}", .{ entry.id, action }) │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │768 } │ │769 │ │770 row.getFocus().child_id = row.children.keys()[button_in_row_index]; │ │754 - try inner.children.put(allocator, row.getFocus().id, .{ .widget = .{ .box = row }, .rect = null, .min_size = null });│ │771 } │ │772 │ │773 // the issue's tags, each linking to this status's list filtered to │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │1097 } │ │1098 } │ │1099 │ │1084 - const button_row_index: usize = 0; │ │1100 const button_in_row_index: usize = 1; │ │1086 - const tags_child_index: usize = 1; │ │1101 + const tags_child_index: usize = 0; │ │1102 │ │1103 fn tagFlow(self: *View, index: usize) ?*ui.TagFlow {│ │1104 const inner = self.detailInner(index); │ ╰──────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │1090 - if (inner.children.count() <= tags_child_index) return null; │ │1105 + if (inner.children.count() == 0) return null; │ │1106 return switch (inner.children.values()[tags_child_index].widget) {│ │1107 .tag_flow => |*tf| tf, │ │1108 else => null, │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1115 return inner.children.getIndex(cid) == tags_child_index and self.tagFlow(index) != null;│ │1116 } │ │1117 │ │1103 - // the open/close button inside the detail pane's leading row. │ │1118 + // the open/close button inside the detail frame's tool row. │ │1119 fn statusButton(self: *View, index: usize) ?*wgt.TextBox(ui.Widget) { │ │1105 - const inner = self.detailInner(index); │ │1106 - if (inner.children.count() == 0) return null; │ │1107 - const row = &inner.children.values()[button_row_index].widget.box; │ │1120 + const row = self.toolRow(index); │ │1121 + if (row.children.count() == 0) return null; │ │1122 return &row.children.values()[button_in_row_index].widget.text_box; │ │1123 } │ │1124 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1125 fn statusButtonFocused(self: *View, index: usize) bool { │ │1112 - const inner = self.detailInner(index); │ │1113 - const cid = inner.getFocus().child_id orelse return false; │ │1114 - return inner.children.getIndex(cid) == button_row_index; │ │1126 + const outer = self.detailOuter(index); │ │1127 + const cid = outer.getFocus().child_id orelse return false; │ │1128 + return outer.children.getIndex(cid) == tool_row_index; │ │1129 } │ │1130 │ │1131 fn focusTag(self: *View, index: usize, tf: *ui.TagFlow, root_focus: *Focus, item: usize) void {│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯