Skip to content

Commit

Permalink
feat(Modal): add "bypass_invalidation_selectors" property to omit ele…
Browse files Browse the repository at this point in the history
…ment invalidation

Co-authored-by: Anders <anderslangseth@gmail.com>
  • Loading branch information
tujoworker and langz committed May 10, 2022
1 parent f8a7795 commit d9cb392
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 50 deletions.

Large diffs are not rendered by default.

Expand Up @@ -704,6 +704,7 @@ exports[`Dialog component snapshot should match component snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down Expand Up @@ -759,6 +760,7 @@ exports[`Dialog component snapshot should match component snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down
Expand Up @@ -702,6 +702,7 @@ exports[`Drawer component snapshot should match component snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down Expand Up @@ -756,6 +757,7 @@ exports[`Drawer component snapshot should match component snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/components/modal/Modal.tsx
Expand Up @@ -420,6 +420,7 @@ class Modal extends React.PureComponent<
focus_selector = null,
header_content = null,
bar_content = null,
bypass_invalidation_selectors = null,

id, // eslint-disable-line
open_state, // eslint-disable-line
Expand Down Expand Up @@ -515,6 +516,7 @@ class Modal extends React.PureComponent<
modal_content={modal_content}
header_content={header_content}
bar_content={bar_content}
bypass_invalidation_selectors={bypass_invalidation_selectors}
close={this.close}
hide={hide}
title={rest.title || fallbackTitle}
Expand Down
3 changes: 2 additions & 1 deletion packages/dnb-eufemia/src/components/modal/ModalContent.tsx
Expand Up @@ -127,7 +127,8 @@ export default class ModalContent extends React.PureComponent<
// TODO: Eventually in future, make it possible to bypass invalidation from outside
// '.dnb-modal--bypass_invalidation',
// '.dnb-modal--bypass_invalidation_deep *',
// this.props.bypass_invalidation_selectors,

...(this.props?.bypass_invalidation_selectors || []),
].filter(Boolean)
)
this._ii.activate()
Expand Down
75 changes: 59 additions & 16 deletions packages/dnb-eufemia/src/components/modal/__tests__/Modal.test.tsx
Expand Up @@ -73,44 +73,87 @@ describe('Modal component', () => {

it('should have aria-hidden and tabindex on other elements', () => {
const Comp = mount(
<Component {...props}>
<button>button</button>
</Component>,
<>
<button className="bypass-me">button</button>
<Component no_animation>
<button className="but-not-me">button</button>
</Component>
</>,
{ attachTo: attachToBody() }
)

// Check the global button
Comp.find('Modal').find('button.dnb-modal__trigger').simulate('click')
expect(document.querySelector('button') instanceof HTMLElement).toBe(
true
)

// Check the global button
expect(
document.querySelector('button').hasAttribute('aria-hidden')
document.querySelector('button.bypass-me') instanceof HTMLElement
).toBe(true)
expect(document.querySelector('button').getAttribute('tabindex')).toBe(
'-1'
)
Comp.update()
expect(
document
.querySelector('button.bypass-me')
.hasAttribute('aria-hidden')
).toBe(true)
expect(
document.querySelector('button.bypass-me').getAttribute('tabindex')
).toBe('-1')
expect(
Comp.find('.dnb-modal__content')
.instance()
.hasAttribute('aria-hidden')
).toBe(false)
expect(
Comp.find('.dnb-modal__content')
.find('button')
.find('button.but-not-me')
.instance()
.hasAttribute('aria-hidden')
).toBe(false)

// And close it again
Comp.find('button.dnb-modal__close-button').simulate('click')
expect(
document.querySelector('button').hasAttribute('aria-hidden')
document
.querySelector('button.bypass-me')
.hasAttribute('aria-hidden')
).toBe(false)
expect(
document.querySelector('button.bypass-me').hasAttribute('tabindex')
).toBe(false)
expect(document.querySelector('button').hasAttribute('tabindex')).toBe(
false
})

it('should bypass elements defined in bypass_invalidation_selectors', () => {
const Comp = mount(
<>
<button className="bypass-me">button</button>
<button className="but-not-me">button</button>
<Component
no_animation
bypassInvalidationSelectors={['.bypass-me']}
>
content
</Component>
</>,
{ attachTo: attachToBody() }
)

Comp.find('Modal').find('button.dnb-modal__trigger').simulate('click')

expect(
document
.querySelector('button.bypass-me')
.hasAttribute('aria-hidden')
).toBe(false)
expect(
document.querySelector('button.bypass-me').hasAttribute('tabindex')
).toBe(false)

expect(
document
.querySelector('button.but-not-me')
.getAttribute('aria-hidden')
).toBe('true')
expect(
document.querySelector('button.but-not-me').getAttribute('tabindex')
).toBe('-1')
})

it('has to have the correct title', () => {
Expand Down
Expand Up @@ -699,6 +699,7 @@ exports[`Modal component have to match snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down Expand Up @@ -745,6 +746,7 @@ exports[`Modal component have to match snapshot 1`] = `
align_content="left"
animation_duration={300}
bar_content={null}
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down Expand Up @@ -798,6 +800,7 @@ exports[`Modal component have to match snapshot 1`] = `
}
}
alignContent="left"
bypass_invalidation_selectors={null}
class={null}
className={null}
class_name={null}
Expand Down Expand Up @@ -830,6 +833,7 @@ exports[`Modal component have to match snapshot 1`] = `
"props": Object {},
}
}
bypass_invalidation_selectors={null}
className="dnb-dialog dnb-dialog--auto-fullscreen dnb-core-style dnb-dialog--information dnb-dialog--spacing dnb-dialog__align--left dnb-dialog--no-animation"
class_name={null}
close_modal={null}
Expand All @@ -855,6 +859,7 @@ exports[`Modal component have to match snapshot 1`] = `
"props": Object {},
}
}
bypass_invalidation_selectors={null}
class={null}
className="dnb-dialog dnb-dialog--auto-fullscreen dnb-core-style dnb-dialog--information dnb-dialog--spacing dnb-dialog__align--left dnb-dialog--no-animation"
class_name={null}
Expand Down
5 changes: 5 additions & 0 deletions packages/dnb-eufemia/src/components/modal/types.ts
Expand Up @@ -307,6 +307,11 @@ export interface ModalContentProps {
*/
overlay_class?: string

/**
* Define an array with HTML class selectors (`['.element-selector']`) which should not get invalidated when the modal opens/closes. Use this in order to let some parts of your site still be accessible by screen readers.
*/
bypass_invalidation_selectors?: Array<string>

/**
* For internal usage
* Will close the modal
Expand Down

0 comments on commit d9cb392

Please sign in to comment.