Skip to content

feat(swift-ios): present the command drawer catalog - #8350

Draft
saphid wants to merge 2 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:feat/command-drawer-presentation-integration
Draft

feat(swift-ios): present the command drawer catalog#8350
saphid wants to merge 2 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:feat/command-drawer-presentation-integration

Conversation

@saphid

@saphid saphid commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Observed problem and reproduction

The SwiftUI workspace has existing task, project, and settings destinations, but no searchable overlay that keeps those destinations available over the current page. After the stacked foundation recognizes a top-bar pull, users need a real drawer surface with useful content and routing rather than gesture state with nothing to present.

To exercise this slice, pull down from the top bar on Home or an open thread, browse or filter the rows, then choose a thread, project, or workspace action.

Important

This is a draft stack. GitHub cannot use the fork-only foundation head as an upstream PR base, so the upstream diff temporarily includes #7345. The presentation-only comparison is foundation 0e0fb949…presentation 32a60bb8. Do not review or merge this draft until #7345 lands and this PR is rebased so its upstream file list contains only the four presentation files.

Cause

The workspace has no shared catalog for its existing destinations and no presentation that renders the foundation drawer state over the workspace. Navigation also has no single typed boundary for translating a drawer row into the workspace behavior that already owns the destination.

Change and boundary

This stacked PR adds the presentation/integration half of the command drawer:

  • a bounded, searchable catalog of recent threads, projects, and existing workspace actions;
  • the visual drawer, scrim, search, empty state, result rows, light/dark styling, and accessibility exposure;
  • one typed selection-to-destination mapping; and
  • workspace composition and routing into the sheets and navigation paths WorkspaceView already owns.

The parent PR owns geometry, the drawer state machine, gesture recognition, and responder ownership. This PR consumes those types without changing their lifecycle.

Intentionally unchanged and follow-ups

  • A non-gesture VoiceOver or hardware-keyboard entry point remains a named follow-up. This PR exposes the presented drawer and every control to accessibility, but does not add that separate entry mechanism.
  • Upward close beginning inside the results list remains a named follow-up. Closing from the foundation-owned handle, tapping the scrim, or selecting a result is unchanged.
  • The accepted Add tagged multi-platform desktop release workflow and unified artifact builder #135 handle gesture belongs to the foundation slice and is not duplicated here.
  • No server commands, providers, contracts, persistence, or connection behavior change.

Affected areas

  • Client and entry points: SwiftUI mobile only; Home and open-thread workspace roots.
  • Platforms: iPhone/iPad on iOS 17 or later.
  • Providers: provider-neutral.
  • Web, desktop, and React Native mobile: unchanged.
  • Contracts, server, projections, and client runtime: unchanged.
  • Local, remote, relay, and tunnel connections: the drawer reads the same already-projected workspace snapshot in every mode and adds no transport behavior.
  • States: populated, filtered, empty, project-filtered, light/dark, drawer open/closed, row selection, scrim dismissal, and deep-link dismissal.

Validation

Current head: 32a60bb8d239ef994a8dd2a28617e20c2a6d0410, stacked on foundation 0e0fb94960b080b724b50a3f14145ecbb6a5dd63.

  • Exact-head combined suites: 59 passed, 0 failed, 0 skipped; real xcodebuild exit 0. The result includes all 50 foundation tests and all 9 presentation/integration tests, with a nonzero count read from the xcresult.
  • Exact-head leased simulator build/install/launch passed. Runtime proof covered pull-down open with search focus, populated catalog exposure, closed-state phantom-element absence, keyboard-hide resize anchoring, and foundation-owned upward handle close. The hygiene wrapper removed its private DerivedData and idle XCTest clone.
  • Light/dark screenshots and interaction recordings were captured from the running SwiftUI client and are embedded below.
  • A direct Claude Opus 5 high read-only review launch was attempted. It exited 1 before reviewing with provider HTTP 429 (session limit; resets 2pm Australia/Sydney), so no independent-review finding is claimed.

