feat(voice): show info banner + mic-click modal on remote instances - #2471
Conversation
Opus 4.8 Review — ✅ no blocking findingsReviewed Review detailsNo semantic defects. The change adds a No findings. [OPUS-REVIEWED] 28c4272 Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
UX Review (Fable 5) — 🟡 CONCERNSAdvisory UX-level review of UX-Verdict: CONCERNS The remote-voice copy hedges ("may not work") while the code hard-blocks, and explains itself in iframe jargon — users will retry a feature that can never start. Watch
Suggestions
[UX-REVIEWED] 28c4272 |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsFINDING -- website/src/pages/ChatPage.tsx:1789 -- False positive or not applicable? A repository writer can comment: |
Design Review (Fable 5) — 🟡 CONCERNSAdvisory design-level review of Design-Verdict: CONCERNS Unconditionally hard-blocking voice in every iframe contradicts the repo's own Watch
Suggestions
[DESIGN-REVIEWED] 28c4272 |
b362211 to
3c64671
Compare
e746603 to
c3d5c45
Compare
When a remote instance is viewed in an iframe, voice input captures audio on the gateway host — not the parent machine. This adds: 1. An info notice in the Speech-to-Text settings (visible only on embedded remote instances) explaining the limitation. 2. A modal when the mic button is clicked on a remote instance, explaining that voice won't work here and directing users to use the local dashboard. The VoiceDisabledModal gains a 'remote' reason variant with its own title, body copy, and no 'Open settings' button (since the fix is to use a different instance, not change settings). Relates to #2455
c3d5c45 to
28c4272
Compare
Design Review — disposition (c3d5c45 → 28c4272)BLOCKER: Replaced WATCH: premise may be wrong (mic delegation might work) — fixed at 28c4272. Updated all user-facing copy to acknowledge that mic delegation may work depending on browser security policies and parent configuration, rather than stating it categorically does not. The modal now says "Voice input may not work here" (not "unavailable") and the hint says "If the mic doesn't respond, use the local dashboard's voice input instead" — a conditional fallback rather than a blanket prohibition. This aligns with the real state: |
UX Review — disposition (28c4272)WATCH 1: Copy contradicts behavior (hedging "may not work" while code hard-blocks) — accepted-and-deferred. Valid observation. The hedge was intentional: WATCH 2: Non-English locales ship English strings — accepted-and-deferred. Correct — the 11 locales carry English placeholders for catalog parity (the test suite requires key presence in all locales). Running the full translation pipeline is out of scope for a UX-messaging PR; localization follows in the normal i18n sweep that runs weekly on main. This is the established pattern for all new keys. WATCH 3: Push-to-talk Good catch. The PTT SUGGESTION: "Not now" → "Close" — accepted-and-deferred. Agree the label reads oddly for a non-deferrable modal. The "Not now" string is shared across all three reason variants via a single i18n key ( |
…irodotdev#2471) When a remote instance is viewed in an iframe, voice input captures audio on the gateway host — not the parent machine. This adds: 1. An info notice in the Speech-to-Text settings (visible only on embedded remote instances) explaining the limitation. 2. A modal when the mic button is clicked on a remote instance, explaining that voice won't work here and directing users to use the local dashboard. The VoiceDisabledModal gains a 'remote' reason variant with its own title, body copy, and no 'Open settings' button (since the fix is to use a different instance, not change settings). Relates to kirodotdev#2455
Problem
When using multi-instance mode (remote gateways viewed as iframes inside a local dashboard), voice input only works on the machine running the gateway — not the parent machine displaying the iframe. Users on remote instances see the mic button but get no transcription, with no explanation of why.
Why it matters
This is a known architectural limitation (tracked as #2455). Without UX messaging, users waste time troubleshooting what appears to be a broken feature, or worse, record audio that silently fails to transcribe.
Fix
Two surfaces, matching the user journey:
Mic-click modal — when the mic button is clicked on a remote instance, the existing
VoiceDisabledModalnow shows a'remote'reason explaining that voice captures audio on the gateway host, not the parent machine, and directing users to use the local dashboard's mic. No "Open settings" button (the fix isn't a setting change — it's using a different instance).Settings info banner — in Settings → Voice → Speech-to-Text, an informational banner (only on embedded instances) explains the same limitation. This catches users who browse to settings looking for why voice doesn't work.
Detection uses the existing
embeddedprop (ChatPage) andisEmbeddedPane()utility (SttSettings) — both true only when the dashboard is running inside an iframe as a remote instance.Tests
tsc --noEmitpasses).isEmbeddedPane()is well-tested in existing test suites.VoiceDisabledModalreason prop is type-checked to the union'disabled' | 'unavailable' | 'remote'.Manual verification
The modal only fires inside an iframe (remote instance view). On the local dashboard the mic button behaves exactly as before. The settings banner is likewise invisible for single-instance users.
Screenshots
N/A — changes only visible when rendered inside an iframe (multi-instance remote view).
no-screenshotslabel applied.