Textarea
Character count: 0
Documentation
value is two‑way bound (bind:value).
use leptos::prelude::*;
use tailwind_fuse::*;
#[derive(TwClass)]
#[tw(
class = "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
)]
struct TextareaStyle {
size: TextareaSize,
}
#[derive(TwVariant)]
pub enum TextareaSize {
#[tw(class = "text-xs py-1.5 px-2.5")]
Sm,
#[tw(default, class = "text-sm py-2 px-3")]
Default,
#[tw(class = "text-base py-2.5 px-3.5")]
Lg,
}
#[component]
pub fn Textarea(
#[prop(optional)] class: &'static str,
#[prop(optional)] size: TextareaSize,
/// Two‑way bound via `bind:value`.
#[prop(optional, default = RwSignal::new(String::new()))]
value: RwSignal<String>,
#[prop(optional, into)] disabled: Signal<bool>,
#[prop(optional, into)] readonly: Signal<bool>,
#[prop(optional, into)] required: Signal<bool>,
#[prop(optional_no_strip, into)] id: Option<&'static str>,
#[prop(optional_no_strip, into)] name: Option<&'static str>,
#[prop(optional_no_strip, into)] placeholder: Option<&'static str>,
#[prop(optional_no_strip, into)] rows: Option<u32>,
#[prop(optional_no_strip, into)] cols: Option<u32>,
) -> impl IntoView {
let class = TextareaStyle { size }.with_class(class);
view! {
<textarea
class=class
bind:value=value
id=id
name=name
placeholder=placeholder
rows=rows
cols=cols
disabled=disabled
readonly=readonly
required=required
data-invalid=move || {
if required.get() && value.get().is_empty() { Some("true") } else { None }
}
/>
}
}
Click to expand