From ae00f181d3eaa4845dcfdc1ad4150b98a5f76fd7 Mon Sep 17 00:00:00 2001 From: AhmadHannan037 Date: Tue, 5 May 2026 00:13:19 +0500 Subject: [PATCH] fix(isVisible): treat in closed
as visible Closes #2626 --- src/utils/isElementVisible.ts | 32 ++++++++++++++++++------- tests/isVisible.spec.ts | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/utils/isElementVisible.ts b/src/utils/isElementVisible.ts index 27aa0cfd4..f2394ee9e 100644 --- a/src/utils/isElementVisible.ts +++ b/src/utils/isElementVisible.ts @@ -19,18 +19,34 @@ function isStyleVisible(element: T) { ) } -function isAttributeVisible(element: T) { - return ( - !element.hasAttribute('hidden') && - (element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true) - ) +function isAttributeVisible( + element: T, + childElement?: Element +) { + if (element.hasAttribute('hidden')) return false + + // A closed
renders only its : the
itself is + // visible, the is visible, but other descendants are not. + if ( + element.nodeName === 'DETAILS' && + !element.hasAttribute('open') && + childElement && + childElement.nodeName !== 'SUMMARY' + ) { + return false + } + + return true } -export function isElementVisible(element: T): boolean { +export function isElementVisible( + element: T, + childElement?: Element +): boolean { return ( element.nodeName !== '#comment' && isStyleVisible(element) && - isAttributeVisible(element) && - (!element.parentElement || isElementVisible(element.parentElement)) + isAttributeVisible(element, childElement) && + (!element.parentElement || isElementVisible(element.parentElement, element)) ) } diff --git a/tests/isVisible.spec.ts b/tests/isVisible.spec.ts index 2de407a61..fc8ff9bf9 100644 --- a/tests/isVisible.spec.ts +++ b/tests/isVisible.spec.ts @@ -117,6 +117,50 @@ describe('isVisible', () => { expect(wrapper.html()).not.toContain('Item: 2') }) + describe('details element', () => { + const Comp = defineComponent({ + props: { + open: { type: Boolean, default: false } + }, + template: ` +
+ Toggle +

Content

+
+ ` + }) + + it('details, summary and content are visible when open', () => { + const wrapper = mount(Comp, { props: { open: true } }) + + expect(wrapper.get('details').isVisible()).toBe(true) + expect(wrapper.get('summary').isVisible()).toBe(true) + expect(wrapper.get('p.content').isVisible()).toBe(true) + }) + + it('details and summary stay visible when closed, content is hidden', () => { + const wrapper = mount(Comp, { props: { open: false } }) + + expect(wrapper.get('details').isVisible()).toBe(true) + expect(wrapper.get('summary').isVisible()).toBe(true) + expect(wrapper.get('p.content').isVisible()).toBe(false) + }) + + it('non-summary descendants of a closed details are hidden even when nested', () => { + const Nested = defineComponent({ + template: ` +
+ Toggle +
Deep
+
+ ` + }) + const wrapper = mount(Nested) + + expect(wrapper.get('span.deep').isVisible()).toBe(false) + }) + }) + it('should take css into account', async () => { const style = document.createElement('style') style.type = 'text/css'