fix(docking): commit tab click-selection; reshape dock-showcase into ReactorIde sample#438
Merged
codemonkeychris merged 2 commits intoMay 28, 2026
Conversation
…ReactorIde sample DockTabTearOff captured the pointer on PointerPressed to track a possible tear-off drag. For a plain click the TabViewItem then never received the release, so WinUI never committed the tab selection — clicking a tab did nothing in multi-tab groups. Commit the selection in OnReleased when the press never crossed the tear-off threshold (a surviving candidate). The threshold path already clears the candidate before tearing off, so this never double-fires. Latent until now because every existing docking demo used a single tab per group. Also rebuild the docking showcase as one cohesive IDE app: - rename samples/apps/dock-showcase -> reactor-ide (DockShowcase -> ReactorIde) - replace the 10-scene spec-review harness + JSON/op-log debug panels with a single VS-shaped app: Solution Explorer, editor well (DocumentArea), Properties/Git, Output/Terminal/Errors, menu bar, status bar - follow the idiomatic ownership model (app owns content, host owns shape): open/close drives manager.Layout key-set changes, reset via .WithKey() -- no OnLiveLayoutChanged round-trip (which breaks float/redock + selection) - editor panes fill via FlexColumn grow; multi-line TextBox uses .AcceptsReturn()/.TextWrapping() element props so the descriptor orders them before Text (a .Set lambda runs after Text and truncates to one line) Add the reactor-docking agent-kit skill documenting the ownership model and these gotchas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CodeQL flagged `indent * 14` as int-multiplication-cast-to-double. The indent is only ever 1–2 so overflow is impossible, but make one operand a double literal to clear the static-analysis finding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
While reshaping the docking sample into a cohesive IDE app, I hit a real framework bug and two usage traps. This PR fixes the framework bug, rebuilds the sample, and captures the traps in an agent-kit skill.
Framework fix — tab click-selection in multi-tab groups
DockTabTearOffcaptures the pointer onPointerPressedto track a possible VS-style tear-off drag. For a plain click, theTabViewItemthen never receives the release, so WinUI never commits the tab selection — clicking a tab did nothing in any group with more than one tab.OnReleasedonly cleared the candidate.Fix: in
OnReleased, when a candidate survives (the press never crossed the tear-off threshold = it was a click), commit the selection. The threshold path already clears the candidate before tearing off, so this never double-fires. Latent until now because every existing docking demo used a single tab per group.Sample —
dock-showcase→reactor-ideReplaced the 10-scene (A–J) spec-review harness + JSON/op-log/replay debug panels with one VS-shaped app: Solution Explorer, an editor well (
DocumentArea), Properties/Git, Output/Terminal/Errors, a menu bar, and a status bar. Files open from the explorer/menu; the layout drags/floats/redocks/persists.Built on the idiomatic ownership model (app owns content, host owns shape): open/close changes
manager.Layout's key set; reset is a.WithKey()remount — noOnLiveLayoutChangedround-trip (that anti-pattern double-owns the shape and breaks float/redock + selection).Project + folder renamed
DockShowcase/dock-showcase→ReactorIde/reactor-ide;Reactor.slnxupdated.Skill —
reactor-dockingNew agent-kit skill documenting the content-vs-shape ownership model (the #1 docking footgun) plus the two pane-content traps below.
Gotchas captured (the "make this un-makeable?" question)
OnLiveLayoutChanged = x => setLayout(x)double-owns shape → no redock, broken selection.FlexColumn(child.Flex(grow:1)), not alignment.TextBox—AcceptsReturn/TextWrappingmust be element props (.AcceptsReturn()), not a.Set(...)lambda; the descriptor orders them beforeText, and.Setruns afterText→ truncates to one line.Follow-up options for #1 (not in this PR — want your call)
REACTOR_DOCK_001): flagOnLiveLayoutChanged = p => <call>(p)(param forwarded straight into a setter). Feasible — mirrors the existingMissingWithKeyAnalyzerheuristic.OnLiveLayoutChangedto hand back a read-only snapshot type distinct fromDockNode, so it physically can't be assigned toLayout— turning the footgun into a compile error. Breaking change; observers that want JSON can use aToJson()on the snapshot (andPersistenceIdalready covers persistence).Tests
Reactor.Tests): 9130 passed, 0 failed, 62 skippedReactor.SelfTests): 1034 passed, 0 failed🤖 Generated with Claude Code