Skip to content

EpTextarea

Props

NameDescriptionTypeDefault
idThe ID attribute for the textarea element.stringnull
nameThe name attribute for the textarea.stringnull
placeholderPlaceholder text shown when textarea is empty.stringnull
disabledIf true, disables the textarea.booleanfalse
requiredIf true, marks the textarea as required.booleanfalse
rowsNumber of visible text rows.number2
colsNumber of visible text columns (width).number20
maxlengthMaximum character length allowed.numbernull
minlengthMinimum character length required.numbernull
readonlyIf true, makes the textarea read-only.booleanfalse
autofocusIf true, automatically focuses on mount.booleanfalse
autocompleteControls autocomplete behavior.string'on'
spellcheckIf true, enables spellcheck.booleanfalse
wrapControls how text wraps.string'soft'

Events

NameDescriptionPayload
update:modelValue--
focus--
blur--

INFO

This component does not use slots.

Component Code

vue
<template>
  <div class="ep-textarea">
    <textarea
      :id="id"
      v-model="modelValue"
      :name="name"
      :placeholder="placeholder"
      :disabled="disabled"
      :required="required"
      :rows="rows"
      :cols="cols"
      :maxlength="maxlength"
      :minlength="minlength"
      :readonly="readonly"
      :autofocus="autofocus"
      :autocomplete="autocomplete"
      :spellcheck="spellcheck"
      :wrap="wrap"
      v-bind="$attrs"
      @focus="onFocus"
      @blur="onBlur"
    />
  </div>
</template>

<script setup>
  defineOptions({
    name: 'EpTextarea',
  })

  const props = defineProps({
    /**
     * The ID attribute for the textarea element.
     */
    id: {
      type: String,
      default: null,
    },
    /**
     * The name attribute for the textarea.
     */
    name: {
      type: String,
      default: null,
    },
    /**
     * Placeholder text shown when textarea is empty.
     */
    placeholder: {
      type: String,
      default: null,
    },
    /**
     * If true, disables the textarea.
     */
    disabled: {
      type: Boolean,
      default: false,
    },
    /**
     * If true, marks the textarea as required.
     */
    required: {
      type: Boolean,
      default: false,
    },
    /**
     * Number of visible text rows.
     */
    rows: {
      type: Number,
      default: 2,
    },
    /**
     * Number of visible text columns (width).
     */
    cols: {
      type: Number,
      default: 20,
    },
    /**
     * Maximum character length allowed.
     */
    maxlength: {
      type: Number,
      default: null,
    },
    /**
     * Minimum character length required.
     */
    minlength: {
      type: Number,
      default: null,
    },
    /**
     * If true, makes the textarea read-only.
     */
    readonly: {
      type: Boolean,
      default: false,
    },
    /**
     * If true, automatically focuses on mount.
     */
    autofocus: {
      type: Boolean,
      default: false,
    },
    /**
     * Controls autocomplete behavior.
     * @values 'on', 'off'
     */
    autocomplete: {
      type: String,
      default: 'on',
    },
    /**
     * If true, enables spellcheck.
     */
    spellcheck: {
      type: Boolean,
      default: false,
    },
    /**
     * Controls how text wraps.
     * @values 'soft', 'hard'
     */
    wrap: {
      type: String,
      default: 'soft',
    },
  })

  const modelValue = defineModel({
    type: String,
    default: '',
  })

  const emit = defineEmits(['update:modelValue', 'focus', 'blur'])

  const onFocus = (event) => {
    emit('focus', event)
  }

  const onBlur = (event) => {
    emit('blur', event)
  }
</script>

Styles (SCSS)

scss
.ep-textarea {
  --ep-textarea-width: 100%;
  --ep-textarea-min-width: 20rem;
  --ep-textarea-max-width: 70rem;
  --ep-textarea-height: 100%;
  --ep-textarea-min-height: none;
  --ep-textarea-max-height: none;
  --ep-textarea-border-color: var(--border-color);
  --ep-textarea-border-radius: var(--border-radius);
  --ep-textarea-bg-color: var(--interface-foreground);
  --ep-textarea-text-color: var(--text-color);
  --ep-textarea-font-size: var(--font-size--body);
  --ep-textarea-padding: 1.6rem 2rem;
  --ep-textarea-line-height: 1.5;
  --ep-textarea-resize: both;
  --ep-textarea-focus-border-color: var(--primary-color-base);
  width: 100%;

  textarea {
    width: var(--ep-textarea-width);
    min-width: var(--ep-textarea-min-width);
    max-width: var(--ep-textarea-max-width);
    height: var(--ep-textarea-height);
    min-height: var(--ep-textarea-min-height);
    max-height: var(--ep-textarea-max-height);
    border: 1px solid var(--ep-textarea-border-color);
    border-radius: var(--ep-textarea-border-radius);
    background-color: var(--ep-textarea-bg-color);
    color: var(--ep-textarea-text-color);
    padding: var(--ep-textarea-padding);
    line-height: var(--ep-textarea-line-height);
    font-size: var(--ep-textarea-font-size);
    resize: var(--ep-textarea-resize);
  }
}