docs/specs/2026-09-11-web-ux-sweep-design.md
79 lines · 4160 bytes
1# Web UI/UX sweep
2
3Closes #182. The findings posted on that issue after walking every route in
4`internal/httpd/routes.go` on gitbay.org at v1.20.1, anonymous and logged
5in, and the rules chosen to fix them.
6
7## Rules
8
9- **Confirmation.** A control that destroys data nothing else holds asks
10 the person to type the object's name into a text field beside the
11 button; the handler refuses with a flash line when the text differs.
12 No JavaScript: the instance CSP is `script-src 'none'`. Covered: release
13 delete (the tag), snippet delete (the id), snippet file remove (the file
14 name), team delete (the team name), label remove (the label), SSH key
15 remove (the 8 characters after `SHA256:` in the fingerprint; a label
16 can be empty), email remove (the address), PGP key remove (the first
17 8 characters of the fingerprint). Reversible state keeps a
18 plain button: close/reopen, merge, protect/unprotect, attach/detach,
19 resolve, cancel, make primary, org member remove.
20- **Refusal wording.** Control-command messages a web form can trigger
21 must not name a flag or a CLI command. The message is rewritten at the
22 source, in `internal/control`, since the CLI reads the same text; no
23 rewrite layer in the web.
24- **Login return-to.** `requireUser` stores the requested local path in a
25 short-lived cookie; the login page says where the person is going; the
26 emailed-link and `web login` paths both redirect there once and clear it.
27 Only a path starting with a single `/` is honoured.
28- **Dates.** One absolute format on every page: `2006-01-02 15:04 UTC`
29 through the existing `when` helper. Tree and blob listings keep their
30 relative time with the absolute one in a `title` attribute.
31- **Tags.** Version-aware order on the refs page, newest first; a tag that
32 does not parse as a version sorts after the ones that do, by name.
33- **Editor.** When the repository requires signed commits, or the ref
34 refuses direct pushes, the edit page explains that and shows no form.
35 A branch that does not exist is a 404; a path that does not exist on
36 a real branch is a new-file form that says so, since `commit-file`
37 creates it.
38- **Repository settings.** Every Save names its field.
39- **Empty states.** Sidebars use "none yet" for things and "nobody yet"
40 for people; lists keep their sentence and, where a command creates the
41 thing, name it.
42
43## Findings and their fixes
44
451. Destructive controls without confirmation: the rule above, applied to
46 `account.html`, `settings.html` (no change: unprotect and detach are
47 reversible), `owner.html` (team delete only), `labels.html`,
48 `releases.html`, `snippet.html`.
492. Refusals verbatim: audit and rewrite.
503. `account.html` says `gitbay auth token mint`; the command is
51 `auth token create`.
524. Login return-to.
535. Four date formats.
546. Refs page sorts tags as strings.
557. Editor offered where it cannot succeed.
568. Twelve unlabelled Save buttons on repository settings.
579. Labels page: colour column shown when no label has a colour; the
58 column and the per-row colour form appear only when a label has a
59 colour or the viewer can write.
6010. Empty-state wording.
6111. Issue close-event line reads "closed by commit X by Y"; becomes
62 "closed by Y in commit X" with the time inline.
6312. Issue rows repeat the state chip under a single-state filter; the
64 milestone reads like a label. The chip appears only under "all"; the
65 milestone renders as "in <milestone>".
6613. Merged MR page: "at" becomes "merged at"; a source branch that no
67 longer exists is marked "branch deleted".
6814. Global search shows a count and the query. No context line.
6915. Repository home shows both clone URLs, HTTPS and SSH.
7016. Landing page: "mint a browser session" becomes "log in from your
71 terminal". The account page's markup picker already sits beside its
72 label; that finding was wrong and nothing changes.
7317. Left alone: the anonymous "1 bookmark" stat, since the count is public
74 by design (the bookmarks page says so).
75
76## Out of scope
77
78A context line on global search results (a search backend change), the
79POST-only routes, `/settings/export`, archives, badges and Atom feeds.