PhiaUi.Components.Editor.RichEditor (phia_ui v0.1.17)

Copy Markdown View Source

Rich Editor Suite — 8 components for building rich text editing experiences with Phoenix LiveView.

This module provides PhiaUI's native rich text editor integration using the vanilla PhiaEditor engine (zero npm dependencies). All formatting is handled via document.execCommand, the Selection API, and DOM manipulation.

Architecture

  • JSON is canonical — documents stored as typed JSON trees
  • Server-driven toolbar — active marks/nodes pushed from client, toolbar state lives in LiveView assigns (not JS)
  • Form integration — hidden input syncs content for standard form submission
  • Phoenix eventson_update and on_selection event names for LiveView handlers

Components

Core

  • rich_editor/1 — main editor with toolbar, content area, form integration (PhiaRichEditor)
  • rich_toolbar/1 — server-driven toolbar rendered from active marks/nodes assigns
  • rich_content/1 — read-only rendered content from editor JSON

Floating UI

Collaboration

Setup

# In app.js (zero npm dependencies needed):
import PhiaRichEditor from "./hooks/phia_rich_editor"
let liveSocket = new LiveSocket("/live", Socket, { hooks: { PhiaRichEditor } })

Summary

Functions

Collaborative cursor indicators for the rich editor.

Selection-aware floating toolbar for the rich editor.

Renders editor JSON content as read-only HTML.

Main rich text editor with toolbar, content area, and form integration.

Empty-line insertion menu for the rich editor.

Mention suggestions dropdown for the rich editor.

Slash command palette for the rich editor.

Server-driven toolbar for the rich editor.

Functions

collab_cursors(assigns)

Collaborative cursor indicators for the rich editor.

Renders colored cursor labels for connected users.

Example

<.collab_cursors
  id="cursors-1"
  editor_id="my-editor"
  cursors={@connected_users}
/>

Each cursor should be a map with :name, :color, and optionally :avatar_url.

Attributes

  • id (:string) (required)
  • editor_id (:string) (required)
  • cursors (:list) - Defaults to [].
  • class (:string) - Defaults to nil.

rich_bubble_menu(assigns)

Selection-aware floating toolbar for the rich editor.

Appears above text selection using the vanilla PhiaEditor positioning.

Example

<.rich_bubble_menu id="bubble-1" editor_id="my-editor">
  <button phx-click={...}>Bold</button>
</.rich_bubble_menu>

Attributes

  • id (:string) (required)
  • editor_id (:string) (required)
  • class (:string) - Defaults to nil.

Slots

  • inner_block (required)

rich_content(assigns)

Renders editor JSON content as read-only HTML.

Uses EditorContent.content_to_html/1 for server-side JSON-to-HTML conversion. Always sanitize content before display.

Examples

<%!-- From JSON map --%>
<.rich_content content={@post.body_json} prose_size={:lg} />

<%!-- From JSON string --%>
<.rich_content content={Jason.decode!(@post.body)} />

Attributes

  • content (:any) - Defaults to nil.
  • prose_size (:atom) - Defaults to :base. Must be one of :sm, :base, or :lg.
  • class (:string) - Defaults to nil.
  • Global attributes are accepted.

rich_editor(assigns)

Main rich text editor with toolbar, content area, and form integration.

Uses the PhiaRichEditor hook which initializes the vanilla PhiaEditor engine (execCommand-based, zero npm dependencies).

Content Flow

[Server: LiveView]
  assigns.content = JSON string
  push_event("editor:command:my-editor", %{command: "toggleBold"})
  |
[Client: PhiaRichEditor hook]
  editor.getHTML()  pushEvent("editor:update", %{json, html, word_count})
  editor.isActive()  pushEvent("editor:selection", %{active_marks, ...})

Examples

<%!-- Standalone --%>
<.rich_editor id="blog-editor" placeholder="Write..." min_height="400px" />

<%!-- Form-integrated --%>
<.form for={@form} phx-submit="publish">
  <.rich_editor id="post-editor" field={@form[:body]} />
</.form>

<%!-- With server-driven commands --%>
def handle_event("make_bold", _, socket) do
  {:noreply, push_event(socket, "editor:command:post-editor", %{command: "toggleBold"})}
end

Attributes

  • id (:string) (required)
  • field (Phoenix.HTML.FormField) - Defaults to nil.
  • value (:string) - Defaults to nil.
  • placeholder (:string) - Defaults to "Type '/' for commands, or start writing...".
  • min_height (:string) - Defaults to "300px".
  • extensions (:list) - Defaults to [:starter_kit, :placeholder].
  • on_update (:string) - Defaults to "editor:update".
  • on_selection (:string) - Defaults to "editor:selection".
  • toolbar_variant (:atom) - Defaults to :default. Must be one of :default, :floating, or :compact.
  • show_word_count (:boolean) - Defaults to true.
  • show_find_replace (:boolean) - Defaults to false.
  • content_format (:atom) - Defaults to :json. Must be one of :json, or :html.
  • collab_enabled (:boolean) - Enable collaborative editing mode. Defaults to false.
  • collab_doc_id (:string) - Document ID for collaboration channel. Defaults to nil.
  • collab_user (:map) - Current user map with :id, :name, :color keys. Defaults to nil.
  • class (:string) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • toolbar_extra - Extra toolbar content appended after default groups.

rich_floating_menu(assigns)

Empty-line insertion menu for the rich editor.

Appears at the cursor when the current block is empty.

Example

<.rich_floating_menu id="float-1" editor_id="my-editor">
  <button phx-click={...}>Heading</button>
  <button phx-click={...}>Image</button>
</.rich_floating_menu>

Attributes

  • id (:string) (required)
  • editor_id (:string) (required)
  • class (:string) - Defaults to nil.

Slots

  • inner_block (required)

rich_mention(assigns)

Mention suggestions dropdown for the rich editor.

Triggered by typing "@". Shows a server-driven list of suggestions.

Example

<.rich_mention
  id="mention-1"
  editor_id="my-editor"
  suggestions={@mention_suggestions}
/>

Each suggestion should be a map with :id, :label, and optionally :avatar_url.

Attributes

  • id (:string) (required)
  • editor_id (:string) (required)
  • suggestions (:list) - Defaults to [].
  • class (:string) - Defaults to nil.

rich_slash_commands(assigns)

Slash command palette for the rich editor.

Triggered by typing "/" at the start of a line.

Example

<.rich_slash_commands id="slash-1" editor_id="my-editor">
  <:command label="Heading 1" description="Large heading" action="setHeading" icon="heading" />
  <:command label="Bullet List" description="Unordered list" action="toggleBulletList" icon="list" />
</.rich_slash_commands>

Attributes

  • id (:string) (required)
  • editor_id (:string) (required)
  • class (:string) - Defaults to nil.

Slots

  • command - Accepts attributes:
    • label (:string) (required)
    • description (:string)
    • icon (:string)
    • action (:string) (required)

rich_toolbar(assigns)

Server-driven toolbar for the rich editor.

Active states are determined by assigns (pushed from client via selection events), not by JavaScript DOM inspection.

Example

<.rich_toolbar
  editor_id="my-editor"
  active_marks={@editor_state.active_marks}
  active_nodes={@editor_state.active_nodes}
  heading_level={@editor_state.heading_level}
/>

Attributes

  • variant (:atom) - Defaults to :default. Must be one of :default, :floating, or :compact.
  • editor_id (:string) (required)
  • active_marks (:list) - Defaults to [].
  • active_nodes (:list) - Defaults to [].
  • heading_level (:any) - Defaults to nil.
  • class (:string) - Defaults to nil.

Slots

  • extra - Extra toolbar content appended after default groups.