Corex. Editable
(Corex v0.2.0)
View Source
Inline editable text for Phoenix LiveView forms. Behavior follows Zag.js Editable.
Anatomy
Basic
<.editable value="Click to edit" class="editable">
<:label>Name</:label>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>Required slots: :label, :edit_trigger, :submit_trigger, :cancel_trigger. Preview value is managed by the component and the Editable TS hook.
API
Pass a stable id when using set_value/2 or set_value/3. Otherwise an id is generated automatically.
| Function | Action | Returns |
|---|---|---|
set_value/2 | Set preview value (client) | %Phoenix.LiveView.JS{} |
set_value/3 | Set preview value (server) | socket |
Events
Pick an event name and pass it to on_* on <.editable>.
Server events
| Event | When | Payload |
|---|---|---|
on_value_change="editable_changed" | Value committed or cancelled | %{"id" => id, "value" => string} |
on_value_change
<.editable
value="Click to edit"
class="editable"
on_value_change="editable_changed"
>
<:label>Name</:label>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>def handle_event("editable_changed", %{"id" => _id, "value" => value}, socket) do
{:noreply, assign(socket, :name, value)}
endClient events
| Event | When | event.detail |
|---|---|---|
on_value_change_client="editable-changed" | Value changes | id, value |
Form
Use field={f[:name]} inside <.form> for changeset-backed forms.
For cross-cutting invalid styling and error presentation, see the Forms guide. With field={@form[:…]}, pass auto_invalid for alert borders from visible errors, or invalid={true} to force the alert state.
<.form for={@form} phx-change="validate">
<.editable field={@form[:name]} class="editable">
<:label>Name</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>
</.form>Style
Use data attributes to target elements:
[data-scope="editable"][data-part="root"] {}
[data-scope="editable"][data-part="area"] {}
[data-scope="editable"][data-part="label"] {}
[data-scope="editable"][data-part="input"] {}
[data-scope="editable"][data-part="preview"] {}
[data-scope="editable"][data-part="edit-trigger"] {}
[data-scope="editable"][data-part="control"] {}
[data-scope="editable"][data-part="submit-trigger"] {}
[data-scope="editable"][data-part="cancel-trigger"] {}
[data-scope="editable"][data-part="error"] {}If you wish to use the default Corex styling, you can use the class editable on the component.
This requires the corex_design dependency and mix corex.design.build; import the component css file.
@import "../corex/corex.css";You can then use modifiers
<.editable class="editable ui-accent ui-size-lg" value="">
<:label>Label</:label>
<:edit_trigger>Edit</:edit_trigger>
<:submit_trigger>Save</:submit_trigger>
<:cancel_trigger>Cancel</:cancel_trigger>
</.editable>Axes: Semantic (ui-accent, ui-brand, ui-alert, ui-info, ui-success), Variant (ui-solid), Size (ui-size-sm … ui-size-xl), Radius (ui-rounded-*). See the modifier guide.
Host width utilities (w-*, max-w-*, w-full) set the track the field fills. Preview and input share that width so entering edit mode stays stable (same pattern as clipboard).
Semantic modifiers set palette variables on the input, preview, and edit trigger. Variant modifiers control field surface treatment. Default is subtle; add editable ui-solid for a filled field. Cancel and submit triggers keep their alert and success styling.
Semantic
Palette variables for editable ink and fill. Does not change surface treatment by itself.
| Modifier | Classes |
|---|---|
| Default | editable |
| Accent | editable ui-accent |
| Brand | editable ui-brand |
| Alert | editable ui-alert |
| Info | editable ui-info |
| Success | editable ui-success |
Variant
Visual treatment of the input, preview, and edit trigger surfaces. Combine with a semantic modifier for palette-driven ink and fill.
| Modifier | Classes |
|---|---|
| Subtle (default) | editable or editable ui-accent |
| Solid | editable ui-accent ui-solid |
Size
| Modifier | Classes |
|---|---|
| SM | editable ui-size-sm |
| MD | editable ui-size-md |
| LG | editable ui-size-lg |
| XL | editable ui-size-xl |
Summary
Components
Attributes
id(:string) - The id of the editable component. Defaults tonil.field(Phoenix.HTML.FormField) - A form field struct, e.g. f[:text] or @form[:text]. Defaults tonil.name(:string) - The name attribute for form submission. Defaults tonil.form(:string) - The id of the form this input belongs to. Defaults tonil.invalid(:boolean) - Whether the control has validation errors. Defaults tonil.auto_invalid(:boolean) - When true withfield, set invalid from visible changeset errors (default false). Defaults tofalse.disabled(:boolean) - Whether the control is disabled. Defaults tofalse.read_only(:boolean) - Whether the editable is read-only. Defaults tofalse.required(:boolean) - Whether the control is required. Defaults tofalse.value(:string) - Initial preview text (Zag defaultValue). Defaults to"".dir(:string) - Text direction. Defaults tonil. Must be one ofnil,"ltr", or"rtl".orientation(:string) - Defaults to"vertical". Must be one of"horizontal", or"vertical".default_edit(:boolean) - Initial edit state. Defaults tofalse.placeholder(:string) - Placeholder text when value is empty. Defaults tonil.activation_mode(:string) - How to activate edit mode. Defaults tonil. Must be one ofnil,"dblclick", or"focus".select_on_focus(:boolean) - Whether to select all text on focus. Defaults totrue.on_value_change(:string) - Server event name when value changes. Defaults tonil.on_value_change_client(:string) - Client event name when value changes. Defaults tonil.translation(Corex.Editable.Translation) - Override translatable strings. Defaults tonil.errors(:list) - List of error messages to display. Defaults to[].- Global attributes are accepted.
Slots
label(required) - Accepts attributes:class(:string)
edit_trigger(required) - Accepts attributes:class(:string)
submit_trigger(required) - Accepts attributes:class(:string)
cancel_trigger(required) - Accepts attributes:class(:string)
error- Accepts attributes:class(:string)
API
@spec set_value(String.t(), String.t()) :: Phoenix.LiveView.JS.t()
Set the visible text value from a control (phx-click).
<.action phx-click={Corex.Editable.set_value("my-editable", "Hello")}>Reset</.action>
<.editable id="my-editable" class="editable" name="title" value="Hi">
<:label>Title</:label>
<:edit_trigger>Edit</:edit_trigger>
<:submit_trigger>Save</:submit_trigger>
<:cancel_trigger>Cancel</:cancel_trigger>
</.editable>document.getElementById("my-editable")?.dispatchEvent(
new CustomEvent("corex:editable:set-value", {
bubbles: false,
detail: { value: "Hello" },
})
);
@spec set_value(Phoenix.LiveView.Socket.t(), String.t(), String.t()) :: Phoenix.LiveView.Socket.t()
Set the value from handle_event.
<.action phx-click="reset_title" phx-value-value="Hello">Reset</.action>
<.editable id="my-editable" class="editable" name="title" value="Hi">
<:label>Title</:label>
<:edit_trigger>Edit</:edit_trigger>
<:submit_trigger>Save</:submit_trigger>
<:cancel_trigger>Cancel</:cancel_trigger>
</.editable>def handle_event("reset_title", %{"value" => v}, socket) do
{:noreply, Corex.Editable.set_value(socket, "my-editable", v)}
end