Created
November 22, 2024 21:28
-
-
Save cferdinandi/7d56eb85342ca17bd766bd1660fd8bf9 to your computer and use it in GitHub Desktop.
Progressively Enhanced Web Components. Watch the tutorial: https://youtu.be/Ir70eirsVJ4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Toggle Password</title> | |
<style type="text/css"> | |
body { | |
margin: 1em auto; | |
max-width: 30em; | |
width: 88%; | |
} | |
label, | |
input:not([type="checkbox"]), | |
toggle-password { | |
display: block; | |
width: 100%; | |
} | |
input, | |
toggle-password { | |
margin-bottom: 1em; | |
} | |
toggle-password [aria-pressed="true"] [is-hidden], | |
toggle-password [aria-pressed="false"] [is-visible] { | |
display: none; | |
} | |
toggle-password { | |
background-color: #f7f7f7; | |
padding: 0.5em; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Toggle Password</h1> | |
<form> | |
<!-- A checkbox toggle --> | |
<toggle-password> | |
<label for="password-1">Password</label> | |
<input id="password-1" name="password" type="password" value="test1234"> | |
<label hidden> | |
<input toggle type="checkbox"> | |
Show password | |
</label> | |
</toggle-password> | |
<!-- A button toggle --> | |
<toggle-password> | |
<label for="password-2">Password</label> | |
<input id="password-2" name="password" type="password" value="test1234"> | |
<button toggle hidden> | |
Show password | |
</button> | |
</toggle-password> | |
<!-- Show password fields by default --> | |
<toggle-password visible> | |
<label for="password-3">Password</label> | |
<input id="password-3" name="password" type="password" value="test1234"> | |
<button toggle hidden> | |
<span is-hidden>Show Password</span> | |
<span is-visible>Hide Password</span> | |
</button> | |
</toggle-password> | |
</form> | |
<script src="toggle-password.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
customElements.define('toggle-password', class extends HTMLElement { | |
/** | |
* Instantiate the Web Component | |
*/ | |
constructor () { | |
// Get parent class properties | |
super(); | |
// Define properties | |
this.passwords = this.querySelectorAll('[type="password"]'); | |
this.trigger = this.querySelector('[toggle]'); | |
if (!this.trigger) return; | |
this.type = this.trigger.tagName.toLowerCase(); | |
this.visible = this.hasAttribute('visible'); | |
// Setup the UI | |
this.init(); | |
} | |
/** | |
* Handle events | |
* @param {Event} event The event object | |
*/ | |
handleEvent (event) { | |
this.toggle(); | |
} | |
/** | |
* Show hidden elements and add ARIA | |
*/ | |
init () { | |
// Show hidden toggle | |
let hidden = this.trigger.closest('[hidden]'); | |
if (hidden) { | |
hidden.removeAttribute('hidden'); | |
} | |
// If toggle is a button, add aria-pressed | |
if (this.type === 'button') { | |
this.trigger.setAttribute('aria-pressed', this.visible); | |
this.trigger.setAttribute('type', 'button'); | |
} | |
// If passwords should be visible, show them by default | |
if (this.visible) { | |
this.show(); | |
} | |
// Listen for click events | |
this.trigger.addEventListener('click', this); | |
} | |
/** | |
* Show passwords | |
*/ | |
show () { | |
for (let pw of this.passwords) { | |
pw.type = 'text'; | |
} | |
if (this.type === 'button') { | |
this.trigger.setAttribute('aria-pressed', true); | |
} | |
} | |
/** | |
* Hide password visibility | |
*/ | |
hide () { | |
for (let pw of this.passwords) { | |
pw.type = 'password'; | |
} | |
if (this.type === 'button') { | |
this.trigger.setAttribute('aria-pressed', false); | |
} | |
} | |
/** | |
* Toggle password visibility on or off | |
*/ | |
toggle () { | |
let show = this.type === 'button' ? this.trigger.getAttribute('aria-pressed') === 'false' : this.trigger.checked; | |
if (show) { | |
this.show(); | |
} else { | |
this.hide(); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment