Extensions Suite — 10 components for extending the PhiaUI rich text editor with plugins, emoji, special characters, and block-level controls.
These components provide the UI layer for editor extension features. They are designed to be composed inside the editor toolbar or sidebar slots.
Components
Extension Management
extension_toolbar_slot/1— renders extension buttons in the toolbarextension_sidebar_panel/1— sidebar panel listing available extensions
Content Insertion
emoji_picker_block/1— tabbed emoji picker with categories and recentsspecial_character_picker/1— tabbed special character picker (math, arrows, etc.)
Block-Level Controls
drag_handle/1— six-dot grip icon for block reorderingblock_type_menu/1— dropdown for changing block type (paragraph, heading, etc.)placeholder_extension/1— gray placeholder text for empty blockstypography_extension/1— status badge for smart typography rules
Node Utilities
unique_id_extension/1— hidden div with a data-extension-id attributecustom_node_renderer/1— wrapper div for rendering custom node types
Summary
Functions
Renders a dropdown menu for changing the current block type.
Renders a wrapper <div> for custom editor node types.
Renders a six-dot grip icon for block-level drag reordering.
Renders a tabbed emoji picker with category tabs and a grid area.
Renders a sidebar panel listing available extensions with active highlighting.
Renders a row of toolbar buttons for registered extensions.
Renders gray placeholder text for an empty editor block.
Renders a tabbed special character picker with category tabs and character grids.
Renders a small status badge showing whether smart typography is on or off.
Renders a hidden <div> with a unique data-extension-id attribute.
Functions
Renders a wrapper <div> for custom editor node types.
Provides data-node-type and data-node-data attributes for JS hooks
to identify and interact with custom blocks.
Example
<.custom_node_renderer id="embed-1" node_type="youtube" data={%{url: "https://..."}}>
<iframe src="..." />
</.custom_node_renderer>Attributes
id(:string) (required)node_type(:string) (required)data(:map) - Defaults to%{}.class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block
Renders a six-dot grip icon for block-level drag reordering.
Example
<.drag_handle />Attributes
class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a tabbed emoji picker with category tabs and a grid area.
Emoji content is populated client-side by a JS hook. This component provides the structural UI with category tabs and a placeholder grid.
Example
<.emoji_picker_block id="emoji" visible={@show_emoji} recent={@recent_emoji} />Attributes
id(:string) (required)visible(:boolean) - Defaults tofalse.categories(:list) - Defaults to[:smileys, :people, :nature, :food, :travel, :activities, :objects, :symbols].recent(:list) - Defaults to[].class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a sidebar panel listing available extensions with active highlighting.
Each item in :extensions should be a map with :id, :label, and
optional :description keys.
Example
<.extension_sidebar_panel
id="ext-panel"
extensions={[
%{id: "emoji", label: "Emoji Picker", description: "Insert emoji"},
%{id: "toc", label: "Table of Contents", description: "Auto-generated TOC"}
]}
active_extension="emoji"
/>Attributes
id(:string) (required)title(:string) - Defaults to"Extensions".extensions(:list) - Defaults to[].active_extension(:string) - Defaults tonil.class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a row of toolbar buttons for registered extensions.
Each item in :extensions should be a map with :id, :label, and :icon
(an icon name string) keys.
Example
<.extension_toolbar_slot
id="ext-toolbar"
extensions={[
%{id: "emoji", label: "Emoji", icon: "smile"},
%{id: "table", label: "Table", icon: "grid"}
]}
/>Attributes
id(:string) (required)extensions(:list) - Defaults to[].class(:string) - Defaults tonil.- Global attributes are accepted.
Renders gray placeholder text for an empty editor block.
The placeholder text is determined by the block :type, or can be overridden
with the :text attr.
Example
<.placeholder_extension type={:heading} />
<.placeholder_extension text="Start typing here..." />Attributes
type(:atom) - Defaults to:paragraph.text(:string) - Defaults tonil.class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a tabbed special character picker with category tabs and character grids.
Each tab shows a grid of clickable special characters. Clicking a character
fires phx-click="special-char:insert".
Example
<.special_character_picker id="chars" visible={@show_chars} />Attributes
id(:string) (required)visible(:boolean) - Defaults tofalse.categories(:list) - Defaults to[:math, :arrows, :currency, :greek, :latin].class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a small status badge showing whether smart typography is on or off.
When enabled, displays the active rules count. Rules include :smart_quotes,
:em_dash, and :ellipsis.
Example
<.typography_extension enabled={true} rules={[:smart_quotes, :em_dash]} />Attributes
enabled(:boolean) - Defaults totrue.rules(:list) - Defaults to[:smart_quotes, :em_dash, :ellipsis].class(:string) - Defaults tonil.- Global attributes are accepted.
Renders a hidden <div> with a unique data-extension-id attribute.
Used internally to assign stable IDs to editor blocks for collaboration, commenting, and version tracking.
Example
<.unique_id_extension prefix="sec" />Attributes
prefix(:string) - Defaults to"block".class(:string) - Defaults tonil.- Global attributes are accepted.