Mask Input

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleJSApache-2.0
Installation mix mishka.ui.gen.headless mask_input
Source View Source

Overview of the Phoenix and LiveView Headless Mask Input Component

The Mishka Chelekom Headless Mask Input is a Phoenix function component that renders one text input and formats what the user types to a pattern, such as a phone number or a date. The MaskInput JS hook re-masks the value on every keystroke, before the LiveView phx-change handler reads it, so the server always receives the masked text. The component ships no styling. Its classes come from class.

The pattern is the mask attribute. 9 accepts a digit, a a letter and * a letter or a digit. Every other character is a literal that the hook inserts for the user. Typed characters that do not fit the next slot are skipped, and a literal appears as soon as the group before it is complete.

Base UI Mask Input example - phone number (Phoenix headless)

Base UI Mask Input example - phone number (Phoenix headless)

heex
<.mask_input
  id="baseui-mask-input"
  mask="(999) 999-9999"
  placeholder="(___) ___-____"
  inputmode="numeric"
  class="w-72 rounded-lg border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 outline-none focus:ring-2 focus:ring-neutral-400 dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-100"
/>

Mask patterns

  • (999) 999-9999 for a phone number
  • 99/99/9999 for a date
  • 99/99 for a card expiry
  • aaa-9999 for three letters, a dash and four digits

Clearing the field gives an empty string, with no leftover literals. Characters beyond the end of the mask are dropped.

Attributes

id and mask are required. name is the form field name, value the current text, placeholder the hint shown while the field is empty, and disabled turns the field off. inputmode sets the on-screen keyboard, for example "numeric" for a digit-only mask. The global attributes accept form, maxlength, minlength, readonly, required and any phx-* binding.

Pass value already masked, for example from @form[:phone].value. When the server patches the input, the hook applies the mask to the new value again.

heex
<.form for={@form} id="contact-form" phx-change="validate" phx-submit="save">
  <.mask_input
    id="contact-phone"
    name={@form[:phone].name}
    value={@form[:phone].value}
    mask="(999) 999-9999"
    inputmode="numeric"
    required
    class="w-72 rounded-lg border border-neutral-300 px-3 py-2 text-sm"
  />
</.form>

Accessibility

The element is a native text input with autocomplete="off", so labels, required and validation messages behave as usual. The component renders no label. Wrap it in a <label> or point a <label for> at its id. Use inputmode="numeric" for digit-only patterns so phones open a number pad.