v0.27.0 0039612

tree.templ RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5// Tree is a directory as a tree: the file finder on top, then the entries
6// with their last commit, and the notes on what is left out. A directory opens
7// in place (files.js); the keyboard walks the rows (j k l h, the arrows).
8templ Tree(l Layout, p TreePage) {
9	@Shell(l, nil) {
10		<div class="tree-find">
11			<div class="filter wide">
12				<label for="finder-q" class="sr">find a file</label>
13				<input
14					id="finder-q"
15					type="search"
16					data-filter
17					role="combobox"
18					aria-autocomplete="list"
19					aria-controls="finder-list"
20					aria-expanded="false"
21					placeholder="Find a file in this repository…"
22					autocomplete="off"
23					spellcheck="false"
24					hx-on:focus="ermiteFinder.load()"
25					hx-on:input="ermiteFinder.input(this)"
26					hx-on:keydown="ermiteFinder.key(this, event)"
27				/>
28			</div>
29			<p class="tree-keys" data-js aria-hidden="true"><kbd>j</kbd> <kbd>k</kbd> move · <kbd>l</kbd> open · <kbd>h</kbd> back</p>
30		</div>
31		<div id="finder" class="tree-card" hidden>
32			<p id="finder-status" class="dim" aria-live="polite"></p>
33			<ul id="finder-list" class="cmd-list" role="listbox" aria-label="Files"></ul>
34		</div>
35		<div id="tree-view" class="tree-card">
36			<div class="tree-head">
37				<span class="tree-path">{ p.Path }</span>
38				if p.Up != "" {
39					<a class="tree-up" href={ templ.SafeURL(p.Up) } title="parent directory (h)">..</a>
40				}
41				<span class="tree-count">{ itoa(len(p.Rows)) } { p.Unit() }</span>
42			</div>
43			<ul
44				id="tree-rows"
45				class="tree"
46				role="tree"
47				aria-label="Entries"
48				data-rows
49				data-tree
50				if p.Up != "" {
51					data-up={ p.Up }
52				}
53				hx-on:click="ermiteTree.click(event)"
54			>
55				@TreeRows(p)
56			</ul>
57			if len(p.Rows) == 0 {
58				<p class="lede dim">this directory is empty.</p>
59			}
60			for _, n := range p.Notes {
61				<p class="note">{ n }</p>
62			}
63		</div>
64	}
65}
66
67// TreeRows is the rows of a directory alone: what files.js inserts under a
68// directory it opens in place. When the directory has more entries than are
69// listed, the last row links to its page.
70templ TreeRows(p TreePage) {
71	for _, r := range p.Rows {
72		@TreeRowView(r)
73	}
74	if p.More != "" {
75		<li class="tree-more" role="treeitem" aria-level="1" aria-posinset={ itoa(p.MorePos) } aria-setsize="-1" data-depth="0">
76			<span class="t-main">
77				<span class="t-twig" aria-hidden="true"></span>
78				<span class="t-node" aria-hidden="true"></span>
79				<a class="t-name" href={ templ.SafeURL(p.More) }>more entries: open the directory</a>
80			</span>
81		</li>
82	}
83}
84
85// TreeRowView is one entry of a directory, a row of the tree: the guides of
86// its depth (t-twig), its node, its name, then its last commit. A directory
87// carries data-expand, the URL of its rows, and aria-expanded; files.js sets
88// the depth of the rows it inserts (data-depth, --depth, aria-level).
89// aria-posinset and aria-setsize count the entries of the row's own directory
90// (setsize -1: the listing is cut and the total unknown), so the positions
91// stay right once the rows of a directory are inserted into the flat list. The
92// node is drawn by the stylesheet from data-kind, which is aria-hidden: the
93// type of a directory, a link or a submodule is said in text for screen readers
94// (the .sr span, part of the name of the treeitem) and in a tooltip.
95templ TreeRowView(r TreeRow) {
96	<li
97		role="treeitem"
98		aria-level="1"
99		aria-posinset={ itoa(r.Pos) }
100		aria-setsize={ itoa(r.Set) }
101		data-kind={ r.Kind }
102		data-depth="0"
103		data-cursor?={ r.Cursor }
104		if r.Expand != "" {
105			data-expand={ r.Expand }
106			aria-expanded="false"
107		}
108	>
109		<span class="t-main">
110			<span class="t-twig" aria-hidden="true"></span>
111			<span class="t-node" aria-hidden="true"></span>
112			if r.Href != "" {
113				<a
114					class="t-name"
115					href={ templ.SafeURL(r.Href) }
116					if r.Hint != "" {
117						title={ r.Hint }
118					}
119				>{ r.Name }</a>
120			} else {
121				<span
122					class="t-name"
123					if r.Hint != "" {
124						title={ r.Hint }
125					}
126				>{ r.Name }</span>
127			}
128			if r.Hint != "" {
129				<span class="sr">{ " (" + r.Hint + ")" }</span>
130			}
131		</span>
132		<span class="t-size">{ r.Size }</span>
133		<span class="t-sub">
134			if r.CHref != "" {
135				<a class="t-commit" href={ templ.SafeURL(r.CHref) } title={ r.Author }>{ r.Subject }</a>
136			}
137		</span>
138		<span class="t-when">
139			if r.WhenAt != "" {
140				<time datetime={ r.WhenAt } title={ r.WhenAt }>{ r.When }</time>
141			}
142		</span>
143	</li>
144}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 44

↑↓ moveenter openesc close