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 <p id="finder-status" class="dim" role="status"></p>
32 <div id="finder" class="tree-card" hidden>
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}