HEEx
<div class="w-md">
<ConnieUI.Chat.composer field={@form[:body]} mentionable={@mentionable} id="catalog-chat-composer" />
</div>
Variant matrix
Every combination of one or two attributes, side by side.
Controls
Set by the example
field mentionable target
Docs
The message composer.
ProseMirror rather than a textarea, because a mention has to be an atom. A
textarea can only hold the characters `@Anna`, which means resolving that to a
person at send time by name, and two people called Anna make it ambiguous
forever. The mention node carries the person's id from the moment it is
inserted, so what was meant is never re-derived from what was typed: the
account member id for a team member, or the collaborator id for an entry
marked `kind: "collaborator"`, somebody outside the account on a document's
comments.
The document is mirrored into a hidden input on every change, so this submits
through LiveView like any other form and the composer needs no push of its
own. `mentionable` is the list the `@` menu offers, and it is the caller's
job to make it the thread's participants: only a participant can be
mentioned, and the database enforces it, so offering anyone else would offer
a name that is silently dropped on save.
Enter sends and Shift+Enter breaks the line, which is what every chat product
a colleague has used does. While the mention menu is open, Enter picks the
highlighted name instead. Cmd+Enter (Ctrl+Enter off a Mac) always sends, the
mention menu and a touch keyboard included.
| Attribute | Type | Default | Description |
|---|---|---|---|
| No data found. | |||
| id * | :string |
|
|
| field * | {:struct, Phoenix.HTML.FormField} |
|
|
| mentionable | :list | [] |
`%{id:, name:}` entries the @ menu may offer
|
| placeholder | :string | "Message" |
|
| target | :any | nil |
the LiveComponent the typing events go to; without it they reach the view instead
|
| typing_event | :string | nil |
pushed, throttled, while someone types; nothing is reported when unset
|
| stop_typing_event | :string | "stop_typing" |
|
| autofocus | :boolean | false |
Takes focus when the composer mounts. Ignored on touch devices, where it
would open the keyboard over the conversation somebody came to read.
|
| variant | :atom | :box |
`:box` draws the composer as a field of its own, two lines tall. `:inline`
draws nothing around the text, for a surface that is the field itself
(`composer_form/1`'s pills): it is one line tall, grows a line at a time as
somebody writes, easing between heights, and scrolls once it reaches the
same maximum the box has.
:box | :inline
|