From 93e17559ceef280b0fc4470300bf71ea85288621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20=C5=A0er=C3=BD?= Date: Fri, 14 Mar 2025 11:10:04 +0100 Subject: [PATCH 1/3] fix: Check for responsive collapsable in `handleExpandCollapse` The `handleExpandCollapse` method checks whether the collapsable element is responsive. If it is, the method proceeds only if the media query matches. --- src/CollapsableItem.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CollapsableItem.ts b/src/CollapsableItem.ts index 0dae07f..2eccfef 100644 --- a/src/CollapsableItem.ts +++ b/src/CollapsableItem.ts @@ -179,6 +179,10 @@ export class CollapsableItem { * Handling common parts of expanding and collapsing */ private handleExpandCollapse(action: CollapsableItemAction, collapsableEvent: any, data: any): boolean { + if (this.media && !this.media.matches) { + return false + } + const { options } = this.collapsable let eventName: CollapsableItemEvents = 'expanded.collapsable' let addClass = options.classNames.expanded From 6262231f007832fefdaf3087452d7e7cae7515d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20=C5=A0er=C3=BD?= Date: Fri, 14 Mar 2025 11:20:43 +0100 Subject: [PATCH 2/3] fix: Better handling of `dataset.collapsableState` The `dataset.collapsableState` is modified only when `CollapsableEvent`s are associated with the expanding or collapsing elements. This ensures that events from nested collapsable elements do not affect the `dataset.collapsableState` further up the DOM tree. --- src/CollapsableItem.ts | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/CollapsableItem.ts b/src/CollapsableItem.ts index 2eccfef..60bbf60 100644 --- a/src/CollapsableItem.ts +++ b/src/CollapsableItem.ts @@ -17,7 +17,7 @@ type ListenersMapItem = { type CollapsableElementListeners = { eventName: CollapsableItemEvents - listener: EventListener + listener: (event: CollapsableEvent) => void } export interface HTMLCollapsableItem extends HTMLElement { @@ -121,6 +121,7 @@ export class CollapsableItem { private addHandlers(): void { const { options } = this.collapsable + const collapsableElement = this.element const interactiveElementsListener = (event: CustomEvent) => { const passEvent = event.detail.collapsableEvent ?? event @@ -137,19 +138,39 @@ export class CollapsableItem { const collapsableListeners: CollapsableElementListeners[] = [ { eventName: 'expand.collapsable', - listener: () => this.boxElements.forEach((box) => (box.dataset.collapsableState = 'expanding')) + listener: (event: CollapsableEvent) => { + if (event.target !== collapsableElement) { + return + } + this.boxElements.forEach((box) => (box.dataset.collapsableState = 'expanding')) + } }, { eventName: 'collapse.collapsable', - listener: () => this.boxElements.forEach((box) => (box.dataset.collapsableState = 'collapsing')) + listener: (event: CollapsableEvent) => { + if (event.target !== collapsableElement) { + return + } + this.boxElements.forEach((box) => (box.dataset.collapsableState = 'collapsing')) + } }, { eventName: 'expanded.collapsable', - listener: () => this.boxElements.forEach((box) => delete box.dataset.collapsableState) + listener: (event: CollapsableEvent) => { + if (event.target !== collapsableElement) { + return + } + this.boxElements.forEach((box) => delete box.dataset.collapsableState) + } }, { eventName: 'collapsed.collapsable', - listener: () => this.boxElements.forEach((box) => delete box.dataset.collapsableState) + listener: (event: CollapsableEvent) => { + if (event.target !== collapsableElement) { + return + } + this.boxElements.forEach((box) => delete box.dataset.collapsableState) + } } ] @@ -165,7 +186,7 @@ export class CollapsableItem { this.addCollapsableEventListener({ element: this.element, eventName: collapsableListener.eventName, - listener: collapsableListener.listener + listener: collapsableListener.listener as EventListener }) }) } From 5dce013aa45b0faa601c61df1f32157f3f1e8065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20=C5=A0er=C3=BD?= Date: Fri, 14 Mar 2025 11:20:55 +0100 Subject: [PATCH 3/3] fix: Better attribute clean up on destroy On destroy, the `dataset.collapsableState` is removed from boxes, and the `role` attribute is removed from `extLink`. --- src/CollapsableExtLink.ts | 1 + src/CollapsableItem.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/CollapsableExtLink.ts b/src/CollapsableExtLink.ts index de4966a..cc6ca18 100644 --- a/src/CollapsableExtLink.ts +++ b/src/CollapsableExtLink.ts @@ -74,6 +74,7 @@ export class CollapsableExtLink { this.extLink.removeEventListener('click', this.listener) this.extLink.removeAttribute('aria-controls') this.extLink.removeAttribute(this.ariaPerRole) + this.extLink.removeAttribute('role') } } } diff --git a/src/CollapsableItem.ts b/src/CollapsableItem.ts index 60bbf60..a085013 100644 --- a/src/CollapsableItem.ts +++ b/src/CollapsableItem.ts @@ -418,6 +418,7 @@ export class CollapsableItem { this.boxElements.forEach((box) => { box.removeAttribute('aria-hidden') box.removeAttribute('hidden') + delete box.dataset.collapsableState }) this.element.dispatchEvent(new CustomEvent('destroy.collapsable', { bubbles: true }))