diff --git a/core/src/components/accordion-group/accordion-group.tsx b/core/src/components/accordion-group/accordion-group.tsx index 3cbf069dd7..f20731757e 100644 --- a/core/src/components/accordion-group/accordion-group.tsx +++ b/core/src/components/accordion-group/accordion-group.tsx @@ -199,7 +199,7 @@ export class AccordionGroup implements ComponentInterface { */ @Method() async getAccordions() { - return Array.from(this.el.querySelectorAll('ion-accordion')); + return Array.from(this.el.querySelectorAll(':scope > ion-accordion')) as HTMLIonAccordionElement[]; } render() { diff --git a/core/src/components/accordion/accordion.scss b/core/src/components/accordion/accordion.scss index 7f7521dec8..1305913a92 100644 --- a/core/src/components/accordion/accordion.scss +++ b/core/src/components/accordion/accordion.scss @@ -58,7 +58,9 @@ } :host(.accordion-disabled) #header, -:host(.accordion-readonly) #header { +:host(.accordion-readonly) #header, +:host(.accordion-disabled) #content, +:host(.accordion-readonly) #content { pointer-events: none; } diff --git a/core/src/components/accordion/test/accordion.e2e.ts b/core/src/components/accordion/test/accordion.e2e.ts new file mode 100644 index 0000000000..f73d03772a --- /dev/null +++ b/core/src/components/accordion/test/accordion.e2e.ts @@ -0,0 +1,55 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('should properly set readonly on child accordions', async () => { + const page = await newE2EPage({ + html: ` + + + Label +
Content
+
+
+ ` + }); + + const accordion = await page.find('ion-accordion'); + const value = await accordion.getProperty('readonly'); + + expect(value).toBe(false); + + await page.$eval('ion-accordion-group', (el: HTMLIonAccordionGroupElement) => { + el.readonly = true; + }); + + await page.waitForChanges(); + + const valueAgain = await accordion.getProperty('readonly'); + expect(valueAgain).toBe(true); +}); + +test('should properly set disabled on child accordions', async () => { + const page = await newE2EPage({ + html: ` + + + Label +
Content
+
+
+ ` + }); + + const accordion = await page.find('ion-accordion'); + const value = await accordion.getProperty('disabled'); + + expect(value).toBe(false); + + await page.$eval('ion-accordion-group', (el: HTMLIonAccordionGroupElement) => { + el.disabled = true; + }); + + await page.waitForChanges(); + + const valueAgain = await accordion.getProperty('disabled'); + expect(valueAgain).toBe(true); +}); diff --git a/core/src/components/accordion/test/accordion.spec.ts b/core/src/components/accordion/test/accordion.spec.ts index 8315c6ccb2..8274f24e6b 100644 --- a/core/src/components/accordion/test/accordion.spec.ts +++ b/core/src/components/accordion/test/accordion.spec.ts @@ -3,64 +3,6 @@ import { AccordionGroup } from '../../accordion-group/accordion-group.tsx'; import { Accordion } from '../accordion.tsx'; import { Item } from '../../item/item.tsx'; -it('should properly set readonly on child accordions', async () => { - const page = await newSpecPage({ - components: [Item, Accordion, AccordionGroup], - html: ` - - - Label -
Content
-
-
- ` - }); - - const accordionGroup = page.body.querySelector('ion-accordion-group'); - const accordions = accordionGroup.querySelectorAll('ion-accordion'); - - expect(accordions.length).toEqual(1); - accordions.forEach(accordion => { - expect(accordion.readonly).toEqual(false); - }); - - accordionGroup.readonly = true; - await page.waitForChanges(); - - accordions.forEach(accordion => { - expect(accordion.readonly).toEqual(true); - }); -}); - -it('should properly set disabled on child accordions', async () => { - const page = await newSpecPage({ - components: [Item, Accordion, AccordionGroup], - html: ` - - - Label -
Content
-
-
- ` - }); - - const accordionGroup = page.body.querySelector('ion-accordion-group'); - const accordions = accordionGroup.querySelectorAll('ion-accordion'); - - expect(accordions.length).toEqual(1); - accordions.forEach(accordion => { - expect(accordion.disabled).toEqual(false); - }); - - accordionGroup.disabled = true; - await page.waitForChanges(); - - accordions.forEach(accordion => { - expect(accordion.disabled).toEqual(true); - }); -}); - it('should open correct accordions', async () => { const page = await newSpecPage({ components: [Item, Accordion, AccordionGroup], diff --git a/core/src/components/accordion/test/nested/e2e.ts b/core/src/components/accordion/test/nested/e2e.ts new file mode 100644 index 0000000000..44f12f3319 --- /dev/null +++ b/core/src/components/accordion/test/nested/e2e.ts @@ -0,0 +1,10 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('nested: basic', async () => { + const page = await newE2EPage({ + url: '/src/components/accordion/test/nested?ionic:_testing=true' + }); + + const compare = await page.compareScreenshot(); + expect(compare).toMatchScreenshot(); +}); diff --git a/core/src/components/accordion/test/nested/index.html b/core/src/components/accordion/test/nested/index.html new file mode 100644 index 0000000000..8b2f283e43 --- /dev/null +++ b/core/src/components/accordion/test/nested/index.html @@ -0,0 +1,145 @@ + + + + + Accordion - Nested + + + + + + + + + + + + Accordion - Nested + + + + + + Accordion - Basic + + + +
+
+

Nested

+ + + + + Attractions + + + + + + First Item + +
First item content!
+
+ + + Second Item + +
Second item content!
+
+ + + Third Item + +
Third item content!
+
+
+
+
+
+
+

Nested Disabled

+ + + + + Attractions + + + + + + First Item + +
First item content!
+
+ + + Second Item + +
Second item content!
+
+ + + Third Item + +
Third item content!
+
+
+
+
+
+
+

Nested Parent Disabled

+ + + + + Attractions + + + + + + First Item + +
First item content!
+
+ + + Second Item + +
Second item content!
+
+ + + Third Item + +
Third item content!
+
+
+
+
+
+
+
+
+ + diff --git a/core/src/css/core.scss b/core/src/css/core.scss index 32641e220c..c2e0ea4868 100644 --- a/core/src/css/core.scss +++ b/core/src/css/core.scss @@ -274,19 +274,19 @@ ion-card-header.ion-color .ion-inherit-color { } // Accordion Styles -ion-accordion-group.accordion-group-expand-inset ion-accordion:first-of-type { +ion-accordion-group.accordion-group-expand-inset > ion-accordion:first-of-type { border-top-left-radius: 8px; border-top-right-radius: 8px; } -ion-accordion-group.accordion-group-expand-inset ion-accordion:last-of-type { +ion-accordion-group.accordion-group-expand-inset > ion-accordion:last-of-type { border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; } -ion-accordion-group ion-accordion:last-of-type ion-item { +ion-accordion-group > ion-accordion:last-of-type ion-item { --border-width: 0px; } -ion-accordion.accordion-animated .ion-accordion-toggle-icon { +ion-accordion.accordion-animated > [slot="header"] .ion-accordion-toggle-icon { transition: 300ms transform cubic-bezier(0.25, 0.8, 0.5, 1); } @@ -296,18 +296,24 @@ ion-accordion.accordion-animated .ion-accordion-toggle-icon { transition: none !important; } } - -ion-accordion.accordion-expanding .ion-accordion-toggle-icon, -ion-accordion.accordion-expanded .ion-accordion-toggle-icon { +/** + * The > [slot="header"] selector ensures that we do + * not modify toggle icons for any nested accordions. The state + * of one accordion should not affect any accordions inside + * of a nested accordion group. + */ +ion-accordion.accordion-expanding > [slot="header"] .ion-accordion-toggle-icon, +ion-accordion.accordion-expanded > [slot="header"] .ion-accordion-toggle-icon { transform: rotate(180deg); } -ion-accordion-group.accordion-group-expand-inset.md ion-accordion.accordion-previous ion-item[slot="header"] { + +ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-previous ion-item[slot="header"] { --border-width: 0px; --inner-border-width: 0px; } -ion-accordion-group.accordion-group-expand-inset.md ion-accordion.accordion-expanding:first-of-type, -ion-accordion-group.accordion-group-expand-inset.md ion-accordion.accordion-expanded:first-of-type { +ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-expanding:first-of-type, +ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-expanded:first-of-type { margin-top: 0; }