Skip to content

Polish the SharpConsoleUI shell: tables, toolbars, graphs, rhythm#809

Open
nickprotop wants to merge 9 commits into
managedcode:mainfrom
nickprotop:feat/tui-polish-tables-graphs
Open

Polish the SharpConsoleUI shell: tables, toolbars, graphs, rhythm#809
nickprotop wants to merge 9 commits into
managedcode:mainfrom
nickprotop:feat/tui-polish-tables-graphs

Conversation

@nickprotop
Copy link
Copy Markdown
Contributor

What this is

Follow-up polish on the SharpConsoleUI command center that landed in #735. After living with it, the six "browse" pages all collapsed into the same shape: tall PropertyPanel header → search chip → 1-column ListControl with markup-salad rows → bottom-of-page Button stack. This PR fixes that, plus a series of related rhythm/visual cleanups across every surface.

No public API changes, no manifest changes, no modal removals — the shape of the shell from a contract standpoint is identical. This is consumer-side polish only.

Commits (8, each self-contained and reviewable)

  1. docs(superpowers) — plan doc at docs/superpowers/plans/2026-05-25-tui-polish.md covering everything that follows.
  2. refactor(cli) — split InteractiveConsoleApp.Shell.cs (2178 lines) into four partials: Shell (orchestration, modals, palette), Home, Catalog (Skills / Collections / Bundles / Packages / Agents), Workspace (Installed / Project / Analysis / Settings / RemoveAll / UpdateAll / About). Pure file move, zero behavior change.
  3. feat(cli) — thin one-line AddIdentityStrip(...) headers replace the five-row PropertyPanel page headers (which duplicated the StatusBar info). Reclaims ~4 vertical rows per page.
  4. feat(cli) — five list pages (Skills / Bundles / Packages / Agents / Project recommendations) convert from ListControl with bracketed markup-salad rows to sortable TableControl with one column per logical dimension. Modal-on-Enter flow preserved. Collections left rail and Command palette stay as ListControl (narrow single-string browsers, not multi-column data grids).
  5. feat(cli) — page-level ToolbarControl replaces the bottom-of-page Button stacks on Installed / Project / Agents. Toolbar buttons carry selection-aware enabled state ("Update all outdated (N)" disabled when N=0). Existing Ctrl+U / Ctrl+I / Ctrl+Del shortcuts unchanged.
  6. feat(cli) — graphs with gradients across Project / Analysis:
    • Project: BarGraph trio (high / med / low confidence, green / yellow / grey)
    • Analysis: heaviest-skills BarGraph recolored from severity gradient (green→yellow→red) to a cool magnitude gradient — heavy ≠ unsafe
    • Analysis: skills-per-collection BarGraph recolored to a turquoise→purple smooth gradient so the two charts are visually distinguishable
    • Analysis: new third chart — LineGraph of the catalog's token-distribution long tail (Braille mode, cool gradient, high/low markers)
  7. feat(cli) — responsive NavigationView thresholds (Expanded ≥160, Compact ≥90, Minimal <90) reclaim horizontal space on typical IDE-side 120–140 col terminals. Modal toolbar gets WithAboveLine(true) for verb-vs-content separation. Outdated row foreground desaturated so it doesn't fight the Project confidence-yellow.
  8. feat(cli) — Collections master-detail + section rhythm + table truncation fade:
    • Collections left rail → sortable 2-column TableControl (Collection + Skills installed/total) instead of markup list
    • Collections right pane → identity strip + tokens-by-lane BarGraph stack + sortable Lanes Table + two-stage install Toolbar (same primitives as the rest of the shell)
    • Splitter added between left and right (WithSplitterAfter(0)) so the user can rebalance
    • BuildStyledTable(title, accent) centralises the table styling (left-aligned title, sortable, rounded, StretchHorizontal)
    • ApplyStyledTableRuntime(...) flips on TruncationFade = true so cells that overflow their column fade to background over the last 4 columns — no ASCII ellipsis
    • AddSectionHeader(panel, title, accent) replaces BuildSectionPanel(title, "", accent) (a full rounded empty PanelControl) — now a blank spacer line + a titled RuleControl, 2 rows instead of 3, and the heading reads as a rule with a caption rather than as an empty panel
    • Analysis page: drops the redundant 12-collection card grid at the top (same data is in the "skills per collection" BarGraph below) and the redundant bottom bullet list of package signals (count is in the identity strip; detail lives on the Packages page)

