Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(accordion): improve functionality with nested accordions #24302

Merged
merged 5 commits into from
Dec 6, 2021
Merged
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
2 changes: 1 addition & 1 deletion core/src/components/accordion-group/accordion-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
4 changes: 3 additions & 1 deletion core/src/components/accordion/accordion.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
55 changes: 55 additions & 0 deletions core/src/components/accordion/test/accordion.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { newE2EPage } from '@stencil/core/testing';

test('should properly set readonly on child accordions', async () => {
const page = await newE2EPage({
html: `
<ion-accordion-group animated="false">
<ion-accordion>
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
</ion-accordion-group>
`
});

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: `
<ion-accordion-group animated="false">
<ion-accordion>
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
</ion-accordion-group>
`
});

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);
});
58 changes: 0 additions & 58 deletions core/src/components/accordion/test/accordion.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `
<ion-accordion-group animated="false">
<ion-accordion>
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
</ion-accordion-group>
`
});

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: `
<ion-accordion-group animated="false">
<ion-accordion>
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
</ion-accordion-group>
`
});

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],
Expand Down
10 changes: 10 additions & 0 deletions core/src/components/accordion/test/nested/e2e.ts
Original file line number Diff line number Diff line change
@@ -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();
});
145 changes: 145 additions & 0 deletions core/src/components/accordion/test/nested/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Accordion - Nested</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<style>
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-row-gap: 20px;
grid-column-gap: 20px;
}
h2 {
font-size: 12px;
font-weight: normal;

color: #6f7378;

margin-top: 10px;
margin-left: 5px;
}
</style>
</head>
<body>
<ion-app>
<ion-header translucent="true">
<ion-toolbar>
<ion-title>Accordion - Nested</ion-title>
</ion-toolbar>
</ion-header>
<ion-content fullscreen="true" color="light">
<ion-header collapse="condense">
<ion-toolbar color="light">
<ion-title size="large">Accordion - Basic</ion-title>
</ion-toolbar>
</ion-header>

<div class="grid ion-padding">
<div class="grid-item">
<h2>Nested</h2>
<ion-accordion-group expand="inset" value="attractions">
<ion-accordion value="attractions">
<ion-item color="primary" slot="header" button detail="false">
<ion-icon slot="start" ios="film-outline" md="film"></ion-icon>
<ion-label> Attractions</ion-label>
</ion-item>

<ion-accordion-group slot="content" value="second">
<ion-accordion value="first">
<ion-item color="primary" slot="header" button detail="false">
<ion-label>First Item</ion-label>
</ion-item>
<div slot="content">First item content!</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item color="warning" slot="header" button detail="false">
<ion-label>Second Item</ion-label>
</ion-item>
<div slot="content">Second item content!</div>
</ion-accordion>
<ion-accordion value="third">
<ion-item color="tertiary" slot="header" button detail="false">
<ion-label>Third Item</ion-label>
</ion-item>
<div slot="content">Third item content!</div>
</ion-accordion>
</ion-accordion-group>
</ion-accordion>
</ion-accordion-group>
</div>
<div class="grid-item">
<h2>Nested Disabled</h2>
<ion-accordion-group expand="inset" value="attractions">
<ion-accordion value="attractions">
<ion-item color="primary" slot="header" button detail="false">
<ion-icon slot="start" ios="film-outline" md="film"></ion-icon>
<ion-label> Attractions</ion-label>
</ion-item>

<ion-accordion-group slot="content" value="second" disabled="true">
<ion-accordion value="first">
<ion-item color="primary" slot="header" button detail="false">
<ion-label>First Item</ion-label>
</ion-item>
<div slot="content">First item content!</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item color="warning" slot="header" button detail="false">
<ion-label>Second Item</ion-label>
</ion-item>
<div slot="content">Second item content!</div>
</ion-accordion>
<ion-accordion value="third">
<ion-item color="tertiary" slot="header" button detail="false">
<ion-label>Third Item</ion-label>
</ion-item>
<div slot="content">Third item content!</div>
</ion-accordion>
</ion-accordion-group>
</ion-accordion>
</ion-accordion-group>
</div>
<div class="grid-item">
<h2>Nested Parent Disabled</h2>
<ion-accordion-group expand="inset" value="attractions" disabled="true">
<ion-accordion value="attractions">
<ion-item color="primary" slot="header" button detail="false">
<ion-icon slot="start" ios="film-outline" md="film"></ion-icon>
<ion-label> Attractions</ion-label>
</ion-item>

<ion-accordion-group slot="content" value="second">
<ion-accordion value="first">
<ion-item color="primary" slot="header" button detail="false">
<ion-label>First Item</ion-label>
</ion-item>
<div slot="content">First item content!</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item color="warning" slot="header" button detail="false">
<ion-label>Second Item</ion-label>
</ion-item>
<div slot="content">Second item content!</div>
</ion-accordion>
<ion-accordion value="third">
<ion-item color="tertiary" slot="header" button detail="false">
<ion-label>Third Item</ion-label>
</ion-item>
<div slot="content">Third item content!</div>
</ion-accordion>
</ion-accordion-group>
</ion-accordion>
</ion-accordion-group>
</div>
</div>
</ion-content>
</ion-app>
</body>
</html>
26 changes: 16 additions & 10 deletions core/src/css/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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;
}

Expand Down