╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭──────────────────────────────────────────────────────╮ │14 pub const User = @import("./ui/User.zig"); │ │15 pub const Repo = @import("./ui/Repo.zig"); │ │16 pub const Title = @import("./ui/Title.zig"); │ │17 +pub const SubTitle = @import("./ui/SubTitle.zig");│ │18 pub const Quit = @import("./ui/Quit.zig"); │ │19 │ │20 pub const PageKind = enum { │ ╰──────────────────────────────────────────────────────╯ ╭───────────────────────────────────────╮ │887 repo: Repo.View, │ │888 quit: Quit.View, │ │889 title: Title.View, │ │890 + sub_title: SubTitle.View, │ │891 home_header: Home.Header.View,│ │892 user_header: User.Header.View,│ │893 repo_header: Repo.Header.View,│ ╰───────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/Repo/Refs.zig│ ╰────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │25 tags: []const []const u8, │ │26 branches_next_after: ?usize, │ │27 tags_next_after: ?usize, │ │28 +// the columns' headers, in the half-height SubTitle font.│ │29 +branches_label: ui.SubTitle, │ │30 +tags_label: ui.SubTitle, │ │31 │ │32 const Self = @This(); │ │33 │ ╰──────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────╮ │45 // the offset only applies to its own column; the other stays at 0.│ │46 const branches_after: usize = if (kind == .branch) after else 0; │ │47 const tags_after: usize = if (kind == .tag) after else 0; │ │48 + const branches_label = try ui.SubTitle.init(arena, "branches"); │ │49 + const tags_label = try ui.SubTitle.init(arena, "tags"); │ │50 const empty: Self = .{ │ │51 .identity = try aa.dupe(u8, identity), │ │52 .kind = kind, │ ╰───────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │55 .tags = &.{}, │ │56 .branches_next_after = null, │ │57 .tags_next_after = null, │ │58 + .branches_label = branches_label, │ │59 + .tags_label = tags_label, │ │60 }; │ │61 │ │62 // no filesystem (wasm) or nowhere to look: empty lists. the wasm path never│ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────╮ │90 .tags = tags.names, │ │91 .branches_next_after = branches.next_after,│ │92 .tags_next_after = tags.next_after, │ │93 + .branches_label = branches_label, │ │94 + .tags_label = tags_label, │ │95 }; │ │96 } │ │97 │ ╰───────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │131 // the offset only applies to its own column; the other starts at 0. │ │132 const branches_after: usize = if (data.kind == .branch) data.after else 0; │ │133 const tags_after: usize = if (data.kind == .tag) data.after else 0; │ │125 - try addColumn(allocator, &box, session, data.identity, .branch, "branches:", data.branches, branches_after, data.branches_next_after); │ │126 - try addColumn(allocator, &box, session, data.identity, .tag, "tags:", data.tags, tags_after, data.tags_next_after); │ │134 + try addColumn(allocator, &box, session, data.identity, .branch, &data.branches_label, data.branches, branches_after, data.branches_next_after);│ │135 + try addColumn(allocator, &box, session, data.identity, .tag, &data.tags_label, data.tags, tags_after, data.tags_next_after); │ │136 │ │137 var self = View{ .box = box, .data = data }; │ │138 // select the first row of the first column that has one. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │151 session: *ui.Session, │ │152 identity: []const u8, │ │153 kind: ui.RoutablePage.RefKind,│ │145 - label: []const u8, │ │154 + label: *const ui.SubTitle, │ │155 names: []const []const u8, │ │156 after: usize, │ │157 next_after: ?usize, │ ╰───────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │159 var column = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .vert }); │ │160 errdefer column.deinit(allocator); │ │161 │ │153 - // a fixed, non-focusable header styled like the rows so it left-aligns │ │154 - // with them; it stays visible while the rows scroll below. it declares │ │155 - // its height as a min so the (fill) scroll reserves room for it rather │ │156 - // than consuming the whole column. one text line framed by a (hidden) │ │157 - // border above and below. │ │162 + // a fixed, non-focusable header in the SubTitle font, nudged off the │ │163 + // left edge by a one-column space. it stays visible while the rows │ │164 + // scroll below, and declares its height (2 rows) as a min so the (fill) │ │165 + // scroll reserves room for it rather than consuming the whole column. │ │166 { │ │159 - var header = try wgt.TextBox(ui.Widget).init(allocator, label, .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .none }); │ │160 - errdefer header.deinit(allocator); │ │161 - try column.children.put(allocator, header.getFocus().id, .{ .widget = .{ .text_box = header }, .rect = null, .min_size = .{ .width = null, .height = 1 + 2 } });│ │167 + var header_box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); │ │168 + errdefer header_box.deinit(allocator); │ │169 + { │ │170 + var space = try wgt.Text(ui.Widget).init(allocator, " "); │ │171 + errdefer space.deinit(allocator); │ │172 + try header_box.children.put(allocator, space.getFocus().id, .{ .widget = .{ .text = space }, .rect = null, .min_size = null }); │ │173 + } │ │174 + { │ │175 + var header = try ui.SubTitle.View.init(allocator, label); │ │176 + errdefer header.deinit(allocator); │ │177 + try header_box.children.put(allocator, header.getFocus().id, .{ .widget = .{ .sub_title = header }, .rect = null, .min_size = null }); │ │178 + } │ │179 + try column.children.put(allocator, header_box.getFocus().id, .{ .widget = .{ .box = header_box }, .rect = null, .min_size = .{ .width = null, .height = 2 } }); │ │180 } │ │181 │ │182 // a long ref list overflows the page height; the rows scroll on their │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ added ────────────╮ │src/ui/SubTitle.zig│ ╰───────────────────╯