CwTextArea

Multi-line input with the same CWUI field treatment as CwInput, plus native-friendly validation hooks and responsive layout behavior.

Basic Usage

Helper text, counter, and full-width responsive behavior.

Use the theme picker in the header to verify both light and dark themes.

0/280

Live preview

Nothing entered yet.

Validation Demo

Combines browser validation attributes with custom client-side rules.

Required. Native validation checks required/minlength/maxlength, then custom rules can layer on top.

0/240

Sizes & states

Code Samples

Basic CwTextArea Copy code
<CwTextArea
	label="Field notes"
	placeholder="Log observations, thresholds, or operator context…"
	bind:value={notes}
	hint="Use the theme picker in the header to verify light and dark mode."
	rows={5}
	maxlength={280}
	showCount
/>
Validation with CwTextArea Copy code
<script lang="ts">
	import { CwTextArea } from '@cropwatchdevelopment/cwui';

	type ValidatableTextArea = {
		reportValidity: () => boolean;
		setCustomValidity: (message: string) => void;
	};

	let summary = $state('');
	let error = $state('');
	let valid = $state(false);
	let field = $state<ValidatableTextArea | null>(null);

	function handleInput() {
		error = '';
		valid = false;
		field?.setCustomValidity('');
	}

	function validate(event: SubmitEvent) {
		event.preventDefault();
		error = '';
		valid = false;
		field?.setCustomValidity('');

		if (!(field?.reportValidity() ?? true)) return;

		if (summary.trim().length < 20) {
			error = 'Add at least 20 characters so the next shift has enough context.';
			return;
		}

		valid = true;
	}
<\/script>

<form onsubmit={validate}>
	<CwTextArea
		bind:this={field}
		label="Shift handoff"
		name="handoff"
		required
		minlength={10}
		maxlength={240}
		bind:value={summary}
		error={error}
		valid={valid}
		oninput={handleInput}
		showCount
	/>
</form>
API

Usage and API reference

CwTextArea is the multi-line counterpart to CwInput and shares its label, hint, error and size styling. It can show a live character count against `maxlength`.

How to think about it

  1. Label it and add a hint `label` renders above the field, and `hint` below it. When `error` is set it replaces the hint and marks the field invalid.
  2. Show the count when there is a limit Combine `maxlength` with `showCount`. The counter updates visually without announcing every keystroke.
  3. Choose a resize mode `resize` controls whether people can drag the field larger; `vertical` suits most forms.

Props and callbacks

APITypeDetails
value

Default: ''

stringBindable text value.
label
stringVisible label above the field.
hint
stringHelper text under the field.
error
stringError message. Sets `aria-invalid` and replaces the hint.
valid

Default: false

booleanShows the success border.
required

Default: false

booleanAdds the required marker and `aria-required`.
readonly / disabled

Default: false

booleanNative read-only and disabled states.
size

Default: 'md'

'sm' | 'md' | 'lg'Padding and font scale, matching CwInput.
rows
numberInitial visible rows.
resize
'none' | 'vertical' | 'horizontal' | 'both'Resize handle behaviour.
showCount

Default: false

booleanShows a character count (with `maxlength`, shows the limit).
oninput / onchange / onblur / onfocus
(event) => voidNative event callbacks.

Copy-paste examples

Each snippet is a complete, working example you can paste into a Svelte 5 component.

Notes field with a limit
Notes field with a limit Copy code
<script lang="ts">
	import { CwTextArea } from '@cropwatchdevelopment/cwui';

	let notes = $state('');
</script>

<CwTextArea
	label="Field notes"
	hint="Visible to everyone in this location."
	bind:value={notes}
	maxlength={500}
	showCount
	rows={4}
	resize="vertical"
/>