feat(mobile): native composer bar — UIKit keyboard tracking, quick keys, glass input
Stacked on #6342. First step of the fully-native input direction: a modules/composer Expo module that owns the input surface, replacing KeyboardAvoidingView + the RN quick-keys row on the terminal screen.
Why native
The Slack/Cursor input feel lives entirely on the native side of the RN boundary: keyboardLayoutGuide rides the keyboard's real animation curve (RN's KeyboardAvoidingView approximates it with a timing animation — the visible jank), and first-responder control means the keyboard actually appears (the WKWebView xterm textarea never reliably focused, #6342's known gap).
Design
ComposerView(UIKitExpoView) mounts as a full-screen overlay; every touch outside the bar passes through viahitTest. The bar pins toself.keyboardLayoutGuide.topAnchor, so UIKit owns tracking end to end.- Props in, events out — no RN children.
placeholder,autoFocus,quickKeys: [{id, label|symbol}](SF Symbols);onSubmitText,onChangeText,onFocusChange,onQuickKey,onBarMetrics(occluded height, used by RN to inset content). The draft lives natively; RN only mirrors it. - Growing
UITextView(1→~5 lines), send button appears with text, clears on submit. - Glass:
UIGlassEffecton iOS 26,systemThickMaterialDarkbefore — the pre-26 no-op gap the home widget has is designed out here. - Terminal screen: quick-key byte map + bracketed-paste framing for multiline submits stay in RN.
Verified on iOS 26.5 simulator (Maestro, full local stack, live claude PTY)
- Bar renders (glass pill, placeholder, SF-symbol quick keys) in the bottom safe area.
- Tap focuses the native field → keyboard appears with the bar riding it; terminal content resizes above via
onBarMetrics. - Typed "hi there" via the soft keyboard, tapped send → claude received it (
\rconfirmed its trust prompt), field auto-cleared, session booted, and the OSC title updated the nav header live. Full native-input → PTY → render round trip. - Repo typecheck + lint clean.
Follow-ups
- Keyboard dismiss affordance (the WebView isn't a scrollview, so no drag-to-dismiss surface yet).
- Home
NewChatWidgetmigration onto this module (chips row, voice dictation moving to nativeSFSpeechRecognizer) — next PR of the native-composer track. - Ref view-functions (
focusInput/blurInput/clearText) are wired but have no call sites yet; exercise when the home widget migrates.
Summary by cubic
Introduces a native UIKit composer bar for iOS that replaces the RN input and quick-keys row on the Terminal screen. Smooth keyboard tracking, reliable focus, glass UI, and built-in quick keys.
-
New Features
- Added
@superset/composerExpo module with a nativeComposerBar(keyboardLayoutGuide tracking, glass background, quick keys). - Terminal screen uses
ComposerBar; removedKeyboardAvoidingViewand the RN quick-keys row. - Emits occluded height to inset content; submit clears input; focus is first-responder native.
- Props/events: placeholder, autoFocus, quickKeys; submit/change/focus/metrics. Methods: focus, blur, clear.
- Multiline input is framed as bracketed paste before sending to the PTY.
- Added
-
Dependencies
- Added iOS module with
Composer.podspec; registeredComposerModule. - Wired module path in Metro and tsconfig (
@superset/composer).
- Added iOS module with