From 59319204327a2f70d2f22c85fe4c31e38a500a45 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Thu, 6 Aug 2020 19:03:48 +0900 Subject: [PATCH] fix: filter click events within portal elements --- src/components/Dropdown/Dropdown.tsx | 9 +++------ src/components/Dropdown/dropdownHelper.ts | 12 ++++++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index bad4e825ab..d0a67ca7dc 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -10,7 +10,7 @@ import React, { } from 'react' import { createPortal } from 'react-dom' -import { Rect, hasParentElement } from './dropdownHelper' +import { Rect, createPortalElement, isElementInPortal } from './dropdownHelper' type Props = { children: ReactNode @@ -44,16 +44,13 @@ export const Dropdown: FC = ({ children }) => { const [active, setActive] = useState(false) const [triggerRect, setTriggerRect] = useState(initialRect) - const portalElementRef = useRef(document.createElement('div')) + const portalElementRef = useRef(createPortalElement()) const triggerElementRef = useRef(null) useEffect(() => { const onClickBody = (e: any) => { // ignore events from events within DropdownTrigger and DropdownContent - if ( - e.target === triggerElementRef.current || - hasParentElement(e.target, portalElementRef.current) - ) { + if (e.target === triggerElementRef.current || isElementInPortal(e.target)) { return } setActive(false) diff --git a/src/components/Dropdown/dropdownHelper.ts b/src/components/Dropdown/dropdownHelper.ts index 90411c6fca..11b1e46c7d 100644 --- a/src/components/Dropdown/dropdownHelper.ts +++ b/src/components/Dropdown/dropdownHelper.ts @@ -5,9 +5,17 @@ export type Rect = { left: number } -export function hasParentElement(element: HTMLElement | null, parent: HTMLElement | null): boolean { +export const PORTAL_CLASSNAME = '__dropdown--portal--root__' + +export function createPortalElement() { + const element = document.createElement('div') + element.className = PORTAL_CLASSNAME + return element +} + +export function isElementInPortal(element: HTMLElement | null): boolean { if (!element) return false - return element === parent || hasParentElement(element.parentElement, parent) + return element.className === PORTAL_CLASSNAME || isElementInPortal(element.parentElement) } type Size = { width: number; height: number }