Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/components/popup/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ const Popup = forwardRef<PopupInstanceFunctions, PopupProps>((originalProps, ref
const portalRef = useRef(null); // portal dom 元素
const contentRef = useRef<HTMLDivElement>(null); // 内容部分
const popperRef = useRef<InnerPopperInstance>(null); // 保存 popper 实例
const arrowRef = useRef<HTMLDivElement>(null); // 箭头元素

// 处理切换 panel 为 null 和正常内容动态切换的情况
useEffect(() => {
Expand Down Expand Up @@ -116,7 +115,9 @@ const Popup = forwardRef<PopupInstanceFunctions, PopupProps>((originalProps, ref
delay,
onVisibleChange,
});
const triggerEl = getTriggerElement();

// TODO: 理论上类型是 Element(包括 SVGElement 等情况,但涉及修改的地方较多,暂时断言)
const triggerEl = getTriggerElement() as HTMLElement;

const arrowModifierEnabled = useMemo(() => {
const arrowModifier = (popperOptions as Options)?.modifiers?.find((m) => m.name === 'arrow');
Expand Down Expand Up @@ -211,7 +212,9 @@ const Popup = forwardRef<PopupInstanceFunctions, PopupProps>((originalProps, ref
useEffect(() => {
if (visible && popupElement) {
updateScrollTop?.(contentRef.current);
updateArrowPosition();
requestAnimationFrame(() => {
updateArrowPosition();
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible, popupElement, updateScrollTop]);
Expand Down Expand Up @@ -301,7 +304,6 @@ const Popup = forwardRef<PopupInstanceFunctions, PopupProps>((originalProps, ref
{content}
{showArrow && (
<div
ref={arrowRef}
style={{ ...styles.arrow, ...arrowStyle }}
className={`${classPrefix}-popup__arrow`}
{...(arrowModifierEnabled && { 'data-popper-arrow': '' })}
Expand Down
24 changes: 19 additions & 5 deletions packages/components/popup/hooks/useTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import useConfig from '../../hooks/useConfig';

const ESC_KEY = 'Escape';

const isEventFromDisabledElement = (e: Event | React.SyntheticEvent, container: Element) => {
const target = e.target as Element;
const disabledEl = target?.closest?.('[disabled]');
return !!(disabledEl && container.contains(disabledEl));
};

export default function useTrigger({ triggerElement, content, disabled, trigger, visible, onVisibleChange, delay }) {
const { classPrefix } = useConfig();

Expand Down Expand Up @@ -36,15 +42,15 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
}
}

const getTriggerElement = useCallback((): HTMLElement | null => {
if (triggerElementIsString) {
return canUseDocument ? document.querySelector(triggerElement) : null;
}
const getTriggerElement = useCallback(() => {
if (!canUseDocument) return null;
if (triggerElementIsString) return document.querySelector(triggerElement);
const element = getRefDom(triggerRef);
return typeof HTMLElement !== 'undefined' && element instanceof HTMLElement ? element : null;
return element instanceof Element ? element : null;
}, [triggerElementIsString, triggerElement]);

const handleMouseLeave = (e: MouseEvent | React.MouseEvent) => {
if (isEventFromDisabledElement(e, getTriggerElement())) return;
if (trigger !== 'hover' || hasPopupMouseDown.current) return;
const relatedTarget = e.relatedTarget as HTMLElement;
const isMovingToContent = relatedTarget?.closest?.(`.${classPrefix}-popup`);
Expand Down Expand Up @@ -74,6 +80,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
if (!element) return;

const handleClick = (e: MouseEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'click') {
callFuncWithDelay({
delay: visible ? appearDelay : exitDelay,
Expand All @@ -83,6 +90,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleMouseDown = (e: MouseEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'mousedown') {
callFuncWithDelay({
delay: visible ? appearDelay : exitDelay,
Expand All @@ -92,6 +100,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleMouseEnter = (e: MouseEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'hover') {
callFuncWithDelay({
delay: appearDelay,
Expand All @@ -101,6 +110,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleFocus = (e: FocusEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'focus') {
callFuncWithDelay({
delay: appearDelay,
Expand All @@ -110,6 +120,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleBlur = (e: FocusEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'focus') {
callFuncWithDelay({
delay: exitDelay,
Expand All @@ -119,6 +130,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleContextMenu = (e: MouseEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'context-menu') {
e.preventDefault();
callFuncWithDelay({
Expand All @@ -129,6 +141,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleTouchStart = (e: TouchEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (trigger === 'hover' || trigger === 'mousedown') {
callFuncWithDelay({
delay: appearDelay,
Expand All @@ -138,6 +151,7 @@ export default function useTrigger({ triggerElement, content, disabled, trigger,
};

const handleKeyDown = (e: KeyboardEvent) => {
if (isEventFromDisabledElement(e, element)) return;
if (e?.key === ESC_KEY) {
callFuncWithDelay({
delay: exitDelay,
Expand Down
7 changes: 7 additions & 0 deletions packages/tdesign-react/.changelog/pr-4057.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
pr_number: 4057
contributor: RylanBot
---

- fix(Popup): 修复 `1.16.0` 版本的重构导致 `trigger` 为 SVG 等元素时弹出层无法出现的问题 @RylanBot ([#4057](https://github.com/Tencent/tdesign-react/pull/4057))
- fix(Popup): 修复 `1.16.0` 版本的重构导致 `trigger` 被 `disabled` 依旧能触发弹出层的问题 @RylanBot ([#4057](https://github.com/Tencent/tdesign-react/pull/4057))
2 changes: 1 addition & 1 deletion test/snap/__snapshots__/csr.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -139675,7 +139675,7 @@ exports[`csr snapshot test > csr test packages/components/tooltip/_example/durat
提示在5秒后消失
<div
class="t-popup__arrow"
style="position: absolute; left: 8px; margin-left: 0px;"
style="position: absolute;"
/>
</div>
</div>
Expand Down
Loading