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
| | | |
|---|
| | Stable identity for the editing field. | |
| | Current displayed or edited text. | |
| | Text shown when value is empty. | Required for a good empty-state experience. |
| | Whether the widget is currently in edit mode. | |
| | Action fired when the text changes in edit mode. | Preserves the bound action; read the edit through ctx.input.text_change(). |
| | Action dispatched when the user presses Enter in the single-line editor. | Use it to commit the controlled draft and leave edit mode. |
| | Action fired when the read-mode button is pressed. | Usually flips is_editing to true. |
| | 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.