Pin Input
A pin input component for entering verification codes, PINs, or OTP values with individual character inputs.
Anatomy
<script>
import { PinInput } from "@saas-ui/svelte/components/pin-input";
</script>
<PinInput count={4} otp />Examples
Alphanumeric Accessibility
numeric, alphabetic, or alphanumeric.
<Stack gap={4}>
<HStack align="center" gap={4}>
<Text size="xs" class="w-24">numeric</Text>
<PinInput type="numeric" />
</HStack>
<HStack align="center" gap={4}>
<Text size="xs" class="w-24">alphabetic</Text>
<PinInput type="alphabetic" />
</HStack>
<HStack align="center" gap={4}>
<Text size="xs" class="w-24">alphanumeric</Text>
<PinInput type="alphanumeric" />
</HStack>
</Stack> Attached Accessibility
attached prop.
<PinInput attached /> Basic Accessibility
<PinInput /> Colours Accessibility
colour prop.
<Stack gap={4}>
{#each colours as colour}
<HStack align="center" gap={4}>
<Text size="xs" class="w-16">{colour}</Text>
<PinInput {colour} />
</HStack>
{/each}
</Stack> Controlled Accessibility
<Stack gap={4}>
<PinInput
bind:value={controlledValue}
onValueComplete={(details) =>
console.log("Complete:", details.valueAsString)}
/>
<Text size="sm">Value: {controlledValue.join("") || "(empty)"}</Text>
</Stack> Count Accessibility
<Stack gap={4}>
<HStack align="center" gap={4}>
<Text size="xs" class="w-16">4 digits</Text>
<PinInput count={4} />
</HStack>
<HStack align="center" gap={4}>
<Text size="xs" class="w-16">6 digits</Text>
<PinInput count={6} />
</HStack>
<HStack align="center" gap={4}>
<Text size="xs" class="w-16">8 digits</Text>
<PinInput count={8} />
</HStack>
</Stack> Disabled Accessibility
<PinInput disabled /> Invalid Accessibility
invalid prop to display validation error styling.
<Field.Root invalid>
<Field.Label>Verification Code</Field.Label>
<PinInput />
<Field.ErrorText>Invalid verification code</Field.ErrorText>
</Field.Root> Mask Accessibility
<PinInput mask /> One Time Code Accessibility
<PinInput otp /> Placeholder Accessibility
<PinInput placeholder="-" /> Sizes Accessibility
xs, sm, md, lg.
<Stack gap={4}>
{#each pinInputSizes as size}
<HStack align="center" gap={4}>
<Text size="xs" class="min-w-[3ch]">{size}</Text>
<PinInput {size} />
</HStack>
{/each}
</Stack> Variants Accessibility
outline, subtle, flushed.
<Stack gap={4}>
{#each inputVariants as variant}
<HStack align="center" gap={4}>
<Text size="xs" class="w-16">{variant}</Text>
<PinInput {variant} />
</HStack>
{/each}
</Stack> With Field Accessibility
Field wrapper for label and helper text support.
<form
class="max-w-sm"
onsubmit={(e) => {
e.preventDefault();
console.log("Form submitted");
}}
>
<Stack gap={4} align="start">
<Field.Root>
<Field.Label>Enter OTP</Field.Label>
<PinInput otp />
</Field.Root>
<Button type="submit">Verify</Button>
</Stack>
</form>Props
PinInput
A composed pin input component that renders individual character inputs for entering codes.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "outline" | "subtle" | "flushed" | "outline" | The visual style of the pin input. |
size | "xs" | "sm" | "md" | "lg" | "md" | The size of the pin input. |
colour | ColourName | "gray" | The colour theme of the pin input. |
invalid | boolean | false | Whether the pin input is in an invalid state. |
disabled | boolean | false | Whether the pin input is disabled. |
placeholder | string | "○" | The placeholder text for each input. |
value | string[] | - | The current value of the pin input (bindable). |
defaultValue | string[] | - | The default value of the pin input. |
onValueChange | (details: { value: string[]; valueAsString: string }) => void | - | Callback when the value changes. |
onValueComplete | (details: { value: string[]; valueAsString: string }) => void | - | Callback when all inputs have valid values. |
onValueInvalid | (details: { value: string; index: number }) => void | - | Callback when an invalid value is entered. |
count | number | 4 | The number of pin inputs to render. |
type | "numeric" | "alphabetic" | "alphanumeric" | "numeric" | The type of value the pin input should allow. |
otp | boolean | false | Whether the pin input is in one-time code (OTP) mode. |
mask | boolean | false | Whether to mask the input value (like password). |
attached | boolean | false | Whether the inputs are visually attached to each other. |
autoFocus | boolean | false | Whether to auto-focus the first input. |
blurOnComplete | boolean | false | Whether to blur on complete. |
selectOnFocus | boolean | true | Whether to select input value on focus. |
name | string | - | The name attribute for form submission. |
required | boolean | false | Whether the pin input is required. |
readOnly | boolean | false | Whether the pin input is read-only. |
class | string | - | Additional CSS classes to apply. |
style | string | - | Inline styles. |
id | string | - | The id of the pin input. |
aria-label | string | - | Accessible label for the pin input group. |