refactor(web): unify the competing head-row patterns (.section-head vs .card-head) onto shared components #280

Closed
opened 2026-08-04 19:24:39 +02:00 by dominik.polakovics · 1 comment

This was generated by AI during triage.

Split out of umbrella #276 (frontend component reuse, follow-up to #275).

The frontend has two competing head-row patterns: page-level .section-head (shell.css — an <h2> plus optional inline controls, hand-rolled in ~13 route files) and card-level .card-head (cards.css — title + spacer + action). #275 extracted SectionCard, whose head (.card-head.section-card-head) already owns the head/hint/body spacing contract for settings-style section cards, and cards.css deliberately mirrors .section-head h2 sizing to keep the two rows visually aligned — duplication the CSS itself comments on.

Unify head-row markup onto shared components so the row's markup and spacing live in one place. The agent brief follows in a comment.

> *This was generated by AI during triage.* Split out of umbrella #276 (frontend component reuse, follow-up to #275). The frontend has two competing head-row patterns: page-level `.section-head` (shell.css — an `<h2>` plus optional inline controls, hand-rolled in ~13 route files) and card-level `.card-head` (cards.css — title + spacer + action). #275 extracted `SectionCard`, whose head (`.card-head.section-card-head`) already owns the head/hint/body spacing contract for settings-style section cards, and cards.css deliberately mirrors `.section-head h2` sizing to keep the two rows visually aligned — duplication the CSS itself comments on. Unify head-row markup onto shared components so the row's markup and spacing live in one place. The agent brief follows in a comment.
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: One shared implementation of the "heading + right-aligned action" head row; page-level and card-level heads stop hand-rolling it.

Current behavior:
Two competing patterns render the same visual row. Page-level heads use .section-head — an <h2> plus optional inline controls — hand-rolled in the list routes (Repos, History, Tokens, Credentials, RepoIssues, RepoCRs), the detail routes, and both settings shells. Card-level heads use .card-head. SectionCard (from #275) already owns the card-level head for settings-style section cards, including the spacing contract: the component owns all spacing between head row, hint, and body, and call sites must not re-add margins. Everywhere else the row is hand-rolled, and the two CSS classes duplicate near-identical sizing rules with cross-referencing comments ("mirrors .section-head h2").

Desired behavior:
Head-row markup is produced by shared components only:

  • SectionCard where the head belongs to a card section — card sections that hand-roll a .card-head with an <h2> migrate to it where the full card shape fits.
  • A new shared page-head component (suggested name SectionHead) for page-level heads that are not cards: heading, always-present spacer, optional action/controls slot (History's filter select, for example, must fit).

The #275 spacing contract extends to the page-level head: the component owns the gap, call sites add no margins around it. The rendered look is unchanged.

Key interfaces:

  • SectionCard — the existing exemplar; do not change its public props for this issue
  • New SectionHead (or similar) component owning the page-level head row, with the same always-present-spacer trick so markup is identical with and without an action
  • The .section-head / .card-head CSS rules — consolidate sizing rules that the unification makes redundant, without visual change; the invariant "the row's height must never depend on whether an action is present" must keep holding for both head kinds

Acceptance criteria:

  • A shared page-head component exists with a colocated test (SectionCard test style)
  • Page-level routes that hand-roll .section-head render through the shared component
  • Card sections whose shape matches SectionCard (heading + optional action + optional hint above a body) use SectionCard instead of a hand-rolled head row
  • Head-row height is unchanged with and without an action, for both page-level and card-level heads
  • No visual change; existing frontend tests pass

Out of scope:

  • Entity list-row heads that use .card-title (TokenCard-style rows) — that's the list-row family under #276
  • Any spacing/visual redesign beyond deleting call-site margins the shared component makes redundant
  • The other pattern families tracked by #276
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** One shared implementation of the "heading + right-aligned action" head row; page-level and card-level heads stop hand-rolling it. **Current behavior:** Two competing patterns render the same visual row. Page-level heads use `.section-head` — an `<h2>` plus optional inline controls — hand-rolled in the list routes (Repos, History, Tokens, Credentials, RepoIssues, RepoCRs), the detail routes, and both settings shells. Card-level heads use `.card-head`. `SectionCard` (from #275) already owns the card-level head for settings-style section cards, including the spacing contract: the component owns all spacing between head row, hint, and body, and call sites must not re-add margins. Everywhere else the row is hand-rolled, and the two CSS classes duplicate near-identical sizing rules with cross-referencing comments ("mirrors `.section-head h2`"). **Desired behavior:** Head-row markup is produced by shared components only: - `SectionCard` where the head belongs to a card section — card sections that hand-roll a `.card-head` with an `<h2>` migrate to it where the full card shape fits. - A new shared page-head component (suggested name `SectionHead`) for page-level heads that are not cards: heading, always-present spacer, optional action/controls slot (History's filter select, for example, must fit). The #275 spacing contract extends to the page-level head: the component owns the gap, call sites add no margins around it. The rendered look is unchanged. **Key interfaces:** - `SectionCard` — the existing exemplar; do not change its public props for this issue - New `SectionHead` (or similar) component owning the page-level head row, with the same always-present-spacer trick so markup is identical with and without an action - The `.section-head` / `.card-head` CSS rules — consolidate sizing rules that the unification makes redundant, without visual change; the invariant "the row's height must never depend on whether an action is present" must keep holding for both head kinds **Acceptance criteria:** - [ ] A shared page-head component exists with a colocated test (SectionCard test style) - [ ] Page-level routes that hand-roll `.section-head` render through the shared component - [ ] Card sections whose shape matches SectionCard (heading + optional action + optional hint above a body) use SectionCard instead of a hand-rolled head row - [ ] Head-row height is unchanged with and without an action, for both page-level and card-level heads - [ ] No visual change; existing frontend tests pass **Out of scope:** - Entity list-row heads that use `.card-title` (TokenCard-style rows) — that's the list-row family under #276 - Any spacing/visual redesign beyond deleting call-site margins the shared component makes redundant - The other pattern families tracked by #276
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab#280
No description provided.