Visual changes per page

Page Before After
Home session card + 5 metric cards + bullet hints identity strip + metric cards + bullet hints (header collapsed to one row)
Skills 1-col ListControl, markup salad sortable TableControl: Collection / Lane / Skill / Version / Tokens
Collections static 1:2 grid, markup-list left, PropertyPanel + bullet-lanes right resizable splitter, sortable Table left, identity strip + per-lane BarGraph + Lanes Table + Toolbar right
Bundles 1-col ListControl sortable TableControl: Bundle / Title / Skills / Tokens
Packages 1-col ListControl sortable TableControl: Signal / Kind / Skill / Collection / Lane / Tokens
Agents 1-col ListControl + bottom button sortable TableControl: Status / Agent / Description / Skills + top Toolbar
Installed already a Table; tall header; bottom button stack thin identity strip; top Toolbar (Browse skills · Update all outdated (N) · Remove all (N)); same Table
Project tall header, 1-col ListControl, bottom button thin strip, confidence-trio BarGraph, top Toolbar, sortable recommendations Table
Analysis tall header, 12-card grid, table, 3× empty-PanelControl titled sections, 2 BarGraph stacks, bottom bullet list thin strip, heavy-skills Table, 3 rule-titled sections each followed by their chart (incl. new LineGraph for token distribution)
Settings tall header listing 7 facts thin strip with key targets; form unchanged
About unchanged unchanged (metadata-only page)

