dile-otp-input
One-time-password / 2FA code input Web Component. Shows one box per character and automatically moves the focus to the next box while typing, just like the codes generated by authenticator apps (Google Authenticator, etc).
<dile-otp-input label="Enter your code" name="code"></dile-otp-input>
Install
npm install @dile/ui
Usage
Import the component.
import '@dile/ui/components/otp-input/otp-input.js';
Use the component
<dile-otp-input
name="code"
label="Enter your authentication code"
length="6"
></dile-otp-input>
Properties
- name: the name of the field. This helps identify which element triggered an event, and is the field name used on form submission.
- label: the element label
- length: number of characters/boxes of the code. Defaults to
6 - value: the current code. This property syncs to every box
- disabled: when true, the element is disabled
- readonly: when true, is not editable
- errored: when true, the element is marked as error
- message: optionally, the element can display a message
- hideErrorOnInput: when true, the errored state turns off when the user changes the value and the message is cleared
- focusOnStart: when true, set application focus to this component after initialization
Form Integration
This component is a form-associated element, meaning it integrates seamlessly with native HTML forms. The value is automatically synchronized with the form state, so it can be read from a submitted FormData using the name property, exactly like dile-input.
Useful Methods
- focus(): focus the first empty box, or the last box if the code is already complete
- clearError(): removes the errored state and clears the error message
- clear(): empties the value and focuses the first box
Events
- enter-pressed: dispatched when the user presses enter on any box.
otpField.addEventListener('enter-pressed', (e) => {
console.log('enter-pressed event, value: ', e.target.value);
});
-
element-changed: dispatched when the value changes. The event detail carries the element
nameandvalueproperties. -
dile-otp-input-changed: dispatched alongside
element-changedwhenever the value changes. The event detail carriesnameandvalue. -
dile-otp-input-completed: dispatched once, the moment the last empty box gets filled in and the code reaches its full
length. This is the event to listen to if you want to trigger an automatic form submission as soon as the user finishes typing the code.
otpField.addEventListener('dile-otp-input-completed', (e) => {
console.log('code complete: ', e.detail.value);
// e.g. submit the form automatically
});
Styling
| Custom property | Description | Default |
|---|---|---|
| --dile-otp-input-box-size | Width and height of each box | 2.5em |
| --dile-otp-input-gap | Space between boxes | 8px |
| --dile-otp-input-border-width | Box border width | 1px |
| --dile-otp-input-border-color | Box border color | #888 |
| --dile-otp-input-border-radius | Box border radius | 5px |
| --dile-otp-input-error-border-color | Box border color on errored property = true | #c00 |
| --dile-otp-input-focus-border-color | Box border color on focus | #6af |
| --dile-otp-input-disabled-border-color | Box border color when disabled | #eee |
| --dile-otp-input-font-size | Box font size | 1.25em |
| --dile-otp-input-background-color | Box background color | #fff |
| --dile-otp-input-error-background-color | Box background color on a errored element | --dile-otp-input-background-color or #fff |
| --dile-otp-input-color | Box text color | #303030 |
| --dile-otp-input-label-font-size | Font size for the label | 1em |
| --dile-otp-input-label-color | Color for the label text | #59e |
| --dile-otp-input-label-font-weight | Label text font weight | normal |
| --dile-otp-input-label-margin-bottom | Label margin bottom | 4px |
| --dile-input-message-padding-top | Space from boxes to message | 4px |
| --dile-input-message-font-size | Message font size | 0.875rem |
| --dile-input-message-color | Message text color | #888 |
| --dile-input-message-error-color | Message text color on errored state | #c00 |
dile-otp-input demos
Default
<script type="module">
import '@dile/ui/components/otp-input/otp-input.js';
</script>
<dile-otp-input
name="code"
label="Enter your authentication code"
></dile-otp-input>
Completed event
<script type="module">
import { LitElement, html, css } from 'lit';
class MyComponent extends LitElement {
static get properties() {
return { result: { type: String } };
}
constructor() {
super();
this.result = '';
}
render() {
return html`
<dile-otp-input
name="code"
label="Auto-submits when complete"
@dile-otp-input-completed="${(e) => this.result = 'Completed with value: ' + e.detail.value}"
></dile-otp-input>
<p>${this.result}</p>
`
}
}
customElements.define('my-component', MyComponent);
</script>
<my-component></my-component>
Errored input
<dile-otp-input
name="code"
label="Enter your code"
errored
message="Invalid code, try again"
></dile-otp-input>
Custom length
<dile-otp-input
name="code"
label="4 digit code"
length="4"
></dile-otp-input>
Styled
<style>
.styled {
--dile-otp-input-label-color: #6d3d6c;
--dile-otp-input-label-font-weight: bold;
--dile-otp-input-border-radius: 0;
--dile-otp-input-border-color: #6d3d6c;
--dile-otp-input-border-width: 2px;
--dile-otp-input-box-size: 3em;
--dile-otp-input-gap: 12px;
}
</style>
<dile-otp-input class="styled" name="code" label="Styled"></dile-otp-input>
dile-components