Problem
The chatroom rules say composer overlays are mutually exclusive: opening one closes the others (apps/webapp/src/components/chatroom/CLAUDE.md:79). That holds in one direction only.
On 14ab7f9c1. Paths are under apps/webapp/src/components/chatroom/components/MessageComposer/.
- Opening an overlay stops a running recording. The emoji button calls
stopComposerVoiceRecording() first (components/Actions/ActionButtons/EmojiButton.tsx:41), and so do the shared dismiss helpers (helpers/dismissComposerOverlays.ts:25-35).
- On a phone, starting a recording closes nothing. The phone hold path runs
startHold from onPointerDown (components/Actions/ActionButtons/ComposerPrimaryAction.tsx:44-53). The desktop mic runs startLockedFromMenu (:55-58). Record voice in the insert menu runs it too, on a phone and on desktop (components/layouts/ComposerBar.tsx:59-61). useVoiceRecorder calls no dismiss helper (hooks/useVoiceRecorder.ts:149-235, :311-316).
- On desktop, the emoji picker already closes on the same click, through emoji-mart's click-outside handler (
apps/webapp/src/components/chatroom/components/EmojiPanel/Picker.tsx:96-100).
- Typed text shows Send in place of the mic. So the mention picker can be open at start only through Record voice in the insert menu.
So on a phone, the emoji panel stays open while the recording runs.
Steps to reproduce
- Sign in on a phone, and open a channel with an empty composer.
- Tap the emoji button, so the emoji panel opens.
- Press and hold the mic.
- See the recording bar appear while the emoji panel stays open.
Acceptance criteria
Agent Brief
Category: bug
Summary: Starting a voice recording must close the other composer overlays, as opening them already stops a recording.
Current behavior:
Opening the emoji panel, the emoji picker, the mention picker, or the link dialog stops a recording. On a phone, starting a recording closes none of them. On desktop, the click that starts a recording already closes the emoji picker.
Desired behavior:
On a phone, starting a recording closes the emoji panel. On both platforms, it closes the mention picker if that is open. The desktop emoji picker still closes, as today.
Key interfaces:
useVoiceRecorder() — startHold and startLockedFromMenu.
dismissComposerEmojiOverlays() and dismissComposerEmojiAndMentionOverlays() — each stops the recording first. A call after the browser grants the microphone ends the new recording.
stopComposerVoiceRecording() — the existing reverse path.
Out of scope
Notes
Each dismiss helper calls stopComposerVoiceRecording() first (helpers/dismissComposerOverlays.ts:26, :32). A reviewer measured this with the real useVoiceRecorder in happy-dom. A helper called after startHold, or in an effect after the recording renders, stops the new recording. A helper called before startHold does not. So close the emoji surfaces before the microphone request, or close them without the stop call.
dismissComposerMentionSuggestion() fires a synthetic Escape that also clears reply, edit, or comment today, as #268 shows. Land this after #268, or close the mention picker another way.
The evidence is a code trace on 14ab7f9c1, confirmed by two verifiers, plus the helper-order measurement above. It was not reproduced on a device.
Problem
The chatroom rules say composer overlays are mutually exclusive: opening one closes the others (
apps/webapp/src/components/chatroom/CLAUDE.md:79). That holds in one direction only.On
14ab7f9c1. Paths are underapps/webapp/src/components/chatroom/components/MessageComposer/.stopComposerVoiceRecording()first (components/Actions/ActionButtons/EmojiButton.tsx:41), and so do the shared dismiss helpers (helpers/dismissComposerOverlays.ts:25-35).startHoldfromonPointerDown(components/Actions/ActionButtons/ComposerPrimaryAction.tsx:44-53). The desktop mic runsstartLockedFromMenu(:55-58). Record voice in the insert menu runs it too, on a phone and on desktop (components/layouts/ComposerBar.tsx:59-61).useVoiceRecordercalls no dismiss helper (hooks/useVoiceRecorder.ts:149-235,:311-316).apps/webapp/src/components/chatroom/components/EmojiPanel/Picker.tsx:96-100).So on a phone, the emoji panel stays open while the recording runs.
Steps to reproduce
Acceptance criteria
Agent Brief
Category: bug
Summary: Starting a voice recording must close the other composer overlays, as opening them already stops a recording.
Current behavior:
Opening the emoji panel, the emoji picker, the mention picker, or the link dialog stops a recording. On a phone, starting a recording closes none of them. On desktop, the click that starts a recording already closes the emoji picker.
Desired behavior:
On a phone, starting a recording closes the emoji panel. On both platforms, it closes the mention picker if that is open. The desktop emoji picker still closes, as today.
Key interfaces:
useVoiceRecorder()—startHoldandstartLockedFromMenu.dismissComposerEmojiOverlays()anddismissComposerEmojiAndMentionOverlays()— each stops the recording first. A call after the browser grants the microphone ends the new recording.stopComposerVoiceRecording()— the existing reverse path.Out of scope
Notes
Each dismiss helper calls
stopComposerVoiceRecording()first (helpers/dismissComposerOverlays.ts:26,:32). A reviewer measured this with the realuseVoiceRecorderin happy-dom. A helper called afterstartHold, or in an effect after the recording renders, stops the new recording. A helper called beforestartHolddoes not. So close the emoji surfaces before the microphone request, or close them without the stop call.dismissComposerMentionSuggestion()fires a synthetic Escape that also clears reply, edit, or comment today, as #268 shows. Land this after #268, or close the mention picker another way.The evidence is a code trace on
14ab7f9c1, confirmed by two verifiers, plus the helper-order measurement above. It was not reproduced on a device.