Input · PinCode

PinCode

For easy and intuitive verification code entry

Demos

How to import

<script setup lang="ts">
    import { PinCode } from '@fibrous/semi-ui-vue';
</script>

Basic usage



Code
<script setup lang="ts">
    import { PinCode } from '@fibrous/semi-ui-vue';

    const onComplete = (value: string) => console.log('pincode: ', value);
    const onChange = (value: string) => console.log(value);
</script>

<template>
    <div>
        <PinCode aria-label="Verification code, small" defaultValue="123456" size="small" @change="onChange" @complete="onComplete" />
        <br />
        <PinCode aria-label="Verification code, default" defaultValue="123456" size="default" @change="onChange" @complete="onComplete" />
        <br />
        <PinCode aria-label="Verification code, large" defaultValue="123456" size="large" @change="onChange" @complete="onComplete" />
    </div>
</template>

Controlled

Use v-model to bind the verification code string



Code
<script setup lang="ts">
    import { ref } from 'vue';
    import { Button, PinCode } from '@fibrous/semi-ui-vue';

    const value = ref('69af41');

    const setRandomValue = () => {
        value.value = String(Math.floor(Math.random() * 100000000)).slice(0, 6);
    };
    const onComplete = (code: string) => console.log('pincode: ', code);
    const onChange = (code: string) => console.log(code);
</script>

<template>
    <div>
        <Button @click="setRandomValue">Set Random Value</Button>
        <br />
        <br />
        <PinCode v-model="value" aria-label="Verification code" format="mixed" @change="onChange" @complete="onComplete" />
    </div>
</template>

Limit verification code format

Set the number of digits

Set the number of digits through count, the default is 6 digits, the demo below is set to 4 digits

Code
<script setup lang="ts">
    import { PinCode } from '@fibrous/semi-ui-vue';

    const onComplete = (value: string) => console.log('pincode: ', value);
    const onChange = (value: string) => console.log(value);
</script>

<template>
    <PinCode aria-label="Verification code" :count="4" defaultValue="6688" size="large" @change="onChange" @complete="onComplete" />
</template>

Set character range

Use format to control the character range that can be entered

  • Pass "number" to only allow numbers
  • Pass "mixed" to allow numbers and letters
  • Pass in a regular expression to only allow characters that can be judged by the regular expression
  • Pass in a function, and the verification code will be passed in as parameters in units of characters for verification when entering. When the function returns true, the character is allowed to be entered into the PinCode
纯数字

字母和数字

只大写字母

只小写字母(函数判断)
Code
<script setup lang="ts">
    import { PinCode, Typography } from '@fibrous/semi-ui-vue';

    const { Text } = Typography;

    const onComplete = (value: string) => console.log('pincode: ', value);
    const isLower = (char: string) => /[a-z]/.test(char);
</script>

<template>
    <div>
        <Text id="pincode-format-number">纯数字</Text>
        <PinCode aria-labelledby="pincode-format-number" format="number" @complete="onComplete" />
        <br />
        <Text id="pincode-format-mixed">字母和数字</Text>
        <PinCode aria-labelledby="pincode-format-mixed" format="mixed" @complete="onComplete" />
        <br />
        <Text id="pincode-format-upper">只大写字母</Text>
        <PinCode aria-labelledby="pincode-format-upper" :format="/[A-Z]/" @complete="onComplete" />
        <br />
        <Text id="pincode-format-lower">只小写字母(函数判断)</Text>
        <PinCode aria-labelledby="pincode-format-lower" :format="isLower" @complete="onComplete" />
    </div>
</template>

Manual focus and blur

Use the focus and blur methods on the template ref, and the input parameter is the serial number of the corresponding Input, counted from 0



Code
<script setup lang="ts">
    import { ref, useTemplateRef } from 'vue';
    import { Button, PinCode, type PinCodeHandle } from '@fibrous/semi-ui-vue';

    const value = ref('69af41');
    const pinCode = useTemplateRef<PinCodeHandle>('pinCode');

    const onComplete = (code: string) => console.log('pincode: ', code);
    const onChange = (code: string) => console.log(code);