Compliance with AGENTS.md

  • Install overview before confirmation: Collections still uses the two-stage inline arm-then-confirm. Skill / bundle / agent detail modals still show the install plan before any installer is called. Toolbar Install / Update / Remove paths fire the existing Runtime/* installers unchanged.
  • Outdated-skill refresh is first-class: now visible in the Toolbar (Update all outdated (N)) and disabled when N=0. Ctrl+U shortcut unchanged. Project page recommendations install with force: true for outdated entries — unchanged from RFC: SharpConsoleUI command center for the interactive shell #735.
  • Direct Skills browse: unchanged, Skills page still lists individual catalog skills with detail/install.
  • Bracketed markup escaping: list/table cells with [stack / lane] text go through Markup.Escape before display — unchanged from RFC: SharpConsoleUI command center for the interactive shell #735.
  • Real terminal only: redirected stdin/stdout still falls through to RunClassicShellAsync. No prompt-degraded mode in the rich path; if SharpConsoleUI can't run, the tool fails clearly.

Status

  • All four projects build clean (ManagedCode.DotnetSkills, ManagedCode.Agents, ManagedCode.DotnetAgents, ManagedCode.DotnetSkills.Tests) — 0 warnings.
  • All 613 tests pass.
  • dotnet skills <subcommand> (list / install / recommend / bundle list / agent install / …) is unchanged — only the bare interactive invocation is affected.
  • The Spectre classic shell (RunClassicShellAsync) is unchanged — redirected stdio still falls through to it.

Diff size

8 files changed, ~+1900 / ~−1100. Most of the delta is the partial-class split (commit 2) and the Collections master-detail rebuild (commit 8). Every other commit is small and reviewable on its own.

🤖 Generated with Claude Code

Plans the follow-up to PR managedcode#735. Splits the 2178-line shell into 4
partials, converts 5 list pages to TableControl, replaces bottom
buttons with selection-aware ToolbarControl, replaces tall
PropertyPanel headers with one-line identity strips, and adds
gradient-styled graphs to Home/Project/Analysis/Settings. NavigationView
and modals are explicitly kept.
Shell.cs was 2178 lines and growing — well past the codebase ceiling.
Split into:

- Shell.cs (1148) — orchestration: RunAsync, CreateCommandCenter, status
  bars, modals, palette, theme, page-shortcut helpers, async callbacks
- Home.cs (80) — BuildHomePage only
- Catalog.cs (468) — Skills, Collections, Bundles, Packages, Agents
- Workspace.cs (541) — Installed, Project, Analysis, Settings,
  RemoveAll/UpdateAll confirmations, About

Zero behavior change. All partials of the same internal sealed class.
Build clean, 0 warnings across all 4 projects. 613/613 tests pass.
…eaders

Page headers were 5-row PanelControls that duplicated info already in the
top StatusBar (project/scope/platform/catalog/target). They cost ~4 rows
of vertical real estate per page above the actual data.

Replace them with `BuildIdentityStrip(title, accent, …facts)` — a single
MarkupControl row: `[bold accent]title[/]  · label₁ value₁  · label₂ …`.
The title carries the page identity in the accent color; the facts carry
only what the StatusBar doesn't already (counts, filters, summary stats).

Converted page headers:
- Home: session
- Catalog: skill browser, collection browser, bundles/packages,
  package signals, orchestration agents
- Workspace: installed skills, project scan, catalog analysis,
  remove all, update all, workspace (settings)

Detail-pane PropertyPanels (inside modals and Collections right-pane)
stay — they're content, not page identity. About also stays since the
property grid IS the page content.

Reclaims ~4 rows per page for the data area in upcoming commits. No
behavior change. Build clean, 613/613 tests pass.
…ject

Five list pages previously crammed three to five logical dimensions into
a single escaped-markup row (`{marker} {alias}  [dim]{status}[/]  …`).
Each is now a sortable TableControl with one column per dimension:

- Skills:    Collection · Lane · Skill · Version · Tokens
- Bundles:   Bundle · Title · Skills · Tokens
- Packages:  Signal · Kind · Skill · Collection · Lane · Tokens
- Agents:    Status · Agent · Description · Skills
- Project:   Confidence · Status · Skill · Reasons

The modal-on-Enter flow is preserved end-to-end. The activator reads
SelectedRow.Tag (typed `as TheEntry`) so it stays correct when the user
re-sorts by clicking a column header — indexing into the source array
would break under user sort.

Default sort matches the legacy ListControl order baked into the array.
Numeric columns right-justified; status/confidence centred; existing
sortable Installed (Workspace) and heaviest-skills (Analysis) tables
unchanged.

Collections left rail and Command palette stay as ListControl — they
are narrow single-string browsers, not multi-column data grids.

Build clean, 613/613 tests pass.
Bulk actions on Installed / Project / Agents used to sit as full-width
ButtonControls beneath a 16-row scrollable table — often off-screen on a
default terminal, and visually indistinguishable from list rows.

Move them into a `BuildPageToolbar(...)` helper that renders a native
ToolbarControl between the identity strip and the table. Each entry has
an Enabled flag so the bar carries the precondition signal:

- Installed: [Browse skills] · [Update all outdated (N)]ᵈⁱˢᵃᵇˡᵉᵈ ⁿ⁼⁰
              · [Remove all (N)]ᵈⁱˢᵃᵇˡᵉᵈ ⁿ⁼⁰
- Project:   [Install all recommended (N)]ᵈⁱˢᵃᵇˡᵉᵈ ⁿ⁼⁰ · [Browse installed]
- Agents:    [Install all into detected platforms]ᵈⁱˢᵃᵇˡᵉᵈ ʷʰᵉⁿ ˡᵃʸᵒᵘᵗ⁼null

Per-row Update / Reinstall / Remove stay in the modal (intentional —
modals are part of PR managedcode#735's contract). Existing Ctrl+U / Ctrl+I /
Ctrl+Del bottom-bar shortcuts are unchanged.

Skills / Bundles / Packages pages don't grow a toolbar — they had no
bulk action and their only entry is modal-on-Enter.

RemoveAll / UpdateAll dedicated pages keep their single Button —
they're confirmation surfaces, not list pages.

Build clean, 613/613 tests pass.
Project page — three native BarGraphs (high / medium / low) showing the
confidence breakdown of the recommendation set. Confidence IS severity-
coded (high = trust, low = noise) so a green/yellow/grey palette is the
right read.

Analysis page —
- Recolor "heaviest skills" BarGraph from WithStandardGradient (a
  green→yellow→red severity ramp that read as "warning") to a smooth
  "cool" gradient. Heavy ≠ unsafe, it's just magnitude.
- Recolor "skills per collection" BarGraph from flat turquoise to a
  turquoise→purple smooth gradient so the two Analysis charts are
  visually distinguishable.
- New third chart: LineGraph (Braille mode) plotting the catalog token
  distribution across the full catalog (X = skill index sorted by
  tokens desc, Y = tokens). Surfaces the long-tail shape of the
  catalog at a glance — a few mega-skills vs. a flat curve is the
  question this answers. "cool" series gradient, high/low markers,
  rounded border, Y-axis labels in N0 format.

Settings disk-footprint chart and Home metric-card sparklines are
deferred — they need data the Runtime layer doesn't expose synchronously
(installed skill bytes, catalog release history). Will land as a
follow-up once the data path is in place.

Build clean, 613/613 tests pass.
…lish

NavigationView pane thresholds — the previous Auto settings
(Expanded ≥96, Compact ≥54) kept the 30-column rail at full width on
typical 120-140 col terminals, eating horizontal space the new tables
and graphs need. Bump to:

- Expanded ≥160 cols (genuinely wide terminals)
- Compact  ≥ 90 cols (typical IDE-side terminal width — icons + selected)
- Minimal  < 90 cols (rail collapses, hotkey to summon)

Modal action toolbar now draws a single-row separator above the
buttons (`WithAboveLine(true)` + matching PanelBorder color), giving
visual separation between detail-pane data and verbs that was missing.

Outdated-row foreground in the Installed table moves from
AccentYellow (215,175,0) to a desaturated OutdatedRowFg (200,180,80).
The previous color doubled as both the chart-severity yellow (Project
confidence "medium" bar) and the row-attention yellow, which made the
two pages fight for the eye. Same warm signal, lower volume.

Build clean, 613/613 tests pass.
A grab-bag of post-PR polish driven by use:

Collections page
- Left rail is now a sortable 2-column TableControl (Collection +
  Skills installed/total) instead of a markup-list. Same visual
  grammar as every other browse page.
- Right pane gets the same primitives the rest of the shell uses:
  identity strip → tokens-by-lane BarGraph stack (cool gradient) →
  sortable Lanes Table → install Toolbar with two-stage arm.
- HorizontalGrid now has WithSplitterAfter(0) so the user can drag
  the divider to rebalance left rail vs. detail pane.

BuildStyledTable helper + ApplyStyledTableRuntime
- Every TableControl now flows through `BuildStyledTable(title, accent)`
  — applies left-aligned title (was centered), sortable, rounded,
  border-color, and StretchHorizontal in one call. Replaces 4-line
  fluent chains scattered across pages.
- `ApplyStyledTableRuntime(...)` flips on `TruncationFade = true`
  on the built TableControl so cells that overflow their column fade
  to background over the last 4 chars instead of clipping. Polished
  read; no ugly ellipsis.

Identity strip ⇒ AddIdentityStrip + AddSectionHeader
- New `AddIdentityStrip(panel, ...)` wraps the strip MarkupControl
  with a colored RuleControl underneath so the page header reads as
  one composite block — same visual rhythm as the modal toolbar's
  AboveLine separator.
- New `AddSectionHeader(panel, title, accent)` replaces the previous
  pattern of `BuildSectionPanel(title, "", accent)` (a full rounded
  empty PanelControl) used as a heading divider. Now emits a blank
  spacer line + a titled RuleControl. Three rows of fake-titled panel
  down to two rows of real rule.

Analysis page cleanup
- Three section headers (tokens by skill / skills per collection /
  token distribution) use the new AddSectionHeader rule.
- Dropped the redundant 12-collection card grid at the top — the
  same data is shown in the "skills per collection" BarGraph below.
- Dropped the redundant bottom bullet list of package signals —
  count is in the identity strip, per-signal detail lives on the
  dedicated Packages page.

Build clean across all 4 projects, 0 warnings. 613/613 tests pass.
Pulls the latest upstream skill-validator nightly into
external-sources/upstreams/dotnet-skills and reimports the catalog.

CI's `Verify imported external sources are committed` check on this
branch was failing because the external nightly mirror had advanced
since the branch was cut. This commit catches up:

- Adds the new dotnet-blazor plugin and its 6 skills + author/collect/
  navigate/render/state/style references
- Adds the new dotnet-aspnet/convert-blazor-server-to-webapp skill
- Refreshes msbuild-code-review agent + extension-points,
  msbuild-antipatterns skills
- Refreshes dotnet-test migrate-vstest-to-mtp / run-tests /
  test-anti-patterns / test-smell-detection skills

Generated by running `bash scripts/sync_external_catalog_sources.sh`
which runs `vendir sync` + `python3 scripts/import_external_catalog_sources.py`.

No source code changes; this is purely a regenerated catalog snapshot
sitting alongside the TUI polish so CI passes on this branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant