Skip to content

iOS: keep the files chip visible while the keyboard is up - #10802

Merged
azooz2003-bit merged 5 commits into
mainfrom
feat-ios-files-chip-keyboard
Aug 26, 2026
Merged

azooz2003-bit merged 5 commits into
mainfrom
feat-ios-files-chip-keyboard

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Aug 26, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Since #10594 the keyboard no longer resizes the terminal: GhosttySurfaceHostView slides the full-height render wrapper up so the render bottom rides the composer bar. The files chip was anchored to the surface's own top edge (safeAreaInsets.top + 8), so the slide carried it above the clipped-visible area and the only Files control disappeared whenever the keyboard was shown.

Fix

The chip is chrome, not render. GhosttySurfaceHostView adopts the chip container into its own keyboard-invariant coordinate space (moveArtifactChip(to:), mirroring moveBottomDock(to:)), constraint-anchored 8pt below the host's safe-area top with the same tap-target floor and width ceiling the old manual frame pass enforced. The keyboard slides only the render wrapper, so the chip is keyboard-invariant by construction: no keyboard math, no per-frame following. Hostless surfaces (tests, previews) keep a surface-anchored fallback with identical resting placement.

This also fixes the artifact-files popover anchor, which was normalized against the surface's bounds and would have drifted downward by the slide while the keyboard is up; it now normalizes against the view backing the SwiftUI representable.

(The first fix iteration used a display-link follow that re-derived the chip's visible-top inset per frame; it was replaced in d1e0609 with the constraint adoption above after review feedback that a follower is the wrong shape for this.)

Commits

Regression pair: commit 1 adds the failing tests, later commits the fix. The final tests assert the chip's frame in host coordinates is identical before, during, and after a keyboard seat ride, end to end through the real host and surface.

Note: no CI lane currently compiles cmuxFeatureTests (the cmux-ios scheme's only testable is cmuxUITests), which is how #10687 silently compile-broke TerminalKeyboardFullHeightPinTests by adding a required keyboardFrameTracker: parameter; commit 1 also repairs that call site.

This branch also carries the two main-red iOS compile fixes from #10813 (required to build any iOS archive from current main).

HIG

Checked Virtual keyboards: "Using the [keyboard] layout guide also helps you keep important parts of your interface visible while the virtual keyboard is onscreen." This fix restores exactly that for the Files control; no deliberate deviation.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved terminal artifact-chip positioning while the keyboard appears, moves, or changes height.
    • Kept chips anchored to the visible host area and prevented them from extending beyond available width.
    • Improved chip placement during terminal transitions for smoother movement.
    • Corrected workspace anchoring for empty groups without an active workspace.
  • Tests

    • Added coverage for chip anchoring, visibility, containment, and restoration across keyboard transitions.
    • Updated full-height keyboard tests to use mobile keyboard tracking.

azooz2003-bit and others added 2 commits August 25, 2026 23:21
… surface

Red half of the regression pair. Since #10594 the host slides the
full-height render wrapper up so the render bottom rides the composer bar
while the keyboard is up; the files chip is anchored to the surface's own
top edge, so the slide carries it above the clipped-visible area and the
only Files control disappears whenever the keyboard is shown.

Also passes the keyboard frame tracker to GhosttySurfaceHostView in the
existing full-height pin test: #10687 added the required parameter without
updating this call site, and no CI lane compiles cmuxFeatureTests, so the
target has been compile-broken since.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…keyboard is up

The chip anchored to the surface's top edge plus safeAreaInsets.top. Since
#10594 keyboard motion no longer resizes the surface: the host slides the
full-height render wrapper up so the render bottom rides the composer bar,
which carries the surface's top edge — and the chip with it — above the
clipped-visible area. The only Files control was therefore unreachable
whenever the keyboard was shown.

The chip now anchors below the highest clipping ancestor's visible top
(falling back to safeAreaInsets.top, so resting placement is unchanged and
hosts that do not slide are unaffected). A display-link follow re-pins it
frame-by-frame during keyboard legs using presentation layers, the same
pattern as the dock's absorption follow, with a rest guard so the walk is
skipped entirely while nothing can be sliding.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2e9ccd6d-547b-4d17-8fe1-d38266be2b13

📥 Commits

Reviewing files that changed from the base of the PR and between c286fd7 and d1e0609.

📒 Files selected for processing (5)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/GhosttySurfaceCoordinator+Artifacts.swift
  • Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceArtifactChipHost.swift
  • Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceHostView.swift
  • Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceView.swift
  • ios/cmuxPackage/Tests/cmuxFeatureTests/TerminalArtifactChipKeyboardTests.swift

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The artifact chip now uses host-view Auto Layout constraints. Host re-homing keeps its position stable during keyboard transitions. Popover coordinates use the host reference view. Tests cover sizing, anchoring, and keyboard invariance. Workspace anchor identifiers and action access also changed.

Changes

Artifact Chip Keyboard Tracking

Layer / File(s) Summary
Constraint-based host layout
Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceArtifactChipHost.swift
The chip container uses host-view constraints for position and size. Hosted content is pinned to the container. Re-installation deactivates prior constraints and removes the previous container placement.
Host anchoring and coordinate normalization
Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceHostView.swift, Packages/iOS/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceView.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/GhosttySurfaceCoordinator+Artifacts.swift
GhosttySurfaceHostView moves the chip into the host. GhosttySurfaceView exposes the host-or-surface anchor reference and removes surface-local layout. Artifact requests normalize chip coordinates against that reference view.
Keyboard-invariant layout validation
ios/cmuxPackage/Tests/cmuxFeatureTests/TerminalArtifactChipKeyboardTests.swift, ios/cmuxPackage/Tests/cmuxFeatureTests/TerminalKeyboardFullHeightPinTests.swift
Tests verify the surface-top anchor, minimum size, unchanged host coordinates during keyboard transitions, and MobileKeyboardFrameTracker injection.

Workspace Updates

Layer / File(s) Summary
Workspace group identifier and action access
Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift
Empty groups without live anchor workspaces now construct anchorWorkspaceID from the namespaced group ID raw value. groupActionCapabilities(for:) is now internally accessible.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to d1e06

The PR keeps the Files control visible during keyboard presentation and adds regression coverage; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant GhosttySurfaceHostView
  participant GhosttySurfaceView
  participant GhosttySurfaceArtifactChipHost
  participant KeyboardFrameTracker
  GhosttySurfaceHostView->>GhosttySurfaceView: Move artifact chip to host
  GhosttySurfaceView->>GhosttySurfaceArtifactChipHost: Install host constraints
  KeyboardFrameTracker->>GhosttySurfaceHostView: Report keyboard frame
  GhosttySurfaceHostView->>GhosttySurfaceArtifactChipHost: Preserve host-relative chip layout
Loading
🚥 Pre-merge checks | ✅ 23 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description clearly explains the problem, implementation, rationale, regression tests, and related fixes. However, it does not use the required Summary and Testing sections, and it omits the requi… Add the required template sections. Include a concise Summary, explicit Testing and manual verification details, a demo video or attachment, the review-trigger comment block, and the completed checklist items. Preserve the existing technica…
✅ Passed checks (23 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed No actor-isolation failure is introduced. MobileWorkspaceAggregation remains a plain Sendable value struct with no @MainActor isolation. WorkspaceListTableCoordinator, `GhosttySurfaceArtifactC…
Cmux Swift Blocking Runtime ✅ Passed PASS. The PR adds no blocking or timing-based synchronization to production Swift. The changed production files add Auto Layout constraints and view re-homing only; primitive counts are unchanged from…
Cmux Browser Automation Off-Main ✅ Passed PASS: The PR diff changes only iOS terminal/shell files and tests. It does not modify Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, browser socket routing, WebKit waits, o…
Cmux Expensive Synchronous Load ✅ Passed PASS: The full PR diff adds only UIKit layout/re-homing, coordinate normalization, a namespaced workspace ID fallback, an access-level change, and tests. No production Swift diff adds or moves `Restor…
Cmux Cache Substitution Correctness ✅ Passed PASS: The production diff changes UIKit layout, host re-homing, popover coordinate normalization, access control, and ID construction. It does not replace a fresh authoritative read with a cached valu…
Cmux No Hacky Sleeps ✅ Passed PASS. The pull request diff changes only Swift production files and Swift tests. It introduces no TypeScript, JavaScript, shell, or build/runtime-script changes covered by runtime-no-hacky-sleeps.md…
Cmux Algorithmic Complexity ✅ Passed PASS — The complete PR diff introduces no scalable nested scan or per-target rescan. GhosttySurfaceArtifactChipHost uses fixed-size constraint arrays and operates on its dedicated container; `moveAr…
Cmux Swift Concurrency ✅ Passed PASS. The pull-request diff adds no background Dispatch queue, Combine state, new internal completion-handler API, or fire-and-forget production Task. The only added concurrency syntax is awaited `Tas…
Cmux Swift @Concurrent ✅ Passed PASS. The diff adds no nonisolated async function and no @concurrent annotation. The only added async code is in TerminalArtifactChipKeyboardTests, where the test suite and delegate are `@MainAc…
Cmux Swift Package Boundaries ✅ Passed PASS. The production diff stays inside existing SwiftPM targets: CmuxMobileTerminal, CmuxMobileShellUI, and CmuxMobileShellModel. The terminal changes are UIKit/Ghostty integration glue, and the…
Cmux Swiftpm Lockfiles ✅ Passed PASS. The PR range changes only Swift source and test files under Packages/iOS/CmuxMobileShellModel, Packages/iOS/CmuxMobileShellUI, Packages/iOS/CmuxMobileTerminal, and ios/cmuxPackage. It do…
Cmux Swift Logging ✅ Passed The PR diff adds or changes no logging statements. The changed production Swift files contain no added print, debugPrint, dump, NSLog, file/stdout logging, or Logger declarations. The existing…
Cmux User-Facing Error Privacy ✅ Passed PASS. The production diff changes UIKit layout, view re-homing, coordinate normalization, and model access. It adds no user-facing error, alert, command-output, API-error, or recovery text. The added …
Cmux Full Internationalization ✅ Passed PASS. The complete PR diff from merge base e96f1b0 changes eight Swift source/test files and adds no localization catalogs, Info.plist entries, web messages, or locale registry files. The only added …
Cmux Swiftui State Layout ✅ Passed PASS. The aggregate PR diff from e96f1b04a changes UIKit terminal views, a coordinator anchor conversion, model access, and tests. It adds no ObservableObject, @Published, SwiftUI state wrapper,…
Cmux Architecture Rethink ✅ Passed PASS. The cumulative diff adds no prohibited production timing, blocking, observer, lock, or polling repair path. The only Task.sleep and polling loop are in the new test and are allowed test-only s…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS — The PR changes UIKit terminal views, artifact-chip constraints, popover coordinate normalization, and one access modifier. The combined PR diff adds no NSWindow, NSPanel, NSWindowController, Sw…
Cmux Source Artifacts ✅ Passed PASS. The aggregate diff changes only seven existing Swift source and test files under Packages/iOS/.../Sources and ios/cmuxPackage/Tests. No artifact directories, added files, binary diffs, logs,…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The PR adds no test/debug seam in production source. The new moveArtifactChip(to:) and artifactChipAnchorReferenceView have production callers in GhosttySurfaceHostView and `GhosttySurface…
Cmux No Ambient Global State ✅ Passed PASS. The production diff adds no file-scope API function, mutable global variable, static-only namespace, or new runtime singleton. The new moveArtifactChip(to:), artifactChipAnchorReferenceView,…
Title check ✅ Passed The title clearly and concisely describes the primary change: keeping the iOS Files chip visible while the keyboard is shown.
Full details: Cmux Swift Actor Isolation

Explanation

No actor-isolation failure is introduced. MobileWorkspaceAggregation remains a plain Sendable value struct with no @MainActor isolation. WorkspaceListTableCoordinator, GhosttySurfaceArtifactChipHost, and GhosttySurfaceHostView are already @MainActor-isolated. The new UIKit re-homing path is called from the @MainActor host initializer, and the new anchor lookup remains inside an @MainActor coordinator method. The diff adds no service protocol isolation, shared mutable Sendable reference type, or background access to a UI-bound store. Test-only changes are allowed by the check.

Full details: Cmux Swift Blocking Runtime

Explanation

PASS. The PR adds no blocking or timing-based synchronization to production Swift. The changed production files add Auto Layout constraints and view re-homing only; primitive counts are unchanged from the PR base. The only new Task.sleep is in TerminalArtifactChipKeyboardTests.swift, inside deterministic test settling code, which the rule allows.

Full details: Cmux Browser Automation Off-Main

Explanation

PASS: The PR diff changes only iOS terminal/shell files and tests. It does not modify Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, browser socket routing, WebKit waits, or worker-lane policy tests. The browser-automation failure conditions are therefore not applicable.

Full details: Cmux Expensive Synchronous Load

Explanation

PASS: The full PR diff adds only UIKit layout/re-homing, coordinate normalization, a namespaced workspace ID fallback, an access-level change, and tests. No production Swift diff adds or moves RestorableAgentSessionIndex.load(), SharedLiveAgentIndex, agent stores, transcript/trajectory/workstream JSONL handling, directory scans, per-record syscalls, or synchronous JSON/file loads. Pickaxe checks for the canonical loaders and listed synchronous APIs returned zero changed lines. The new Task.sleep calls are test-only and are not expensive agent-history loads.

Full details: Cmux Cache Substitution Correctness

Explanation

PASS: The production diff changes UIKit layout, host re-homing, popover coordinate normalization, access control, and ID construction. It does not replace a fresh authoritative read with a cached value in a persistence, history, undo, or snapshot path. The nearby cachedVisibleTextForArtifactHitTesting() use is pre-existing and remains a transient tap-hint check; the changed code does not alter that read. No TypeScript or JavaScript files changed.

Full details: Cmux No Hacky Sleeps

Explanation

PASS. The pull request diff changes only Swift production files and Swift tests. It introduces no TypeScript, JavaScript, shell, or build/runtime-script changes covered by runtime-no-hacky-sleeps.md. The added Task.sleep appears only in a Swift test helper, which is outside this check's scope.

Full details: Cmux Algorithmic Complexity

Explanation

PASS — The complete PR diff introduces no scalable nested scan or per-target rescan. GhosttySurfaceArtifactChipHost uses fixed-size constraint arrays and operates on its dedicated container; moveArtifactChip installs constraints once. The coordinator change performs constant-time view conversion and normalization. MobileWorkspaceAggregation changes only an ID conversion, and groupActionCapabilities changes only access level. Existing collection scans remain unchanged. The added tests are test-only and exempt.

Full details: Cmux Swift Concurrency

Explanation

PASS. The pull-request diff adds no background Dispatch queue, Combine state, new internal completion-handler API, or fire-and-forget production Task. The only added concurrency syntax is awaited Task.sleep in the new UIKit test, which is test-only settling and is allowed by the modernization rules. Existing production Tasks, queue calls, and completion handlers remain unchanged or are only in surrounding code.

Full details: Cmux Swift `@Concurrent`

Explanation

PASS. The diff adds no nonisolated async function and no @concurrent annotation. The only added async code is in TerminalArtifactChipKeyboardTests, where the test suite and delegate are @MainActor; its local settle helper only performs Task.sleep to coordinate UIKit tests. The production changes are synchronous UIKit layout, view re-homing, and coordinate conversion. No changed call site introduces CPU-heavy, file-heavy, parsing-heavy, or network-heavy async work from UI isolation.

Full details: Cmux Swift Package Boundaries

Explanation

PASS. The production diff stays inside existing SwiftPM targets: CmuxMobileTerminal, CmuxMobileShellUI, and CmuxMobileShellModel. The terminal changes are UIKit/Ghostty integration glue, and the workspace aggregation change is already in the reusable CmuxMobileShellModel package. The remaining Swift changes are test-target changes. No independently testable domain logic was added to the cmuxFeature app target, and no new extraction is required by the boundary rule.

Full details: Cmux Swiftpm Lockfiles

Explanation

PASS. The PR range changes only Swift source and test files under Packages/iOS/CmuxMobileShellModel, Packages/iOS/CmuxMobileShellUI, Packages/iOS/CmuxMobileTerminal, and ios/cmuxPackage. It does not change any Package.swift, package-local Package.resolved, .gitignore, workflow, or Xcode project package-reference file. Therefore, the SwiftPM lockfile policy has no applicable failure condition.

Full details: Cmux Swift Logging

Explanation

The PR diff adds or changes no logging statements. The changed production Swift files contain no added print, debugPrint, dump, NSLog, file/stdout logging, or Logger declarations. The existing file-scoped Logger in GhosttySurfaceView.swift is unchanged. The new logging-related test code contains no prohibited logging.

Full details: Cmux User-Facing Error Privacy

Explanation

PASS. The production diff changes UIKit layout, view re-homing, coordinate normalization, and model access. It adds no user-facing error, alert, command-output, API-error, or recovery text. The added test strings and developer comments are explicitly allowed. Existing recovery-alert code in the coordinator is not modified by this diff.

Full details: Cmux Full Internationalization

Explanation

PASS. The complete PR diff from merge base e96f1b0 changes eight Swift source/test files and adds no localization catalogs, Info.plist entries, web messages, or locale registry files. The only added quoted text is in TerminalArtifactChipKeyboardTests.swift, which the rule explicitly exempts. Production additions are layout code and developer comments; no new user-facing text is introduced.

Full details: Cmux Swiftui State Layout

Explanation

PASS. The aggregate PR diff from e96f1b04a changes UIKit terminal views, a coordinator anchor conversion, model access, and tests. It adds no ObservableObject, @Published, SwiftUI state wrapper, GeometryReader, lazy/list row store reference, or render-time state mutation. The only SwiftUI-related change normalizes UIKit coordinates against artifactChipAnchorReferenceView; it does not change SwiftUI state or layout.

Full details: Cmux Architecture Rethink

Explanation

PASS. The cumulative diff adds no prohibited production timing, blocking, observer, lock, or polling repair path. The only Task.sleep and polling loop are in the new test and are allowed test-only synchronization. The chip host owns its local UIKit constraints and re-homing state. GhosttySurfaceHostView adopts the chip through one explicit host-space path that mirrors the existing dock adoption. artifactChipAnchorReferenceView is a computed UIKit bridge, not a second mutable owner of model state. The model and access changes are small correctness fixes with clear owners.

Full details: Cmux Swift Auxiliary Window Close Shortcuts

Explanation

PASS — The PR changes UIKit terminal views, artifact-chip constraints, popover coordinate normalization, and one access modifier. The combined PR diff adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window/WindowGroup, close-shortcut override, or auxiliary-window identifier code. The test changes use UIWindow only as a test fixture, which the rule allows.

Full details: Cmux Source Artifacts

Explanation

PASS. The aggregate diff changes only seven existing Swift source and test files under Packages/iOS/.../Sources and ios/cmuxPackage/Tests. No artifact directories, added files, binary diffs, logs, screenshots, recordings, caches, or build output appear. The changes implement product behavior and regression tests, which the rule explicitly permits.

Full details: Cmux No Test Or Debug Seam In Production Source

Explanation

PASS. The PR adds no test/debug seam in production source. The new moveArtifactChip(to:) and artifactChipAnchorReferenceView have production callers in GhosttySurfaceHostView and GhosttySurfaceCoordinator+Artifacts.swift. The groupActionCapabilities access change supports an existing production caller in WorkspaceListTableCoordinator+Actions.swift; it adds no test wrapper or test-named member. The new test code is under ios/cmuxPackage/Tests/ and uses the pre-existing setKeyboardHeightForTesting(_:) hook, which is unchanged in the PR. No added production #if DEBUG or test-build guard was found.

Full details: Cmux No Ambient Global State

Explanation

PASS. The production diff adds no file-scope API function, mutable global variable, static-only namespace, or new runtime singleton. The new moveArtifactChip(to:), artifactChipAnchorReferenceView, and groupActionCapabilities(for:) declarations are instance members of owning types. The new mutable properties in GhosttySurfaceArtifactChipHost are private instance state. The changed static declarations are pre-existing constants or incidental context.

Full details: Description check

Explanation

The description clearly explains the problem, implementation, rationale, regression tests, and related fixes. However, it does not use the required Summary and Testing sections, and it omits the required Demo Video, Review Trigger, and Checklist sections.

Resolution

Add the required template sections. Include a concise Summary, explicit Testing and manual verification details, a demo video or attachment, the review-trigger comment block, and the completed checklist items. Preserve the existing technical explanation under the appropriate sections.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-ios-files-chip-keyboard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

#10662 assigns the namespaced group id (MobileWorkspaceGroupPreview.ID)
directly to anchorWorkspaceID (MobileWorkspacePreview.ID), which does not
compile for the iOS app. Convert through rawValue, the same idiom the
group preview initializer already uses for its empty-group fallback.

Carried on this branch only to unblock the tagged iOS build; same patch
offered to main separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
azooz2003-bit and others added 2 commits August 26, 2026 00:41
Second iOS compile break from #10662: groupActionCapabilities(for:) was
declared fileprivate in WorkspaceListTableCoordinator.swift but is called
from the +Actions extension file, so the iOS app does not compile. Widen
to internal.

Carried on this branch only to unblock the tagged iOS build; same patch
offered to main separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ad of following the keyboard

Replaces the display-link follow from the previous commit with the same
adoption the dock already uses: GhosttySurfaceHostView re-homes the chip
container (moveArtifactChip(to:), mirroring moveBottomDock(to:)) and the
container is constraint-anchored to the host's safe-area top. The keyboard
slides only the render wrapper, never the host, so the chip is
keyboard-invariant by construction — no per-frame presentation-layer reads,
no visible-top ancestor walk, no drift guards. Hostless surfaces (tests)
keep the surface-anchored fallback with identical resting placement.

Also fixes the artifact-files popover anchor: it was normalized against the
surface's bounds, which drift downward by the slide while the keyboard is
up; it now normalizes against the view backing the SwiftUI representable.

The regression tests now assert the stronger contract directly: the chip's
frame in host coordinates is identical before, during, and after a keyboard
seat ride. The earlier slid-clip-ancestor unit test modeled the follower
design's topology and is superseded by the host-space invariance test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@azooz2003-bit
azooz2003-bit merged commit cf8e251 into main Aug 26, 2026
7 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-ios-files-chip-keyboard branch August 26, 2026 21:25
rustybret pushed a commit to rustybret/bmux that referenced this pull request Aug 26, 2026
4c0a26e iOS 27: restore the will-only keyboard seat for composer bar pinning (manaflow-ai#10810)
cf8e251 iOS: keep the files chip visible while the keyboard is up (manaflow-ai#10802)
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