Skip to content
Open
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
32 changes: 28 additions & 4 deletions src/utils/isElementVisible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,41 @@ function isStyleVisible<T extends Element>(element: T) {
}

function isAttributeVisible<T extends Element>(element: T) {
return (
!element.hasAttribute('hidden') &&
(element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true)
)
if (element instanceof HTMLInputElement && element.type === 'hidden') {
return false
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated to the issue, but an interesting addition. Could you either:

  • add a unit test in this PR
  • remove this change from this PR and open another one with a unit test

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the funciton no longer use attribute checking, maybe rename it to isElementVisible?


if (element instanceof HTMLElement && element.hidden) {
return false
}

return true
}

function isHiddenByClosedDetails<T extends Element>(element: T) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a few lines of jsdoc to explain what this function does

let parent = element.parentElement

while (parent) {
if (parent.nodeName === 'DETAILS' && !(parent as HTMLDetailsElement).open) {
if (
!(element.nodeName === 'SUMMARY' && element.parentElement === parent)
) {
return true
}
}

parent = parent.parentElement
}

return false
}

export function isElementVisible<T extends Element>(element: T): boolean {
return (
element.nodeName !== '#comment' &&
isStyleVisible(element) &&
isAttributeVisible(element) &&
!isHiddenByClosedDetails(element) &&
(!element.parentElement || isElementVisible(element.parentElement))
)
}
44 changes: 44 additions & 0 deletions tests/isVisible.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,50 @@ describe('isVisible', () => {
})
expect(wrapper.isVisible()).toBe(false)
})
it('DetailContent should be visible when summary is visible', () => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tests are under an unrelated test suite, maybe move them a new test suite:

describe('details and summary elements', () => {
  // test cases here
})

const DetailContent = defineComponent({
template: `<details><summary>Summary</summary><div>Content</div></details>`
})

const wrapper = mount(DetailContent)
expect(wrapper.find('details').isVisible()).toBe(true)
expect(wrapper.find('summary').isVisible()).toBe(true)
expect(wrapper.find('div').isVisible()).toBe(false)
})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a test case, like:

template: `<details><summary><span>Summary</span></summary><div>Content</div></details>`

expect(wrapper.find('summary span').isVisible()).toBe(true)

it('should consider a summary as hidden when an ancestor is hidden', () => {
const HiddenAncestorSummary = defineComponent({
template: `
<div style="display: none;">
<details>
<summary>Summary</summary>
</details>
</div>
`
})

const wrapper = mount(HiddenAncestorSummary)
expect(wrapper.find('summary').isVisible()).toBe(false)
})
it('should consider a summary as hidden when nested inside closed details content', () => {
const NestedSummaryInClosedDetails = defineComponent({
template: `
<details>
<summary>Main summary</summary>
<div>
<details>
<summary>Nested summary</summary>
</details>
</div>
</details>
`
})

const wrapper = mount(NestedSummaryInClosedDetails)
const summaries = wrapper.findAll('summary')

expect(summaries[0].isVisible()).toBe(true)
expect(summaries[1].isVisible()).toBe(false)
})
})
})
})
Loading