Skip to content

Show active state in the mobile format grid #269

Description

@HMarzban

Problem

The mobile format grid does not update its active state while the user types or moves the caret. A tapped Bold button can stay unmarked. A button can stay marked after the caret leaves bold text.

The cause, traced on 14ab7f9c1, is below. Paths are under apps/webapp/src/components/chatroom/components/MessageComposer/.

  • Nine of the ten format buttons compute editor.isActive(type) only when they render (components/ui/Button.tsx:39). The Mention button reads its own store and is not affected.
  • The editor runs with shouldRerenderOnTransaction: false, so a re-render must come from somewhere else.
  • The desktop row gets it from useReRenderOnEditorTransaction (components/layouts/FormattingToolbar.tsx:36).
  • The mobile grid, ComposerFormatPanel, has no such subscription (components/layouts/ComposerFormatPanel.tsx:10-31).
  • Its other triggers are the composer context and re-renders of its parent, ComposerBar. None of them follows the selection. The context changes on reply, edit, comment, canSend, and a few flags (MessageComposer.tsx:248-280). By house rule it must stay that way (apps/webapp/src/components/chatroom/CLAUDE.md:73).

The desktop row has the reverse defect. FormattingToolbar subscribes before its early return. On desktop it re-renders after editor transactions, at most about once per 50 ms, while the row is hidden. On mobile it does the same while it always renders null.

The mobile grid lost the subscription in 3e08d6a71 (2026-07-01), when phones moved from FormattingToolbar to ComposerFormatPanel. The chatroom rules still say "FormattingToolbar must call useReRenderOnEditorTransaction(editor)" (apps/webapp/src/components/chatroom/CLAUDE.md:78).

Steps to reproduce

  1. On a phone, open a channel and focus the composer.
  2. Type plain so the composer is not empty.
  3. Open Text formatting from the insert menu.
  4. Tap Bold. See the button stay unmarked.
  5. Type bold. See the Bold button stay unmarked, though the new text is bold.
  6. Move the caret into plain, then back into bold. See no change on the Bold button.

Acceptance criteria

  • On a phone, each format button shows its active state as the selection changes, as the desktop row does. The Inline code button follows once Show the active state of the composer's Inline code button #282 lands.
  • With the format UI closed, moving the caret in the composer re-renders neither the desktop row nor the mobile grid.
  • Desktop behavior does not change.
  • The chatroom rules name the component that owns the transaction subscription.

Agent Brief

Category: bug
Summary: Move the transaction subscription into the component that renders the format buttons, and keep it only while that UI is open.

Current behavior:
The desktop row subscribes to editor transactions even when hidden, and even on mobile, where it renders nothing. The mobile grid never subscribes, so its active states are stale.

Desired behavior:
The format buttons re-render on editor transactions on both platforms, and only while the format UI is open. This replaces the chatroom rule that FormattingToolbar must call useReRenderOnEditorTransaction. That rule has been wrong for phones since the mobile grid moved out of FormattingToolbar. Update the rule in the same change.

Key interfaces:

  • useReRenderOnEditorTransaction(editor) — the throttled transaction subscription.
  • FormattingToolbar and ComposerFormatPanel — the desktop row and the mobile grid, both mounted by ComposerBar.
  • The composer ToolbarButton — reads editor.isActive() at render.

Out of scope

Notes

The evidence is a code trace on 14ab7f9c1. It was not checked on a device. Confirm steps 4 and 5 on iOS Safari and Android Chrome, before and after the fix.

Activity

  1. added
    bugSomething isn't working
    ChatRelated to chat features
    on Sep 14, 2026
  2. HMarzban commented on Sep 22, 2026

    @HMarzban
    CollaboratorAuthor

    Closing. Fixed in 7570f5d. The mobile format grid shows each button's active state. Checked on a phone on 2026-09-22.

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 featuresMobileUIbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions