Textarea
Multi-line text field for longer form content.
TailwindCSS
Alpine.js
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaDefault() {
<div class="w-full max-w-md">
@components.Textarea(components.TextareaProps{})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
Usage
1. Add the script to your page/layout:
// Option A: All components (recommended)
@utils.ComponentScripts()
// Option B: Just Textarea
@components.TextareaScript()
2. Use the component:
@components.Textarea(components.TextareaProps{...})
Examples
With Value
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaWithValue() {
<div class="w-full max-w-md">
@components.Textarea(components.TextareaProps{
Value: "This is a text area with a value.",
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
With Rows
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaWithRows() {
<div class="w-full max-w-md">
@components.Textarea(components.TextareaProps{
Placeholder: "Type your message here.",
Rows: 6,
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
Auto Resize
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaAutoResize() {
<div class="w-full max-w-md">
@components.Textarea(components.TextareaProps{
Placeholder: "Start typing to see the magic...",
AutoResize: true,
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
With Label
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaWithLabel() {
<div class="space-y-2 w-full max-w-md">
@components.Label(components.LabelProps{
Text: "Your Message",
For: "textarea-with-label",
})
@components.Textarea(components.TextareaProps{
ID: "textarea-with-label",
Rows: 4,
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
Disabled
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaDisabled() {
<div class="space-y-2 w-full max-w-md">
@components.Label(components.LabelProps{
Text: "Your Message",
For: "textarea-disabled",
})
@components.Textarea(components.TextareaProps{
ID: "textarea-disabled",
Disabled: true,
Placeholder: "This textarea is disabled.",
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}
Form
Please type your message in the textarea.
This message is required.
package showcase
import "github.com/axzilla/templui/pkg/components"
templ TextareaForm() {
<div class="w-full max-w-md">
@components.FormItem(components.FormItemProps{}) {
@components.Label(components.LabelProps{
Text: "Your Message",
For: "textarea-form",
})
@components.Textarea(components.TextareaProps{
ID: "textarea-form",
Name: "message",
Placeholder: "Type your message here",
})
@components.FormDescription(components.FormDescriptionProps{}) {
Please type your message in the textarea.
}
@components.FormMessage(components.FormMessageProps{
Type: "error",
Message: "This message is required.",
})
}
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/utils"
"strconv"
)
type TextareaProps struct {
ID string // DOM identifier
Name string // Form field name
Value string // Initial content
Placeholder string // Helper text shown when empty
Rows int // Visible lines of text
Disabled bool // Prevents interaction
AutoResize bool // Enables dynamic resizing
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
templ TextareaScript() {
{{ handle := templ.NewOnceHandle() }}
@handle.Once() {
<script defer nonce={ templ.GetNonce(ctx) }>
document.addEventListener('alpine:init', () => {
Alpine.data('textarea', () => ({
resize() {
this.$el.style.height = '80px';
this.$el.style.height = this.$el.scrollHeight + 'px';
}
}));
});
</script>
}
}
// Textarea renders a multi-line text input field
templ Textarea(props TextareaProps) {
<textarea
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
placeholder={ props.Placeholder }
disabled?={ props.Disabled }
if props.Rows != 0 {
rows={ strconv.Itoa(props.Rows) }
}
class={
utils.TwMerge(
// Layout
"flex w-full px-3 py-2",
"min-h-[80px]",
// Styling
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Custom
props.Class,
),
}
if props.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ props.Attributes... }
>
if props.Value != "" {
{ props.Value }
}
</textarea>
}