fix: - rearranging invokers and content for a correct tab order is now implemented by changing the slot attributes of both instead of moving them

- changed css for this implementation
     - fixed tests
     - added changeset
This commit is contained in:
Danny Moerkerke 2023-01-12 15:55:39 +01:00 committed by Thomas Allmer
parent af2e0293a1
commit 9fb14fa1c5
3 changed files with 56 additions and 41 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
`accordion`: rearranging invokers and content for a correct tab order is now implemented by changing the slot attributes of both instead of moving them, changed css for this implementation, updated tests

View file

@ -44,21 +44,21 @@ export class LionAccordion extends LitElement {
flex-direction: column; flex-direction: column;
} }
.accordion [slot='invoker'] { .accordion ::slotted(.invoker) {
margin: 0; margin: 0;
} }
.accordion [slot='invoker'][expanded] { .accordion ::slotted(.invoker)[expanded] {
font-weight: bold; font-weight: bold;
} }
.accordion [slot='content'] { .accordion ::slotted(.content) {
margin: 0; margin: 0;
visibility: hidden; visibility: hidden;
display: none; display: none;
} }
.accordion [slot='content'][expanded] { .accordion ::slotted(.content[expanded]) {
visibility: visible; visibility: visible;
display: block; display: block;
} }
@ -159,9 +159,15 @@ export class LionAccordion extends LitElement {
* @private * @private
*/ */
__setupStore() { __setupStore() {
const accordion = this.shadowRoot?.querySelector('slot[name=_accordion]'); const accordion = /** @type {HTMLSlotElement} */ (
const existingInvokers = accordion ? accordion.querySelectorAll('[slot=invoker]') : []; this.shadowRoot?.querySelector('slot[name=_accordion]')
const existingContent = accordion ? accordion.querySelectorAll('[slot=content]') : []; );
const existingInvokers = accordion
? accordion.assignedElements().filter(child => child.classList.contains('invoker'))
: [];
const existingContent = accordion
? accordion.assignedElements().filter(child => child.classList.contains('content'))
: [];
const invokers = /** @type {HTMLElement[]} */ ([ const invokers = /** @type {HTMLElement[]} */ ([
...Array.from(existingInvokers), ...Array.from(existingInvokers),
@ -212,14 +218,21 @@ export class LionAccordion extends LitElement {
const invokers = /** @type {HTMLElement[]} */ ( const invokers = /** @type {HTMLElement[]} */ (
Array.from(this.children).filter(child => child.slot === 'invoker') Array.from(this.children).filter(child => child.slot === 'invoker')
); );
const contents = /** @type {HTMLElement[]} */ ( const contents = /** @type {HTMLElement[]} */ (
Array.from(this.children).filter(child => child.slot === 'content') Array.from(this.children).filter(child => child.slot === 'content')
); );
const accordion = this.shadowRoot?.querySelector('slot[name=_accordion]'); const accordion = this.shadowRoot?.querySelector('slot[name=_accordion]');
if (accordion) { if (accordion) {
invokers.forEach((invoker, index) => { invokers.forEach((invoker, index) => {
accordion.insertAdjacentElement('beforeend', invoker); invoker.classList.add('invoker');
accordion.insertAdjacentElement('beforeend', contents[index]); // eslint-disable-next-line no-param-reassign
invoker.slot = '_accordion';
contents[index].classList.add('content');
contents[index].slot = '_accordion';
}); });
} }
} }

View file

@ -23,27 +23,27 @@ const basicAccordion = html`
* @param {Element} el * @param {Element} el
*/ */
function getAccordionChildren(el) { function getAccordionChildren(el) {
if (el.shadowRoot) {
const slot = el.shadowRoot?.querySelector('slot[name=_accordion]'); const slot = el.shadowRoot?.querySelector('slot[name=_accordion]');
return slot ? slot.children : []; return slot && slot instanceof HTMLSlotElement ? slot.assignedElements() : [];
}
return [];
} }
/** /**
* @param {Element} el * @param {Element} el
*/ */
function getInvokers(el) { function getInvokers(el) {
const slot = el.shadowRoot?.querySelector('slot[name=_accordion]'); return getAccordionChildren(el).filter(child => child.classList.contains('invoker'));
return slot ? slot.querySelectorAll('[slot=invoker]') : [];
} }
/** /**
* @param {Element} el * @param {Element} el
*/ */
function getContents(el) { function getContents(el) {
const slot = el.shadowRoot?.querySelector('slot[name=_accordion]'); return getAccordionChildren(el).filter(child => child.classList.contains('content'));
return slot ? slot.querySelectorAll('[slot=content]') : [];
} }
describe('<lion-accordion>', () => { describe('<lion-accordion>', () => {
@ -68,14 +68,14 @@ describe('<lion-accordion>', () => {
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getAccordionChildren(el)).find(
child => child.slot === 'invoker' && child.hasAttribute('expanded'), child => child.className === 'invoker' && child.hasAttribute('expanded'),
)?.textContent, )?.textContent,
).to.equal('invoker 2'); ).to.equal('invoker 2');
el.expanded = [0]; el.expanded = [0];
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getAccordionChildren(el)).find(
child => child.slot === 'invoker' && child.hasAttribute('expanded'), child => child.className === 'invoker' && child.hasAttribute('expanded'),
)?.textContent, )?.textContent,
).to.equal('invoker 1'); ).to.equal('invoker 1');
}); });
@ -146,17 +146,16 @@ describe('<lion-accordion>', () => {
`) `)
); );
expect(el.focusedIndex).to.equal(1); expect(el.focusedIndex).to.equal(1);
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getInvokers(el)).find(child => child.firstElementChild?.hasAttribute('focused'))
child => child.slot === 'invoker' && child.firstElementChild?.hasAttribute('focused'), ?.textContent,
)?.textContent,
).to.equal('invoker 2'); ).to.equal('invoker 2');
el.focusedIndex = 0; el.focusedIndex = 0;
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getInvokers(el)).find(child => child.firstElementChild?.hasAttribute('focused'))
child => child.slot === 'invoker' && child.firstElementChild?.hasAttribute('focused'), ?.textContent,
)?.textContent,
).to.equal('invoker 1'); ).to.equal('invoker 1');
}); });
@ -360,14 +359,10 @@ describe('<lion-accordion>', () => {
await el.updateComplete; await el.updateComplete;
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getInvokers(el)).find(child => child.hasAttribute('expanded'))?.textContent,
child => child.slot === 'invoker' && child.hasAttribute('expanded'),
)?.textContent,
).to.equal('invoker 5'); ).to.equal('invoker 5');
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getContents(el)).find(child => child.hasAttribute('expanded'))?.textContent,
child => child.slot === 'content' && child.hasAttribute('expanded'),
)?.textContent,
).to.equal('content 5'); ).to.equal('content 5');
}); });
@ -410,11 +405,13 @@ describe('<lion-accordion>', () => {
<div slot="content">content 2</div> <div slot="content">content 2</div>
</lion-accordion> </lion-accordion>
`); `);
// console.log(getAccordionChildren(el));
expect( expect(
Array.from(getAccordionChildren(el)).find(child => child.slot === 'content'), Array.from(getAccordionChildren(el)).find(child => child.classList.contains('content')),
).to.not.have.attribute('tabindex'); ).to.not.have.attribute('tabindex');
expect( expect(
Array.from(getAccordionChildren(el)).find(child => child.slot === 'content'), Array.from(getAccordionChildren(el)).find(child => child.classList.contains('content')),
).to.not.have.attribute('tabindex'); ).to.not.have.attribute('tabindex');
}); });
@ -445,10 +442,10 @@ describe('<lion-accordion>', () => {
<div slot="content">content</div> <div slot="content">content</div>
</lion-accordion> </lion-accordion>
`); `);
expect( expect(Array.from(getInvokers(el))[0]?.firstElementChild).to.have.attribute(
Array.from(getAccordionChildren(el)).find(child => child.slot === 'invoker') 'aria-expanded',
?.firstElementChild, 'false',
).to.have.attribute('aria-expanded', 'false'); );
}); });
it('adds aria-expanded="true" to invoker when its content is expanded', async () => { it('adds aria-expanded="true" to invoker when its content is expanded', async () => {
@ -461,10 +458,10 @@ describe('<lion-accordion>', () => {
`) `)
); );
el.expanded = [0]; el.expanded = [0];
expect( expect(Array.from(getInvokers(el))[0]?.firstElementChild).to.have.attribute(
Array.from(getAccordionChildren(el)).find(child => child.slot === 'invoker') 'aria-expanded',
?.firstElementChild, 'true',
).to.have.attribute('aria-expanded', 'true'); );
}); });
}); });