---
title: "Pin Input"
description: "A sequence of one-character alphanumeric inputs."
canonical_url: "https://vinicunca.dev/akar/components/pin-input"
---
# Pin Input

> A sequence of one-character alphanumeric inputs.

```vue [index.vue]
<script setup lang="ts">
import { Label, PinInputInput, PinInputRoot } from 'akar'
import { ref } from 'vue'
import './styles.css'

const value = ref<string[]>([])
function handleComplete(e: string[]) {
  // eslint-disable-next-line no-alert
  alert(e.join(''))
}
</script>

<template>
  <div class="akar-demo akar-demo-PinInput">
    <div>
        <Label
          for="pin-input"
          class="Text"
        >Pin Input</Label>
        <PinInputRoot
          id="pin-input"
          v-model="value"
          class="PinInputRoot"
          @complete="handleComplete"
        >
          <PinInputInput
            v-for="(id, index) in 5"
            :key="id"
            :index="index"
            placeholder="○"
            class="PinInputInput"
          />
        </PinInputRoot>
      </div>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';

@scope (.akar-demo-PinInput) {
/* reset */
input {
  all: unset;
}

.Text {
  color: white
}

.PinInputInput{
  text-align: center;
  font-size: 15px;
  line-height: 1;
  align-items: center;
  justify-content: center;
  height: 2.25rem;
  width: 2.25rem;
  border-radius: 0.25rem; 
  transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
}

.PinInputInput:disabled {
  opacity: .5
}

.PinInputRoot{
  display: flex;
  align-items: center;
  gap: 0.25rem; 
  margin-top: 0.25rem;
  color: rgb(255 255 255)
}
}
```

## 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 [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup>
import { PinInputInput, PinInputRoot } from 'akar';
</script>

<template>
  <PinInputRoot>
    <PinInputInput />
  </PinInputRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a pin. An `input` will also render when used within a `form` to ensure events propagate correctly.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `defaultValue` |  | `PinInputValue<Type>` | The default value of the pin inputs when it is initially rendered. Use when you do not need to control its checked state. |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the pin input |
| `id` |  | `string` | Id of the element |
| `mask` |  | `boolean` | When `true`, pin inputs will be treated as password. |
| `modelValue` |  | `PinInputValue<Type> \| null` | The controlled checked state of the pin input. Can be binded as `v-model`. |
| `name` |  | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. |
| `otp` |  | `boolean` | When `true`, mobile devices will autodetect the OTP from messages or clipboard, and enable the autocomplete field. |
| `placeholder` | `""` | `string` | The placeholder character to use for empty pin-inputs. |
| `required` |  | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. |
| `type` | `"text" as any` | `Type` | Input type for the inputs. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `complete` | `value: PinInputValue<Type>` |  |
| `update:modelValue` | `value: PinInputValue<Type>` |  |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `modelValue` | `PinInputValue<Type>` | Current input values |

[PinInputRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput/PinInputRoot.vue)

| 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.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the pin input |
| `index*` |  | `number` | Position of the value this input binds to. |

[PinInputInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput/PinInputInput.vue)

| 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 'akar'
</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 'akar'
</script>

<template>
  <PinInputRoot v-model="value" type="number">
    …
  </PinInputRoot>
</template>
```

## Accessibility

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>ArrowLeft</kbd> | Focus on previous input. |
| <kbd>ArrowRight</kbd> | Focus on next input. |
| <kbd>Home</kbd> | Focus on the first input. |
| <kbd>End</kbd> | Focus on the last input. |
| <kbd>Backspace</kbd> | Deletes the value of the current input. If the input is empty, moves to the previous input and deletes that value as well. |
| <kbd>Delete</kbd> | Deletes the value of the current input. |
| <kbd>Ctrl + V</kbd> | 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. |

---

- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
