Skip to content

Input

The VInput component is a form control for receiving user input. It can be used in various ways, such as a single line text input, a password input, or a search bar.

Usage

Basic Usage

To use the VInput component, simply add the component to your template:

INFO

The VInput component is registered globally when you install with @morpheme/ui. So you don't need to import it manually.

Placeholder

You can also provide a placeholder attribute to display a hint to the user:

vue
<template>
  <VInput placeholder="Enter your name" />
</template>
<template>
  <VInput placeholder="Enter your name" />
</template>

Colors

You can customize the color of the VInput component using the color prop. The available color options are: primary, secondary, info, warning, success, error, and dark.

Readonly

To make the VInput component readonly, set the readonly prop to true.

Disabled

To disable the VInput component, set the disabled prop to true.

Shadow

To add a shadow to the VInput component, set the shadow prop to true.

Rounded

To add a shadow to the VInput component, set the rounded prop to true.

Text

To use the VInput component as a text input, set the text prop to true and provide a model-value and label.

Error

To display an error message with the VInput component, set the error prop to true.

Icons

You can add icons to the VInput component using the prepend-icon and append-icon props.

To customize the icon classes, use the prepend-icon-class and append-icon-class props. To customize the wrapper element classes, use the prepend-class and append-class props.

Slots

You can use slots to insert custom content into the input field, such as icons, text, or buttons.

  • Prepend Slot (Outer Position)

    The prepend.outer slot allows you to insert content before the input field, outside of the input field's container. This can be useful for adding icons or buttons that are positioned on the left side of the input field.

  • Append Slot (Outer Position)

    The prepend.outer slot allows you to insert content before the input field, outside of the input field's container. This can be useful for adding icons or buttons that are positioned on the left side of the input field.

  • Prepend Slot (Inner Position)

    The prepend slot allows you to insert content before the input field, inside of the input field's container. This can be useful for adding icons or text that are positioned on the left side of the input field and are aligned with the input text.

  • Append Slot (Inner Position)

    The append slot allows you to insert content after the input field, inside of the input field's container. This can be useful for adding icons or text that are positioned on the right side of the input field and are aligned with the input text.

  • Button or Text Slots

    You can use the prepend.outer and append.outer slots to insert button or text content on either side of the input field.

Validation

To use the VInput component with a form validation library, you can use the name prop to bind the component to a form control. For example, with VeeValidate, you can use the useForm hook to create a form with validation schema:

Validation Mode

There are 2 modes. The first is eager mode, and the second is aggressive mode. The eager mode validates input when the blur event occurs. Meanwhile, aggressive mode validates the input every time the input itself changes. This can be useful when you are validating for example the minimum or maximum limits of an input.

You can change the default value for this validation mode by adding an attribute or property named validation-mode to this component.

Field Array

Here is example of using VInput as field array with vee-validate.

Field Array of Objects

Here is example of using VInput as field array of object with vee-validate.

Field Array Nested

Here is example of using VInput as nested field array with vee-validate.

Props

NameTypeDefault
modelValue[String, Number]''
typeString'text'
nameString''
errorBooleanfalse
errorMessagesArray[]
readonlyBooleanfalse
disabledBooleanfalse
sizeString as PropType<'sm' | 'md' | 'lg'>'md'
placeholderString''
prependIconString''
appendIconString''
colorString'default'
textBooleanfalse
shadowBooleanfalse
roundedBooleanfalse
validationModeString'aggressive'
classesObject{}
labelString''
rules[Object, String]null
idString''
inputClassString''
wrapperClassString''
prependClassString''
prependIconClassString''
appendClassString''
appendIconClassString''
hintString''
hideErrorBooleanfalse

Events

Emitted when the value of the v-model directive changes. Can be used to perform an action when the value changes, such as updating other data or displaying a message to the user.

vue
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @update:modelValue="handle" />
</template>
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @update:modelValue="handle" />
</template>

Triggered when the element with the prepend slot is clicked.

vue
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-prepend="handle" />
</template>
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-prepend="handle" />
</template>

Triggered when the element with the prepend-icon slot is clicked.

vue
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-prepend-icon="handle" />
</template>
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-prepend-icon="handle" />
</template>

Triggered when the element with the append slot is clicked.

vue
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-append="handle" />
</template>
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-append="handle" />
</template>

Triggered when the element with the append-icon slot is clicked.

vue
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-append-icon="handle" />
</template>
<script setup lang="ts">
const handle = () => alert('Triggered!');
</script>

<template>
  <VInput @click-append-icon="handle" />
</template>

Slots

Allows you to customize the label of the input element.

vue
<template>
  <VInput>
    <template #label>My Label</template>
  </VInput>
</template>
<template>
  <VInput>
    <template #label>My Label</template>
  </VInput>
</template>

Allows you to customize the outer element of the prepend slot.

vue
<template>
  <VInput>
    <template #prepend.outer>Prepend Outer</template>
  </VInput>
</template>
<template>
  <VInput>
    <template #prepend.outer>Prepend Outer</template>
  </VInput>
</template>

Allows you to customize the prepend slot.

vue
<template>
  <VInput>
    <template #prepend>Prepend</template>
  </VInput>
</template>
<template>
  <VInput>
    <template #prepend>Prepend</template>
  </VInput>
</template>

Allows you to customize the outer element of the append slot.

vue
<template>
  <VInput>
    <template #append.outer>Append Outer</template>
  </VInput>
</template>
<template>
  <VInput>
    <template #append.outer>Append Outer</template>
  </VInput>
</template>

Allows you to customize the append slot.

vue
<template>
  <VInput>
    <template #append>Append</template>
  </VInput>
</template>
<template>
  <VInput>
    <template #append>Append</template>
  </VInput>
</template>

CSS Variables

scss
:root {
  /* input control */
  --v-input-height: 44px;
  --v-input-border-color: var(--color-gray-300);
  --v-input-placeholder-color: var(--color-gray-500);
  --v-input-border-radius: var(--border-radius-lg);
  --v-input-padding-x: var(--size-spacing-3);
  --v-input-padding-y: var(--size-spacing-3);
  --v-input-font-size: var(--size-font-sm);
  --v-input-line-height: 20px;
  --v-input-bg-color: var(--color-white);
  --v-input-color: var(--color-gray-700);

  /* label */
  --v-input-label-font-size: var(--size-font-sm);
  --v-input-label-font-weight: var(--font-weight-semibold);
  --v-input-label-display: block;
  --v-input-label-margin-bottom: var(--size-spacing-1);

  /* text */
  --v-input-text-color: var(--color-gray-700);
  --v-input-text-font-size: var(--size-font-sm);
  --v-input-text-font-weight: var(--font-weight-regular);

  /* icon */
  --v-input-icon-width: var(--size-spacing-5);
  --v-input-icon-height: var(--size-spacing-5);
  --v-input-icon-color: var(--color-gray-500);

  // disabled
  --v-input-disabled-bg-color: var(--color-gray-50);
  --v-input-disabled-color: var(--color-gray-500);
  --v-input-disabled-border-color: var(--color-gray-300);
  --v-input-disabled-placeholder-color: var(--color-gray-500);
  --v-input-disabled-icon-color: var(--color-gray-500);

  // hint
  --v-input-hint-font-size: var(--size-font-sm);
  --v-input-hint-color: var(--color-gray-600);
  --v-input-hint-margin-top: var(--size-spacing-1);

  // focus effect
  --v-input-effect-border-color: var(--color-primary-300);
  --v-input-effect-shadow-color: var(--color-primary-100);

  // shadow
  --v-input-shadow: var(--effect-shadow-xs);
}
:root {
  /* input control */
  --v-input-height: 44px;
  --v-input-border-color: var(--color-gray-300);
  --v-input-placeholder-color: var(--color-gray-500);
  --v-input-border-radius: var(--border-radius-lg);
  --v-input-padding-x: var(--size-spacing-3);
  --v-input-padding-y: var(--size-spacing-3);
  --v-input-font-size: var(--size-font-sm);
  --v-input-line-height: 20px;
  --v-input-bg-color: var(--color-white);
  --v-input-color: var(--color-gray-700);

  /* label */
  --v-input-label-font-size: var(--size-font-sm);
  --v-input-label-font-weight: var(--font-weight-semibold);
  --v-input-label-display: block;
  --v-input-label-margin-bottom: var(--size-spacing-1);

  /* text */
  --v-input-text-color: var(--color-gray-700);
  --v-input-text-font-size: var(--size-font-sm);
  --v-input-text-font-weight: var(--font-weight-regular);

  /* icon */
  --v-input-icon-width: var(--size-spacing-5);
  --v-input-icon-height: var(--size-spacing-5);
  --v-input-icon-color: var(--color-gray-500);

  // disabled
  --v-input-disabled-bg-color: var(--color-gray-50);
  --v-input-disabled-color: var(--color-gray-500);
  --v-input-disabled-border-color: var(--color-gray-300);
  --v-input-disabled-placeholder-color: var(--color-gray-500);
  --v-input-disabled-icon-color: var(--color-gray-500);

  // hint
  --v-input-hint-font-size: var(--size-font-sm);
  --v-input-hint-color: var(--color-gray-600);
  --v-input-hint-margin-top: var(--size-spacing-1);

  // focus effect
  --v-input-effect-border-color: var(--color-primary-300);
  --v-input-effect-shadow-color: var(--color-primary-100);

  // shadow
  --v-input-shadow: var(--effect-shadow-xs);
}

Standalone Installation

You can also install the VInput component individually via @morpheme/forms package:

bash
npm i @morpheme/forms
npm i @morpheme/forms
vue
<script setup lang="ts">
import {VInput} from '@morpheme/forms';
</script>

<template>
  <VInput />
</template>
<script setup lang="ts">
import {VInput} from '@morpheme/forms';
</script>

<template>
  <VInput />
</template>

Storybook

View Storybook documentation here.