Multi-line text input component with form participation, validation, clear buttons, and slot-based customization.
Basic Usage
Code
<form class="form" id="example-form">
<m-textarea
label="Normal textarea"
name="normal-textarea"
></m-textarea>
<m-textarea
label="Textarea disabled"
name="textarea-disabled"
disabled
></m-textarea>
<m-textarea
label="Textarea with default value"
name="textarea-default-value"
value="Default value"
></m-textarea>
<m-textarea
label="Textarea readonly"
name="textarea-readonly"
value="Readonly value"
readonly
></m-textarea>
<m-textarea
label="Textarea placeholder"
name="textarea-placeholder"
placeholder="Enter your text here..."
></m-textarea>
<m-textarea
label="Textarea clearable"
name="textarea-clearable"
clearable
></m-textarea>
<m-textarea
label="Textarea with 5 rows"
name="textarea-rows"
rows="5"
></m-textarea>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</form>
<pre id="example-form-output"></pre>
<script>
document.querySelector('#example-form').addEventListener('submit', function(e) {
e.preventDefault();
const outputEl = document.querySelector("#example-form-output");
const formData = new FormData(e.target);
if(outputEl){
outputEl.textContent = JSON.stringify(Object.fromEntries(formData), null, 2);
}
});
</script> Validation
Code
<form class="form" id="validation-form">
<m-textarea
label="Required textarea"
name="required-textarea"
required
placeholder="This field is required"
></m-textarea>
<m-textarea
label="Minimum length (10 characters)"
name="minlength-textarea"
minlength="10"
placeholder="Enter at least 10 characters"
></m-textarea>
<m-textarea
label="Maximum length (100 characters)"
name="maxlength-textarea"
maxlength="100"
placeholder="Max 100 characters"
></m-textarea>
<m-textarea
label="Description (required, min 20 chars)"
name="description"
required
minlength="20"
rows="4"
placeholder="Enter a description (at least 20 characters)"
></m-textarea>
<button type="submit">Submit</button>
</form>
<pre id="validation-form-output"></pre>
<script>
const form = document.querySelector('#validation-form');
form.addEventListener('submit', function(e) {
e.preventDefault();
const outputEl = document.querySelector("#validation-form-output");
const formData = new FormData(e.target);
if(outputEl){
outputEl.textContent = JSON.stringify(Object.fromEntries(formData), null, 2);
}
});
</script> Clearable
Code
<form class="form">
<m-textarea
label="Notes"
name="notes"
clearable
rows="4"
placeholder="Enter your notes..."
></m-textarea>
</form> Clear Event
Code
<form class="form">
<m-textarea
id="clear-event-demo"
label="Textarea with clear event"
name="demo"
clearable
value="Try to clear me!"
></m-textarea>
</form>
<p id="clear-output"></p>
<script>
const textarea = document.querySelector('#clear-event-demo');
const output = document.querySelector('#clear-output');
textarea.addEventListener('m-textarea-clear', (e) => {
output.textContent = 'Clear button clicked! Event can be prevented with e.preventDefault()';
});
</script> Rows And Columns
Code
<form class="form">
<m-textarea
label="Small (3 rows - default)"
name="small"
placeholder="Default size"
></m-textarea>
<m-textarea
label="Medium (5 rows)"
name="medium"
rows="5"
placeholder="5 rows"
></m-textarea>
<m-textarea
label="Large (10 rows)"
name="large"
rows="10"
placeholder="10 rows"
></m-textarea>
<m-textarea
label="Custom columns (30 cols)"
name="cols"
cols="30"
placeholder="30 character columns"
></m-textarea>
</form> Slots
Code
<form class="form">
<m-textarea
label="With before/after slots"
name="slotted"
rows="4"
>
<span slot="before" style="color: var(--color-text-softer);">📝</span>
<span slot="after" style="color: var(--color-accent);">✓</span>
</m-textarea>
<m-textarea
label="Custom clear button"
name="custom-clear"
clearable
value="Custom clear icon"
>
<button slot="clear" type="button" style="color: var(--color-destructive);">🗑️</button>
</m-textarea>
</form> Wrap Mode
Code
<form class="form" id="wrap-form">
<m-textarea
label="Soft wrap (default)"
name="soft"
wrap="soft"
rows="3"
placeholder="Text wraps but no line breaks in value"
></m-textarea>
<m-textarea
label="Hard wrap"
name="hard"
wrap="hard"
cols="40"
rows="3"
placeholder="Line breaks are inserted at wrap point"
></m-textarea>
<m-textarea
label="No wrap"
name="off"
wrap="off"
rows="3"
placeholder="No wrapping, scroll horizontally"
></m-textarea>
<button type="submit">Submit</button>
</form>
<pre id="wrap-output"></pre>
<script>
document.querySelector('#wrap-form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(e.target);
const output = document.querySelector('#wrap-output');
output.textContent = JSON.stringify(Object.fromEntries(formData), null, 2);
});
</script> Comment Form
Code
<form class="form" id="comment-form">
<m-textarea
label="Your comment"
name="comment"
required
minlength="10"
maxlength="500"
rows="5"
placeholder="Share your thoughts... (10-500 characters)"
clearable
></m-textarea>
<button type="submit">Post Comment</button>
</form>
<pre id="comment-output"></pre>
<script>
document.querySelector('#comment-form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(e.target);
const output = document.querySelector('#comment-output');
output.textContent = 'Comment submitted: ' + JSON.stringify(Object.fromEntries(formData), null, 2);
});
</script> Feedback Form
Code
<form class="form" id="feedback-form">
<m-input
label="Name"
name="name"
required
></m-input>
<m-input
label="Email"
name="email"
type="email"
required
></m-input>
<m-textarea
label="Message"
name="message"
required
minlength="20"
rows="6"
placeholder="Tell us what you think..."
clearable
></m-textarea>
<button type="submit">Send Feedback</button>
</form>
<pre id="feedback-output"></pre>
<script>
document.querySelector('#feedback-form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(e.target);
const output = document.querySelector('#feedback-output');
output.textContent = 'Feedback submitted: ' + JSON.stringify(Object.fromEntries(formData), null, 2);
});
</script> - rows number 3
- cols number | undefined —
- wrap "soft" | "hard" | "off" | undefined —
- minLength number | undefined —
- maxLength number | undefined —
- placeholder string | undefined —
- clearable boolean false
- autofocus boolean false
- clearSlotHasContent — —
- selectionStart number | null —
- selectionEnd number | null —
- selectionDirection "forward" | "backward" | "none" | null —
- handleBlur — —
- handleInput — —
- adoptedStyleSheets array [baseStyleSheet]
- select void
- focus void
- blur void
- setSelectionRange void
- setRangeText void
- setRangeText void
- setRangeText void
- m-invalid CustomEvent
- Fires when validation fails. Detail: { validity: ValidityState, validationMessage: string, value: string }
- m-textarea-clear CustomEvent
- Fires when clear button is clicked (cancelable). Detail: { value: string }
- (default)
- Default slot for component content
- before
- Content before the textarea element (icons, chips, buttons)
- after
- Content after the textarea element
- clear
- Override the default clear button
- ::part(label)
- The label element
- ::part(textarea-wrapper)
- The wrapper containing the textarea and slots
- ::part(textarea)
- The native textarea element
- ::part(clear-button)
- The clear button
- ::part(clear-icon)
- The icon inside the clear button
- ::part(error)
- The error message container