File tree Expand file tree Collapse file tree 5 files changed +88
-0
lines changed Expand file tree Collapse file tree 5 files changed +88
-0
lines changed Original file line number Diff line number Diff line change @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020- Reset Combobox Input when the value gets reset ([ #1181 ] ( https://github.com/tailwindlabs/headlessui/pull/1181 ) )
2121- Fix double ` beforeEnter ` due to SSR ([ #1183 ] ( https://github.com/tailwindlabs/headlessui/pull/1183 ) )
2222- Adjust active {item,option} index ([ #1184 ] ( https://github.com/tailwindlabs/headlessui/pull/1184 ) )
23+ - Only activate the ` Tab ` on mouseup ([ #1192 ] ( https://github.com/tailwindlabs/headlessui/pull/1192 ) )
24+ - Ignore "outside click" on removed elements ([ #1193 ] ( https://github.com/tailwindlabs/headlessui/pull/1193 ) )
2325
2426## [ Unreleased - @headlessui/vue ]
2527
@@ -36,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3638- Adjust active {item,option} index ([ #1184 ] ( https://github.com/tailwindlabs/headlessui/pull/1184 ) )
3739- Fix re-focusing element after close ([ #1186 ] ( https://github.com/tailwindlabs/headlessui/pull/1186 ) )
3840- Fix ` Dialog ` cycling ([ #553 ] ( https://github.com/tailwindlabs/headlessui/pull/553 ) )
41+ - Only activate the ` Tab ` on mouseup ([ #1192 ] ( https://github.com/tailwindlabs/headlessui/pull/1192 ) )
42+ - Ignore "outside click" on removed elements ([ #1193 ] ( https://github.com/tailwindlabs/headlessui/pull/1193 ) )
3943
4044## [ @headlessui/react @v1.5.0] - 2022-02-17
4145
Original file line number Diff line number Diff line change @@ -806,6 +806,43 @@ describe('Mouse interactions', () => {
806806 expect ( wrapperFn ) . toHaveBeenCalledTimes ( 0 )
807807 } )
808808 )
809+
810+ it (
811+ 'should should be possible to click on removed elements without closing the Dialog' ,
812+ suppressConsoleLogs ( async ( ) => {
813+ function Example ( ) {
814+ let [ isOpen , setIsOpen ] = useState ( true )
815+ let wrapper = useRef < HTMLDivElement | null > ( null )
816+
817+ return (
818+ < Dialog open = { isOpen } onClose = { setIsOpen } >
819+ < div ref = { wrapper } >
820+ Contents
821+ < button
822+ onMouseDown = { ( ) => {
823+ // Remove this button before the Dialog's mousedown listener fires:
824+ wrapper . current ?. remove ( )
825+ } }
826+ >
827+ Inside
828+ </ button >
829+ < TabSentinel />
830+ </ div >
831+ </ Dialog >
832+ )
833+ }
834+ render ( < Example /> )
835+
836+ // Verify it is open
837+ assertDialog ( { state : DialogState . Visible } )
838+
839+ // Click the button inside the the Dialog
840+ await click ( getByText ( 'Inside' ) )
841+
842+ // Verify it is still open
843+ assertDialog ( { state : DialogState . Visible } )
844+ } )
845+ )
809846} )
810847
811848describe ( 'Nesting' , ( ) => {
Original file line number Diff line number Diff line change @@ -47,6 +47,10 @@ export function useOutsideClick(
4747
4848 let target = event . target as HTMLElement
4949
50+ // Ignore if the target doesn't exist in the DOM anymore
51+ if ( ! target . ownerDocument . documentElement . contains ( target ) ) return
52+
53+ // Ignore if the target exists in one of the containers
5054 for ( let container of _containers ) {
5155 if ( container === null ) continue
5256 let domNode = container instanceof HTMLElement ? container : container . current
Original file line number Diff line number Diff line change @@ -997,6 +997,44 @@ describe('Mouse interactions', () => {
997997 expect ( wrapperFn ) . toHaveBeenCalledTimes ( 0 )
998998 } )
999999 )
1000+
1001+ it (
1002+ 'should should be possible to click on removed elements without closing the Dialog' ,
1003+ suppressConsoleLogs ( async ( ) => {
1004+ renderTemplate ( {
1005+ template : `
1006+ <Dialog :open="isOpen" @close="setIsOpen">
1007+ <div ref="wrapper">
1008+ Contents
1009+ <!-- Remove this button before the Dialog's mousedown listener fires: -->
1010+ <button @mousedown="wrapper.remove()">Inside</button>
1011+ <TabSentinel />
1012+ </div>
1013+ </Dialog>
1014+ ` ,
1015+ setup ( ) {
1016+ let isOpen = ref ( true )
1017+ let wrapper = ref < HTMLDivElement | null > ( null )
1018+ return {
1019+ isOpen,
1020+ wrapper,
1021+ setIsOpen ( value : boolean ) {
1022+ isOpen . value = value
1023+ } ,
1024+ }
1025+ } ,
1026+ } )
1027+
1028+ // Verify it is open
1029+ assertDialog ( { state : DialogState . Visible } )
1030+
1031+ // Click the button inside the the Dialog
1032+ await click ( getByText ( 'Inside' ) )
1033+
1034+ // Verify it is still open
1035+ assertDialog ( { state : DialogState . Visible } )
1036+ } )
1037+ )
10001038} )
10011039
10021040describe ( 'Nesting' , ( ) => {
Original file line number Diff line number Diff line change @@ -34,6 +34,10 @@ export function useOutsideClick(
3434 } )
3535
3636 let target = event . target as HTMLElement
37+
38+ // Ignore if the target doesn't exist in the DOM anymore
39+ if ( ! target . ownerDocument . documentElement . contains ( target ) ) return
40+
3741 let _containers = ( ( ) => {
3842 if ( Array . isArray ( containers ) ) {
3943 return containers
@@ -46,6 +50,7 @@ export function useOutsideClick(
4650 return [ containers ]
4751 } ) ( )
4852
53+ // Ignore if the target exists in one of the containers
4954 for ( let container of _containers ) {
5055 if ( container === null ) continue
5156 let domNode = container instanceof HTMLElement ? container : dom ( container )
You can’t perform that action at this time.
0 commit comments