Skip to main content
The Input component provides a text input field with support for placeholders, validation, password mode, and different visual styles.

Basic Usage

use freya::prelude::*;

fn app() -> impl IntoElement {
    let text = use_state(String::new);
    
    Input::new(text)
        .placeholder("Type something...")
}

Style Variants

Normal (Default)

let text = use_state(String::new);

Input::new(text)
    .placeholder("Normal input")

Filled

let text = use_state(String::new);

Input::new(text)
    .placeholder("Filled input")
    .filled()

Flat

let text = use_state(String::new);

Input::new(text)
    .placeholder("Flat input")
    .flat()

Layout Variants

Compact

Input::new(text)
    .placeholder("Compact")
    .compact()

Expanded

Input::new(text)
    .placeholder("Expanded")
    .expanded()

Password Mode

Hide input text for passwords:
let password = use_state(String::new);

Input::new(password)
    .placeholder("Enter password")
    .mode(InputMode::new_password())
Or use a custom masking character:
Input::new(password)
    .mode(InputMode::Hidden('•'))

Properties

value
Writable<String>
required
The text value (typically from use_state)
placeholder
impl Into<Cow<'static, str>>
Placeholder text shown when input is empty
on_validate
EventHandler<InputValidator>
Callback for validating input changes. Set validator.set_valid(false) to reject changes
on_submit
EventHandler<String>
Callback fired when Enter key is pressed
mode
InputMode
default:"InputMode::Shown"
Display mode: Shown or Hidden(char) for passwords
auto_focus
bool
default:"false"
Whether to automatically focus when mounted
enabled
bool
default:"true"
Whether the input can be interacted with
width
Size
default:"Size::px(150.)"
Width of the input field
text_align
TextAlign
Text alignment within the input
style_variant
InputStyleVariant
Visual style: Normal, Filled, or Flat
layout_variant
InputLayoutVariant
Size variant: Normal, Compact, or Expanded

Validation Example

Validate input to only allow numbers:
use freya::prelude::*;

fn app() -> impl IntoElement {
    let text = use_state(String::new);
    
    Input::new(text)
        .placeholder("Numbers only")
        .on_validate(move |validator: InputValidator| {
            let is_valid = validator.text().chars().all(|c| c.is_numeric());
            validator.set_valid(is_valid);
        })
}

Submit Handler Example

Handle form submission:
let text = use_state(String::new);
let mut submitted = use_state(|| None::<String>);

rect()
    .spacing(8.)
    .child(
        Input::new(text)
            .placeholder("Enter text and press Enter")
            .on_submit(move |value| {
                submitted.set(Some(value));
                text.set(String::new());
            })
    )
    .child(
        submitted()
            .as_ref()
            .map(|s| format!("Submitted: {}", s))
            .unwrap_or_default()
    )

Complete Example

use freya::prelude::*;

fn app() -> impl IntoElement {
    let username = use_state(String::new);
    let password = use_state(String::new);
    let mut message = use_state(|| String::new());
    
    let on_login = move |_| {
        if !username().is_empty() && !password().is_empty() {
            message.set(format!("Logging in as {}...", username()));
        }
    };
    
    rect()
        .center()
        .spacing(12.)
        .child(
            Input::new(username)
                .placeholder("Username")
                .width(Size::px(200.))
        )
        .child(
            Input::new(password)
                .placeholder("Password")
                .mode(InputMode::new_password())
                .width(Size::px(200.))
        )
        .child(
            Button::new()
                .on_press(on_login)
                .filled()
                .child("Login")
        )
        .child(message())
}

Text Editing

The input supports standard text editing features:
  • Selection: Click and drag to select text
  • Cut/Copy/Paste: Standard keyboard shortcuts
  • Undo/Redo: Ctrl+Z / Ctrl+Y
  • Navigation: Arrow keys, Home, End
  • Deletion: Backspace, Delete

Accessibility

  • role="textInput" (or "passwordInput" in password mode)
  • Keyboard navigation with Tab
  • Focus indicators
  • Screen reader support

Theming

Customize appearance:
Input::new(text)
    .theme_colors(InputColorsThemePartial {
        background: Some(Color::from_rgb(240, 240, 255)),
        color: Some(Color::BLACK),
        ..Default::default()
    })

Source

View the full implementation: input.rs

Build docs developers (and LLMs) love