mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
fix: Visible change not show Tooltip of Typography (#37147)
* test: Update snapshot * test: Add test case * test: fix react 18
This commit is contained in:
parent
8010cd19b6
commit
15e4b93e43
@ -227,6 +227,7 @@ const Base = React.forwardRef((props: InternalBlockProps, ref: any) => {
|
||||
const [expanded, setExpanded] = React.useState(false);
|
||||
const [isJsEllipsis, setIsJsEllipsis] = React.useState(false);
|
||||
const [isNativeEllipsis, setIsNativeEllipsis] = React.useState(false);
|
||||
const [isNativeVisible, setIsNativeVisible] = React.useState(true);
|
||||
const [enableEllipsis, ellipsisConfig] = useMergedConfig<EllipsisConfig>(ellipsis, {
|
||||
expandable: false,
|
||||
});
|
||||
@ -307,7 +308,31 @@ const Base = React.forwardRef((props: InternalBlockProps, ref: any) => {
|
||||
setIsNativeEllipsis(currentEllipsis);
|
||||
}
|
||||
}
|
||||
}, [enableEllipsis, cssEllipsis, children, cssLineClamp]);
|
||||
}, [enableEllipsis, cssEllipsis, children, cssLineClamp, isNativeVisible]);
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/36786
|
||||
// Use IntersectionObserver to check if element is invisible
|
||||
React.useEffect(() => {
|
||||
const textEle = typographyRef.current;
|
||||
if (
|
||||
typeof IntersectionObserver === 'undefined' ||
|
||||
!textEle ||
|
||||
!cssEllipsis ||
|
||||
!mergedEnableEllipsis
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
const observer = new IntersectionObserver(() => {
|
||||
setIsNativeVisible(!!textEle.offsetParent);
|
||||
});
|
||||
observer.observe(textEle!);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [cssEllipsis, mergedEnableEllipsis]);
|
||||
|
||||
// ========================== Tooltip ===========================
|
||||
let tooltipProps: TooltipProps = {};
|
||||
|
@ -618,6 +618,57 @@ Array [
|
||||
</span>
|
||||
[After]
|
||||
</p>,
|
||||
<div
|
||||
style="display:none"
|
||||
>
|
||||
<span
|
||||
aria-label="默认display none 样式的超长文字, 悬停tooltip失效了"
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
style="width:100px"
|
||||
>
|
||||
默认display none 样式的超长文字, 悬停tooltip失效了
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tooltip"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
I am ellipsis now!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
|
@ -522,6 +522,33 @@ Array [
|
||||
</span>
|
||||
[After]
|
||||
</p>,
|
||||
<div
|
||||
style="display:none"
|
||||
>
|
||||
<span
|
||||
aria-label="默认display none 样式的超长文字, 悬停tooltip失效了"
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
style="width:100px"
|
||||
>
|
||||
默认display none 样式的超长文字, 悬停tooltip失效了
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { fireEvent, render, sleep, triggerResize, waitFor } from '../../../tests/utils';
|
||||
import Base from '../Base';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -14,6 +15,7 @@ describe('Typography.Ellipsis', () => {
|
||||
const LINE_STR_COUNT = 20;
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
let mockRectSpy;
|
||||
let getWidthTimes = 0;
|
||||
|
||||
beforeAll(() => {
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
@ -26,7 +28,10 @@ describe('Typography.Ellipsis', () => {
|
||||
},
|
||||
},
|
||||
offsetWidth: {
|
||||
get: () => 100,
|
||||
get: () => {
|
||||
getWidthTimes += 1;
|
||||
return 100;
|
||||
},
|
||||
},
|
||||
getBoundingClientRect() {
|
||||
let html = this.innerHTML;
|
||||
@ -39,6 +44,7 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
afterEach(() => {
|
||||
errorSpy.mockReset();
|
||||
getWidthTimes = 0;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@ -223,28 +229,70 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
it('should have custom expand style', async () => {
|
||||
const symbol = 'more';
|
||||
const { container: wrapper } = render(
|
||||
const { container } = render(
|
||||
<Base ellipsis={{ expandable: true, symbol }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.querySelector('.ant-typography-expand').textContent).toEqual('more');
|
||||
expect(container.querySelector('.ant-typography-expand').textContent).toEqual('more');
|
||||
});
|
||||
|
||||
it('can use css ellipsis', () => {
|
||||
const { container: wrapper } = render(<Base ellipsis component="p" />);
|
||||
expect(wrapper.querySelectorAll('.ant-typography-ellipsis-single-line').length).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
});
|
||||
describe('native css ellipsis', () => {
|
||||
it('can use css ellipsis', () => {
|
||||
const { container } = render(<Base ellipsis component="p" />);
|
||||
expect(container.querySelector('.ant-typography-ellipsis-single-line')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should calculate padding', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis component="p" style={{ paddingTop: '12px', paddingBottom: '12px' }} />,
|
||||
);
|
||||
expect(wrapper.querySelectorAll('.ant-typography-ellipsis-single-line').length).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
// https://github.com/ant-design/ant-design/issues/36786
|
||||
it('Tooltip should recheck on parent visible change', () => {
|
||||
const originIntersectionObserver = global.IntersectionObserver;
|
||||
|
||||
let elementChangeCallback;
|
||||
const observeFn = jest.fn();
|
||||
const disconnectFn = jest.fn();
|
||||
|
||||
global.IntersectionObserver = class MockIntersectionObserver {
|
||||
constructor(callback) {
|
||||
elementChangeCallback = callback;
|
||||
}
|
||||
|
||||
observe = observeFn;
|
||||
|
||||
disconnect = disconnectFn;
|
||||
};
|
||||
|
||||
const { container, unmount } = render(<Base ellipsis component="p" />);
|
||||
|
||||
expect(observeFn).toHaveBeenCalled();
|
||||
|
||||
// Hide first
|
||||
act(() => {
|
||||
elementChangeCallback();
|
||||
});
|
||||
|
||||
// Trigger visible should trigger recheck
|
||||
getWidthTimes = 0;
|
||||
Object.defineProperty(container.querySelector('.ant-typography'), 'offsetParent', {
|
||||
get: () => document.body,
|
||||
});
|
||||
act(() => {
|
||||
elementChangeCallback();
|
||||
});
|
||||
|
||||
expect(getWidthTimes).toBeGreaterThan(0);
|
||||
|
||||
unmount();
|
||||
expect(disconnectFn).toHaveBeenCalled();
|
||||
|
||||
global.IntersectionObserver = originIntersectionObserver;
|
||||
});
|
||||
|
||||
it('should calculate padding', () => {
|
||||
const { container } = render(
|
||||
<Base ellipsis component="p" style={{ paddingTop: '12px', paddingBottom: '12px' }} />,
|
||||
);
|
||||
expect(container.querySelector('.ant-typography-ellipsis-single-line')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should tooltip support', () => {
|
||||
|
@ -26,6 +26,13 @@ const App: React.FC = () => {
|
||||
const [copyable, setCopyable] = useState(false);
|
||||
const [editable, setEditable] = useState(false);
|
||||
const [expandable, setExpandable] = useState(false);
|
||||
const [display, setDisplay] = useState('none');
|
||||
|
||||
React.useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setDisplay('block');
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -60,6 +67,12 @@ const App: React.FC = () => {
|
||||
<p>
|
||||
[Before]<Text ellipsis>not ellipsis</Text>[After]
|
||||
</p>
|
||||
|
||||
<div style={{ display }}>
|
||||
<Text style={{ width: 100 }} ellipsis={{ tooltip: 'I am ellipsis now!' }}>
|
||||
默认display none 样式的超长文字, 悬停tooltip失效了
|
||||
</Text>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user