@@ -127,6 +129,7 @@ customElements.define('sm-menu', class extends HTMLElement {
this.collapse = this.collapse.bind(this)
this.toggle = this.toggle.bind(this)
this.handleKeyDown = this.handleKeyDown.bind(this)
+ this.handleClick = this.handleClick.bind(this)
this.handleClickOutside = this.handleClickOutside.bind(this)
}
@@ -155,6 +158,11 @@ customElements.define('sm-menu', class extends HTMLElement {
.onfinish = () => {
this.isOpen = true
this.icon.classList.add('focused')
+ document.addEventListener('mousedown', this.handleClickOutside)
+ const firstElement = this.optionList.firstElementChild.assignedElements().find(el => el.tagName === 'MENU-OPTION')
+ if (firstElement) {
+ firstElement.focus()
+ }
}
}
}
@@ -174,6 +182,7 @@ customElements.define('sm-menu', class extends HTMLElement {
this.isOpen = false
this.icon.classList.remove('focused')
this.optionList.classList.add('hide')
+ document.removeEventListener('mousedown', this.handleClickOutside)
}
}
}
@@ -184,6 +193,13 @@ customElements.define('sm-menu', class extends HTMLElement {
this.collapse()
}
}
+ handleClick(e) {
+ if (e.target === this) {
+ this.toggle()
+ } else {
+ this.collapse()
+ }
+ }
handleKeyDown(e) {
// If key is pressed on menu button
if (e.target === this) {
@@ -191,7 +207,7 @@ customElements.define('sm-menu', class extends HTMLElement {
e.preventDefault()
this.availableOptions[0].focus()
}
- else if (e.key === 'Enter' || e.key === ' ') {
+ else if (e.key === ' ') {
e.preventDefault()
this.toggle()
}
@@ -203,18 +219,18 @@ customElements.define('sm-menu', class extends HTMLElement {
} else {
this.availableOptions[this.availableOptions.length - 1].focus()
}
- }
- else if (e.key === 'ArrowDown') {
+ } else if (e.key === 'ArrowDown') {
e.preventDefault()
if (document.activeElement.nextElementSibling) {
document.activeElement.nextElementSibling.focus()
} else {
this.availableOptions[0].focus()
}
- }
- else if (e.key === 'Enter' || e.key === ' ') {
+ } else if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
e.target.click()
+ this.collapse()
+ this.menu.focus()
}
}
}
@@ -231,12 +247,11 @@ customElements.define('sm-menu', class extends HTMLElement {
this.availableOptions = e.target.assignedElements()
this.containerDimensions = this.optionList.getBoundingClientRect()
});
- this.addEventListener('click', this.toggle)
+ this.addEventListener('click', this.handleClick)
this.addEventListener('keydown', this.handleKeyDown)
- document.addEventListener('mousedown', this.handleClickOutside)
}
disconnectedCallback() {
- this.removeEventListener('click', this.toggle)
+ this.removeEventListener('click', this.handleClick)
this.removeEventListener('keydown', this.handleKeyDown)
document.removeEventListener('mousedown', this.handleClickOutside)
}
@@ -249,17 +264,14 @@ menuOption.innerHTML = `
*{
padding: 0;
margin: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
+ box-sizing: border-box;
}
:host{
- display: -webkit-box;
- display: -ms-flexbox;
display: flex;
+ border-radius: var(--border-radius,0.3rem);
+ overflow: hidden;
}
.option{
- display: -webkit-box;
- display: -ms-flexbox;
display: flex;
min-width: 100%;
padding: var(--padding, 0.6rem 1rem);
@@ -268,10 +280,7 @@ menuOption.innerHTML = `
white-space: nowrap;
outline: none;
user-select: none;
- border-radius: 0.3rem;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
+ align-items: center;
}
:host(:focus){
outline: none;
diff --git a/components/dist/menu.min.js b/components/dist/menu.min.js
index ca23443..90195a4 100644
--- a/components/dist/menu.min.js
+++ b/components/dist/menu.min.js
@@ -1 +1 @@
-const smMenu=document.createElement("template");smMenu.innerHTML='\n\n
',customElements.define("sm-menu",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenu.content.cloneNode(!0)),this.isOpen=!1,this.availableOptions,this.containerDimensions,this.animOptions={duration:200,easing:"ease"},this.optionList=this.shadowRoot.querySelector(".options"),this.menu=this.shadowRoot.querySelector(".menu"),this.icon=this.shadowRoot.querySelector(".icon"),this.expand=this.expand.bind(this),this.collapse=this.collapse.bind(this),this.toggle=this.toggle.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleClickOutside=this.handleClickOutside.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.isOpen||(this.optionList.classList.remove("hide"),this.optionList.animate([{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animOptions).onfinish=(()=>{this.isOpen=!0,this.icon.classList.add("focused")}))}collapse(){this.isOpen&&(this.optionList.animate([{transform:"none",opacity:"1"},{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"}],this.animOptions).onfinish=(()=>{this.isOpen=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide")}))}toggle(){this.isOpen?this.collapse():this.expand()}handleKeyDown(n){n.target===this?"ArrowDown"===n.key?(n.preventDefault(),this.availableOptions[0].focus()):"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),this.toggle()):"ArrowUp"===n.key?(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"===n.key?(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus()):"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),n.target.click())}handleClickOutside(n){this.contains(n.target)||2===n.button||this.collapse()}connectedCallback(){this.setAttribute("role","listbox"),this.setAttribute("aria-label","dropdown menu");const n=this.shadowRoot.querySelector(".options slot");n.addEventListener("slotchange",n=>{this.availableOptions=n.target.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),this.addEventListener("click",this.toggle),this.addEventListener("keydown",this.handleKeyDown),document.addEventListener("mousedown",this.handleClickOutside)}disconnectedCallback(){this.removeEventListener("click",this.toggle),this.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("mousedown",this.handleClickOutside)}});const menuOption=document.createElement("template");menuOption.innerHTML='\n\n
\n \n
',customElements.define("menu-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(menuOption.content.cloneNode(!0))}connectedCallback(){this.setAttribute("role","option"),this.setAttribute("tabindex","0"),this.addEventListener("keyup",n=>{"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),this.click())})}});
\ No newline at end of file
+const smMenu=document.createElement("template");smMenu.innerHTML='\n\n
',customElements.define("sm-menu",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenu.content.cloneNode(!0)),this.isOpen=!1,this.availableOptions,this.containerDimensions,this.animOptions={duration:200,easing:"ease"},this.optionList=this.shadowRoot.querySelector(".options"),this.menu=this.shadowRoot.querySelector(".menu"),this.icon=this.shadowRoot.querySelector(".icon"),this.expand=this.expand.bind(this),this.collapse=this.collapse.bind(this),this.toggle=this.toggle.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleClick=this.handleClick.bind(this),this.handleClickOutside=this.handleClickOutside.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.isOpen||(this.optionList.classList.remove("hide"),this.optionList.animate([{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animOptions).onfinish=(()=>{this.isOpen=!0,this.icon.classList.add("focused"),document.addEventListener("mousedown",this.handleClickOutside);const n=this.optionList.firstElementChild.assignedElements().find(n=>"MENU-OPTION"===n.tagName);n&&n.focus()}))}collapse(){this.isOpen&&(this.optionList.animate([{transform:"none",opacity:"1"},{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"}],this.animOptions).onfinish=(()=>{this.isOpen=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide"),document.removeEventListener("mousedown",this.handleClickOutside)}))}toggle(){this.isOpen?this.collapse():this.expand()}handleClick(n){n.target===this?this.toggle():this.collapse()}handleKeyDown(n){n.target===this?"ArrowDown"===n.key?(n.preventDefault(),this.availableOptions[0].focus()):" "===n.key&&(n.preventDefault(),this.toggle()):"ArrowUp"===n.key?(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"===n.key?(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus()):"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),n.target.click(),this.collapse(),this.menu.focus())}handleClickOutside(n){this.contains(n.target)||2===n.button||this.collapse()}connectedCallback(){this.setAttribute("role","listbox"),this.setAttribute("aria-label","dropdown menu");const n=this.shadowRoot.querySelector(".options slot");n.addEventListener("slotchange",n=>{this.availableOptions=n.target.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("mousedown",this.handleClickOutside)}});const menuOption=document.createElement("template");menuOption.innerHTML='\n\n
\n \n
',customElements.define("menu-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(menuOption.content.cloneNode(!0))}connectedCallback(){this.setAttribute("role","option"),this.setAttribute("tabindex","0"),this.addEventListener("keyup",n=>{"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),this.click())})}});
\ No newline at end of file
diff --git a/components/dist/switch.js b/components/dist/switch.js
index 7822cc6..63e4314 100644
--- a/components/dist/switch.js
+++ b/components/dist/switch.js
@@ -83,7 +83,7 @@ smSwitch.innerHTML = `
align-items: center;
border-radius: 1rem;
box-shadow: 0 0.1rem 0.4rem #00000060, 0 0 0 0.3rem white inset;
- transition: 0.3s;
+ transition: 0.3s cubic-bezier(0.68, -0.6, 0.32, 1.6);
background-color: inherit;
}
diff --git a/components/dist/switch.min.js b/components/dist/switch.min.js
index a4637e9..76d6b3e 100644
--- a/components/dist/switch.min.js
+++ b/components/dist/switch.min.js
@@ -1 +1 @@
-const smSwitch=document.createElement("template");smSwitch.innerHTML='\t\n\n
\n \n \n \n ',customElements.define("sm-switch",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smSwitch.content.cloneNode(!0)),this.switch=this.shadowRoot.querySelector(".switch"),this.input=this.shadowRoot.querySelector("input"),this.isChecked=!1,this.isDisabled=!1,this.dispatch=this.dispatch.bind(this)}static get observedAttributes(){return["disabled","checked"]}get disabled(){return this.isDisabled}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.isChecked}set checked(e){e?this.setAttribute("checked",""):this.removeAttribute("checked")}get value(){return this.isChecked}reset(){}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this.isChecked}}))}connectedCallback(){this.addEventListener("keydown",e=>{" "!==e.key||this.isDisabled||(e.preventDefault(),this.input.click())}),this.input.addEventListener("click",e=>{this.input.checked?this.checked=!0:this.checked=!1,this.dispatch()})}attributeChangedCallback(e,t,n){t!==n&&("disabled"===e?this.hasAttribute("disabled")?this.disabled=!0:this.disabled=!1:"checked"===e&&(this.hasAttribute("checked")?(this.isChecked=!0,this.input.checked=!0):(this.isChecked=!1,this.input.checked=!1)))}});
\ No newline at end of file
+const smSwitch=document.createElement("template");smSwitch.innerHTML='\t\n\n
\n \n \n \n ',customElements.define("sm-switch",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smSwitch.content.cloneNode(!0)),this.switch=this.shadowRoot.querySelector(".switch"),this.input=this.shadowRoot.querySelector("input"),this.isChecked=!1,this.isDisabled=!1,this.dispatch=this.dispatch.bind(this)}static get observedAttributes(){return["disabled","checked"]}get disabled(){return this.isDisabled}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.isChecked}set checked(e){e?this.setAttribute("checked",""):this.removeAttribute("checked")}get value(){return this.isChecked}reset(){}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this.isChecked}}))}connectedCallback(){this.addEventListener("keydown",e=>{" "!==e.key||this.isDisabled||(e.preventDefault(),this.input.click())}),this.input.addEventListener("click",e=>{this.input.checked?this.checked=!0:this.checked=!1,this.dispatch()})}attributeChangedCallback(e,t,n){t!==n&&("disabled"===e?this.hasAttribute("disabled")?this.disabled=!0:this.disabled=!1:"checked"===e&&(this.hasAttribute("checked")?(this.isChecked=!0,this.input.checked=!0):(this.isChecked=!1,this.input.checked=!1)))}});
\ No newline at end of file
diff --git a/components/test.html b/components/test.html
index d6f56c4..184ccc8 100644
--- a/components/test.html
+++ b/components/test.html
@@ -13,6 +13,9 @@
+
+
+