Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/accordion/src/vaadin-accordion-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export declare class AccordionMixinClass {
*/
opened: number | null;

/**
* Indicates whether all the accordion panels are closed.
* Setting this property to true closes all the accordion panels.
*/
closed: boolean | null;

/**
* The list of `<vaadin-accordion-panel>` child elements.
* It is populated from the elements passed to the light DOM,
Expand Down
35 changes: 29 additions & 6 deletions packages/accordion/src/vaadin-accordion-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ export const AccordionMixin = (superClass) =>
reflectToAttribute: true,
},

/**
* Indicates whether all the accordion panels are closed.
* Setting this property to true closes all the accordion panels.
*/
closed: {
type: Boolean,
notify: true,
reflectToAttribute: true,
},

/**
* The list of `<vaadin-accordion-panel>` child elements.
* It is populated from the elements passed to the light DOM,
Expand All @@ -45,7 +55,7 @@ export const AccordionMixin = (superClass) =>
}

static get observers() {
return ['_updateItems(items, opened)'];
return ['_updateItems(items, opened, closed)'];
}

constructor() {
Expand Down Expand Up @@ -112,13 +122,21 @@ export const AccordionMixin = (superClass) =>
}

/** @private */
_updateItems(items, opened) {
_updateItems(items, opened, closed) {
if (items) {
this.__itemsSync = true;
const itemToOpen = items[opened];
items.forEach((item) => {
item.opened = item === itemToOpen;
});
if (closed) {
items.forEach((item) => {
item.opened = false;
});
this.opened = null;
} else {
const itemToOpen = items[opened];
items.forEach((item) => {
item.opened = item === itemToOpen;
});
}

this.__itemsSync = false;
}
}
Expand Down Expand Up @@ -147,6 +165,7 @@ export const AccordionMixin = (superClass) =>
if (this.__itemsSync) {
return;
}

const target = this._filterItems(e.composedPath())[0];
const idx = this.items.indexOf(target);
if (e.detail.value) {
Expand All @@ -155,8 +174,12 @@ export const AccordionMixin = (superClass) =>
}

this.opened = idx;
this.closed = null;
} else if (!this.items.some((item) => item.opened)) {
this.opened = null;
this.closed = true;
} else {
this.closed = true;
}
}
};
15 changes: 14 additions & 1 deletion packages/accordion/test/accordion.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ describe('vaadin-accordion', () => {
it('should open the first panel by default', () => {
expect(accordion.opened).to.equal(0);
expect(accordion.items[0].opened).to.be.true;
expect(accordion.closed).to.be.null;
});

it('should reflect opened property to attribute', () => {
Expand All @@ -100,6 +101,7 @@ describe('vaadin-accordion', () => {
await nextUpdate(accordion);
expect(accordion.items[1].opened).to.be.true;
expect(accordion.opened).to.equal(1);
expect(accordion.closed).to.be.null;
});

it('should not update opened to new index when clicking disabled panel', async () => {
Expand All @@ -108,26 +110,37 @@ describe('vaadin-accordion', () => {
await nextUpdate(accordion);
expect(accordion.items[1].opened).to.be.false;
expect(accordion.opened).to.equal(0);
expect(accordion.closed).to.be.null;
});

it('should close currently opened panel when another one is opened', async () => {
getHeading(1).click();
await nextUpdate(accordion);
expect(accordion.items[1].opened).to.be.true;
expect(accordion.items[0].opened).to.be.false;
expect(accordion.closed).to.be.null;
});

it('should set opened to null when the opened panel is closed', async () => {
it('should set opened to null and add closed to true when the opened panel is closed', async () => {
getHeading(0).click();
await nextUpdate(accordion);
expect(accordion.items[0].opened).to.be.false;
expect(accordion.opened).to.equal(null);
expect(accordion.closed).to.be.true;
});

it('should close currently opened panel when opened set to null', async () => {
accordion.opened = null;
await nextUpdate(accordion);
expect(accordion.items[0].opened).to.be.false;
expect(accordion.closed).to.be.true;
});

it('should close currently opened panel when closed set to true', async () => {
accordion.closed = true;
await nextUpdate(accordion);
expect(accordion.items[0].opened).to.be.false;
expect(accordion.closed).to.be.true;
});

it('should not change opened state if panel has been removed', async () => {
Expand Down