Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Standardize filter rows and add tag selection to the code page

55615c7a4b8472f8bfccab8048f608978d389821 · Keenan Nemetz · 11d ago · parent 3a068983

Standardize filter rows and add tag selection to the code page

The code page kept its branch picker in the header actions, had no tag picker,
and left every list page to shape its own filters: search inputs ranged from
10rem to 18rem, some selects had a visible label and some did not, and text
searches submitted through a Filter button, a Search button, or Enter alone
while selects sometimes waited for a click.

- One .filters row on issues, requests, activity, the code page and code
  search. One --search-w (18rem) for page and global search, a visible label on
  every filter select, auto-apply on select change, and one icon-and-Search
  button for text.
- The code page puts its search, branch picker and new tag picker on the shared
  row under the header. The tag picker lists tags newest first and leaves the
  branch picker unclaimed when a tag is open.
- data-autosubmit uses requestSubmit() so htmx swaps the filtered pane instead
  of a full page load.

Checks: ./vole workflow check; ./vole workflow run verify.

server/web/static/vole.css +31−6

@@ -79,6 +79,9 @@
79 79 /* shape and type */
80 80 --radius: 6px;
81 81 --radius-lg: 8px;
82 /* One width for every search input: the global bar and a page's filter row
83 should not resize the field when the reader moves between them. */
84 --search-w: 18rem;
82 85 --font: "Lexend", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Liberation Sans", Arial, sans-serif;
83 86 --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
84 87 --fs: 15.4px;
@@ -246,8 +249,9 @@ img { max-width: 100%; }
246 249 color: var(--accent);
247 250 }
248 251
249 .topsearch { margin-left: auto; }
250 .topsearch input[type="search"] { width: 12rem; max-width: 28vw; }
252 .topsearch { display: flex; align-items: center; gap: 6px; min-width: 0; margin-left: auto; }
253 .topsearch input[type="search"] { flex: 1 1 auto; width: var(--search-w); min-width: 8rem; max-width: 28vw; }
254 .topsearch button { flex: 0 0 auto; }
251 255
252 256 .topright {
253 257 display: flex;
@@ -327,7 +331,7 @@ img { max-width: 100%; }
327 331 gap: 8px 12px;
328 332 }
329 333 .topsearch { order: 3; flex: 1 1 100%; margin-left: 0; }
330 .topsearch input[type="search"] { width: 100%; max-width: none; }
334 .topsearch input[type="search"] { width: 100%; min-width: 0; max-width: none; }
331 335 .topright { margin-left: auto; }
332 336 .topnav { gap: 4px; }
333 337 .topnav a { padding: 4px 8px; }
@@ -573,6 +577,9 @@ label > input, label > textarea, label > select {
573 577 }
574 578 label > select { width: 100%; max-width: 34rem; }
575 579
580 /* Every filter/search row is one component: controls in a wrapping row, a
581 visible label on every select, selects that apply on change, and a Search
582 button for the text field. Search inputs share --search-w on every surface. */
576 583 .filters {
577 584 display: flex;
578 585 flex-wrap: wrap;
@@ -580,8 +587,16 @@ label > select { width: 100%; max-width: 34rem; }
580 587 gap: 8px;
581 588 margin: 10px 0 12px;
582 589 }
590 /* The code page needs a form per ref picker (two refs in one form would submit
591 twice), so the row can contain forms as well as be one. */
592 .filters form {
593 display: inline-flex;
594 flex-wrap: wrap;
595 align-items: center;
596 gap: 8px;
597 }
583 598 .filters input[type="text"],
584 .filters input[type="search"] { max-width: 18rem; }
599 .filters input[type="search"] { width: var(--search-w); max-width: 100%; }
585 600 /* A label and its control stay on one line when the filter row wraps. */
586 601 .filter-field {
587 602 display: inline-flex;
@@ -596,6 +611,18 @@ label > select { width: 100%; max-width: 34rem; }
596 611 margin-top: 0;
597 612 }
598 613 .chips + .filters { margin-top: 0; }
614 .page-head + .filters { margin-top: 0; }
615
616 @media (max-width: 720px) {
617 .filters { flex-direction: column; align-items: stretch; }
618 .filters form { flex-direction: column; align-items: stretch; }
619 .filters input[type="text"],
620 .filters input[type="search"] { width: 100%; }
621 /* A phone stacks the label above its control: a label and an 18rem select
622 cannot share a 20rem-wide row without the control overflowing it. */
623 .filter-field { flex-direction: column; align-items: stretch; gap: 4px; }
624 .filters .filter-field > select { width: 100%; }
625 }
599 626
600 627 /* ---------- labels, flashes, empty pages ---------- */
601 628
@@ -2326,7 +2353,6 @@ textarea:focus-visible {
2326 2353 /* ---------- code search ---------- */
2327 2354
2328 2355 /* One block per file, with line numbers linked to blob anchors. */
2329 .search-code input[type="search"] { width: 10rem; }
2330 2356 .search-group { margin: 14px 0; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg-panel); overflow: hidden; }
2331 2357 .search-group h3 { margin: 0; padding: 7px 10px; background: var(--bg-raised); border-bottom: 1px solid var(--border); font-size: calc(13.2px * var(--font-scale)); }
2332 2358 .search-group h3 a { color: var(--fg); }
@@ -2334,7 +2360,6 @@ textarea:focus-visible {
2334 2360 .search-lines td.ln { width: 5ch; text-align: right; color: var(--fg-faint); font-family: var(--mono); font-size: calc(12.1px * var(--font-scale)); }
2335 2361 .search-lines td.ln a { color: var(--fg-faint); }
2336 2362 .search-lines tr:hover td.ln a { color: var(--accent); }
2337 @media (max-width: 720px) { .search-code { display: none; } }
2338 2363 .code-main tr:target { background: var(--accent-soft); }
2339 2364
2340 2365 /* ---------- blame ---------- */