Implementation
Build this example
Copy this markup, initialize its root, then adjust the label, hint, name, and validation flow for your product.
JavaScript
Guard the query before creating the field so the integration fails safely if the expected root is absent.
import { createA11yOtpField } from "../dist/index.js";
const root = document.querySelector("[data-a11y-otp]");
if (root instanceof HTMLElement) {
createA11yOtpField(root);
}
HTML
Keep all semantics on one input and let the component generate its decorative slots.
<form>
<div class="a11y-otp" data-a11y-otp
data-otp-length="6" data-otp-type="numeric">
<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 sent to your phone.
</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></p>
<p class="a11y-otp__status" data-a11y-otp-status
aria-live="polite"></p>
</div>
<button type="submit">Verify code</button>
</form>