coral-spectrum/coral-component-anchorbutton/src/scripts/AnchorButton.js
- /**
- * Copyright 2019 Adobe. All rights reserved.
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License. You may obtain a copy
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-
- import {BaseComponent} from '../../../coral-base-component';
- import {BaseButton} from '../../../coral-base-button';
- import {transform, commons} from '../../../coral-utils';
- import {Decorator} from '../../../coral-decorator';
-
- // Key code
- const SPACE = 32;
-
- /**
- @class Coral.AnchorButton
- @classdesc A Link component rendering as a button allowing us to style an anchor element that both looks and behaves
- like a button rather than a link. It can receive keyboard focus regardless of whether or not it has an <code>href</code>
- attribute, can be activated using either the <code>SPACE</code> key or the <code>ENTER</code> key, and is identified to
- assistive technology as a button element.
- @htmltag coral-anchorbutton
- @htmlbasetag a
- @extends {HTMLAnchorElement}
- @extends {BaseComponent}
- @extends {BaseButton}
- */
- const AnchorButton = Decorator(class extends BaseButton(BaseComponent(HTMLAnchorElement)) {
- /** @ignore */
- constructor() {
- super();
-
- // Events
- this._delegateEvents(commons.extend(this._events, {
- keydown: '_onKeyDown',
- keyup: '_onKeyUp'
- }));
-
- // cannot use the events hash because events on disabled items are not reported
- this.addEventListener('click', this._onDisabledClick.bind(this));
- }
-
- /**
- Disables the button from user interaction.
-
- @type {Boolean}
- @default false
- @htmlattribute disabled
- @htmlattributereflected
- */
- get disabled() {
- return this._disabled || false;
- }
-
- set disabled(value) {
- this._disabled = transform.booleanAttr(value);
- this._reflectAttribute('disabled', this._disabled);
-
- this.classList.toggle('is-disabled', this._disabled);
- this.setAttribute('tabindex', this._disabled ? '-1' : '0');
- this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled);
- }
-
- /**
- Keyboard handling per the WAI-ARIA button widget design pattern:
- https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role
-
- @ignore
- */
- _onKeyDown(event) {
- if (event.keyCode === SPACE) {
- event.preventDefault();
- this.click();
- this.classList.add('is-selected');
- }
- }
-
- /** @ignore */
- _onKeyUp(event) {
- if (event.keyCode === SPACE) {
- event.preventDefault();
- this.classList.remove('is-selected');
- }
- }
-
- /** @ignore */
- _onDisabledClick(event) {
- if (this.disabled) {
- event.preventDefault();
- }
- }
-
- // Override content zone name
- get _contentZones() {
- return {'coral-anchorbutton-label': 'label'};
- }
-
- /** @ignore */
- static get observedAttributes() {
- return super.observedAttributes.concat(['disabled']);
- }
-
- /** @ignore */
- render() {
- super.render();
-
- // a11y
- this.setAttribute('role', 'button');
- if (!this.disabled) {
- // Force tabindex and aria-disabled attribute reflection
- this.setAttribute('tabindex', '0');
- this.removeAttribute('aria-disabled');
- }
- }
- });
-
- export default AnchorButton;