Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Forms

Text Area

A multi-line text input.

Rust
use herogpui::components::textarea::TextArea;

TextArea on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

Platform edits support composed text and paste. Enter confirms active composition before inserting a newline. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::TextArea;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![gpui::div()
                 .w(px(384.))
                 .child(TextArea::new(self.demo_text("ta-usage", "", cx))
                         .placeholder("Share a quick project update...")
                         .cols(48)
                         .rows(6)
                         .full_width())
                 .into_any_element()])

Variants

Labels use 14px text with 20px lines; helper and error text use 12px text with 16px lines. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{FieldVariant, TextArea};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![
        TextArea::new(self.demo_text("ta-primary", "", cx))
            .label("Primary")
            .placeholder("Primary textarea")
            .rows(3)
            .into_any_element(),
        TextArea::new(self.demo_text("ta-secondary", "", cx))
            .label("Secondary")
            .placeholder("Secondary textarea")
            .variant(FieldVariant::Secondary)
            .rows(3)
            .into_any_element(),
    ])

In Surface

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{FieldVariant, Surface, TextArea};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![Surface::new()
        .padding(px(24.))
        .gap(px(16.))
        .child(
            TextArea::new(self.demo_text("ta-surface", "", cx))
                .label("Notes")
                .placeholder("Describe your product")
                .variant(FieldVariant::Secondary)
                .rows(3),
        )
        .into_any_element()])

Full Width

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::TextArea;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![TextArea::new(self.demo_text("ta-full", "", cx))
        .label("Notes")
        .placeholder("Full width textarea")
        .rows(3)
        .full_width()
        .into_any_element()])

Controlled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, TextArea};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let ta_controlled = self
    .demo_text("ta-controlled", "", cx)
    .read(cx)
    .value()
    .to_owned();

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        gpui::div()
            .w(px(256.))
            .flex()
            .flex_col()
            .child(TextArea::new(self.demo_text("ta-controlled", "", cx))
                        .label("Notes")
                        .placeholder("Compose an announcement...")
                        .rows(3)
                        .on_change(|_, _, _| {}))
            .into_any_element(),
        para(&format!("{} characters", ta_controlled.chars().count()), cx),
    ])

Also calls para (included when you copy).

Rows and Resizing

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::TextArea;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![
        TextArea::new(self.demo_text("ta-one-row-floor", "", cx))
            .label("One row (38px minimum)")
            .placeholder("A compact note")
            .rows(1)
            .into_any_element(),
        TextArea::new(self.input_bio.clone())
            .label("Six rows")
            .placeholder("Write out the full meeting notes...")
            .rows(6)
            .into_any_element(),
    ])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

TextArea

Text Area is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Text Area looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Text Area styling
MethodValuesDescription
full_width()true | falseStretches to the available container width.
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondaryPrimary field chrome or the lower-emphasis surface variant.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 20 entries ported, 1 partial, 3 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Text Area builders
BuilderValuesDefaultDescription
rows(u32)number3Sets the visible height from the requested line count and field padding.
cols(u32)Partialnumber—GPUI has no ch unit, so columns use an 8px character-advance approximation.
value(text)string—Seeds the owned InputState with the controlled value on the first render; InputState::set_value updates it afterwards.
default_value(text)string—Seeds the uncontrolled InputState once.
on_change(callback)Fn(event: change event) -> ()—Reports accepted text and newline edits without reporting rejected maxLength edits.
placeholder(text)string—Placeholder shown while empty and unfocused.
is_disabled(bool)true | falsefalseRemoves focus and editing and applies disabled opacity.
is_read_only(bool)true | falsefalseKeeps focus and selection while suppressing edits.
is_required(bool)true | falsefalseParticipates in the HeroGPUI form validity registry.
name(text)string—Submission name stored with the current multi-line value.
max_length(usize)number—Rejects character and newline edits beyond the limit without reporting an unchanged value.
min_length(usize)number—Marks a non-empty value invalid below the character minimum.
full_width()true | falsefalseStretches to the available container width.
focus_ring(bool)true | falsetrueGPUI extension: hides only the visual focus ring while retaining focus and editing.
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondaryFieldVariant::PrimaryPrimary field chrome or the lower-emphasis surface variant.
Not ported3 HeroUI entries not ported
Text Area builders not ported
HeroUI v3Why it is not ported
TextArea.classNameTailwind class merging has no GPUI analogue.
TextArea.autoCompleteBrowser autofill hints have no desktop GPUI equivalent.
TextArea.wrapGPUI provides one visual wrapping mode and does not inject hard line breaks for submission.

Parts

Text Area parts
PartDescription
TextAreaMulti-line editable field backed by InputState with caret, selection and validation.

States

Text Area states
StateBuilderDescription
Hoverinner Input hoverChanges field background and border while unfocused.
Focusedinner Input focusDraws focused field background, border and ring.
Focus visiblefocused field treatmentPinned CSS adds no rule beyond the focused field treatment.
Invalidinner Input validityUses invalid field ring and focused background.
Disabledis_disabled(bool)Applies theme disabled opacity and removes editing and focus.