Skip to content

🐛 Complete missing items from PR #313 popover redesign (issue #178 / #294 gaps) #324

@eonist

Description

@eonist

Overview

PR #313 delivered the core popover redesign (issue #294) and passes all CI gates. However, a strict comparison of the final design spec in #178 comment 4405046489 and #178 comment 4405047942 against the merged diff reveals four residual gaps.


Gap 1 — Runner rows not tappable (Phase 6 / #310)

Spec says: Every row with a > chevron is navigable — the final ASCII art shows > on runner rows:

| ● eons-MacBookPro-2   CPU: 38.2%   MEM: 4.1%   > |

PR does: PopoverLocalRunnerRow renders Image(systemName: "chevron.right") but wraps nothing in a Button — the chevron is cosmetic only and the row is inert.

Fix required:

  • Wrap each runner row in a Button that navigates to a runner detail view (or at minimum calls an onSelectRunner callback wired in AppDelegate).
  • Follow the same navigate(to:) pattern used by onSelectAction and onSelectJob.
  • If a full runner detail view is out of scope, remove the chevron.right from the row until navigation is wired — showing a non-functional affordance is worse than showing none.

Related: #310


Gap 2 — inline job rows are silently tappable (Phase 3 spec violation)

Spec says (final design comment #4405047942):

child rows have no > since they're not independently tappable

PR does: InlineJobRowsView.jobRow is correctly missing the > icon ✅, but each row is still wrapped in:

Button(action: { onSelectJob(job) }, label: { jobRow(job) })
    .buttonStyle(.plain)

This makes the rows silently tappable (navigation fires on click) with no visual indication — violating the spec's intent that inline job rows are read-only/passive context.

Fix required:

  • Remove the Button wrapper from InlineJobRowsView.body.
  • Render job rows as plain HStack / VStack with no tap action.
  • If a future phase adds job drill-down from inline rows, reintroduce the Button with the > chevron at that point.

Gap 3 — System stats header missing progress bar characters

Spec says (both final ASCII art blocks):

| CPU ██░ 24.6%  MEM ██░ 6.8/16GB  DISK ███ 342/460GB  [⚙] [×] |

Each stat has a short block-character bar (██░, ███░) before the numeric value, providing instant at-a-glance fill feedback.

PR does: statChip renders label + value only — no bar characters:

statChip(label: "CPU", value: String(format: "%.1f%%", stats.cpuPct), pct: stats.cpuPct)

Fix required:

  • Add a compact 3-character block bar before each value using Unicode block characters (, ) scaled to pct.
  • Suggested helper (pure, no new dependencies):
private func blockBar(pct: Double, width: Int = 3) -> String {
    let filled = Int((pct / 100.0 * Double(width)).rounded())
    return String(repeating: "", count: filled) + String(repeating: "", count: width - filled)
}

Gap 4 — + N more… inline jobs caption is passive, not a tappable "Load more" button

PR description says: "expanded groups with > 4 jobs show a tappable "Load more jobs…" button (reveals +4 at a time)"

PR diff does: Renders a passive Text("+ \(activeJobs.count - cap) more…") with no tap action:

if activeJobs.count > cap {
    Text("+ \(activeJobs.count - cap) more…")
        .font(.caption2).foregroundColor(.secondary)
        ...
}

This means users can never reveal the hidden inline jobs — they're silently truncated.

Fix required:

  • Add @State private var inlineJobsLimit: [String: Int] (keyed by group.id) in PopoverMainView (or pass a binding into InlineJobRowsView).
  • Replace the passive caption with a tappable button that increments the per-group cap:
Button(action: { inlineJobsLimit[group.id, default: 4] += 4 }) {
    Text("+ \(activeJobs.count - cap) more jobs…")
        .font(.caption2).foregroundColor(.accentColor)
}
.buttonStyle(.plain)
  • Initial cap: 4. Each tap reveals +4 more.

Acceptance Criteria

  • Runner rows are tappable (or > chevron is removed until navigation exists)
  • inline job rows have no Button wrapper and are not tappable
  • System stats header shows block-bar characters before each value (██░ 24.6%)
  • Overflow inline jobs caption is a tappable button that reveals +4 more per tap
  • All existing SwiftLint, SonarQube, and Octopus Review checks continue to pass

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions