| <link rel="import" href="../polymer/polymer.html"> |
| |
| <dom-module id="chops-button"> |
| <template> |
| <style> |
| :host { |
| background: hsla(0, 0%, 96%, 1); |
| margin: 0.25em 4px; |
| padding: 0.5em 16px; |
| cursor: pointer; |
| border-radius: 3px; |
| text-align: center; |
| display: inline-block; |
| user-select: none; |
| transition: filter 0.3s ease-in-out, box-shadow 0.3s ease-in-out; |
| font-family: Roboto, Noto, sans-serif; |
| } |
| :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> |