Skip to main content

tablo_ui/components/primitives/
textarea.rs

1// SYNC: topcoat-ui-registry@0.11.0 sha256:2187e350ae708cc9fcf9935773dfc354ee740032a2a8893a4aa0d5ffbb432527 — do not hand-edit. Sync via `cargo xtask sync-topcoat-ui` (ADR-0007).
2use topcoat::{
3    Result,
4    view::{Attributes, Child, StaticClass, View, class, component, view},
5};
6
7/// Classes for a textarea that grows with its content. Browsers without content sizing
8/// support keep the minimum height and scroll.
9const TEXTAREA: StaticClass = class!(
10    "field-sizing-content min-h-16 w-full rounded-lg border border-border",
11    "bg-transparent px-3 py-2 text-sm transition-colors outline-none",
12    "placeholder:text-muted-foreground",
13    "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
14    "aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive",
15    "focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
16);
17
18/// A text input for multiple lines.
19///
20/// Pass the initial value as children. `attrs` are forwarded to the `<textarea>`, with
21/// extra classes added to its classes. It fills its container and grows with its
22/// content where the browser supports this. Set `aria-invalid="true"` to show the error
23/// border and focus ring.
24///
25/// ```ignore
26/// view! {
27///     textarea(attrs: attributes! { name="feedback" placeholder="Tell us more" })
28/// }
29/// ```
30#[component]
31pub async fn textarea(
32    #[default] mut attrs: Attributes,
33    #[default] child: Child<'_>,
34) -> Result<impl View> {
35    Ok(view! {
36        <textarea class=(class!(TEXTAREA, attrs.remove("class"))) (attrs)>
37            (child)
38        </textarea>
39    })
40}