Pin Input 
Alpha
 A sequence of one-character alphanumeric inputs. 
vue
<script setup lang="ts">
import { ref } from 'vue'
import { Label, PinInputInput, PinInputRoot } from 'radix-vue'
const value = ref<string[]>([])
const handleComplete = (e: string[]) => alert(e.join(''))
</script>
<template>
  <div>
    <Label for="pin-input" class="text-white">Pin Input</Label>
    <PinInputRoot
      id="pin-input"
      v-model="value"
      placeholder="○"
      class="flex gap-2 items-center mt-1"
      @complete="handleComplete"
    >
      <PinInputInput
        v-for="(id, index) in 5"
        :key="id"
        :index="index"
        class="w-10 h-10 bg-white rounded text-center shadow-lg text-green10 placeholder:text-mauve8 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white"
      />
    </PinInputRoot>
  </div>
</template>Features 
- Full keyboard navigation.
- Can be controlled or uncontrolled.
- Supports pasting from clipboard
- Emit event when inputs were filled.
Installation 
Install the component from your command line.
bash
npm install radix-vueAnatomy 
Import all parts and piece them together.
vue
<script setup>
import { PinInputInput, PinInputRoot } from 'radix-vue'
</script>
<template>
  <PinInputRoot>
    <PinInputInput />
  </PinInputRoot>
</template>API Reference 
Root 
Contains all the parts of a checkbox. An input will also render when used within a form to ensure events propagate correctly.
| Prop | Type | Default | 
|---|---|---|
| as | string | Component | div | 
| asChild | boolean | false | 
| defaultValue | string[] | |
| modelValue | string[] | |
| placeholder | string | |
| mask | boolean | false | 
| otp | boolean | false | 
| type | text | number | text | 
| disabled | boolean | |
| required | boolean | |
| name | string | 
| Emit | Type | 
|---|---|
| @update:modelValue | (value: string[]) => void | 
| @complete | (value: string[]) => void | 
| Data Attribute | Value | 
|---|---|
| [data-complete] | Present when completed | 
| [data-disabled] | Present when disabled | 
Input 
Input field for Pin Input. You can add as many input as you like.
| Prop | Type | Default | 
|---|---|---|
| as | string | Component | span | 
| asChild | boolean | false | 
| index | number | |
| disabled | boolean | 
| Data Attribute | Value | 
|---|---|
| [data-complete] | Present when completed | 
| [data-disabled] | Present when disabled | 
Examples 
OTP mode 
You can set the pin input to otp mode by setting otp to true.
vue
<script setup lang="ts"> 
import { Label, PinInputInput, PinInputRoot } from 'radix-vue' 
</script>
<template>
  <PinInputRoot v-model="value" otp>
    …
  </PinInputRoot>
</template>Numeric mode 
You can set the pin input to only accept number type by setting type to number.
vue
<script setup lang="ts"> 
import { Label, PinInputInput, PinInputRoot } from 'radix-vue' 
</script>
<template>
  <PinInputRoot v-model="value" type="number">
    …
  </PinInputRoot>
</template>Accessibility 
Keyboard Interactions 
| Key | Description | 
|---|---|
| ArrowLeft | Focus on previous input. | 
| ArrowRight | Focus on next input. | 
| Home | Focus on the first input. | 
| End | Focus on the last input. | 
| Backspace | Deletes the value of the current input. If the input is empty, moves to the previous input and deletes that value as well. | 
| Delete | Deletes the value of the current input. | 
| Ctrl + V | 	
Pastes the contents of the clipboard into the pin input. If the number of characters in the clipboard equals exceeds the number of inputs, the contents are pasted from the first input. Otherwise, the contents are pasted from the current input onwards. |