Skip to content

Repository files navigation

Password Input

tests types module install size GZip size semantic versioning Common Changelog license

A password input with less style than password-field.

Accessible by default — aria-* attributes, the id attribute, and a label attribute, if present, are all handled correctly.

See a live demo

Contents

Install

npm i -S @substrate-system/password-input

API

This exposes ESM and common JS via package.json exports field.

ESM

import { PasswordInput } from '@substrate-system/password-input'

Common JS

require('@substrate-system/password-input')

Attributes

You can pass attributes on <password-input>, and the component maps them to the inner <input> as described below. Do not pass the type attribute. That is controlled by the component.

Attribute Should pass? Behavior
label Optional, recommended Renders visible label text above the input.
visible Optional If present, initial state is visible text (type="text"). If absent, initial state is hidden (type="password").
id Recommended when used with external labels/help text Moved to the inner <input id="..."> and removed from <password-input>.
aria-* Recommended for accessibility Any supported ARIA attribute passed on <password-input> is moved to the inner <input> and removed from <password-input>.
Standard input attributes (name, placeholder, value, autocomplete, required, disabled, readonly, minlength, maxlength, pattern, etc.) Optional as needed Forwarded to the inner <input>.

Supported aria-* attributes

aria-activedescendant, aria-atomic, aria-autocomplete, aria-braillelabel, aria-brailleroledescription, aria-busy, aria-checked, aria-colcount, aria-colindex, aria-colindextext, aria-colspan, aria-controls, aria-current, aria-describedby, aria-description, aria-details, aria-disabled, aria-dropeffect, aria-errormessage, aria-expanded, aria-flowto, aria-grabbed, aria-haspopup, aria-hidden, aria-invalid, aria-keyshortcuts, aria-label, aria-labelledby, aria-level, aria-live, aria-modal, aria-multiline, aria-multiselectable, aria-orientation, aria-owns, aria-placeholder, aria-posinset, aria-pressed, aria-readonly, aria-relevant, aria-required, aria-roledescription, aria-rowcount, aria-rowindex, aria-rowindextext, aria-rowspan, aria-selected, aria-setsize, aria-sort, aria-valuemax, aria-valuemin, aria-valuenow, aria-valuetext

Usage Notes

  • Do not pass type. The component controls type internally (password or text) based on the visibility toggle.
  • If an ARIA attribute changes later (setAttribute('aria-label', '...') on <password-input>), the inner <input> is updated through attributeChangedCallback.

Example

<password-input
    id="account-password"
    label="New Password"
    name="password"
    placeholder="At least 12 characters"
    autocomplete="new-password"
    required
    minlength="12"
    aria-describedby="password-help">
</password-input>
<p id="password-help">Use a strong, unique password.</p>

Events

The component emits namespaced custom events whenever its visibility changes. The events bubble, so you can listen on the element itself or on any ancestor.

Event Emitted when
password-input:show The input becomes visible (type="text").
password-input:hide The input becomes hidden (type="password").

Build the event name with the static PasswordInput.event(...) helper, or pass the string directly. ev.target is the <password-input> that changed.

import { PasswordInput } from '@substrate-system/password-input'

const input = document.querySelector('password-input')

input.addEventListener(PasswordInput.event('show'), (ev) => {
    console.log(ev.target.isVisible)  // true
})

There is also a short-hand .on(...) method on the element that namespaces the event name for you:

input.on('hide', (ev) => { /* ... */ })

Example: keep several inputs in sync

Because the events bubble, a single delegated listener can keep every <password-input> on the page in sync — clicking any input's eye button shows or hides them all.

import { PasswordInput } from '@substrate-system/password-input'

function syncVisibility (ev) {
    const visible = ev.target.isVisible
    document.querySelectorAll('password-input').forEach(el => {
        el.isVisible = visible
    })
}

document.addEventListener(PasswordInput.event('show'), syncVisibility)
document.addEventListener(PasswordInput.event('hide'), syncVisibility)

Use

This calls the global function customElements.define. Just import, then use the tag in your HTML.

JS

import '@substrate-system/password-input'

HTML

<div>
    <password-input></password-input>
</div>

pre-built

This package exposes minified JS and CSS files too. Copy them to a location that is accessible to your web server, then link to them in HTML.

copy

cp ./node_modules/@substrate-system/password-input/dist/index.min.js ./public/password-input.min.js
cp ./node_modules/@substrate-system/password-input/dist/style.min.css ./public/password-input.css

HTML

<head>
    <link rel="stylesheet" href="./password-input.css">
</head>
<body>
    <!-- ... -->
    <script type="module" src="./password-input.min.js"></script>
</body>

CSS

Import CSS

import '@substrate-system/password-input/css'

Or minified:

import '@substrate-system/password-input/min/css'

Notes

Implementation notes.

ignoredAriaCallbackNames property

  1. You set an aria-* attribute on <password-input>.
  2. attributeChangedCallback routes to handleChange_aria (index.ts (line 105)).
  3. handleChange_aria copies that value to the inner <input> (index.ts (line 189)).
  4. Then it removes the same aria-* from the host (index.ts (line 194)) so host stays clean.
  5. That removal triggers attributeChangedCallback again with newValue === null.
  6. The guard sees the name in ignoredAriaCallbackNames, deletes it, and returns early (index.ts (line 178)), so it does not remove the attribute from the input/cache.

Without this guard, the second callback would treat the host removal as a real “delete” request and clear the input attribute you just transferred.

About

Password input with fewer opinions

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages