Browse Source

fix(tooltip): select in popover close bug #818 (#822)

走鹃 3 years ago
parent
commit
748c1dbc3f

+ 10 - 0
cypress/integration/popover.spec.js

@@ -91,4 +91,14 @@ describe('popover', () => {
         cy.get('[data-cy=pop-focusable-first]').type('{esc}', { force: true });
         cy.get('[data-cy=returnFocusOnClose-false]').should('not.be.focused');
     });
+
+    it('click select option in popover ', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=popover--fix-nested-popover&args=&viewMode=story');
+        cy.get('[data-cy=fix-nested-popover] .semi-tag').click();
+        cy.get('[data-cy=select-in-popover] .semi-select').click();
+        cy.get('[data-cy=select-in-popover] .semi-select').click();
+        cy.get('.semi-select-option').contains('西瓜视频').click();
+        cy.get('[data-cy=select-in-popover] .semi-select').should('be.visible');
+        cy.get('.semi-select-option').contains('西瓜视频').should('be.not.exist')
+    })
 });

+ 38 - 2
packages/semi-ui/popover/_story/popover.stories.js

@@ -2,7 +2,7 @@ import React, { useState } from 'react';
 
 import Popover from '../index';
 import { strings } from '@douyinfe/semi-foundation/tooltip/constants';
-import { Button, Input, Table, IconButton, Modal, Tag, Space } from '@douyinfe/semi-ui';
+import { Button, Input, Table, IconButton, Modal, Tag, Space, Select } from '@douyinfe/semi-ui';
 import SelectInPopover from './SelectInPopover';
 import BtnClose from './BtnClose';
 import PopRight from './PopRight';
@@ -10,6 +10,8 @@ import NestedPopover from './NestedPopover';
 import ArrowPointAtCenter from './ArrowPointAtCenter';
 import { IconDelete } from '@douyinfe/semi-icons';
 
+const Option = Select.Option;
+
 export default {
   title: 'Popover',
   parameters: {
@@ -645,4 +647,38 @@ export const A11yKeyboard = () => {
       </div>
   );
 };
-A11yKeyboard.storyName = "a11y keyboard and focus";
+A11yKeyboard.storyName = "a11y keyboard and focus";
+
+/**
+ * fix 嵌套 popover 的弹出层会导致外部 popover 关闭问题
+ * 
+ * @see https://github.com/DouyinFE/semi-design/issues/818
+ * @see https://github.com/facebook/react/issues/4335#issuecomment-421705171
+ */
+export const FixNestedPopover = () => {
+    return (
+        <div data-cy="fix-nested-popover" style={{ paddingLeft: 100 }}>
+            <Popover
+                content={(
+                    <div data-cy="select-in-popover" style={{ padding: 20 }}>
+                        <Select
+                            defaultValue="abc"
+                            style={{ width: 120 }}
+                        >
+                            <Option value="abc">抖音</Option>
+                            <Option value="hotsoon">火山</Option>
+                            <Option value="pipixia" disabled>
+                                皮皮虾
+                            </Option>
+                            <Option value="xigua">西瓜视频</Option>
+                        </Select>
+                    </div>
+                )}
+                trigger="click"
+                showArrow
+            >
+                <Tag>点击此处</Tag>
+            </Popover>
+        </div>
+    );
+}

+ 9 - 2
packages/semi-ui/tooltip/index.tsx

@@ -343,11 +343,11 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
                         cb();
                     }
                 };
-                document.addEventListener('mousedown', this.clickOutsideHandler, { capture: true });
+                window.addEventListener('mousedown', this.clickOutsideHandler);
             },
             unregisterClickOutsideHandler: () => {
                 if (this.clickOutsideHandler) {
-                    document.removeEventListener('mousedown', this.clickOutsideHandler, { capture: true });
+                    window.removeEventListener('mousedown', this.clickOutsideHandler);
                     this.clickOutsideHandler = null;
                 }
             },
@@ -528,6 +528,12 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
         }
     };
 
+    handlePortalMouseDown = (e: React.MouseEvent) => {
+        if (this.props.stopPropagation) {
+            stopPropagation(e);
+        }
+    }
+
     handlePortalInnerKeyDown = (e: React.KeyboardEvent) => {
         this.foundation.handleContainerKeydown(e);
     }
@@ -595,6 +601,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
                     style={portalInnerStyle}
                     ref={this.setContainerEl}
                     onClick={this.handlePortalInnerClick}
+                    onMouseDown={this.handlePortalMouseDown}
                     onKeyDown={this.handlePortalInnerKeyDown}
                 >
                     {inner}