blob: 816f6c18f0db997f3f363e31fb3db2696be3860f [file] [log] [blame]
<link rel="import" href="../polymer/polymer.html">
<dom-module id="chops-button">
<template>
<style>
:host {
background: hsla(0, 0%, 95%, 1);
margin: 0.25em 4px;
padding: 0.5em 16px;
cursor: pointer;
border-radius: 3px;
text-align: center;
display: inline-flex;
align-items: center;
justify-content: center;
user-select: none;
transition: filter 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
font-family: Roboto, Noto, sans-serif;
}
:host([hidden]) {
display: none;
}
:host([raised]) {
box-shadow: 0px 2px 8px -1px hsla(0, 0%, 0%, 0.5);
}
:host(:hover) {
filter: brightness(95%);
}
:host(:active), :host(.active) {
filter: brightness(115%);
}
:host([raised]:active), :host([raised].active) {
box-shadow: 0px 1px 8px -1px hsla(0, 0%, 0%, 0.5);
}
:host([disabled]),
:host([disabled]:hover) {
filter: grayscale(30%);
opacity: 0.4;
background: hsla(0, 0%, 87%, 1);
cursor: default;
pointer-events: none;
box-shadow: none;
}
</style>
<slot></slot>
</template>
<script>
'use strict';
/**
* `<chops-button>` displays a styled button component with a few niceties.
*
* @customElement
* @polymer
* @demo /demo/chops-button_demo.html
*/
class ChopsButton extends Polymer.Element {
static get is() { return 'chops-button'; }
static get properties() {
return {
/** Whether the button is available for input or not. */
disabled: {
type: Boolean,
reflectToAttribute: true,
},
/**
* For accessibility. These are the keys that you can use to fire the
* onclick event for chops-button. The value is an Array of
* JavaScript key input codes, defaulting to space and enter keys.
*/
inputKeys: {
type: Array,
value: [13, 32],
},
/**
* If true, the element currently has focus. Changed through focus
* and blur event listeners.
*/
focused: {
type: Boolean,
value: false,
notify: true,
readOnly: true,
reflectToAttribute: true,
},
/** Whether the button should have a shadow or not. */
raised: {
type: Boolean,
value: false,
reflectToAttribute: true,
},
/** Used for accessibility to state this component is a button. **/
role: {
type: String,
value: 'button',
readOnly: true,
reflectToAttribute: true,
},
/** Causes the button to be focusable for accessbility. **/
tabindex: {
type: Number,
value: 0,
reflectToAttribute: true,
},
_boundKeypressHandler: {
type: Function,
value: function() {
return this._keypressHandler.bind(this);
},
},
_boundFocusBlurHandler: {
type: Function,
value: function() {
return this._focusBlurHandler.bind(this);
},
},
_debouncedRemoveActive: Object,
};
}
ready() {
super.ready();
this.addEventListener('focus', this._boundFocusBlurHandler, true);
this.addEventListener('blur', this._boundFocusBlurHandler, true);
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('keypress', this._boundKeypressHandler, true);
}
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener('keypress', this._boundKeypressHandler,
true);
}
_keypressHandler(event) {
if (!this.focused) return;
let keyCode = event.keyCode;
if (this.inputKeys.includes(keyCode)) {
this.click();
// Trigger the animation for a button click.
this.classList.add('active');
this._debouncedRemoveActive = Polymer.Debouncer.debounce(
this._debouncedRemoveActive,
Polymer.Async.timeOut.after(400),
() => {
this.classList.remove('active');
}
);
}
}
_focusBlurHandler(event) {
this._setFocused(event.type === 'focus');
}
}
customElements.define(ChopsButton.is, ChopsButton);
</script>
<dom-module>