Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsForm Blocks

OTP Input

One-time password input with individual digit cells. Supports three visual variants, five sizes, five intents, masking, separator groups, numeric/alphanumeric/alphabetic input types, and full RTL/LTR support.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { OtpInput, OtpInputSeparator } from "@tessinaui/ui";
{/* Default — 6-digit numeric */}
<OtpInput length={6} onComplete={(code) => console.log(code)} />

{/* Controlled */}
<OtpInput length={6} value={code} onValueChange={setCode} />

{/* 4-digit PIN */}
<OtpInput length={4} />

{/* Masked (password-style) */}
<OtpInput length={6} mask />

{/* Filled variant */}
<OtpInput length={6} variant="filled" />

{/* Underline variant */}
<OtpInput length={6} variant="underline" rounded="none" />

{/* With separator — 3 + 3 groups */}
<OtpInput
  length={6}
  separator={<OtpInputSeparator />}
  separatorAfter={2}
/>

{/* Multiple separators */}
<OtpInput
  length={6}
  separator={<OtpInputSeparator>·</OtpInputSeparator>}
  separatorAfter={[1, 3]}
/>

{/* Alphanumeric */}
<OtpInput length={6} type="alphanumeric" />

{/* Error state */}
<OtpInput length={6} intent="error" />

{/* Auto-focus on mount */}
<OtpInput length={6} autoFocus />

{/* RTL */}
<OtpInput length={6} dir="rtl" />

Showcase

Variants

VariantDescription
outlineIndividual bordered cells — the classic OTP look
filledCells with a background fill; intent colours tint the fill
underlineBottom-border only for a minimal, form-field feel

Props

PropTypeDefaultDescription
lengthnumber6Number of input cells
valuestring—Controlled value
defaultValuestring""Uncontrolled initial value
onValueChange(value: string) => void—Called on every character change
onComplete(value: string) => void—Called when all cells are filled
variantoutline | filled | underlineoutlineVisual style
sizexs | sm | md | lg | xlmdCell size
intentnone | error | warning | success | infononeColour intent
roundednone | sm | md | lg | fullmdCell corner radius
typenumeric | alphanumeric | alphabeticnumericAllowed character set
maskbooleanfalseShow bullets instead of characters
separatorReactNode—Element rendered between groups
separatorAfternumber | number[]—Cell index (0-based) after which to insert the separator
placeholderstring—Character shown in empty cells (e.g. ·, ○, –)
disabledbooleanfalseDisables all cells
readOnlybooleanfalseCells are read-only
autoFocusbooleanfalseFocus the first empty cell on mount
dirltr | rtlltrText direction
aria-labelstring"One-time password"Accessible label for the group

Keyboard navigation

KeyAction
0–9 / A–ZEnter a character and advance to next cell
BackspaceClear current cell, or move back and clear previous
DeleteClear current cell without moving focus
← / →Move focus between cells
HomeFocus first cell
EndFocus last cell
PasteDistribute clipboard content across cells from the focused position

Accessibility

  • The group container uses role="group" with an aria-label
  • Each individual input has aria-label="Digit N"
  • autocomplete="one-time-code" is set automatically for numeric inputs
  • Focus is fully keyboard-navigable
  • Disabled state is communicated via disabled attribute on each input

Time Picker

Three time-picker variants — a drum-roll wheel, a typed HH:MM input field, and a button-triggered popover. Supports 12h/24h formats, seconds, configurable minute steps, all intent colours, RTL, and keyboard navigation.

File Upload

Drag-and-drop file upload with file list, progress, validation, four visual variants, five sizes, intent colours, and per-file status (idle/uploading/success/error).

On this page

PlaygroundInstallationUsageShowcaseVariantsPropsKeyboard navigationAccessibility