╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │330 + .tabs_id = tabs_id, │ │331 + .first_group_width = first_group_width, │ │332 }; │ │305 - self.getFocus().child_id = selected_tab orelse self.tab_ids.keys()[0];│ │306 - return self; │ │333 } │ │334 │ │335 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │339 │ │340 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ │341 self.clearGrid(); │ │342 + const box = &self.scroll.child.box; │ │343 + const tabs_child = self.tabsChild(); │ │344 + const tabs_box = &tabs_child.widget.box; │ │345 + │ │346 + const viewport_width = constraint.max_size.width orelse constraint.min_size.width; │ │347 + // the outer box's hidden border occupies two columns │ │348 + const content_width = if (viewport_width) |width| width -| 2 else null; │ │349 + const wrap = if (content_width) |width| self.first_group_width >= width / 2 else false; │ │350 + box.options.direction = if (wrap) .vert else .horiz; │ │351 + tabs_child.min_size = if (wrap) .{ .width = content_width, .height = null } else null; │ │352 + │ │353 // only the selected tab shows its border │ │317 - const box = &self.scroll.child.box; │ │318 - for (box.children.keys(), box.children.values()) |id, *child| { │ │354 + const selected_tab = if (box.getFocus().child_id == self.tabs_id) tabs_box.getFocus().child_id else null; │ │355 + for (tabs_box.children.keys(), tabs_box.children.values()) |id, *child| { │ │356 const tb: ?*wgt.TextBox(ui.Widget) = switch (child.widget) { │ │357 .text_box => |*x| x, │ │358 .auth_tab => |*at| blk: { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │363 else => null, │ │364 }; │ │365 if (tb) |t| { │ │329 - t.options.border_style = if (self.getFocus().child_id == id) .single else .hidden;│ │366 + t.options.border_style = if (selected_tab == id) .single else .hidden; │ │367 } │ │368 } │ │369 var scroll_constraint = constraint; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │333 - scroll_constraint.min_size.width = constraint.max_size.width orelse constraint.min_size.width;│ │370 + scroll_constraint.min_size.width = viewport_width; │ │371 try self.scroll.build(allocator, scroll_constraint, root_focus); │ │372 } │ │373 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │377 if (inp.moveTab(key, current_tab, self.tab_ids.count())) |new_tab| { │ │378 const tab_id = self.tab_ids.keys()[new_tab]; │ │379 root_focus.setFocus(tab_id); │ │343 - const tab = self.scroll.child.box.children.get(tab_id) orelse return;│ │344 - if (tab.rect) |rect| self.scroll.scrollToRect(rect); │ │380 + const tabs_child = self.tabsChild(); │ │381 + const tabs_rect = tabs_child.rect orelse return; │ │382 + const tab = tabs_child.widget.box.children.get(tab_id) orelse return;│ │383 + var rect = tab.rect orelse return; │ │384 + rect.x += tabs_rect.x; │ │385 + rect.y += tabs_rect.y; │ │386 + self.scroll.scrollToRect(rect); │ │387 } │ │388 } │ │389 │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │404 } │ │405 │ │406 fn currentTabIndex(self: View) ?usize { │ │365 - const child_id = self.scroll.child.box.focus.child_id orelse return null; │ │407 + if (self.scroll.child.box.focus.child_id != self.tabs_id) return null; │ │408 + const child_id = self.tabsChild().widget.box.focus.child_id orelse return null;│ │409 return self.tab_ids.getIndex(child_id); │ │410 + } │ │411 + │ │412 + fn tabsChild(self: *const View) *wgt.Box(ui.Widget).Child { │ │413 + return self.scroll.child.box.children.getPtr(self.tabs_id) orelse unreachable; │ │414 } │ │415 }; │ │416 │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────╮ │src/ui/Title.zig│ ╰────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │18 }; │ │19 } │ │20 │ │21 +pub fn width(self: Self) !usize { │ │22 + const line_end = std.mem.indexOfScalar(u8, self.content, '\n') orelse self.content.len;│ │23 + return xitui.width.displayWidth(self.content[0..line_end]); │ │24 +} │ │25 + │ │26 pub const View = struct { │ │27 text_box: wgt.TextBox(ui.Widget), │ │28 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