Input OTP

A specialized input component for one-time password entry

Basic Usage

Default 6-digit OTP input with two groups separated by a dash.


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4
5	let basicValue = $state("");
6</script>
7
8<InputOTP maxlength={6} groups={2} bind:value={basicValue} />
9{#if basicValue}
10	<p class="text-sm text-muted-foreground">Value: {basicValue}</p>
11{/if}

Variants

Available visual styles for the OTP input.

default

outline

underline


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7	<div class="space-y-2">
8		<p class="text-sm font-medium">Default</p>
9		<InputOTP maxlength={6} groups={2} variant="default" />
10	</div>
11	<div class="space-y-2">
12		<p class="text-sm font-medium">Outline</p>
13		<InputOTP maxlength={6} groups={2} variant="outline" />
14	</div>
15	<div class="space-y-2">
16		<p class="text-sm font-medium">Underline</p>
17		<InputOTP maxlength={6} groups={2} variant="underline" />
18	</div>
19</div>

Sizes

Different size options for the OTP input.

sm

default

lg


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7	<div class="space-y-2">
8		<p class="text-sm font-medium">Small</p>
9		<InputOTP maxlength={6} groups={1} size="sm" />
10	</div>
11	<div class="space-y-2">
12		<p class="text-sm font-medium">Default</p>
13		<InputOTP maxlength={6} groups={1} size="default" />
14	</div>
15	<div class="space-y-2">
16		<p class="text-sm font-medium">Large</p>
17		<InputOTP maxlength={6} groups={1} size="lg" />
18	</div>
19</div>

Groups Configuration

Control how digits are grouped with automatic separators.

Single Group (4 digits)

Two Groups (6 digits)

Three Groups (6 digits)

Without Separators


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7	<!-- Single Group (4 digits) -->
8	<InputOTP maxlength={4} groups={1} />
9
10	<!-- Two Groups (6 digits) -->
11	<InputOTP maxlength={6} groups={2} />
12
13	<!-- Three Groups (6 digits) -->
14	<InputOTP maxlength={6} groups={3} />
15
16	<!-- Without Separators -->
17	<InputOTP maxlength={6} groups={2} showSeparator={false} />
18</div>

Error State

OTP input showing an error state with optional error message.


Code Svelte
1
2<script lang="ts">
3	import { InputOTP, Field } from "@kareyes/aether";
4
5	let errorValue = $state("");
6	let showError = $state(false);
7</script>
8
9<Field label="Verification Code" error={showError ? "Invalid verification code. Please try again." : undefined}>
10	<InputOTP
11		maxlength={6}
12		groups={2}
13		bind:value={errorValue}
14		error={showError}
15	/>
16	<button
17		type="button"
18		class="text-sm px-3 py-1.5 rounded-md bg-destructive text-destructive-foreground hover:bg-destructive/90"
19		onclick={() => showError = !showError}
20	>
21		Toggle Error: {showError ? 'On' : 'Off'}
22	</button>
23</Field>

onError Callback

Get notified when the error state changes.

Error callback triggered: No

(Error shows when value is partially filled)


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4
5	let errorCallbackValue = $state("");
6	let errorCallbackTriggered = $state(false);
7
8	function handleErrorChange(hasError: boolean) {
9		errorCallbackTriggered = hasError;
10	}
11</script>
12
13<InputOTP
14	maxlength={6}
15	groups={2}
16	bind:value={errorCallbackValue}
17	error={errorCallbackValue.length > 0 && errorCallbackValue.length < 6}
18	onError={handleErrorChange}
19/>
20<p class="text-sm text-muted-foreground">
21	Error callback triggered:
22	<span class={errorCallbackTriggered ? "text-destructive" : "text-green-600"}>
23		{errorCallbackTriggered ? 'Yes' : 'No'}
24	</span>
25</p>

Disabled State

OTP input in disabled state.


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4</script>
5
6<InputOTP maxlength={6} groups={2} disabled />

Complete Handler

Callback triggered when all slots are filled.


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4
5	let completedValue = $state("");
6	let isComplete = $state(false);
7
8	function handleComplete(value: string) {
9		isComplete = true;
10		setTimeout(() => { isComplete = false; }, 2000);
11	}
12</script>
13
14<InputOTP
15	maxlength={6}
16	groups={2}
17	bind:value={completedValue}
18	onComplete={handleComplete}
19/>
20{#if isComplete}
21	<p class="text-sm text-green-600">OTP Complete: {completedValue}</p>
22{/if}

Variant + Size Combinations

Combining different variants with sizes.

Outline + Small

Default + Default

Underline + Large


Code Svelte
1
2<script lang="ts">
3	import { InputOTP } from "@kareyes/aether";
4</script>
5
6<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
7	<div class="space-y-2">
8		<p class="text-sm font-medium">Outline + Small</p>
9		<InputOTP maxlength={4} groups={1} variant="outline" size="sm" />
10	</div>
11	<div class="space-y-2">
12		<p class="text-sm font-medium">Default + Default</p>
13		<InputOTP maxlength={4} groups={1} variant="default" size="default" />
14	</div>
15	<div class="space-y-2">
16		<p class="text-sm font-medium">Underline + Large</p>
17		<InputOTP maxlength={4} groups={1} variant="underline" size="lg" />
18	</div>
19</div>