</script>

<template>
    <div>
        <Button @click="pinCode?.focus(2)">Focus Third Input</Button>
        <br />
        <br />
        <PinCode ref="pinCode" v-model="value" aria-label="Verification code" format="mixed" @change="onChange" @complete="onComplete" />
    </div>
</template>

API Reference

Props

PropertyDescriptionTypeDefault
modelValueInput content, used with v-model.stringundefined
modelModifiersThe v-model modifiers, passed by Vue for v-model.trim and the like; declaring them keeps the modifiers off the root element.ModelModifiersundefined
defaultValueInitial content when uncontrolled.stringsemiGlobalDefault("PinCode", "defaultValue")
countNumber of digits.numbersemiDefault("PinCode", "count", 6)
formatFormat limit for a single character: number allows digits only, mixed allows digits and letters, and a regular expression or function judges each character.PinCodeFormatundefined
autofocusWhether to focus the first input on mount. Turn it on only when the user has just entered the code step: focus moving at page load makes screen readers skip the content before it.booleansemiDefault("PinCode", "autofocus", false)
disabledWhether the input is disabled.booleansemiGlobalDefault("PinCode", "disabled")
sizeInput size: large, default or small.SizesemiGlobalDefault("PinCode", "size")
validateStatusValidation status, passed to every input; error shows the error style."default" | "error" | "warning" | "success"semiGlobalDefault("PinCode", "validateStatus")

Events

EventDescriptionCallback parameters
update:modelValueEmitted when the content changes, for v-model to write back.[value: string]
changeEmitted when the content changes, with the current content.[value: string]
completeEmitted once all digits are entered, with the current content.[value: string]
focusEmitted when focus enters the code from outside; moving between the inputs does not emit it.[event: FocusEvent]
blurEmitted when focus leaves the whole code.[event: FocusEvent]

Slots

SlotDescriptionScope parameters
None

Exposes

NameDescriptionType
focusFocuses the input at index, counted from 0 and ignored when out of range, with the caret after its character.Type(index: number) => void
blurBlurs the input at index, counted from 0 and ignored when out of range.Type(index: number) => void

class, style, aria-label, aria-labelledby and data-* land on the role="group" root element through attrs. id lands on the first input box, so <label for> points at the first digit. aria-describedby, aria-errormessage, aria-invalid, aria-required and tabindex land on every input box. name, insetLabel and insetLabelId are discarded.

Call focus(index) and blur(index) through the template ref. The index is counted from 0 and ignored when out of range; after focus the caret sits after that digit's character.

Accessibility

ARIA

  • The root element is role="group", named through aria-label or aria-labelledby; pass aria-label when there is no visible label, otherwise the group has no name.
  • Each input box takes its accessible name from the locale, for example "Digit 1 of 6", which follows count and the box index, so nothing needs to be set by hand.
  • aria-describedby, aria-errormessage, aria-invalid and aria-required land on every input box; validateStatus is passed to every input box.
  • With format set to "number" the input boxes use the numeric soft keyboard (inputmode="numeric"); otherwise the text keyboard.

Keyboard and Focus

  • Each box is its own input; after a valid character is entered, focus moves to the next box, and entering the last box blurs it. The filled characters always run from the first box without gaps, so a character typed after an empty box lands in the first empty box. Tab and Shift + Tab move between boxes.
  • Left Arrow and Right Arrow move focus between boxes. Backspace and Delete both delete the character in the current box and the following characters move forward; Backspace also moves focus to the previous box.
  • Pasting a whole code fills the boxes by character from the current box, and stops at the first invalid character.
  • autoFocus (autofocus in Vue) should be turned on only when the user has just entered the code step: focus moving at page load makes screen readers skip the content before it.