Usage
Use the v-model directive to control the value of the PinInput.
<script setup lang="ts">
const value = ref([])
</script>
<template>
<PPinInput v-model="value" />
</template><script setup lang="ts">
import { ref } from 'vue'
const value = ref([])
</script>
<template>
<PPinInput v-model="value" />
</template>Use the default-value prop to set the initial value when you do not need to control its state.
<template>
<PPinInput :default-value="['1', '2', '3']" />
</template>Type
Use the type prop to change the input type. Defaults to text.
<template>
<PPinInput type="number" />
</template>type is set to number, it will only accept numeric characters.Mask
Use the mask prop to treat the input like a password.
<template>
<PPinInput 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>
<PPinInput otp />
</template>Placeholder
Use the placeholder prop to set a placeholder text.
<template>
<PPinInput placeholder="○" />
</template>Length
Use the length prop to change the amount of inputs.
<template>
<PPinInput :length="6" placeholder="○" />
</template>Separator
Use the separator prop to insert a separator between groups of inputs. Pass a number to insert one after every Nth input.
<template>
<PPinInput :length="6" :separator="3" placeholder="○" />
</template>You can also pass an array of positions to insert separators after specific inputs.
<template>
<PPinInput :length="7" :separator="[3, 4]" placeholder="○" />
</template>Color
Use the color prop to change the ring color when the PinInput is focused.
<template>
<PPinInput color="neutral" highlight placeholder="○" />
</template>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>
<PPinInput color="neutral" variant="subtle" placeholder="○" />
</template>Size
Use the size prop to change the size of the PinInput.
<template>
<PPinInput size="xl" placeholder="○" />
</template>Disabled
Use the disabled prop to disable the PinInput.
<template>
<PPinInput disabled placeholder="○" />
</template>Examples
With separator slot
Use the separator slot to customize the separator appearance.
<template>
<PPinInput
:length="6"
:separator="3"
placeholder="○"
>
<template #separator>
<PIcon
name="i-lucide-minus"
class="size-4"
/>
</template>
</PPinInput>
</template>
API
Props
| Prop | Default | Type |
|---|
Slots
| Slot | Type |
|---|
Emits
| Event | Type |
|---|
Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
|---|---|
inputsRef | Ref<ComponentPublicInstance[]> |
Theme
export default defineAppConfig({
ui: {
pinInput: {
slots: {
root: 'relative inline-flex items-center gap-1.5',
base: [
'text-center border-0 rounded-md placeholder:color-text-dimmed disabled:opacity-75 disabled:cursor-not-allowed',
'transition-colors'
],
separator: 'color-text-dimmed flex items-center justify-center'
},
variants: {
size: {
xs: {
base: 'size-6 text-sm/4'
},
sm: {
base: 'size-7 text-sm/4'
},
md: {
base: 'size-8 text-base/5'
},
lg: {
base: 'size-9 text-base/5'
},
xl: {
base: 'size-10 text-base'
}
},
variant: {
outline: 'color-text-highlighted bg-background ring ring-inset ring-border-accented',
soft: 'color-text-highlighted bg-background-elevated/50 hover:bg-background-elevated focus:bg-background-elevated disabled:bg-background-elevated/50',
subtle: 'color-text-highlighted bg-background-elevated ring ring-inset ring-border-accented',
ghost: 'color-text-highlighted bg-transparent hover:bg-background-elevated focus:bg-background-elevated disabled:bg-transparent dark:disabled:bg-transparent',
none: 'color-text-highlighted bg-transparent focus:outline-none'
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
highlight: {
true: ''
},
fixed: {
false: ''
}
},
compoundVariants: [
{
color: 'primary',
variant: [
'outline',
'subtle'
],
class: 'outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
},
{
color: 'primary',
variant: [
'soft',
'ghost'
],
class: 'outline-primary/25 focus-visible:outline-3'
},
{
color: 'primary',
highlight: true,
class: 'ring ring-inset pohon:ring-primary'
},
{
color: 'neutral',
variant: [
'outline',
'subtle'
],
class: 'outline-border-inverted/25 focus-visible:outline-3 focus-visible:ring-border-inverted'
},
{
color: 'neutral',
variant: [
'soft',
'ghost'
],
class: 'outline-border-inverted/25 focus-visible:outline-3'
},
{
color: 'neutral',
highlight: true,
class: 'ring ring-inset ring-border-inverted'
},
{
fixed: false,
size: 'xs',
class: 'md:text-xs'
},
{
fixed: false,
size: 'sm',
class: 'md:text-xs'
},
{
fixed: false,
size: 'md',
class: 'md:text-sm'
},
{
fixed: false,
size: 'lg',
class: 'md:text-sm'
}
],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
pinInput: {
slots: {
root: 'relative inline-flex items-center gap-1.5',
base: [
'text-center border-0 rounded-md placeholder:color-text-dimmed disabled:opacity-75 disabled:cursor-not-allowed',
'transition-colors'
],
separator: 'color-text-dimmed flex items-center justify-center'
},
variants: {
size: {
xs: {
base: 'size-6 text-sm/4'
},
sm: {
base: 'size-7 text-sm/4'
},
md: {
base: 'size-8 text-base/5'
},
lg: {
base: 'size-9 text-base/5'
},
xl: {
base: 'size-10 text-base'
}
},
variant: {
outline: 'color-text-highlighted bg-background ring ring-inset ring-border-accented',
soft: 'color-text-highlighted bg-background-elevated/50 hover:bg-background-elevated focus:bg-background-elevated disabled:bg-background-elevated/50',
subtle: 'color-text-highlighted bg-background-elevated ring ring-inset ring-border-accented',
ghost: 'color-text-highlighted bg-transparent hover:bg-background-elevated focus:bg-background-elevated disabled:bg-transparent dark:disabled:bg-transparent',
none: 'color-text-highlighted bg-transparent focus:outline-none'
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
highlight: {
true: ''
},
fixed: {
false: ''
}
},
compoundVariants: [
{
color: 'primary',
variant: [
'outline',
'subtle'
],
class: 'outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
},
{
color: 'primary',
variant: [
'soft',
'ghost'
],
class: 'outline-primary/25 focus-visible:outline-3'
},
{
color: 'primary',
highlight: true,
class: 'ring ring-inset pohon:ring-primary'
},
{
color: 'neutral',
variant: [
'outline',
'subtle'
],
class: 'outline-border-inverted/25 focus-visible:outline-3 focus-visible:ring-border-inverted'
},
{
color: 'neutral',
variant: [
'soft',
'ghost'
],
class: 'outline-border-inverted/25 focus-visible:outline-3'
},
{
color: 'neutral',
highlight: true,
class: 'ring ring-inset ring-border-inverted'
},
{
fixed: false,
size: 'xs',
class: 'md:text-xs'
},
{
fixed: false,
size: 'sm',
class: 'md:text-xs'
},
{
fixed: false,
size: 'md',
class: 'md:text-sm'
},
{
fixed: false,
size: 'lg',
class: 'md:text-sm'
}
],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
})
]
})