Skip to content

Keep the keyboard state when the composer link dialog opens and cancels #285

Description

@HMarzban

Problem

The rule for the composer link dialog says every path must keep the soft keyboard as it was: "open stays open, closed stays closed" (extensions/CLAUDE.md:68). It names the preview tap, edit and add open, Cancel, and dismiss. The code trace shows two paths that break it. The refocus paths may break too; see Notes.

On 14ab7f9c1. Paths are under apps/webapp/src/components/chatroom/components/MessageComposer/.

Add and edit open. The editor dialog focuses its URL field on every open (components/ComposerLinkDialog/ComposerLinkEditorDialog.tsx:39-49). It only delays the focus when the dialog came from a preview while the keyboard was closed. Add open focuses the field during the same tap, so a closed keyboard opens. Edit from a preview focuses after 50 ms. A device check must show whether that opens the keyboard.

Cancel from an edit that came from a preview. cancel() returns to the preview phase (stores/composerLinkDialogStore.ts:181-184). That unmounts the focused URL field and focuses nothing. On a phone, removing the focused field closes the keyboard. So an open keyboard does not stay open. Back from that edit runs the same return to the preview in handleComposerLinkDialogPopState (stores/composerLinkDialogStore.ts:66-74).

Decide first. The first path may be intended, because a user who adds a link will type a URL. If so, change the rule to say that add and edit open focus the URL field. Say which on this issue before the fix is merged.

Steps to reproduce

  1. On a phone, open a channel and type a message that contains a link.
  2. With the keyboard open, tap the link, then choose Edit.
  3. Choose Cancel.
  4. See the keyboard close.

Acceptance criteria

  • Cancel from an edit that came from a preview keeps an open keyboard open.
  • extensions/CLAUDE.md states whether add and edit open focus the URL field.
  • With the keyboard closed, add and edit open match that statement: the keyboard stays closed, or the URL field takes focus.
  • On iOS Safari and Android Chrome, Save, Remove, Cancel from add, and dismiss (a tap outside the preview) each keep the keyboard state. If one fails at HEAD, fix it in the same change.

Agent Brief

Category: bug
Summary: Make the composer link dialog keep the keyboard state on every path, or change the rule where focus is intended.

Current behavior:
Add open focuses the URL field during the same tap, which opens a closed keyboard. Edit from a preview focuses it after a short delay. Cancel from an edit that came from a preview unmounts the focused field, which closes an open keyboard.

Desired behavior:
Each dialog path keeps the keyboard state it had when the dialog opened, except where the rule is changed on purpose. The rule and the code agree.

Key interfaces:

  • The composer link dialog store — openCreate, openEdit, openEditFromPreview, cancel, and keyboardWasOpenAtOpen.
  • ComposerLinkEditorDialog — the URL field focus on open.
  • ComposerLinkModalShell — the focusin trap that moves outside focus to the card's first control. The Cancel fix must let focus stay in the composer while the preview shows.
  • handleComposerLinkDialogPopState — back from an edit that came from a preview returns to the preview, the same as Cancel.
  • The keyboard-state rule for the composer link dialog in the extensions agent doc.

Out of scope

  • The pad hyperlink popovers.
  • The dialog's look and motion.

Notes

When the dialog closes, AnimatePresence keeps the shell mounted during its exit tween (components/ComposerLinkDialog/ComposerLinkDialogHost.tsx:48). On close, the store's refocus calls editor.commands.focus() on the composer. On iOS and Android, TipTap calls view.dom.focus() at once, then view.focus() in the next frame. Both calls run while the shell's focusin trap is still active (components/ComposerLinkDialog/ComposerLinkModalShell.tsx:45-50). Check where focus lands after the exit tween.

The preview shell's trap also moves composer focus to the first card button (components/ComposerLinkDialog/ComposerLinkModalShell.tsx:45-50). A change in the store alone cannot keep the keyboard open on Cancel.

The evidence is a code trace on 14ab7f9c1, confirmed by two verifiers. Keyboard behavior needs a check on iOS Safari and Android Chrome.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    ChatRelated to chat featuresMobilebugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions