Skip to content

Commit 48a428f

Browse files
committed
Add test for search
1 parent f7e0452 commit 48a428f

6 files changed

Lines changed: 86 additions & 11 deletions

File tree

cypress/e2e/useMultipleCombobox.cy.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('useMultipleCombobox', () => {
2626
})
2727

2828
describe('useMultipleCombobox in shadow DOM', () => {
29-
before(() => {
29+
beforeEach(() => {
3030
cy.visit('/shadow-dom/useMultipleCombobox')
3131
})
3232

@@ -54,4 +54,25 @@ describe('useMultipleCombobox in shadow DOM', () => {
5454
cy.findByText('Gray').should('be.visible')
5555
})
5656
})
57+
58+
it('can filter the items', () => {
59+
cy.get('[data-testid="shadow-root"]')
60+
.shadow()
61+
.within(() => {
62+
cy.findByRole('button', {name: 'toggle menu'}).click()
63+
cy.findAllByRole('option').should('have.length', 12)
64+
cy.findByRole('combobox').type('g')
65+
cy.findByRole('button', {name: 'toggle menu'}).should(
66+
'have.attr',
67+
'aria-expanded',
68+
'true',
69+
)
70+
cy.findAllByRole('option').should('have.length', 2)
71+
cy.findByText('Green').should('be.visible')
72+
cy.findByText('Gray').should('be.visible')
73+
74+
cy.findByRole('combobox').type('{backspace}')
75+
cy.findAllByRole('option').should('have.length', 12)
76+
})
77+
})
5778
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'react'
2+
3+
import DropdownCombobox from '../useCombobox'
4+
import {ReactShadowRoot} from '../../../test/react-shadow'
5+
6+
const style = {
7+
padding: '20px',
8+
}
9+
10+
export default function MultipleComboboxShadow() {
11+
return (
12+
<div style={style}>
13+
<h2>Shadow DOM</h2>
14+
<div data-testid="shadow-root">
15+
<ReactShadowRoot>
16+
<DropdownCombobox />
17+
</ReactShadowRoot>
18+
</div>
19+
</div>
20+
)
21+
}

docusaurus/pages/shadow-dom/useMultipleCombobox.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import * as React from 'react'
33
import DropdownMultipleCombobox from '../useMultipleCombobox'
44
import {ReactShadowRoot} from '../../../test/react-shadow'
55

6+
const style = {
7+
padding: '20px',
8+
}
9+
610
export default function MultipleComboboxShadow() {
711
return (
8-
<div>
12+
<div style={style}>
913
<div>
1014
<button>Button before shadow root</button>
1115
</div>

src/downshift.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,15 @@ class Downshift extends Component {
764764
return
765765
}
766766

767-
const {activeElement} = this.props.environment.document
767+
let {activeElement} = this.props.environment.document
768+
769+
// find the real activeElement not a custom element with a shadowRoot
770+
while (
771+
activeElement?.shadowRoot &&
772+
activeElement.shadowRoot.activeElement != null
773+
) {
774+
activeElement = activeElement.shadowRoot.activeElement
775+
}
768776

769777
if (
770778
(activeElement == null || activeElement.id !== this.inputId) &&
@@ -877,13 +885,26 @@ class Downshift extends Component {
877885
return
878886
}
879887

880-
const {activeElement} = this.props.environment.document
888+
let {activeElement} = this.props.environment.document
889+
while (
890+
activeElement?.shadowRoot &&
891+
activeElement.shadowRoot.activeElement != null
892+
) {
893+
activeElement = activeElement.shadowRoot.activeElement
894+
}
895+
881896
const downshiftButtonIsActive =
882897
activeElement?.dataset?.toggle &&
883898
this._rootNode &&
884899
this._rootNode.contains(activeElement)
885900

886-
if (!downshiftButtonIsActive) {
901+
// We check for the containment of the newly activeElement in the _menuNode here due to iOS emitting a blur event right away when the menu is opened (maybe due to not showing the keyboard?)
902+
const activeElementIsInMenu =
903+
activeElement &&
904+
this._menuNode &&
905+
this._menuNode.contains(activeElement)
906+
907+
if (!downshiftButtonIsActive && !activeElementIsInMenu) {
887908
this.reset({type: stateChangeTypes.blurInput})
888909
}
889910
})

src/hooks/useCombobox/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,16 @@ function useCombobox(userProps = {}) {
129129
if (!isOpen || !environment?.document || !inputRef?.current?.focus) {
130130
return
131131
}
132+
let {activeElement} = environment.document
133+
// find the real activeElement not a custom element with a shadowRoot
134+
while (
135+
activeElement?.shadowRoot &&
136+
activeElement.shadowRoot.activeElement != null
137+
) {
138+
activeElement = activeElement.shadowRoot.activeElement
139+
}
132140

133-
if (environment.document.activeElement !== inputRef.current) {
141+
if (activeElement !== inputRef.current) {
134142
inputRef.current.focus()
135143
}
136144
}, [isOpen, environment])

test/react-shadow.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ const shadowRootSupported =
2121

2222
/**
2323
* @param {object} props Properties passed to the component
24-
* @param {boolean} props.declarative When true, uses a declarative shadow root
25-
* @param {boolean} props.delegatesFocus Expands the focus behavior of elements within the shadow DOM.
26-
* @param {string} props.mode Sets the mode of the shadow root. (open or closed)
27-
* @param {CSSStyleSheet[]} props.stylesheets Takes an array of CSSStyleSheet objects for constructable stylesheets.
28-
* @param {React.ReactNode} props.children The children of the component
24+
* @param {boolean} [props.declarative] When true, uses a declarative shadow root
25+
* @param {boolean} [props.delegatesFocus] Expands the focus behavior of elements within the shadow DOM.
26+
* @param {string} [props.mode] Sets the mode of the shadow root. (open or closed)
27+
* @param {CSSStyleSheet[]} [props.stylesheets] Takes an array of CSSStyleSheet objects for constructable stylesheets.
28+
* @param {React.ReactNode} props.children The component to render within the shadow root.
2929
*/
3030
const ReactShadowRoot = ({
3131
declarative = false,

0 commit comments

Comments
 (0)