feat(listbox): add click on enter for options with href
This commit is contained in:
parent
6498ab716f
commit
c844c017a9
6 changed files with 105 additions and 0 deletions
5
.changeset/eight-lions-provide.md
Normal file
5
.changeset/eight-lions-provide.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/listbox': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add click on enter for options with href, to ensure that anchors are navigated towards, for example when applying LinkMixin to LionOption as part of a listbox.
|
||||||
|
|
@ -51,6 +51,9 @@ const LinkMixinImplementation = superclass =>
|
||||||
if (changedProperties.has('target')) {
|
if (changedProperties.has('target')) {
|
||||||
this._nativeAnchor.target = this.target;
|
this._nativeAnchor.target = this.target;
|
||||||
}
|
}
|
||||||
|
if (changedProperties.has('rel')) {
|
||||||
|
this._nativeAnchor.rel = this.rel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__navigate() {
|
__navigate() {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { html } from 'lit-html';
|
||||||
import './md-combobox/md-combobox.js';
|
import './md-combobox/md-combobox.js';
|
||||||
import './gh-combobox/gh-combobox.js';
|
import './gh-combobox/gh-combobox.js';
|
||||||
import './wa-combobox/wa-combobox.js';
|
import './wa-combobox/wa-combobox.js';
|
||||||
|
import './lm-option/lm-option.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Forms/Combobox/Extensions',
|
title: 'Forms/Combobox/Extensions',
|
||||||
|
|
@ -79,3 +80,45 @@ export const Whatsapp = () => html`
|
||||||
</wa-combobox>
|
</wa-combobox>
|
||||||
`;
|
`;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```js preview-story
|
||||||
|
export const LinkMixinBox = () => html`
|
||||||
|
<lion-combobox name="combo" label="Default">
|
||||||
|
<lm-option
|
||||||
|
href="https://www.google.com/search?query=apple"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
.choiceValue=${'Apple'}
|
||||||
|
>Apple</lm-option
|
||||||
|
>
|
||||||
|
<lm-option
|
||||||
|
href="https://www.google.com/search?query=Artichoke"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
.choiceValue=${'Artichoke'}
|
||||||
|
>Artichoke</lm-option
|
||||||
|
>
|
||||||
|
<lm-option
|
||||||
|
href="https://www.google.com/search?query=Asparagus"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
.choiceValue=${'Asparagus'}
|
||||||
|
>Asparagus</lm-option
|
||||||
|
>
|
||||||
|
<lm-option
|
||||||
|
href="https://www.google.com/search?query=Banana"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
.choiceValue=${'Banana'}
|
||||||
|
>Banana</lm-option
|
||||||
|
>
|
||||||
|
<lm-option
|
||||||
|
href="https://www.google.com/search?query=Beets"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
.choiceValue=${'Beets'}
|
||||||
|
>Beets</lm-option
|
||||||
|
>
|
||||||
|
</lion-combobox>
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
|
||||||
6
packages/combobox/docs/lm-option/lm-option.js
Normal file
6
packages/combobox/docs/lm-option/lm-option.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { LionOption } from '@lion/listbox';
|
||||||
|
import { LinkMixin } from '../LinkMixin.js';
|
||||||
|
|
||||||
|
export class LmOption extends LinkMixin(LionOption) {}
|
||||||
|
|
||||||
|
customElements.define('lm-option', LmOption);
|
||||||
|
|
@ -493,6 +493,11 @@ const ListboxMixinImplementation = superclass =>
|
||||||
if (this.formElements[this.activeIndex].disabled) {
|
if (this.formElements[this.activeIndex].disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.formElements[this.activeIndex].href) {
|
||||||
|
this.formElements[this.activeIndex].click();
|
||||||
|
}
|
||||||
|
|
||||||
this.setCheckedIndex(this.activeIndex);
|
this.setCheckedIndex(this.activeIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1184,5 +1184,48 @@ export function runListboxMixinSuite(customConfig = {}) {
|
||||||
expect(listbox.children[0].tagName).to.equal(cfg.optionTagString.toUpperCase());
|
expect(listbox.children[0].tagName).to.equal(cfg.optionTagString.toUpperCase());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Href Options', () => {
|
||||||
|
it('allows anchors to be clicked when a [href] attribute is present', async () => {
|
||||||
|
const el = await fixture(html`
|
||||||
|
<${tag}>
|
||||||
|
<${optionTag}>Google</${optionTag}>
|
||||||
|
<${optionTag} .href=${'https://duckduckgo.com'}>DuckDuck Go</${optionTag}>
|
||||||
|
</${tag}>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { listbox } = getProtectedMembers(el);
|
||||||
|
|
||||||
|
el.activeIndex = 1;
|
||||||
|
|
||||||
|
// Allow options that behave like anchors (think of Google Search) to trigger the anchor behavior
|
||||||
|
const activeOption = el.formElements[1];
|
||||||
|
const clickSpy = sinon.spy(activeOption, 'click');
|
||||||
|
|
||||||
|
listbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
|
||||||
|
|
||||||
|
expect(clickSpy).to.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not allow anchors to be clicked when a [href] attribute is not present', async () => {
|
||||||
|
const el = await fixture(html`
|
||||||
|
<${tag}>
|
||||||
|
<${optionTag}>Google</${optionTag}>
|
||||||
|
<${optionTag} .href=${'https://duckduckgo.com'}>DuckDuck Go</${optionTag}>
|
||||||
|
</${tag}>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { listbox } = getProtectedMembers(el);
|
||||||
|
|
||||||
|
el.activeIndex = 0;
|
||||||
|
|
||||||
|
const activeOption = el.formElements[0];
|
||||||
|
const clickSpy = sinon.spy(activeOption, 'click');
|
||||||
|
|
||||||
|
listbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
|
||||||
|
|
||||||
|
expect(clickSpy).to.not.have.been.called;
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue