Skip to content

Commit c1d8811

Browse files
committed
feat(accordion): add skip-accordion-toggle attribute
1 parent 9e11fcb commit c1d8811

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

core/src/components/accordion/accordion.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,22 @@ export class Accordion implements ComponentInterface {
381381
return previousSibling as HTMLIonAccordionElement;
382382
};
383383

384-
private toggleExpanded() {
384+
private toggleExpanded(event: MouseEvent) {
385385
const { accordionGroupEl, disabled, readonly, value, state } = this;
386386

387387
if (disabled || readonly) return;
388388

389389
if (accordionGroupEl) {
390+
/**
391+
* We check if the element that was clicked has the attribute
392+
* skip-accordion-toggle. In case the element has it, then the accordion
393+
* won't request an accordion toggle if it's inside an accordion group
394+
*/
395+
const target = event.target as HTMLInputElement;
396+
if (target.hasAttribute('skip-accordion-toggle') && target.getAttribute('skip-accordion-toggle') !== 'false') {
397+
return;
398+
}
399+
390400
/**
391401
* Because the accordion group may or may
392402
* not allow multiple accordions open, we
@@ -428,7 +438,7 @@ export class Accordion implements ComponentInterface {
428438
}}
429439
>
430440
<div
431-
onClick={() => this.toggleExpanded()}
441+
onClick={($event) => this.toggleExpanded($event)}
432442
id="header"
433443
part={headerPart}
434444
aria-controls="content"

core/src/components/accordion/test/basic/accordion.e2e.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
3030
<button slot="header">Header</button>
3131
<div slot="content">Third Content</div>
3232
</ion-accordion>
33+
<ion-accordion value="fourth">
34+
<ion-item slot="header">
35+
<ion-button slot="start" skip-accordion-toggle>Skip Toggle</ion-button>
36+
<ion-label>Header</ion-label>
37+
</ion-item>
38+
<div slot="content">Fourth Content</div>
39+
</ion-accordion>
40+
<ion-accordion value="fifth">
41+
<ion-item slot="header">
42+
<ion-button slot="start" skip-accordion-toggle="false">Skip Toggle</ion-button>
43+
<ion-label>Header</ion-label>
44+
</ion-item>
45+
<div slot="content">Fifth Content</div>
46+
</ion-accordion>
3347
</ion-accordion-group>
3448
`,
3549
config
@@ -49,6 +63,24 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
4963
await expect(ionChange).toHaveReceivedEventDetail({ value: 'third' });
5064
});
5165

66+
test('should not fire ionChange when click comes from an element with skip-accordion-toggle', async ({ page }) => {
67+
const ionChange = await page.spyOnEvent('ionChange');
68+
const skipAccordionToggles = page.locator('[skip-accordion-toggle]');
69+
70+
await skipAccordionToggles.nth(0).click();
71+
await expect(ionChange).not.toHaveReceivedEvent();
72+
});
73+
74+
test('should fire ionChange when click comes from an element with skip-accordion-toggle set to false', async ({
75+
page,
76+
}) => {
77+
const ionChange = await page.spyOnEvent('ionChange');
78+
const skipAccordionToggles = page.locator('[skip-accordion-toggle="false"]');
79+
80+
await skipAccordionToggles.nth(0).click();
81+
await expect(ionChange).toHaveReceivedEventDetail({ value: 'fourth' });
82+
});
83+
5284
test('should not fire when programmatically setting a valid value', async ({ page }) => {
5385
const ionChange = await page.spyOnEvent('ionChange');
5486
const accordionGroup = page.locator('ion-accordion-group');

core/src/components/accordion/test/basic/index.html

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,87 @@ <h2>Compact</h2>
344344
</ion-accordion>
345345
</ion-accordion-group>
346346
</div>
347+
348+
<div class="grid-item">
349+
<h2>Radio Group with skip-accordion-toggle</h2>
350+
<ion-accordion-group value="attractions">
351+
<ion-radio-group>
352+
<ion-accordion value="attractions">
353+
<ion-item color="primary" slot="header" button detail="false">
354+
<ion-radio slot="start" value="attractions" color="light" skip-accordion-toggle></ion-radio>
355+
<ion-icon slot="start" ios="film-outline" md="film"></ion-icon>
356+
<ion-label>Attractions</ion-label>
357+
</ion-item>
358+
<ion-list lines="none" slot="content">
359+
<ion-item>
360+
<ion-label>Movie Theaters</ion-label>
361+
</ion-item>
362+
<ion-item>
363+
<ion-label>Amusement Parks</ion-label>
364+
</ion-item>
365+
<ion-item>
366+
<ion-label>Mini Golf</ion-label>
367+
</ion-item>
368+
</ion-list>
369+
</ion-accordion>
370+
<ion-accordion value="dining">
371+
<ion-item color="warning" slot="header" button detail="false">
372+
<ion-radio slot="start" value="dining" color="light" skip-accordion-toggle></ion-radio>
373+
<ion-icon slot="start" name="pizza"></ion-icon>
374+
<ion-label>Dining</ion-label>
375+
</ion-item>
376+
<ion-list lines="none" slot="content">
377+
<ion-item>
378+
<ion-label>Breakfast & Brunch</ion-label>
379+
</ion-item>
380+
<ion-item>
381+
<ion-label>New American</ion-label>
382+
</ion-item>
383+
<ion-item>
384+
<ion-label>Sushi Bars</ion-label>
385+
</ion-item>
386+
</ion-list>
387+
</ion-accordion>
388+
<ion-accordion value="games">
389+
<ion-item color="danger" slot="header" button detail="false">
390+
<ion-radio slot="start" value="games" color="light" skip-accordion-toggle></ion-radio>
391+
<ion-icon slot="start" ios="game-controller-outline" md="game-controller"></ion-icon>
392+
<ion-label>Games</ion-label>
393+
</ion-item>
394+
395+
<ion-list lines="none" slot="content">
396+
<ion-item>
397+
<ion-label>Xbox</ion-label>
398+
</ion-item>
399+
<ion-item>
400+
<ion-label>Playstation</ion-label>
401+
</ion-item>
402+
<ion-item>
403+
<ion-label>Switch</ion-label>
404+
</ion-item>
405+
</ion-list>
406+
</ion-accordion>
407+
<ion-accordion value="exercise">
408+
<ion-item color="success" slot="header" button detail="false">
409+
<ion-radio slot="start" value="exercise" color="light" [skip-accordion-toggle]="false"></ion-radio>
410+
<ion-label>This radio button toggles accordion</ion-label>
411+
</ion-item>
412+
413+
<ion-list lines="none" slot="content">
414+
<ion-item>
415+
<ion-label>Jog</ion-label>
416+
</ion-item>
417+
<ion-item>
418+
<ion-label>Swim</ion-label>
419+
</ion-item>
420+
<ion-item>
421+
<ion-label>Nap</ion-label>
422+
</ion-item>
423+
</ion-list>
424+
</ion-accordion>
425+
</ion-radio-group>
426+
</ion-accordion-group>
427+
</div>
347428
</div>
348429
</ion-content>
349430
</ion-app>

0 commit comments

Comments
 (0)