DevactionUI.Composer (devaction_ui v0.4.0)

Copy Markdown View Source

The message field of the AI chat, of comments and of notes: a card with a textarea that grows with the text (up to max_rows, then it scrolls inside), a row of actions under it and a round send button. Enter sends the form, Shift + Enter breaks the line, and Enter while an accent or a word is being composed does neither; the send button is off while there is nothing to send, and over max_length the card turns red and a counter shows from 80% of the limit (DevactionUI.Composer hook).

It is a form: the LiveView gets event with %{name => text} (%{"prompt" => "..."} by default). LiveView never overwrites a field that has focus, so after a send the server empties it with push_event(socket, "composer:clear", %{id: "chat"}) (the id of the composer).

With busy the AI is answering: the field is read only and the send button becomes a stop button (its icon is the stop slot, its name stop_label). A click on it, or Esc, sends stop_event to target when there is one, and fires composer:stop on the card for a hook of your own.

edit_last_event is what ↑ in an empty field sends (to target when there is one): the LiveView answers with push_event(socket, "composer:fill", %{id: "chat", text: last_message}), which puts the text in the field.

suggest_event turns on the / and @ menus. A / at the very start of the text, or an @ at the start of any word, sends the event with %{"id" => id, "trigger" => "/" | "@", "query" => "what follows the sign"}, and "trigger" => nil once the word is gone or Esc closed the list. The LiveView draws the list in the suggestions slot (DevactionUI.Editor.suggest/1 is made for it) only while the trigger is open and filters it by the query; the hook owns the keys of the open list: ↑ ↓ move the highlight, Enter or Tab choose the row and Esc closes. A row with insert puts that text in place of the typed word; a row with event also tells the server.

The mode or model chip (Reviewer · strict) is a DevactionUI.Dropdown with variant={:chip} in the leading slot, fixed so the card never cuts its menu.

With an upload (an allow_upload of the LiveView) a file pasted into the field or dropped on the card is uploaded by LiveView, and Composer.file/1 chips in the header slot show each one with a button to remove it. The form then needs a change_event, which LiveView requires of a form with a file input. Composer.button/1 is a round action of the row under the field (leading on the left, trailing before the send button); given the upload, it opens the file chooser.

Every text comes from the caller (label, send_label, stop_label, the labels of the buttons and chips), and so do the icons, as slots.

Summary

Functions

An action of the row under the field; with an upload it is the label of the file input.

The chip of one file of the upload: its preview when it is an image, its name and progress when it is not.

Functions

button(assigns)

@spec button(map()) :: Phoenix.LiveView.Rendered.t()

An action of the row under the field; with an upload it is the label of the file input.

Attributes

  • label (:string) (required) - the name of the button, also its tooltip.
  • variant (:atom) - Defaults to :plain. Must be one of :plain, or :filled.
  • upload (:any) - a @uploads.name: the button opens the file chooser of the composer. Defaults to nil.
  • Global attributes are accepted.

Slots

  • icon (required)

composer(assigns)

@spec composer(map()) :: Phoenix.LiveView.Rendered.t()

Attributes

  • id (:string) (required)
  • name (:string) - the name of the field in the params of event. Defaults to "prompt".
  • value (:string) - the text the field starts with. Defaults to "".
  • label (:string) (required) - what the field is, for assistive technology.
  • placeholder (:string) - Defaults to nil.
  • event (:string) (required) - the phx-submit of the form.
  • send_label (:string) (required) - the name of the send button.
  • stop_label (:string) (required) - the name of the button while the AI answers (busy).
  • change_event (:string) - the phx-change of the form; an upload needs it. Defaults to nil.
  • stop_event (:string) - the event the stop button and Esc send; leave it out to listen to composer:stop instead. Defaults to nil.
  • max_rows (:integer) - how many lines the field grows to before it scrolls. Defaults to 8.
  • max_length (:integer) - the longest text that can be sent; 0 for no limit. Defaults to 0.
  • busy (:boolean) - the AI is answering: stop instead of send. Defaults to false.
  • suggest_event (:string) - sent when a / or an @ is being typed (and when it is gone); leave it out for no menus. Defaults to nil.
  • edit_last_event (:string) - sent when ↑ is pressed in an empty field, so the server can fill in the last message. Defaults to nil.
  • size (:atom) - :sm is a one-line field with the actions at its end. Defaults to :md. Must be one of :md, or :sm.
  • upload (:any) - a @uploads.name to paste and drop files into. Defaults to nil.
  • class (:any) - Defaults to nil.
  • target (:any) - a phx-target (a @myself) when used inside a LiveComponent. Defaults to nil.
  • Global attributes are accepted.

Slots

  • header - above the field: the chips of the files, Composer.file/1 for each entry.
  • suggestions - the open / or @ list, drawn by the server above the card.
  • leading - actions at the start of the row under the field.
  • trailing - actions before the send button.
  • icon (required) - the arrow of the send button.
  • stop (required) - the icon of the stop button.

file(assigns)

@spec file(map()) :: Phoenix.LiveView.Rendered.t()

The chip of one file of the upload: its preview when it is an image, its name and progress when it is not.

Attributes

  • entry (:any) (required) - a Phoenix.LiveView.UploadEntry.
  • remove_label (:string) (required) - the name of the remove button, for this file.
  • kind (:string) - the tag of a file that is not an image (PDF); the extension of its name by default. Defaults to nil.
  • detail (:string) - the line under the name of a file that is not an image (1.8 MB); its progress by default. Defaults to nil.
  • cancel_event (:string) - sent with ref, the entry to cancel. Defaults to "cancel-upload".
  • target (:any) - a phx-target (a @myself) when used inside a LiveComponent. Defaults to nil.
  • Global attributes are accepted.

Slots

  • icon (required) - the cross of the remove button.