Skip to content

The command line follows the character's colour, and the tints get darker - #24

Merged
HarryCordewener merged 2 commits into
mainfrom
feat/tinted-command-line
Aug 11, 2026
Merged

The command line follows the character's colour, and the tints get darker#24
HarryCordewener merged 2 commits into
mainfrom
feat/tinted-command-line

Conversation

@HarryCordewener

@HarryCordewenerHarryCordewener commented Aug 11, 2026

Copy link
Copy Markdown
Member

Extends the per-character pane tint (#22) with the two things that were asked for: the input bar follows the colour scheme so a glance says what is active, and the six colours are re-picked for a client used on black.

1. The command line wears the colour of the character ⏎ reaches

The bands follow the focused window's character through SendTarget — the resolver the send path itself uses — falling back to the owner the workspace records when no session is open for that window. That fallback is the second arm WindowSession already walks and the same record PaneTintOf reads, so the bar and the pane above it are one answer rather than two that agree most of the time. Never _active.

How tint and armed-ness compose: the colour moves both bands' hue and neither band's brightness. On a pane, luminance carries focus as a ratio that a step applied equally to all six leaves intact; on the input row luminance is already spoken for — it is the whole armed-versus-idle cue — so a colour that moved it would put a second fact on a channel that carries one. Measured off the rendered frames, default theme, 120×32:

armedidlestep
untinted#435676 L 83.97#252533 L 38.6045.37
Moss#336552 L 83.88#183213 L 38.6945.19

The armed band is derived from the tinted idle band rather than tinted itself, so the lean toward Theme.Prompt survives on top of the character's hue and the pair still differ in brightness and colour — on top of the bold-versus-dim prompt and the bright-versus-dim ink.

The colour says whose, never whether. A focused window whose owner has no session this run wears that owner's colour while the prompt reads no connection › and ⏎ refuses out loud. A window nobody owns (the web view), and a character who has chosen no colour, leave both bands exactly as they were.

2. Darker tints

The plane a MU*'s own bright ANSI is read on wants to be darker than the client's chrome. All six now sit one TintDepth step below the untinted surface, and the anchors are re-picked saturated — chroma is bounded by luminance, so a muted anchor re-lit down to a dark pane has nothing left.

closest pairclosest to the surfacepane luma
beforeΔE 8.20ΔE 7.6834.4
afterΔE 14.43ΔE 12.0527.2

Luminance neutrality is kept in the half that carries the design and given up in the other half, explicitly. All six still sit at exactly one luma, by construction — so no character's pane is brighter than another's and the focus step lands the same ratio above each. What is dropped is equality with the untinted surface. That is stated in the doc comment and in the commit message rather than quietly.

The depth is bounded by arithmetic, not taste. A client may hold tinted and untinted characters at once, so a depth reaching 1 ÷ FocusScale would leave a focused tinted pane no brighter than an unfocused untinted one — the focus cue reporting the wrong fact. TintDepth is the geometric mean of that floor and no darkening at all. Every focused pane (43.00 at worst) outshines every unfocused one (34.46 at best), whatever colours are in play; EveryFocusedPaneOutshinesEveryUnfocusedOneAcrossTheWholePalette is the pin.

Costs no cells

TintingACharacterMovesNoPaneRectangle now pins LaidOutRows as well as the rectangles: a command line is a sticky band, and one that grew a row would take that row off every pane and re-announce a new terminal size to every connected server.

Frames

New views tint-input / tint-input-moved — the tint scene with both command lines up, before and after a real ⌃→. The moved frame is the only one that shows the colour travelling with the focus and a bar wearing a character's hue while its prompt says no connection ›.

Verification

dotnet build SharpMUTerm.slnx clean, 0 warnings. All five suites run directly: Core 850, Tui 1550, Graphics 83, Scripting 42, Web 37 — 2562 passed, 0 failed.

🤖 Generated with Claude Code

https://claude.ai/code/session_015nuKnWthnELNkrd86q5KWN

Summary by CodeRabbit

  • New Features

    • Added refined pane tinting with balanced luminance, richer colors, and clearer focused-pane contrast.
    • Added tint-aware command-line input bars, preserving distinct armed and idle states.
    • Added snapshot views for dual input bars and moved focus states.
  • Bug Fixes

    • Updated tint behavior when focus moves or windows are disconnected.
    • Preserved workspace layout and terminal dimensions while applying tint changes.
  • Documentation

    • Expanded guidance for pane focus, input tinting, saturation, brightness, and command-line behavior.

HarryCordewenerand others added 2 commits August 10, 2026 23:59
…an wear one
MU* servers are written for black terminals and their own bright ANSI is read on
the pane's plane, so the plane wants to be darker than the client's chrome rather
than level with it. The first cut held a tinted pane at the untinted surface's
exact luma; it now sits one TintDepth step below it, and the six anchors are
re-picked saturated, because chroma is bounded by luminance and a muted anchor
re-lit down to a dark theme's pane has nothing left.
Measured on the default theme (BT.601 luma, and dE on CIE76):
untinted surface #222226 L 34.46 focused #36363d L 54.80
Slate #0e1c3b L 27.35 Teal #072423 L 27.21 Moss #11230b L 26.88
Ochre #231b08 L 27.23 Ember #34110e L 27.12 Plum #2a1032 L 27.65
focused, in the same order:
#162d5e L 43.71 #0b3938 L 43.13 #1b3812 L 43.00
#382b0d L 43.47 #531b16 L 43.17 #431a50 L 44.41
closest pair dE 8.20 -> 14.43
closest to the surface dE 7.68 -> 12.05
pane luminance 34.4 -> 27.2, a fifth darker, one value for all six
What is kept of luminance neutrality is the half that carries the design: all six
sit at exactly one luma (the plane is re-lit before the anchor is mixed in, and
luma is linear in the channels), so no character's pane is brighter than another's
and the focus step lands the same ratio above each. What is given up is equality
with the untinted surface, which is stated in the doc comment rather than dropped
quietly.
The depth is bounded and the bound is arithmetic, not taste: a client may hold
tinted and untinted characters at once, so a depth reaching 1/FocusScale would
leave a focused tinted pane no brighter than an unfocused untinted one — the focus
cue reporting the wrong fact. TintDepth is the geometric mean of that floor and no
darkening at all, so the untinted surface sits midway in ratio between a tinted
pane and a focused tinted one. Every focused pane on the screen (43.00 at worst)
outshines every unfocused one (34.46 at best), whatever colours are in play.
IdleBand/ArmedBand gain a PaneTint overload, unused until the command line is
wired to it. It takes the hue and not the depth: on the input row luminance is
already the armed-versus-idle cue, and a colour that moved it would put a second
fact on a channel that carries one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nuKnWthnELNkrd86q5KWN
A glance at the bar now says who Enter will reach. The bands follow the focused
window's character through SendTarget — the resolver the send path itself uses —
falling back to the owner the workspace records when no session is open for that
window, which is the second arm WindowSession already walks and the same record
PaneTintOf reads. The bar and the pane above it are therefore one answer rather
than two that agree most of the time. Never _active: that fallback is the
misdelivery bug in every shape it has had, and a bar wearing the colour of a
character whose pane you are not in would be the loudest shape yet.
Tint and armed-ness compose the way hue and luminance do everywhere else here.
The colour moves both bands' hue and neither band's brightness, so the armed bar
stays exactly the step above the idle one that it always was. Measured on the
default theme at 120x32, off the rendered frames:
untinted armed #435676 L 83.97 idle #252533 L 38.60 step 45.37
Moss armed #336552 L 83.88 idle #183213 L 38.69 step 45.19
Slate armed #2e589f L 83.54 idle #0f1e44 L 38.6* step ~45
(* the moved frame shows one bar; the pair is in tint-input.)
The armed band is derived from the tinted idle one rather than tinted itself, so
the lean toward Theme.Prompt survives on top of the character's hue and the pair
still differ in brightness and in colour, on top of the bold-versus-dim prompt and
the bright-versus-dim ink. The prompt cells read the pair the bar was given rather
than re-deriving it, so the fill and the label on it cannot disagree.
The colour says whose, never whether: a focused window whose owner has no session
this run wears that owner's colour while the prompt reads `no connection ›` and ⏎
refuses out loud. Identity and reachability are two facts and the row already
states the second twice. A window nobody owns leaves both bands exactly as they
were, as does a character who has chosen no colour — an untinted client's command
line is byte-identical to the one it had before this existed.
Costs no cells: TintingACharacterMovesNoPaneRectangle now pins LaidOutRows as well
as the rectangles, because a command line is a sticky band and one that grew a row
would take that row off every pane on the screen and re-announce a new terminal
size to every connected server.
New views tint-input / tint-input-moved: the tint scene with both command lines up,
before and after a real ⌃→ — the only geometry that shows an armed tinted band over
an idle one, and the colour travelling with the focus.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nuKnWthnELNkrd86q5KWN
@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 67bc8802-f850-468e-852c-189e306c6937

📥 Commits

Reviewing files that changed from the base of the PR and between 79fd7ec and 21e4261.

📒 Files selected for processing (7)
  • CLAUDE.md
  • docs/design/README.md
  • src/SharpMUTerm.Tui/SharpMUTermApp.cs
  • src/SharpMUTerm.Tui/WorkspacePalette.cs
  • tests/SharpMUTerm.Tui.Tests/PaneTintTests.cs
  • tests/SharpMUTerm.Tui.Tests/SnapshotViewEmptyConfigTests.cs
  • tests/SharpMUTerm.Tui.Tests/WorkspacePaletteTests.cs

Walkthrough

The PR redesigns pane tint luminance, adds character-tinted command-line bands, introduces tint-input snapshot views, and expands tests and documentation for focus, ownership, contrast, and layout behavior.

Changes

Pane and input tinting

Layer / File(s)Summary
Palette tint and band behavior
src/SharpMUTerm.Tui/WorkspacePalette.cs
Tinted panes use darker equalized luminance, saturated anchors, and consistent focus ratios. Idle and armed input bands preserve their brightness and contrast cues while adopting character hues.
Snapshot and application integration
src/SharpMUTerm.Tui/SharpMUTermApp.cs
The application supports tint-input and tint-input-moved, resolves tints from focused-window ownership, dynamically paints both input bands, and uses applied band colors for prompt backgrounds.
Tint validation and documented views
tests/SharpMUTerm.Tui.Tests/*, CLAUDE.md, docs/design/README.md
Tests cover luminance, focus ratios, band contrast, ownership fallbacks, hue separation, layout stability, and empty configurations. Documentation describes the new views and tint rules.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
participant SnapshotView
participant SharpMUTermApp
participant WorkspacePalette
SnapshotView->>SharpMUTermApp: select tint-input or tint-input-moved
SharpMUTermApp->>SharpMUTermApp: resolve focused window tint
SharpMUTermApp->>WorkspacePalette: paint tinted idle and armed bands
WorkspacePalette-->>SharpMUTermApp: return applied band colors
SharpMUTermApp-->>SnapshotView: render panes, input bars, and prompt backgrounds
Loading

Possibly related PRs

Suggested reviewers:claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the two main changes: character-based command-line coloring and darker pane tints.
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@HarryCordewener
HarryCordewener merged commit 466b5ef into mainAug 11, 2026
3 checks passed
@HarryCordewener
HarryCordewener deleted the feat/tinted-command-line branch August 12, 2026 18:33
Sign up for freeto 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

@HarryCordewener