Risks, limitations, and untested paths

  • This PR is intentionally stacked and must land after the foundation PR. Until then, GitHub's upstream diff also includes the foundation; use the exact comparison linked above.
  • The two named entry/close follow-ups above are not presented as passing behavior.
  • Physical-phone behavior was previously accepted for the combined command drawer, but the proof for this rewritten exact head is the simulator evidence below; no new phone verdict is claimed here.
  • The runtime snapshot confirms stable identifiers, modal drawer semantics, and no closed-state phantom scrim. Its raw rs/1 dump still enumerates underlying NavigationSplitView UIKit descendants while open, so actual VoiceOver traversal isolation remains a known proof gap rather than a claimed pass.
  • The Test publication gate remains HOLD until feat(swift-ios): add command drawer gesture foundation #7345 lands, this PR's upstream diff shrinks to presentation-only, affected proof is refreshed against the then-current base, and Add tagged multi-platform desktop release workflow and unified artifact builder #135 has renewed exact-head Test/Alex acceptance.

UI evidence

This is a new surface, so there is no truthful before-state drawer to show. After-only evidence is appropriate. The evidence lives on a separate media branch and no PR-only media is committed in the product diff.

After — populated drawer, light appearance

Populated command drawer with software keyboard in light appearance

After — populated drawer, dark appearance

Populated command drawer with software keyboard in dark appearance

Interaction — light appearance

Open the drawer, browse the catalog, search react, and select a project

Interaction — dark appearance

Open the drawer, browse the catalog, search boot, and open a thread

Owning issue and stack

This is slice (b) of the split authorized for #7345, tracked by saphid/t3code-personal#86. It is stacked on the rewritten foundation PR, which owns gesture/state/focus behavior and the #154 abandoned-pull fix.

Maintainer edits are enabled. This draft does not request review. After #7345 lands, the branch will be rebased, the affected checks and proof will be refreshed, and only then can the vouched handoff gate be reconsidered.

Checklist

  • This PR is one coherent presentation/integration slice with no unrelated work
  • I explained what changed and why
  • I included real light/dark UI evidence; a new surface has no truthful before image
  • I included videos for the gesture-driven interaction

Implemented by GPT-5.6 Sol via the Codex harness.

Note

Add command drawer catalog to WorkspaceView in swift-ios

  • Introduces a top-down command drawer overlay with a scrim, drag gesture, search field, and item list that routes selections to existing workspace navigation flows (threads, projects, new task, settings)
  • Adds a gesture-driven state machine (FeatureCommandDrawerState), geometry helpers, gesture policy, responder ownership/lookup utilities, and a FeatureCommandDrawerCatalog builder that filters and sorts actions, threads, and projects by query
  • Wraps the existing NavigationSplitView body inside FeatureCommandDrawerContainer and extends dismissTransientPresentations to close the drawer without restoring prior responder when navigation is requested
  • Risk: dismissTransientPresentations now closes the command drawer and sets commandDrawerRestoresPriorResponderOnClose to false; callers relying on the drawer staying open during transient dismissal will see it close
📊 Macroscope summarized 32a60bb. 5 files reviewed, 2 issues evaluated, 0 issues filtered, 1 comment posted

🗂️ Filtered Issues

saphid added 2 commits August 27, 2026 12:30
Define the command drawer geometry, gesture arbitration, responder ownership, and bounded focus renewal as a focused foundation slice. Restore the exact prior responder after an abandoned pull and cover cancellation, teardown, and eligibility paths with focused tests.
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e20db87d-d718-4f11-8397-64f5acdd5003

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 27, 2026
/// ever receiving `.began`.
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium Workspace/FeatureCommandDrawerView.swift:435

The drawer pan waits for the scroll view's pan to fail, so a vertical pull in the grab band lets the scroll view begin first and prevents the drawer from opening or closing. shouldBeRequiredToFailBy reverses the intended priority here; use shouldRequireFailureOf so the scroll view waits for the drawer.

Suggested change
shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer
shouldRequireFailureOf otherGestureRecognizer
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/swift-ios/Features/Workspace/FeatureCommandDrawerView.swift around line 435:

The drawer pan waits for the scroll view's pan to fail, so a vertical pull in the grab band lets the scroll view begin first and prevents the drawer from opening or closing. `shouldBeRequiredToFailBy` reverses the intended priority here; use `shouldRequireFailureOf` so the scroll view waits for the drawer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant