v0.3.0 9fdf386

overlays.templ RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5import "strings"
6
7// OverlayHelp is the keyboard map panel.
8templ OverlayHelp() {
9	<dialog id="panel-help" class="panel" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())">
10		<div class="panel-head"><span>keys</span><button type="button" hx-on:click="closest('dialog').close()">[esc] close</button></div>
11		<dl class="keys">
12			<div><dt><kbd>j</kbd> <kbd>k</kbd></dt><dd>move cursor down / up</dd></div>
13			<div><dt><kbd>enter</kbd></dt><dd>open row under cursor</dd></div>
14			<div><dt><kbd>g</kbd> <kbd>g</kbd> / <kbd>G</kbd></dt><dd>first / last row</dd></div>
15			<div><dt><kbd>/</kbd></dt><dd>focus the filter</dd></div>
16			<div><dt><kbd>g h</kbd> <kbd>g t</kbd></dt><dd>go home / tree</dd></div>
17			<div><dt><kbd>g c</kbd> <kbd>g r</kbd></dt><dd>go commits / refs</dd></div>
18			<div><dt><kbd>b</kbd></dt><dd>{ "switch" } ref (branches, tags)</dd></div>
19			<div><dt><kbd>:</kbd> <kbd>f</kbd></dt><dd>go to: section, ref, file, repo</dd></div>
20			<div><dt><kbd>y</kbd></dt><dd>permalink: ref becomes the full sha</dd></div>
21			<div><dt><kbd>s</kbd> <kbd>t</kbd> <kbd>c</kbd> <kbd>r</kbd></dt><dd>repo sections (when shown)</dd></div>
22			<div><dt><kbd>m</kbd> <kbd>g m</kbd></dt><dd>merge requests (when shown)</dd></div>
23			<div><dt><kbd>d</kbd> <kbd>u</kbd> <kbd>x</kbd></dt><dd>diff: split / unified / collapse all</dd></div>
24			<div><dt><kbd>n</kbd></dt><dd>merge request: next note in the diff</dd></div>
25			<div><dt><kbd>esc</kbd></dt><dd>close panel</dd></div>
26		</dl>
27	</dialog>
28}
29
30// OverlayRefs is the ref switcher. It exists only inside a repository.
31templ OverlayRefs(l Layout) {
32	if l.Ref != "" {
33		<dialog id="panel-refs" class="panel" aria-label="Switch ref" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())">
34			<div class="panel-head">
35				<label for="refs-filter">ref&gt;</label>
36				<input
37					id="refs-filter"
38					type="search"
39					placeholder="filter branches and tags"
40					autocomplete="off"
41					data-pick
42					hx-on:input="let t = this.value.toLowerCase(); q('#panel-refs li').arr().forEach(li => li.hidden = !li.textContent.toLowerCase().includes(t))"
43				/>
44				<button type="button" hx-on:click="closest('dialog').close()">[esc] close</button>
45			</div>
46			<div class="panel-cols" data-picklist>
47				<section aria-label="Branches">
48					<h2>branches <span class="mute">{ itoa(len(l.Heads)) }</span></h2>
49					<ul>
50						for _, r := range l.Heads {
51							@refItem(r)
52						}
53					</ul>
54				</section>
55				<section aria-label="Tags">
56					<h2>tags <span class="mute">{ itoa(len(l.Tags)) }</span></h2>
57					<ul>
58						for _, r := range l.Tags {
59							@refItem(r)
60						}
61					</ul>
62				</section>
63			</div>
64		</dialog>
65	}
66}
67
68templ refItem(r RefItem) {
69	<li>
70		<a
71			href={ templ.SafeURL(r.Href) }
72			if r.Current {
73				aria-current="true"
74			}
75		>
76			<span class="mark" aria-hidden="true">
77				if r.Current {
78					●
79				} else {
80					&nbsp;
81				}
82			</span>{ r.Name }
83		</a>
84	</li>
85}
86
87// OverlayCmd is the ":" command line: one filterable list mixing sections,
88// refs, files of this directory and repos.
89templ OverlayCmd(items []CmdItem) {
90	<dialog id="panel-cmd" class="panel" aria-label="Go to" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())">
91		<div class="panel-head">
92			<label for="cmd-q" class="hi">:</label>
93			<input
94				id="cmd-q"
95				type="search"
96				placeholder="section, ref, file or repo"
97				autocomplete="off"
98				spellcheck="false"
99				aria-controls="cmd-list"
100				hx-on:input="let t = this.value.toLowerCase().trim();
101        q('#cmd-list > li').arr().forEach(li => li.hidden = !li.dataset.k.includes(t));
102        let first = q('#cmd-list > li:not([hidden])').arr()[0]; first && q(first).take('data-cursor', '#cmd-list > li')"
103				hx-on:keydown="let vis = q('#cmd-list > li:not([hidden])').arr();
104        let i = vis.findIndex(li => li.hasAttribute('data-cursor'));
105        let step = event.key === 'ArrowDown' ? 1 : event.key === 'ArrowUp' ? -1 : 0;
106        if (step) { event.preventDefault(); let n = vis[Math.max(0, Math.min(vis.length - 1, i + step))]; n && (q(n).take('data-cursor', '#cmd-list > li'), n.scrollIntoView({ block: 'nearest' })) }
107        else if (event.key === 'Enter') { event.preventDefault(); vis[Math.max(i, 0)]?.querySelector('a').click() }"
108			/>
109			<button type="button" hx-on:click="closest('dialog').close()">[esc] close</button>
110		</div>
111		<ul id="cmd-list" class="cmd-list">
112			for i, c := range items {
113				<li data-k={ strings.ToLower(c.Kind + " " + c.Label) } data-cursor?={ i == 0 }><a href={ templ.SafeURL(c.Href) } tabindex="-1"><span class="k">{ c.Kind }</span>{ c.Label }</a></li>
114			}
115		</ul>
116	</dialog>
117}

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 2

Tags 45

↑↓ moveenter openesc close