PinInput

An input element to enter a pin.

Usage

Use the v-model directive to control the value of the PinInput.

<script setup lang="ts">
const value = ref([])
</script>

<template>
  <UPinInput v-model="value" />
</template>

Use the default-value prop to set the initial value when you do not need to control its state.

<template>
  <UPinInput :default-value="['1', '2', '3']" />
</template>

Type

Use the type prop to change the input type. Defaults to text.

<template>
  <UPinInput type="number" />
</template>
When type is set to number, it will only accept numeric characters.

Mask

Use the mask prop to treat the input like a password.

<template>
  <UPinInput mask :default-value="['1', '2', '3', '4', '5']" />
</template>

OTP

Use the otp prop to enable One-Time Password functionality. When enabled, mobile devices can automatically detect and fill OTP codes from SMS messages or clipboard content, with autocomplete support.

<template>
  <UPinInput otp />
</template>

Length

Use the length prop to change the amount of inputs.

<template>
  <UPinInput :length="6" />
</template>

Placeholder

Use the placeholder prop to set a placeholder text.

<template>
  <UPinInput placeholder="â—‹" />
</template>

Color

Use the color prop to change the ring color when the PinInput is focused.

<template>
  <UPinInput color="neutral" highlight placeholder="â—‹" />
</template>
The highlight prop is used here to show the focus state. It's used internally when a validation error occurs.

Variant

Use the variant prop to change the variant of the PinInput.

<template>
  <UPinInput color="neutral" variant="subtle" placeholder="â—‹" />
</template>

Size

Use the size prop to change the size of the PinInput.

<template>
  <UPinInput size="xl" placeholder="â—‹" />
</template>

Disabled

Use the disabled prop to disable the PinInput.

<template>
  <UPinInput disabled placeholder="â—‹" />
</template>

API

Props

Prop Default Type
as

'div'

any

The element or component this component should render as.

color

primary

"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"

variant

outline

"outline" | "soft" | "subtle" | "ghost" | "none"

size

md

"md" | "xs" | "sm" | "lg" | "xl"

length

5

string | number

highlight

boolean

name

string

The name of the pin input. Submitted with its owning form as part of a name/value pair.

type

"text"

"number" | "text"

Input type for the inputs.

disabled

boolean

When true, prevents the user from interacting with the pin input

defaultValue

string[]

The default value of the pin inputs when it is initially rendered. Use when you do not need to control its checked state.

modelValue

string[]

The controlled checked state of the pin input. Can be binded as v-model.

required

boolean

When true, indicates that the user must check the pin input before the owning form can be submitted.

id

string

Id of the element

mask

boolean

When true, pin inputs will be treated as password.

placeholder

string

The placeholder character to use for empty pin-inputs.

otp

boolean

When true, mobile devices will autodetect the OTP from messages or clipboard, and enable the autocomplete field.

ui

PartialString<{ root: string; base: string[]; }>

Emits

Event Type
blur

[payload: Event]

change

[payload: Event]

update:modelValue

[value: string[]]

complete

[value: string[]]

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    pinInput: {
      slots: {
        root: 'relative inline-flex items-center gap-1.5',
        base: [
          'rounded-[calc(var(--ui-radius)*1.5)] border-0 placeholder:text-[var(--ui-text-dimmed)] text-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-75',
          'transition-colors'
        ]
      },
      variants: {
        size: {
          xs: {
            base: 'size-6 text-xs'
          },
          sm: {
            base: 'size-7 text-xs'
          },
          md: {
            base: 'size-8 text-sm'
          },
          lg: {
            base: 'size-9 text-sm'
          },
          xl: {
            base: 'size-10 text-base'
          }
        },
        variant: {
          outline: 'text-[var(--ui-text-highlighted)] bg-[var(--ui-bg)] ring ring-inset ring-[var(--ui-border-accented)]',
          soft: 'text-[var(--ui-text-highlighted)] bg-[var(--ui-bg-elevated)]/50 hover:bg-[var(--ui-bg-elevated)] focus:bg-[var(--ui-bg-elevated)] disabled:bg-[var(--ui-bg-elevated)]/50',
          subtle: 'text-[var(--ui-text-highlighted)] bg-[var(--ui-bg-elevated)] ring ring-inset ring-[var(--ui-border-accented)]',
          ghost: 'text-[var(--ui-text-highlighted)] bg-transparent hover:bg-[var(--ui-bg-elevated)] focus:bg-[var(--ui-bg-elevated)] disabled:bg-transparent dark:disabled:bg-transparent',
          none: 'text-[var(--ui-text-highlighted)] bg-transparent'
        },
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        highlight: {
          true: ''
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--ui-primary)]'
        },
        {
          color: 'primary',
          highlight: true,
          class: 'ring ring-inset ring-[var(--ui-primary)]'
        },
        {
          color: 'neutral',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--ui-border-inverted)]'
        },
        {
          color: 'neutral',
          highlight: true,
          class: 'ring ring-inset ring-[var(--ui-border-inverted)]'
        }
      ],
      defaultVariants: {
        size: 'md',
        color: 'primary',
        variant: 'outline'
      }
    }
  }
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.