A11y OTP Field

Example 07 · Composed add-on

Resend code flow

Compose a real resend button, a cooldown, and polite status updates around the OTP field while keeping transport and rate-limit policy outside the core component.

Live example

Request a new code

Activate the resend button once. It becomes disabled for 30 seconds and the polite status region explains when another request is available.

Resend logic is handled outside the core component.

Implementation

Build this example

Place the button and status region inside the root, then keep the resend policy in application code. This demo dispatches a namespaced custom event for integration.

JavaScript

Dispatch an integration event, disable the action, and announce both cooldown states.

import { createA11yOtpField } from "./dist/index.js";

const root = document.querySelector("[data-a11y-otp]");
const otp = createA11yOtpField(root);
const button = root.querySelector(".a11y-otp__resend");
const status = root.querySelector(".a11y-otp__status");

button.addEventListener("click", () => {
  root.dispatchEvent(new CustomEvent("a11y-otp-field:resend", {
    detail: { value: otp.getValue() }
  }));
  button.disabled = true;
  status.textContent = "You can request a new code in 30 seconds.";

  setTimeout(() => {
    button.disabled = false;
    status.textContent = "You can request a new code again now.";
  }, 30000);
});

HTML

The resend action is a separate button; it is not part of the input itself.

<div class="a11y-otp" data-a11y-otp
  data-otp-length="6" data-otp-type="numeric">
  <label for="resend-code">Verification code</label>
  <p id="resend-code-hint">
    Resend logic is handled outside the component.
  </p>
  <div class="a11y-otp__control">
    <input class="a11y-otp__input" id="resend-code"
      name="resendCode" type="text" inputmode="numeric"
      autocomplete="one-time-code" maxlength="6"
      aria-describedby="resend-code-hint" />
  </div>
  <div class="a11y-otp__actions">
    <button class="a11y-otp__resend" type="button">
      Resend code
    </button>
  </div>
  <p class="a11y-otp__error"></p>
  <p class="a11y-otp__status" aria-live="polite"></p>
</div>