SIGN IN SIGN UP

Write rich messages in a new composer, with layer 229 buttons and folded quotes

The composer is a Tiptap 3 / ProseMirror document now, and it is the only
formatting path: the chat input, captions, forward comments, fact checks, poll
and checklist fields, the gift message and every InputFieldEmoji field mount the
same engine, a plain field with a schema that simply has no blocks it cannot
send. The old execCommand formatting and its markup bookkeeping are gone;
helpers/dom/markdown.ts only dispatches into the editor. The engine and its
rules are described in components/chat/inputEditor/README.md.

Expanded, the composer writes native rich messages: headings, lists, tables,
folds, quotes and pull quotes, code blocks with a detected language, math,
photos and videos inside the text, a map, and buttons. It checks them against
the app config limits before sending, follows rich_message_posting (Premium, or
offering to send without formatting where it is not allowed), and edits a rich message
back into the same document. Create with AI starts a rich message from a prompt.

Layer 229, as the other clients have it:

- Buttons in rich messages and Instant View pages (pageBlockButtonRow and inline
  textButton), with their styles and alignment, doing what a keyboard button of
  the same type does. The composer adds them through a dialog with a live
  preview; a button that needs a message is drawn but inert outside one.
- The new keyboard button types: open a user's profile, share a location (asked
  first, then sent as a reply), create a poll or a quiz. Keyboard and page
  buttons share one handler.
- Quotes can be sent collapsed; the composer offers the switch on a long quote,
  and a collapsed one opens with a disclosure button. Compact tables.
- A welcome template's buttons fire only when they need no message, and a
  template can be rich: ephemeral sends and edits carry rich_message.

Keyboard and screen readers: composer chips and quote switches are buttons
reachable with Tab and pressed with Enter or Space, a toast no longer swallows a
keyboard click, the markup tooltip keeps its focus inside a popup, and the
in-app browser's header buttons have names. Checked with Axe in every theme and
the focus-visibility sweep.

In development CSS module class names are hashed from the file path alone, so
an SCSS edit no longer renames every class under DOM built imperatively
(ProseMirror node views).

New Playwright suites: test:editor:e2e for the engine and test:popups on its own
config, both on servers without hot reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
E
Eduard Kuzmenko committed
36d1db91bc191acb9514e97876b9527f69e8ad2f
Parent: 1749a0d