feat(button): move active to host for cross-browser support (fix #188)

This commit is contained in:
Mikhail Bashkirov 2019-07-26 15:40:12 +02:00
parent e269b5d040
commit 471d662cb2
2 changed files with 72 additions and 4 deletions

View file

@ -10,6 +10,10 @@ export class LionButton extends DisabledWithTabIndexMixin(
type: String, type: String,
reflect: true, reflect: true,
}, },
active: {
type: Boolean,
reflect: true,
},
}; };
} }
@ -83,8 +87,8 @@ export class LionButton extends DisabledWithTabIndexMixin(
background: #f4f6f7; background: #f4f6f7;
} }
:host(:active) .btn, :host(:active) .btn, /* keep native :active to render quickly where possible */
.btn[active] { :host([active]) .btn /* use custom [active] to fix IE11 */ {
/* if you extend, please overwrite */ /* if you extend, please overwrite */
background: gray; background: gray;
} }
@ -128,6 +132,7 @@ export class LionButton extends DisabledWithTabIndexMixin(
constructor() { constructor() {
super(); super();
this.role = 'button'; this.role = 'button';
this.active = false;
this.__setupDelegationInConstructor(); this.__setupDelegationInConstructor();
} }
@ -176,19 +181,31 @@ export class LionButton extends DisabledWithTabIndexMixin(
} }
__setupDelegation() { __setupDelegation() {
this.addEventListener('mousedown', this.__mousedownDelegationHandler);
this.addEventListener('mouseup', this.__mouseupDelegationHandler);
this.addEventListener('keydown', this.__keydownDelegationHandler); this.addEventListener('keydown', this.__keydownDelegationHandler);
this.addEventListener('keyup', this.__keyupDelegationHandler); this.addEventListener('keyup', this.__keyupDelegationHandler);
} }
__teardownDelegation() { __teardownDelegation() {
this.removeEventListener('mousedown', this.__mousedownDelegationHandler);
this.removeEventListener('mouseup', this.__mouseupDelegationHandler);
this.removeEventListener('keydown', this.__keydownDelegationHandler); this.removeEventListener('keydown', this.__keydownDelegationHandler);
this.removeEventListener('keyup', this.__keyupDelegationHandler); this.removeEventListener('keyup', this.__keyupDelegationHandler);
} }
__mousedownDelegationHandler() {
this.active = true;
}
__mouseupDelegationHandler() {
this.active = false;
}
__keydownDelegationHandler(e) { __keydownDelegationHandler(e) {
if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) { if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) {
e.preventDefault(); e.preventDefault();
this.shadowRoot.querySelector('.btn').setAttribute('active', ''); this.active = true;
} }
} }
@ -197,7 +214,7 @@ export class LionButton extends DisabledWithTabIndexMixin(
// and make click handlers on button work on space and enter // and make click handlers on button work on space and enter
if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) { if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) {
e.preventDefault(); e.preventDefault();
this.shadowRoot.querySelector('.btn').removeAttribute('active'); this.active = false;
this.shadowRoot.querySelector('.click-area').click(); this.shadowRoot.querySelector('.click-area').click();
} }
} }

View file

@ -4,6 +4,10 @@ import {
makeMouseEvent, makeMouseEvent,
pressEnter, pressEnter,
pressSpace, pressSpace,
down,
up,
keyDownOn,
keyUpOn,
} from '@polymer/iron-test-helpers/mock-interactions.js'; } from '@polymer/iron-test-helpers/mock-interactions.js';
import '../lion-button.js'; import '../lion-button.js';
@ -57,6 +61,53 @@ describe('lion-button', () => {
expect(el.hasAttribute('disabled')).to.equal(true); expect(el.hasAttribute('disabled')).to.equal(true);
}); });
describe('active', () => {
it('updates "active" attribute on host when mousedown/mouseup on button', async () => {
const el = await fixture(`<lion-button>foo</lion-button>`);
const topEl = getTopElement(el);
down(topEl);
expect(el.active).to.be.true;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.true;
up(topEl);
expect(el.active).to.be.false;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.false;
});
it('updates "active" attribute on host when space keydown/keyup on button', async () => {
const el = await fixture(`<lion-button>foo</lion-button>`);
const topEl = getTopElement(el);
keyDownOn(topEl, 32);
expect(el.active).to.be.true;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.true;
keyUpOn(topEl, 32);
expect(el.active).to.be.false;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.false;
});
it('updates "active" attribute on host when enter keydown/keyup on button', async () => {
const el = await fixture(`<lion-button>foo</lion-button>`);
const topEl = getTopElement(el);
keyDownOn(topEl, 13);
expect(el.active).to.be.true;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.true;
keyUpOn(topEl, 13);
expect(el.active).to.be.false;
await el.updateComplete;
expect(el.hasAttribute('active')).to.be.false;
});
});
describe('a11y', () => { describe('a11y', () => {
it('has a role="button" by default', async () => { it('has a role="button" by default', async () => {
const el = await fixture(`<lion-button>foo</lion-button>`); const el = await fixture(`<lion-button>foo</lion-button>`);