Skip to main content

TextInput

TextInput is the main text-editing widget in Fission.

It covers ordinary single-line fields, multiline editors, password fields, syntax-highlighted editing, and input method editor composition. The important architectural rule is the same in every case: the widget does not own your product text. Your app state owns the text, the runtime delivers editing events, reducers update state, and the next build() pass renders the new value.

Example

use fission::core::ui::TextInput;

let node = TextInput {
value: view.state.email.clone(),
label: Some("Email address".into()),
placeholder: Some("name@example.com".into()),
on_change: Some(ctx.bind(
SetEmail(String::new()),
reduce_with!((|state: &mut SettingsState, action: SetEmail, _| state.email = action.0)),
)),
on_submit: Some(save_email_action),
width: Some(320.0),
..Default::default()
}
.into_node();

The empty string inside SetEmail(String::new()) is only a placeholder so ctx.bind(...) knows the action type. When the user edits the field, the runtime replaces the payload with the current String before dispatching the action.

Core field table

FieldTypeMeaningNotes / default behavior
idOption<NodeId>Stable identity for focus, selection, and runtime edit state.Defaults to None. Give important fields stable ids.
valueStringCurrent text value.Controlled by app state.
labelOption<TextContent>Semantic and visual label text.Defaults to None. Use this for accessibility instead of relying only on placeholders.
placeholderOption<TextContent>Hint text shown when the field is empty.Defaults to None.
helper_textOption<TextContent>Supporting text below the field.Defaults to None.
error_textOption<TextContent>Validation message below the field.Defaults to None.
counter_textOption<TextContent>Explicit counter text below the field.Defaults to None.
on_changeOption<ActionEnvelope>Action fired when the text changes.The runtime serializes the current String into the payload.
on_submitOption<ActionEnvelope>Action fired when the user submits the field.Uses the payload you provided on the envelope.
on_editing_completeOption<ActionEnvelope>Action fired when editing is explicitly completed.Defaults to None.
on_tap_outsideOption<ActionEnvelope>Action fired when the user taps or clicks away from the active field.Defaults to None.
widthOption<f32>Fixed width.Defaults to None.
heightOption<f32>Fixed height.Defaults to None.
paddingOption<[f32; 4]>Inner padding [left, right, top, bottom].Defaults to themed field padding.

Editing behavior table

FieldTypeMeaningNotes / default behavior
multilineboolWhether the field accepts newlines.Defaults to false. Multiline fields scroll vertically.
autofocusboolWhether the field should request focus on mount.Defaults to false.
enabledboolWhether the field is interactive.Defaults to true. Disabled fields do not receive focus.
read_onlyboolWhether the field can be focused and selected but not edited.Defaults to false.
min_linesOption<usize>Minimum visible line count for multiline fields.Defaults to None.
max_linesOption<usize>Maximum visible line count for multiline fields.Defaults to None.
obscure_textboolWhether the field masks characters.Defaults to false. Useful for passwords.
obscuring_charactercharCharacter used when masking text.Defaults to the implementation's bullet masking character.
prefixOption<Box<Node>>Leading decoration inside the field.Defaults to None.
suffixOption<Box<Node>>Trailing decoration inside the field.Defaults to None.
on_cursor_changeOption<ActionEnvelope>Action fired when caret or selection anchor changes.The runtime sends a CursorChanged payload.

Advanced editor and input table

FieldTypeMeaningNotes / default behavior
keyboard_typeTextInputTypePreferred keyboard or input mode.Defaults to plain text. Useful for email, number, and phone fields.
text_input_actionTextInputActionPreferred return-key action.Defaults to Done.
text_capitalizationTextCapitalizationAutomatic capitalization hint.Defaults to None.
max_lengthOption<usize>Maximum allowed text length.Defaults to None.
input_formattersVec<InputFormatter>Structured formatters applied during editing.Defaults to an empty list.
borderlessboolRemove the normal field chrome.Defaults to false. Useful for embedded editors.
capture_tabboolInsert tab characters instead of moving focus.Defaults to false.
auto_indentboolCopy leading whitespace on Enter.Defaults to false. Useful for code-like editors.
styled_runsOption<Vec<TextRun>>Pre-styled text runs for syntax-highlighted rendering.When present, the concatenated runs must match value exactly.
localeOption<String>Locale override for shaping and accessibility.Defaults to None.
scroll_paddingOption<[f32; 4]>Extra space kept around the caret during auto-scroll.Defaults to None.

How text, actions, and input method editor state work together

TextInput is a controlled widget. The runtime handles low-level editing details such as caret movement, selection, clipboard operations, and input method editor composition, then dispatches higher-level events back into your reducer loop. Your reducer updates the text in AppState, and build() passes that value back in.

This is why build() stays pure even for rich text entry. The widget describes the field, the runtime manages the live editing mechanics, and state remains explicit.

Specific advice

Use a real label for accessibility; placeholder text is not a good substitute because it disappears once typing begins. Keep expensive parsing or validation out of the raw keystroke path unless you truly need it on every change. If a field needs stable focus or selection behavior across rebuilds, give it a stable id.

FormControl, Editable, Combobox, and Environment, input, and input method editor.