Demos
How to import
<script lang="ts">
import { Button, PinCode, TypographyText } from '@fibrae/semi-ui-svelte';
</script>
Basic usage
Code
<script lang="ts">
import { PinCode } from '@fibrae/semi-ui-svelte';
const onComplete = (value: string) => console.log('pincode: ', value);
const onChange = (value: string) => console.log(value);
</script>
<div>
<PinCode aria-label="Verification code, small" {onChange} {onComplete} size="small" value="123456" />
<br />
<PinCode aria-label="Verification code, default" {onChange} {onComplete} size="default" value="123456" />
<br />
<PinCode aria-label="Verification code, large" {onChange} {onComplete} size="large" value="123456" />
</div>Controlled
Use bind:value to bind the verification code string; a plain value is the initial content, and there is no defaultValue
Code
<script lang="ts">
import { Button, PinCode } from '@fibrae/semi-ui-svelte';
let value = $state('69af41');
const setRandomValue = () => {
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>
<div>
<Button onclick={setRandomValue}>Set Random Value</Button>
<br />
<br />
<PinCode aria-label="Verification code" bind:value format="mixed" {onChange} {onComplete} />
</div>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 lang="ts">
import { PinCode } from '@fibrae/semi-ui-svelte';
const onComplete = (value: string) => console.log('pincode: ', value);
const onChange = (value: string) => console.log(value);
</script>
<PinCode aria-label="Verification code" count={4} {onChange} {onComplete} size="large" value="6688" />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 lang="ts">
import { PinCode, TypographyText } from '@fibrae/semi-ui-svelte';
const onComplete = (value: string) => console.log('pincode: ', value);
const isLower = (char: string) => /[a-z]/.test(char);
</script>
<div>
<TypographyText id="pincode-format-number">纯数字</TypographyText>
<PinCode aria-labelledby="pincode-format-number" format="number" {onComplete} />
<br />
<TypographyText id="pincode-format-mixed">字母和数字</TypographyText>
<PinCode aria-labelledby="pincode-format-mixed" format="mixed" {onComplete} />
<br />
<TypographyText id="pincode-format-upper">只大写字母</TypographyText>
<PinCode aria-labelledby="pincode-format-upper" format={/[A-Z]/} {onComplete} />
<br />
<TypographyText id="pincode-format-lower">只小写字母(函数判断)</TypographyText>
<PinCode aria-labelledby="pincode-format-lower" format={isLower} {onComplete} />
</div>Manual focus and blur
Get the component instance with bind:this and call focus(index) and blur(index); the argument is the index of the corresponding Input, counted from 0
Code
<script lang="ts">
import { Button, PinCode } from '@fibrae/semi-ui-svelte';
let value = $state('69af41');
let pinCode = $state<ReturnType<typeof PinCode>>();
const onComplete = (code: string) => console.log('pincode: ', code);
const onChange = (code: string) => console.log(code);
</script>
<div>
<Button onclick={() => pinCode?.focus(2)}>Focus Third Input</Button>
<br />
<br />
<PinCode aria-label="Verification code" bind:this={pinCode} bind:value format="mixed" {onChange} {onComplete} />
</div>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| autofocus | Whether 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. | boolean | false |
| count | Number of digits. | number | 6 |
| disabled | Whether the input is disabled. | boolean | - |
| format | Format limit for a single character: number allows digits only, mixed allows digits and letters, and a regular expression or function judges each character. | PinCodeFormat | "number" |
| onBlur | Called when focus leaves the whole code. | Type(event: FocusEvent) => void | - |
| onChange | Called when the content changes, with the current content. | Type(value: string) => void | - |
| onComplete | Called once all digits are entered, with the current content. | Type(value: string) => void | - |
| onFocus | Called when focus enters the code from outside; moving between the inputs does not call it. | Type(event: FocusEvent) => void | - |
| size | Input size: large, default or small. | InputSize | - |
| validateStatus | Validation status, passed to every input; error shows the error style. | ValidateStatus | - |
| value | Input content; bind it with bind:value. bind:value={get, set} makes it fully controlled; a plain value is the initial value. | string | - |
Methods
| Method | Description | Type |
|---|---|---|
| blur | Blurs the input at index, counted from 0 and ignored when out of range. | Type(index: number) => void |
| focus | Focuses the input at index, counted from 0 and ignored when out of range, with the caret after its character. | Type(index: number) => void |
class, style (a string), aria-label, aria-labelledby and data-* land on the role="group" root element. 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. onFocus and onBlur are counted for the whole code. autofocus focuses the first input box on mount and defaults to false; turn it on only when the user has just entered the code step.
Accessibility
ARIA
- The root element is
role="group", named througharia-labeloraria-labelledby; passaria-labelwhen 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
countand the box index, so nothing needs to be set by hand. aria-describedby,aria-errormessage,aria-invalidandaria-requiredland on every input box;validateStatusis passed to every input box.- With
formatset 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.
TabandShift+Tabmove between boxes. Left ArrowandRight Arrowmove focus between boxes.BackspaceandDeleteboth delete the character in the current box and the following characters move forward;Backspacealso 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(autofocusin 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.