Inputs

MaskPro

FormKit Pro Quick Installation Guide 🚀

Introduction

The mask input automatically transforms user input to match a provided format. Used appropriately, mask inputs can provide an improved user experience by removing any ambiguity for the desired value (for example a phone number or social security number).

Mask Input Overview

2 mins

Basic example

<FormKit  type="mask"  name="phone"  mask="+1 (###) ###-####"  label="Phone number"  help="Please enter a phone number"/>
Please enter a phone number

Masks

The mask is the desired format of the input. It is passed to the mask prop where it is parsed for tokens. The mask is comprised of:

  • Tokens - A string representation of a user-editable region. Shown in white below.
  • String literals - Any character that is not a token. Not user-editable. Shown in orange below.
Image of mask string with tokens and string literals in different colors.

Built-in tokens

The mask input comes with 4 built-in tokens:

  • h - Accepts a hexadecimal character (0-9a-fA-F).
  • # - Accepts a digit character.
  • a - Accepts an alphabetical character.
  • * - Accepts any character.
<script setup>import { ref } from 'vue'const color = ref(null)</script><template>  <FormKit    type="mask"    name="favorite_color"    v-model="color"    mask="\#hhhhhh"    label="Favorite Color in Hex"    help="Enter your favorite color in hexadecimal format. Or try FFA500."  />  <div class="box" :style="{ backgroundColor: color }"></div></template><style scoped>.box {  width: 30px;  height: 30px;}</style>
Enter your favorite color in hexadecimal format. Or try FFA500.

Escaping built-ins

If you need to use one of the built-in tokens as a string literal in your mask, you can escape them with \. Here we are escaping the pound sign # to use in our hex color:

<FormKit mask="\#hhhhhh" type="mask" />

Modes

The mask input supports 3 entry modes:

  • Shift (default)
  • Replace
  • Select

Shift & replace mode

By default, the characters of a mask are automatically shifted forward when typing. This is notable when a mask is already populated and you place the cursor at or near the beginning of the input and begin typing. The characters following your cursor are "shifted" forward as you type. In replace mode, however, subsequent characters are overwritten with a new value:

<FormKit  type="mask"  mask="###-###-####"  value="123-456-7890"  label="(Shift mode) Social security number"  help="Notice when you type new numbers the characters shift to the right."/><FormKit  type="mask"  mode="replace"  mask="###-###-####"  value="123-456-7890"  label="(Replace mode) Social security number"  help="Notice when you type new numbers the characters are replaced."/>
Notice when you type new numbers the characters shift to the right.
Notice when you type new numbers the characters are replaced.

Select mode

In select mode, equivalent char type tokens are grouped into selectable text ranges. FormKit automatically selects these text ranges when clicking or focusing the input. These selection ranges are maintained as the user is typing. When used tastefully, this produces a clear UX as the user is aware of what value they are expected to enter.

Additionally, when an input is in select mode, the user can use the arrow or tab keys to shift their focus from one selection range to another:

<FormKit  type="mask"  mode="select"  mask="###-###-####"  label="(Select mode) Social security number"  help="In select mode the active range is always highlighted."/>
In select mode the active range is always highlighted.
Select mode options

The selectDirection token property controls which direction new characters flow into the selected range. You can fill "empty" selection characters with a predetermined value (like leading zeros "0") by using the selectFill property. See token properties.

Tokens

Creating new tokens

What if a pattern can accept letters or numbers in the same position? It’s relatively simple to create new tokens. There are 2 types of tokens:

  • char accepts a single character.
  • enum accepts any strings from an array of possible values.

The following properties must be defined to create a new token:

{
  /**
   * The type of token. Can be a `char` or `enum`.
   */
  type: 'char',
  /**
   * The token to parse out of the mask.
   */
  token: 'z',
  /**
   * A placeholder character to display in the input when `show-mask` is
   * enabled.
   */
  placeholder: '_',
  /**
   * When using `select` mode, determines which direction do new characters flow
   * in.
   */
  selectDirection: 'left',
  /**
   * (Only for `char` type). A regular expression that describes the types of
   * characters that can appear in this slot. This pattern will be evaluated
   * against individual characters — not in the context of the entire string.
   */
  pattern: /[A-Za-z0-9]/,
  /**
   * (Only for `char` type, optional). An optional character to "fill" the
   * selection range with when in select mode. For example, a selectFill set to
   * "0" can be helpful with numbers to produce leading zeros like "001".
   */
  selectFill: "0",
  /**
   * (Only for `enum` type). An array of possible values.
   */
  values: [
    'March',
    'April',
    'May'
  ],
}

For example, a new token that accepts letters and numbers, and is represented by the letter z in the mask string would look like this:

{
  type: 'char',
  token: 'z',
  pattern: /[A-Za-z0-9]/,
  placeholder: '_',
  selectDirection: 'left',
}
Placeholders should not match pattern

Any placeholder you define should not match the Regex pattern provided in the token definition.

Add tokens via prop

To pass a new token to the mask input, you can use the tokens prop which expects an object with keys that match the token property. For example, our new token in the above example can be applied directly:

<FormKit  type="mask"  name="promo_code"  mask="zzz-#### ####"  :tokens="{    z: {      type: 'char',      token: 'z',      pattern: /[A-Za-z0-9]/,      placeholder: '_',      selectDirection: 'left',    },  }"  value="a6d-7789 4398"  label="Promo code"  help="Enter a promo code in the format: fkt-1234 5678"/>
Enter a promo code in the format: fkt-1234 5678

Add tokens globally

To register your mask tokens globally, extend the config property of your global FormKit configuration:

tokens-global
formkit.config
<FormKit  type="mask"  name="tracking"  mask="usps-zzz-zzzz-zzzz-zzzz"  value="usps-mk6-8d2z-8fggy-921x"  label="Tracking number"/>
import { defineFormKitConfig } from '@formkit/vue'import { genesisIcons } from '@formkit/icons'import { rootClasses } from '~/formkit.theme'import { createProPlugin, inputs } from '@formkit/pro'const pro = createProPlugin(import.meta.env.VITE_FORMKIT_PRO_KEY, inputs)export default defineFormKitConfig({  plugins: [pro],  icons: {    ...genesisIcons,  },  config: {    rootClasses,    tokens: {      z: {        type: 'char',        token: 'z',        pattern: /[A-Za-z0-9]/,        placeholder: '_',        selectDirection: 'left',      },    },  },})

Modify tokens

In addition to creating new tokens, the tokens prop can also modify existing tokens. Any value provided to the tokens prop will be merged into the existing tokens for that input. For example, the digit token’s (#) has no selectFill by default. To add one, extend it:

<FormKit  type="mask"  mode="select"  name="year"  mask="####"  label="What year were you born?"  help="You must be at least 21 to enter this site."  :tokens="{    '#': {      selectFill: '0',    },  }"  :validation="`required|max:${new Date().getFullYear() - 21}|min:${    new Date().getFullYear() - 120  }`"  validation-label="Birth year"  validation-visibility="live"  :validation-messages="{    min: 'Alright gramps, you\'re too old for this site.',  }"/>
You must be at least 21 to enter this site.
  • Birth year is required.

Char tokens

char tokens accept a single character. In order for a character to be accepted, it must match the token.pattern regular expression. The four built in tokens (h, #, a, and *) are all char type tokens.

In select mode, char tokens are grouped together into a selection range.

Placeholders

A char token should only ever represent 1 character, and its placeholder should also only be a single character in length.

Enum Tokens

Enum tokens allow for variable length masks within a predefined set of options. As a user begins to type, the enum token’s value will change to the first matching value, and the selection range will reflect the currently unmatched characters. In practice, this operates much like an autocomplete for that specific token. Additionally, users can cycle through available options for a given token by hitting the up/down arrow keys.

A date with auto-completing month names could be well represented with enums:

<script setup>const tokens = {  month: {    type: 'enum',    token: 'month',    placeholder: 'month',    selectDirection: 'left',    values: [      'January',      'February',      'March',      'April',      'May',      'June',      'July',      'August',      'September',      'October',      'November',      'December',    ],  },  day: {    type: 'enum',    token: 'day',    placeholder: 'day',    selectDirection: 'left',    values: new Array(31).fill(0).map((_, i) => `${i}`.padStart(2, '0')),  },  year: {    type: 'enum',    token: 'year',    placeholder: 'year',    selectDirection: 'left',    values: new Array(200).fill(0).map((_, i) => `${1900 + i}`),  },}</script><template>  <FormKit    type="mask"    mode="select"    mask="month day, year"    :tokens="tokens"    label="(Enums) Birthday"    help="Select a token and then type to autocomplete, or use the up/down arrows to select a value."  /></template>
Select a token and then type to autocomplete, or use the up/down arrows to select a value.
Select mode requirement

Enums are only supported in select mode. When any enum token is found in a mask string, the mode of the input is forcibly set to select.

Groups

Groups are a way to to treat multiple mask characters as a single unit. You create a group by surrounding the desired mask characters in {}:

<FormKit mask="id{-a#a}" type="mask" />
<!-- "-a#a" is the group -->

On their own, groups don't do anything unless you define group options.

Group options

Group options allow you to apply functionality to an entire group using a pipe | followed by the option name and any arguments. The available options are:

  • repeat — allows a group to be repeated an infinite number of times.
  • placeholder — A character to hold space prior to user input.
Group placeholders

A placeholder defined within a group has a higher specificity than a placeholder defined in the token definition and will override it.

Option parameters

Arguments can be passed to a group option by using a colon, such as placeholder:+, where the plus symbol + is passed to the placeholder option.

You can string group options together:

<FormKit  type="mask"  name="school_id"  mask="id{-a#a|repeat|placeholder:+}"  label="Id number"  help="Id number in the format: id-b4b-b4b-b4b-b4b"/><!-- "-a#a" is the group, "repeat" and "placeholder" are the options -->
Id number in the format: id-b4b-b4b-b4b-b4b
Can't be used in select mode

Groups cannot be used in select mode. An exception will be thrown.

Prefix & suffix

You can ensure certain characters always appear at the beginning or end of an input by using the prefix and suffix props, respectively:

<FormKit  type="mask"  name="years_old"  prefix="I am "  suffix=" years old."  mask="##"  mode="select"  validation="required"  :tokens="{    '#': {      selectFill: '0'    }  }"  label="Age"  help="How old are you?"/>
How old are you?
Values can't match the mask

Your prefix and suffix content can't match the mask. For instance, if your mask has a digit token #, your prefix/suffix can't contain numbers.

Running the mask in reverse

In specific circumstances, you may want to run your mask in reverse. The mask will test if user input fulfills the mask from right to left. This is common in currency-type inputs and can be applied by adding the reverse prop:

<FormKit type="form" :actions="false" #default="{ value }">  <FormKit    type="mask"    reverse    prefix=""    name="bid"    mask="{#,##|repeat}#.##"    label="Bid"    show-mask="false"    allow-incomplete="true"    help="Enter your bid for the art piece."  />  <pre wrap>{{ value }}</pre>  </FormKit>
Enter your bid for the art piece.
{}
Shift mode requirement

Running a mask in reverse only works in shift mode.

Mask values

Incomplete values

A mask’s value is not considered "complete" until the user has filled the entire pattern. Until that point, FormKit will consider the value of the input "empty". This makes it convenient to use with validation rules like required. However, if you’d like to accept incomplete values, you can via the allow-incomplete prop:

<FormKit type="form" #default="{ value }">  <FormKit    type="mask"    name="phone"    mask="(###) ###-####"    label="Phone number"    help="Enter a phone number. See the value change as you type."    allow-incomplete="true"  />  <pre wrap>{{ value }}</pre></FormKit>
Enter a phone number. See the value change as you type.
{}

Unmasked values

By default, the value of a mask input includes the formatting provided via the mask prop. However, if you'd like the raw unmasked value with the string literals removed, you can use the unmask-value prop:

<FormKit type="form" #default="{ value }">  <FormKit    type="mask"    name="phone"    mask="(###) ###-####"    label="Phone number"    help="Enter a full phone number. See the value has no string literals."    unmask-value="true"  />  <pre wrap>{{ value }}</pre></FormKit>
Enter a full phone number. See the value has no string literals.
{}

Hiding the mask

By default, the mask input displays each token’s placeholder character. You can disable this behavior (except in select mode) while still applying formatting automatically via the show-mask prop:

<FormKit  type="mask"  name="phone"  mask="+39 ###.######"  label="Número de teléfono"  help="Inserisci il tuo numero di cellulare."  show-mask="false"/>
Inserisci il tuo numero di cellulare.

Overlay (colorizing a mask)

By default, a mask’s value is displayed via the value of its input element. Although this works "out of the box" it does now allow for the text be stylistically differentiated. For example it would be nice if the "literal" portions of the mask looked different than the "placeholder" portions.

To achieve this effect, you can enable an overlay which renders DOM elements that are positioned directly over the input itself. The text inside the input is still there, but it will be transparent. In general the necessary overlay positioning styles are automatically applied for you.

The overlay contains 4 possible sections you can target your styles at:

  • Literal (.formkit-overlay-literal or overlay-literal-class)
  • Placeholder (.formkit-overlay-placeholder or overlay-placeholder-class)
  • Enum (.formkit-overlay-enum or overlay-enum-class)
  • Char (.formkit-overlay-char or overlay-char-class)

The default genesis theme automatically supports the overlay and applies light gray colors to the placeholder. If you are not using Genesis, please ensure the inner section is positioned (like position: relative).

<template>  <FormKit    type="mask"    mode="select"    mask="month day, year"    :tokens="tokens"    label="Birthday (with overlay)"    help="Notice the placeholder text is a lighter gray color."    overlay  />  <FormKit    type="mask"    name="phone"    mask="+1 (###) ###-####"    label="Phone number (with overlay)"    help="Let’s add some crazy colors to the overlay."    overlay-placeholder-class="yellow"    overlay-literal-class="blue"    overlay-char-class="red"    overlay  /></template><style scoped>.red {  color: red;}.yellow {  color: #d1c813;}.blue {  color: blue;}</style>

Props & Attributes

PropType Default Description
allow-incompletebooleanfalseBy default, the value of a mask input is empty until the pattern is complete. This prop allows the input to use incomplete values.
maskstringnoneThe mask to apply. This is a string composed of tokens (like “#”) and literal string values.
modestringshiftDetermines how the mask input operates. Options are shift, replace and select.
overlaybooleanfalseRenders DOM elements that mimic the text input to allow the differentiation in the stylization of the mask.
prefixstringnoneCharacters that will always appear at the beginning of the input.
reversebooleanfalseRuns the mask in reverse — from right to left.
show-maskbooleantrueDisplays a live representation of the pattern’s placeholder as the internal value of the input.
suffixstringnoneCharacters that will always appear at the end of the input.
tokensObject{}Add new tokens or modify existing ones.
unmask-valuebooleanfalseBy default, the value of the input is the same as what is displayed (with formatting). The string literals will removed from the value if this prop is set to true.
Show Universal props
configObject{}Configuration options to provide to the input’s node and any descendent node of this input.
delayNumber20Number of milliseconds to debounce an input’s value before the commit hook is dispatched.
dirtyBehaviorstringtouchedDetermines how the "dirty" flag of this input is set. Can be set to touched or comparetouched (the default) is more performant, but will not detect when the form is once again matching its initial state.
errorsArray[]Array of strings to show as error messages on this field.
helpString''Text for help text associated with the input.
idStringinput_{n}The unique id of the input. Providing an id also allows the input’s node to be globally accessed.
ignoreBooleanfalsePrevents an input from being included in any parent (group, list, form etc). Useful when using inputs for UI instead of actual values.
indexNumberundefinedAllows an input to be inserted at the given index if the parent is a list. If the input’s value is undefined, it inherits the value from that index position. If it has a value it inserts it into the lists’s values at the given index.
labelString''Text for the label element associated with the input.
nameStringinput_{n}The name of the input as identified in the data object. This should be unique within a group of fields.
parentFormKitNodecontextualBy default the parent is a wrapping group, list or form — but this props allows explicit assignment of the parent node.
prefix-iconString''Specifies an icon to put in the prefixIcon section.
preserveBooleanfalsePreserves the value of the input on a parent group, list, or form when the input unmounts.
preserve-errorsBooleanfalseBy default errors set on inputs using setErrors are automatically cleared on input, setting this prop to true maintains the error until it is explicitly cleared.
sections-schemaObject{}An object of section keys and schema partial values, where each schema partial is applied to the respective section.
suffix-iconString''Specifies an icon to put in the suffixIcon section.
typeStringtextThe type of input to render from the library.
validationString, Array[]The validation rules to be applied to the input.
validation-visibilityStringblurDetermines when to show an input's failing validation rules. Valid values are blur, dirty, and live.
validation-labelString{label prop}Determines what label to use in validation error messages, by default it uses the label prop if available, otherwise it uses the name prop.
validation-rulesObject{}Additional custom validation rules to make available to the validation prop.
valueAnyundefinedSeeds the initial value of an input and/or its children. Not reactive. Can seed entire groups (forms) and lists..

Sections

You can target a specific section of an input using that section's "key", allowing you to modify that section's classes, HTML (via :sections-schema, or content (via slots)). Read more about sections here.

Basic structure

The mask input follows the standard text-family structure.

Enter a phone number
📞
+1 (434) 221-7541
❤️
Please enter your phone number.
Phone number is required.

Overlay structure

When overlay is enabled, additional sections render styled text over the input.

_
(
4
Jan
+1 (434) 221-7541
Section-key Description
outerThe outermost wrapping element.
wrapperA wrapper around the label and input.
labelThe label of the input.
prefixHas no output by default, but allows content directly before an input element.
prefixIconAn element for outputting an icon before the prefix section.
innerA wrapper around the actual input element.
suffixHas no output by default, but allows content directly after an input element.
suffixIconAn element for outputting an icon after the suffix section.
inputThe input element itself.
helpThe element containing help text.
messagesA wrapper around all the messages.
messageThe element (or many elements) containing a message — most often validation and error messages.

Accessibility

All FormKit inputs are designed with the following accessibility considerations in mind. Help us continually improve accessibility for all by filing accessibility issues here:

  • Semantic markup
  • ARIA attributes
  • Keyboard accessibility
  • Focus indicators
  • Color contrast with the provided theme
  • Accessible labels, help text, and errors

Accessibility attributes

Section KeyAttributeValueDescription
labellabelforAssociates a label to an input element. Users can click on the label to focus the input or to toggle between states.
inputinputdisabledDisables an HTML element, preventing user interaction and signaling a non-interactive state.
aria-describedbyAssociates an element with a description, aiding screen readers.
aria-requiredAdded when input validation is set to required.
iconiconforLinks icon to input element when icon in rendered as a label.

Keyboard Interactions

Keyboard EventDescription
TabWhile in select mode, moves forward through available mask selection ranges. If at the end of available selection ranges the focus will be moved to the next focusable element on the page.
Shift+TabWhile in select mode, moves backward through available mask selection ranges. if at the beginning of available selection ranges the focus will be moved to the previous focusable element on the page.
While in select mode, navigates through available options for selection ranges that are enum tokens.
Universal Keyboard Events
TabMoves the focus to the next focusable element on the page.
Shift+TabMoves the focus to the previous focusable element on the page.