style(web): move the row-count select into the card header
It was sitting in a strip below the heading with a "Show" label and a "newest first" hint — three lines of chrome for one control. The select now lives at the right end of the card's own header bar (`margin-left:auto` inside the flex h2), compact and case-normal so it reads as a control and does not grow the bar. Label and hint are gone; the header text names the card, the values speak for themselves, and screen readers keep the `aria-label`.
This commit is contained in:
+3
-3
@@ -295,9 +295,9 @@ Gitea at most one call per 10s window; the VM columns are re-read on every
|
||||
refresh.
|
||||
|
||||
Rows are ordered **newest first** (a queued run, which has no start time yet,
|
||||
sorts above everything; ties break on Gitea's run id). The **Show** selector in
|
||||
the card's header picks how many to list — 10 / 25 / 50 / 100, default from
|
||||
`[web].executions_limit` (10). The choice rides on the card's own polling URL
|
||||
sorts above everything; ties break on Gitea's run id). The row-count dropdown at
|
||||
the right end of the card's header bar picks how many to list — 10 / 25 / 50 /
|
||||
100, default from `[web].executions_limit` (10). The choice rides on the card's own polling URL
|
||||
(`/executions?limit=N`), so it survives every 5s refresh with no client-side
|
||||
state; a value set in the config outside those four is offered as an extra
|
||||
option rather than dropped.
|
||||
|
||||
@@ -281,17 +281,19 @@ dd code, dd .mono { overflow-wrap: anywhere; }
|
||||
/* A row of buttons (e.g. Purge / Empty all) that wraps on narrow cards. */
|
||||
.btn-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
||||
|
||||
/* Small control strip under a card's heading (Executions row count): right
|
||||
* aligned so it reads as a view option, not as part of the data below. */
|
||||
.card-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
margin: -0.35rem 0 0.7rem;
|
||||
/* A control living inside a card's header bar (Executions row count), pushed to
|
||||
* the bar's right end. Compact and case-normal so it reads as a control rather
|
||||
* than part of the uppercase heading text, and short enough not to grow the
|
||||
* bar's height. */
|
||||
.head-select {
|
||||
margin-left: auto;
|
||||
padding: 0.1rem 0.35rem;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.2;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
color: var(--text);
|
||||
}
|
||||
.card-toolbar select { padding: 0.2rem 0.4rem; }
|
||||
|
||||
/* Per-template expandable backup list (Templates panel). */
|
||||
.backups-details > summary {
|
||||
|
||||
@@ -11,15 +11,18 @@
|
||||
scrolled out of the window (or that no run ever claimed) keeps its row and
|
||||
its Remove button.
|
||||
|
||||
The row-count selector re-fetches the card with ``?limit=N``, and the card it
|
||||
renders carries that same limit on its own polling URL -- that is what makes
|
||||
the choice survive the 5s refresh without any client-side state.
|
||||
The row-count selector sits in the card's own header bar (right end) and
|
||||
re-fetches the card with ``?limit=N``; the card it renders carries that same
|
||||
limit on its polling URL, which is what makes the choice survive the 5s
|
||||
refresh without any client-side state. It carries no visible label -- the
|
||||
header text names the card and the values are self-evident -- so screen
|
||||
readers get ``aria-label`` instead.
|
||||
#}
|
||||
<section class="card card--wide" id="executions-card" hx-get="/executions?limit={{ limit }}" hx-trigger="every 5s, ci:refresh from:body" hx-swap="outerHTML">
|
||||
<h2><svg class="icon" aria-hidden="true"><use href="#i-play"></use></svg>Executions</h2>
|
||||
<div class="card-toolbar">
|
||||
<label for="executions-limit">Show</label>
|
||||
<select id="executions-limit" name="limit" aria-label="Number of executions to show"
|
||||
<h2>
|
||||
<svg class="icon" aria-hidden="true"><use href="#i-play"></use></svg>Executions
|
||||
<select id="executions-limit" name="limit" class="head-select"
|
||||
aria-label="Number of executions to show"
|
||||
hx-get="/executions" hx-target="#executions-card" hx-swap="outerHTML" hx-trigger="change">
|
||||
{% for choice in limit_choices %}
|
||||
<option value="{{ choice }}" {{ 'selected' if choice == limit else '' }}>{{ choice }}</option>
|
||||
@@ -28,8 +31,7 @@
|
||||
<option value="{{ limit }}" selected>{{ limit }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
<span class="field-hint">newest first</span>
|
||||
</div>
|
||||
</h2>
|
||||
{% if not backend_available %}
|
||||
<p class="notice notice-warn" role="alert">Backend unavailable (vmrun not found on this host).</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -385,7 +385,10 @@ def test_default_limit_is_ten(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -
|
||||
|
||||
assert limits == [10]
|
||||
assert '<option value="10" selected>10</option>' in resp.text
|
||||
assert "newest first" in resp.text
|
||||
# The selector lives inside the card's header bar, not in a strip below it.
|
||||
head = resp.text.split("</h2>", 1)[0]
|
||||
assert "head-select" in head
|
||||
assert "<label" not in resp.text
|
||||
|
||||
|
||||
def test_selector_offers_the_choices_and_marks_the_current_one(
|
||||
|
||||
Reference in New Issue
Block a user