Textarea
Multi-line text input with auto-grow option and validation states.
Overview
The Textarea component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.
Why this exists
Multi-line text input needs differ from single-line inputs. Textareas need height, resize behavior, and character counting for constrained inputs.
Mental model
A textarea is an expandable text field. It should grow with content up to a max-height, then scroll. Use it when the expected input spans multiple lines.
When to use
When not to use
Basic example
The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.
Description must be at least 20 characters.
import { Textarea } from '@byteion/react';
export default function TextareaDemo() {
return (
<div className="grid max-w-md gap-4 p-6">
<Textarea label="Bio" placeholder="Tell us about yourself…"
helperText="Markdown is supported." rows={4} />
<Textarea label="Release notes" rows={6}
defaultValue={'• Added: dark mode toggle\n• Fixed: pagination overflow'} />
<Textarea label="Feedback" state="error" rows={3}
helperText="Please provide at least 20 characters." />
</div>
);
}
<script setup lang="ts">
import { ref } from 'vue';
import { Textarea } from '@byteion/vue';
const notes = ref('• Added: dark mode toggle\n• Fixed: pagination overflow');
</script>
<template>
<div class="grid max-w-md gap-4 p-6">
<Textarea label="Bio" placeholder="Tell us about yourself…"
helper-text="Markdown is supported." :rows="4" />
<Textarea v-model="notes" label="Release notes" :rows="6" />
<Textarea label="Feedback" state="error" :rows="3"
helper-text="Please provide at least 20 characters." />
</div>
</template>
Variants
Each variant communicates a different meaning. Choose based on priority, not aesthetics.
Single default variant.
Sizes
Size should match the importance and context of the component.
- md — md size.
States
This component reacts seamlessly to the following interaction and data states:
- default — Resting appearance before interaction.
- focus — Keyboard or tab focus — shows ring indicator for accessibility.
- disabled — Non-interactive — grayed out, cursor not-allowed.
- error — Validation failed — red border and error message.
- hover — Pointer is over the element — visual feedback via color or shadow.
- active — Currently selected or in use.
Anatomy
Usage guidelines
- Set a reasonable min-height (3-4 lines).
- Enable vertical resize only.
- Add character counter when max-length is enforced.
Do and Don't
Do
- Set min-rows for readability.
- Allow vertical resize.
- Show character count for constrained fields.
Don't
- Do not disable resize entirely.
- Do not use for single-line inputs.
- Do not set a fixed small height.
Accessibility
Same as input — label association and aria-describedby for errors.
Role:textbox
Customization
Use the same border and focus-ring tokens as input.
Compose with React cva()
Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.
import { cva, cn, type VariantProps } from '@byteion/react';
const myTextarea = cva('base classes…', {
variants: {
accent: { soft:'border-primary-200', loud:'border-primary-500' },
},
defaultVariants: { accent:'soft' },
});
type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myTextarea>;
Compose with Vue cva()
Use the exportedcva() +cn() utilities inside standard Vue setup blocks.
<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';
interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();
const myTextarea = cva('base classes…', {
variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});
const cls = computed(() => myTextarea({ accent: props.accent, class: attrs.class as string | undefined }));
</script>
Runtime events
Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.
HTML / JS events
No HTML runtime events are declared by this adapter.
React callbacks
No React callback events are declared by this adapter.
Vue emits
update:modelValue[value: string]
Remote / AJAX
This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.
API Reference
Native textarea element.
HTML Data Attributes
No custom data attributes required.
React Props · TextareaProps
Extracted directly fromreact/src/components/Textarea.tsx.
export interface TextareaProps
extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'children'>,
VariantProps<typeof textarea> {
label?: ReactNode;
helperText?: ReactNode;
error?: ReactNode;
success?: ReactNode;
counter?: ReactNode;
}
React Variant Schema
Internal variant composition defined viacva().
cva(
'block w-full resize-y rounded-lg border bg-card px-3.5 py-2.5 text-sm leading-6 font-medium text-foreground outline-none transition-colors duration-200 ease-out-soft shadow-field hover:shadow-field-hover focus-visible:shadow-field-focus dark:bg-input dark:shadow-field-dark dark:hover:shadow-field-dark-hover dark:focus-visible:shadow-field-focus-dark placeholder:text-muted-foreground placeholder:font-normal',
{
variants: {
variant: {
outline: 'border-border hover:border-border focus-visible:border-primary-400 dark:focus-visible:border-primary-500',
filled: 'border-border bg-muted/60 hover:border-border hover:bg-muted focus-visible:border-primary-400 dark:border-border dark:bg-input dark:hover:border-border dark:hover:bg-input dark:focus-visible:border-primary-500',
},
state: {
default: '',
error: '!border-danger-500 text-danger-900 focus-visible:!shadow-field-error dark:text-danger-300',
success: '!border-success-400 focus-visible:!shadow-field-success',
},
},
defaultVariants: { variant: 'outline', state: 'default' },
},
)
Vue Props · TextareaProps
Extracted directly fromvue/src/components/Textarea.vue.
export interface TextareaProps {
modelValue?: string;
variant?: 'outline' | 'filled';
state?: 'default' | 'error' | 'success';
label?: string;
helperText?: string;
error?: string;
success?: string;
required?: boolean;
id?: string;
rows?: number;
}
Developer tips
Common mistakes
Production usage tips
data-bi-* attributes instead of styling hooks.
Premium examples
Advanced patterns available in Byteion Pro:
Related components
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.
Explore Pro Components