Editable

Editable is a small inline-edit helper.
In read mode it renders a low-emphasis button showing the current value. In edit mode it swaps that out for a TextInput. This is useful for rename-in-place flows such as editable titles, tags, or list item names.

Example

use fission::prelude::*;

#[fission_reducer(SetProjectNameDraft)]
fn on_set_project_name_draft(
    state: &mut ProjectState,
    ctx: &mut ReducerContext<ProjectState>,
) {
    if let Some(change) = ctx.input.text_change() {
        state.project_name_draft = change.new_text.clone();
    }
}

let widget: Widget = Editable {
id: Some(WidgetId::explicit("rename_project")),
value: view.state().project_name_draft.clone(),
placeholder: "Untitled project".into(),
is_editing: view.state().renaming_project,
on_input: Some(with_reducer!(ctx, SetProjectNameDraft, on_set_project_name_draft)),
on_edit: Some(with_reducer!(ctx, BeginProjectRename, on_begin_project_rename)),
on_submit: Some(finish_project_rename_action),
on_cancel: Some(cancel_project_rename_action),
}
.into();
The usual reducer flow is to keep both the committed value and the draft in state, start editing with on_edit, update the draft from on_input, and only commit when the product decides the edit is complete.

Field table

Field
Type
Meaning
Notes / default behavior
id
Option<WidgetId>
Stable identity for the editing field.
Defaults to None.
value
String
Current displayed or edited text.
Controlled by app state.
placeholder
String
Text shown when value is empty.
Required for a good empty-state experience.
is_editing
bool
Whether the widget is currently in edit mode.
Controlled by app state.
on_input
Option<ActionEnvelope>
Action fired when the text changes in edit mode.
Preserves the bound action; read the edit through ctx.input.text_change().
on_submit
Option<ActionEnvelope>
Action dispatched when the user presses Enter in the single-line editor.
Use it to commit the controlled draft and leave edit mode.
on_edit
Option<ActionEnvelope>
Action fired when the read-mode button is pressed.
Usually flips is_editing to true.
on_cancel
Option<ActionEnvelope>
Action dispatched when the user presses Escape in the editor.
Use it to restore the committed value and leave edit mode.

Current behavior

on_edit enters the controlled editing state, on_input carries live text changes, Enter dispatches on_submit, and Escape dispatches on_cancel. Losing focus does not imply cancellation: products differ on whether blur commits, cancels, or keeps a draft, so that decision remains in application state rather than being hidden in the widget.

Specific advice

Keep a committed value and an editing draft separately when cancellation must restore the pre-edit value. The widget deliberately does not retain a hidden backup copy.

Production checklist

For Editable, review the fields that change behavior before treating the widget as finished: id, value, placeholder, is_editing, on_input, on_submit. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
•
Bind on_input, on_submit, on_edit, and on_cancel to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
•
Set id only when identity must be stable across filtering, reordering, diagnostics, or tests; otherwise let Fission derive identity from structure.
•
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
•
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same Editable setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.
Previous
Dropzone