Textarea
Multi-line text field for longer form content.
TailwindCSS
Alpine.js
package showcase
import "github.com/axzilla/templui/components"
templ TextareaDefault() {
<div class="w-full max-w-md">
@components.Textarea(components.TextareaProps{
Placeholder: "Type your message here...",
})
</div>
}
package components
import (
"github.com/axzilla/templui/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}
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
Custom Rows
package showcase
import "github.com/axzilla/templui/components"
templ TextareaCustomRows() {
<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/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}
Auto Resize
package showcase
import "github.com/axzilla/templui/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/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}
With Label
package showcase
import "github.com/axzilla/templui/components"
templ TextareaWithLabel() {
<div class="space-y-2 w-full max-w-md">
@components.Label(components.LabelProps{
For: "textarea-with-label",
}) {
Your Message
}
@components.Textarea(components.TextareaProps{
ID: "textarea-with-label",
Placeholder: "Type your message here...",
Rows: 4,
})
</div>
}
package components
import (
"github.com/axzilla/templui/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}
Disabled
package showcase
import "github.com/axzilla/templui/components"
templ TextareaDisabled() {
<div class="space-y-2 w-full max-w-md">
@components.Label(components.LabelProps{
For: "textarea-disabled",
}) {
Your Message
}
@components.Textarea(components.TextareaProps{
ID: "textarea-disabled",
Disabled: true,
Placeholder: "Type your message here...",
})
</div>
}
package components
import (
"github.com/axzilla/templui/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}
Form
Please type your message in the textarea.
This message is required.
package showcase
import "github.com/axzilla/templui/components"
templ TextareaForm() {
<div class="w-full max-w-md">
@components.FormItem() {
@components.Label(components.LabelProps{
For: "textarea-form",
}) {
Your Message
}
@components.Textarea(components.TextareaProps{
ID: "textarea-form",
Name: "message",
Placeholder: "Type your message here...",
})
@components.FormDescription() {
Please type your message in the textarea.
}
@components.FormMessage(components.FormMessageProps{
Variant: components.FormMessageVariantError,
}) {
This message is required.
}
}
</div>
}
package components
import (
"github.com/axzilla/templui/utils"
"strconv"
)
type TextareaProps struct {
ID string
Class string
Attributes templ.Attributes
Name string
Value string
Placeholder string
Rows int
Disabled bool
Required bool
AutoResize bool
}
templ Textarea(props ...TextareaProps) {
{{ var p TextareaProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
if p.ID == "" {
{{ p.ID = utils.RandomID() }}
}
<textarea
x-ref={ p.ID }
id={ p.ID }
if p.Name != "" {
name={ p.Name }
}
if p.Placeholder != "" {
placeholder={ p.Placeholder }
}
if p.Rows > 0 {
rows={ strconv.Itoa(p.Rows) }
}
disabled?={ p.Disabled }
required?={ p.Required }
class={
utils.TwMerge(
"flex w-full px-3 py-2",
"min-h-[80px]",
"rounded-md border border-input bg-background text-sm",
"ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
p.Class,
),
}
if p.AutoResize {
x-data="textarea"
x-init="resize"
@input="resize"
}
{ p.Attributes... }
>{ p.Value }</textarea>
}
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>
}
}