npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

a11y-otp-field

v1.0.0

Published

Accessible, progressively enhanced one-time-code input with decorative visual slots.

Readme

A11y OTP Field

An accessible, progressively enhanced one-time-code field. One native text input owns the real form value; the visual character slots are decorative and hidden from assistive technology.

Installation

npm install a11y-otp-field
# or: pnpm add a11y-otp-field
# or: yarn add a11y-otp-field

Usage

import { createA11yOtpField } from "a11y-otp-field";
import "a11y-otp-field/styles.css";

const root = document.querySelector("[data-a11y-otp]");
if (root instanceof HTMLElement) {
  const otp = createA11yOtpField(root, { length: 6 });
  console.log(otp.getValue());
}

Importing the package never initializes fields automatically. Use createA11yOtpField() for one field or explicitly call initA11yOtpFields() for all matching fields.

CSS

Import a11y-otp-field/styles.css for the default slot presentation. Public custom properties such as --a11y-otp-slot-size, --a11y-otp-focus-color, and --a11y-otp-error-color can be overridden on .a11y-otp.

HTML structure

<div class="a11y-otp" data-a11y-otp data-otp-length="6">
  <label class="a11y-otp__label" for="verification-code">Verification code</label>
  <p class="a11y-otp__hint" id="verification-code-hint">Enter the six-digit code.</p>
  <div class="a11y-otp__control" data-a11y-otp-control>
    <input
      class="a11y-otp__input"
      data-a11y-otp-input
      id="verification-code"
      name="verificationCode"
      type="text"
      inputmode="numeric"
      autocomplete="one-time-code"
      pattern="[0-9]*"
      maxlength="6"
      aria-describedby="verification-code-hint"
    />
  </div>
  <p class="a11y-otp__error" data-a11y-otp-error id="verification-code-error"></p>
  <p class="a11y-otp__status" data-a11y-otp-status aria-live="polite"></p>
</div>

The slots are generated during enhancement. Do not create one input per character.

API

Creation

  • createA11yOtpField(root, options) enhances one root and returns its existing instance if called again.
  • initA11yOtpFields(options?, scope?) enhances every [data-a11y-otp] within a scope.
  • getA11yOtpField(root) returns an existing instance or null.
  • A11yOtpField is the plugin-specific class.

Options

  • length (default 6, maximum 64)
  • type: numeric, alphanumeric, or custom
  • groups: decorative visual grouping, for example [3, 3]
  • mask, revealLast, or privacyMode
  • uppercase and allowSeparators
  • validateOn: submit, blur, or manual
  • normalizer for custom values
  • messages for validation and status text
  • clearErrorOnInput
  • autoSubmit (default false) and autoSubmitDelay

Instance methods

getValue(), setValue(), clear(), focus(), blur(), enable(), disable(), setReadonly(), setMasked(), setError(), clearError(), validate(), and destroy().

Events

The root dispatches bubbling a11y-otp-field:init, input, change, complete, incomplete, paste, error, clear, and destroy events. Each event detail includes the plugin instance and current state. The plugin does not emit analytics or persist codes.

Accessibility notes

  • The real value lives in one labeled native type="text" input.
  • Numeric mode uses inputmode="numeric"; the component never uses type="number".
  • autocomplete="one-time-code" is preserved or added for OTP autofill.
  • Slots are decorative and receive aria-hidden="true".
  • Native keyboard editing, selection, focus, and clipboard commands remain available.
  • Paste is never prevented; formatted pasted codes are normalized after the native paste event.
  • Errors synchronize visible text, aria-invalid, and aria-describedby.
  • Auto-submit is disabled by default and must be explicitly enabled.
  • The unenhanced form remains usable when JavaScript is unavailable.
  • destroy() restores attributes and author-provided slot content that existed before enhancement.
  • Masking only changes decorative output; do not treat it as protection from scripts or browser tools.

Examples

Build package output before serving the source examples:

npm run build:dist
python3 -m http.server 4173

Docs metadata

import { docs } from "a11y-otp-field/docs";

The named export contains package details, usage, selectors, keyboard behavior, API entries, and example metadata for documentation aggregators.

GitHub Pages

Generate the committed Pages site with:

npm run pages:build

docs/ is generated output and must not be edited by hand. In GitHub, configure Settings → Pages → Build and deployment → Deploy from a branch → main/docs. The expected project URL is https://vmitsaras.github.io/A11y-OTP-Field/.

The npm package build remains in ignored root dist/; only the runtime copy under committed docs/dist/ is published by Pages.

Development

npm run pages:build
npm run typecheck
npm test
npm run pack:check

License

MIT © Vasileios Mitsaras