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:
parent
af2e0293a1
commit
9fb14fa1c5
3 changed files with 56 additions and 41 deletions
5
.changeset/tricky-squids-dress.md
Normal file
5
.changeset/tricky-squids-dress.md
Normal 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
|
||||||
|
|
@ -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';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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');
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue