Skip to content

fix(ios): grok composer keeps focus — stop shell placement flipping on focus - #10

Merged
boggspa merged 2 commits into
masterfrom
fix/grok-focus-shell-identity
Jun 18, 2026
Merged

boggspa merged 2 commits into
masterfrom
fix/grok-focus-shell-identity

Conversation

@boggspa

@boggspa boggspa commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Symptom

On the grok composer shell, focusing the composer (keyboard up) showed neither the above rows nor the bottom telemetry row — just a bare one-line input. Every other shell (e.g. cursor) shows both when focused. Build 24's zIndex(0) did not fix it.

Root cause (3 independent Opus 4.8 reviewers converged)

The core VStack's .composerShellIf((detached && !inputOwnsSurface) || tuckedTab) and the outer .composerShellIf(!detached && !tuckedTab) toggle a ViewModifier on/off based on tuckedTab, which folds in hasAboveContent → composerFocused. composerShellIf is a @ViewBuilder if/else, so flipping it changes the subtree's structural identity → SwiftUI tears down + rebuilds the Composer → its @FocusState resets to false → onFocusChange(false) → composerFocused can never latch true → both focus-gated halves (above rows and telemetry) collapse.

grok is the only tuckedAboveTab shell, so it's the only one whose shell placement depends on focus; cursor & co. have focus-stable predicates (hence immune). This also explains why the symptom is "both halves" (a shared composerFocused gate that can't stabilise) and why zIndex couldn't help (paint order ≠ identity).

Fix

Key the two shell placements + the core zIndex off the static resolved.layout.tuckedAboveTab (new tuckedShell) instead of the focus-derived tuckedTab. grok now always wears its shell on the core (focused or not) — no identity churn, focus latches, both halves render. tuckedTab still drives the focus-gated tab geometry/spacing (those don't change identity).

Byte-identical for the other 12 shells — their tuckedAboveTab is false, so tuckedShell == tuckedTab == false and every changed expression evaluates the same as before.

Verification

swift build ✓ · swift test 73/73 ✓ · iPhone-17 simulator BUILD SUCCEEDED ✓. Diagnosed by 3 adversarial Opus 4.8 reviewers (independent convergence, high confidence). On-device confirm to follow in build 25.

🤖 Generated with Claude Code

boggspa and others added 2 commits June 18, 2026 18:49
…n focus

Real root cause of "grok composer shows neither above rows nor telemetry when
focused" (build-24's zIndex(0) treated the wrong layer). 3 independent Opus
reviewers converged:

The core VStack's `.composerShellIf((detached && !inputOwnsSurface) || tuckedTab)`
and the outer `.composerShellIf(!detached && !tuckedTab)` toggle a ViewModifier
on/off based on `tuckedTab`, which folds in `hasAboveContent` → `composerFocused`.
`composerShellIf` is a @ViewBuilder if/else, so flipping it changes the subtree's
STRUCTURAL IDENTITY → SwiftUI tears down + rebuilds the Composer → its
@focusstate resets to false → onFocusChange(false) → composerFocused can never
latch true → BOTH focus-gated halves (above rows + telemetry) collapse. grok is
the only `tuckedAboveTab` shell, so it's the only one whose shell placement
depends on focus; cursor et al. have focus-stable predicates, hence immune.

Fix: key the two shell placements + the core zIndex off the STATIC
`resolved.layout.tuckedAboveTab` (new `tuckedShell`) instead of the focus-derived
`tuckedTab`. grok now always wears its shell on the core (focused or not) — no
identity churn, focus latches, both halves render. `tuckedTab` still drives the
focus-gated tab geometry/spacing (those don't change identity). Byte-identical
for the other 12 shells (their tuckedAboveTab is false).

Verified: swift build + 73 tests + iPhone-17 simulator build. Diagnosed via 3
adversarial Opus 4.8 reviewers (independent convergence, high confidence).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@boggspa
boggspa merged commit 4c0236b into master Jun 18, 2026
16 checks passed
@boggspa
boggspa deleted the fix/grok-focus-shell-identity branch June 18, 2026 18:07
boggspa added a commit that referenced this pull request Jun 18, 2026
Build 25 = PR #10 (4c0236b): grok composer keeps focus — shell placement keyed
off the static tuckedAboveTab recipe flag, so the above rows + telemetry no
longer collapse when the grok composer is focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
boggspa added a commit that referenced this pull request Jul 29, 2026
The selected row's label already cycles to its "Workspace/branch" identity;
this hangs up to three git status icons off the right of that face, so the
thread's git state is readable without opening it.

Colour vocabulary is GitHub's: a green PR is OPEN and not yet merged, a green
ringed tick is ready to merge, orange is queued (auto-merge armed - accepted
but NOT landed), purple is merged and is the only final-success state, red is
closed without merging. A bare green tick is "pushed", and a plain ahead
count is the fallback when work is in flight and no pull request applies. A
detached HEAD renders nothing at all - there is no branch identity to grade.

Two independent sources feed the strip, which is where more than one icon
comes from: the workspace's live PR, and the thread's own durable
chat.gitWorkflow marker - already transition-gated, so it means "the PR THIS
session shipped" rather than "this workspace is near a PR". A thread whose
#10 landed shows purple beside the branch's current green #12. They collapse
to one icon only when it is the same PR in the same state, and non-terminal
markers are ignored because they would duplicate the live PR and go stale
while the thread is unfocused.

Merge-queue detection needed plumbing: autoMergeRequest joins the
`gh pr view --json` field list and collapses to GitPrSummary.autoMergeEnabled.
There is no mergeQueueEntry on `gh pr view`.

The strip crosses the prop chain as one encoded string, not an array - the
sidebar row memo comparators gate primitives only, and a fresh array each
render would either churn the memo or, compared by reference, never update.

Note .github-satellite-icon in shard 07 has open and merged inverted against
this vocabulary. That surface is left alone here, deliberately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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