diff --git a/components/typography/Base.tsx b/components/typography/Base.tsx index 28283eeeff..5cb4bfd6b8 100644 --- a/components/typography/Base.tsx +++ b/components/typography/Base.tsx @@ -3,6 +3,7 @@ import classNames from 'classnames'; import toArray from 'rc-util/lib/Children/toArray'; import copy from 'copy-to-clipboard'; import omit from 'rc-util/lib/omit'; +import { composeRef } from 'rc-util/lib/ref'; import EditOutlined from '@ant-design/icons/EditOutlined'; import CheckOutlined from '@ant-design/icons/CheckOutlined'; import CopyOutlined from '@ant-design/icons/CopyOutlined'; @@ -112,6 +113,7 @@ interface BaseState { ellipsisText: string; ellipsisContent: React.ReactNode; isEllipsis: boolean; + isNativeEllipsis: boolean; expanded: boolean; clientRendered: boolean; } @@ -169,6 +171,7 @@ class Base extends React.Component { ellipsisText: '', ellipsisContent: null, isEllipsis: false, + isNativeEllipsis: false, expanded: false, clientRendered: false, }; @@ -180,11 +183,25 @@ class Base extends React.Component { componentDidUpdate(prevProps: BlockProps) { const { children } = this.props; + const { isNativeEllipsis } = this.state; + const ellipsis = this.getEllipsis(); const prevEllipsis = this.getEllipsis(prevProps); if (children !== prevProps.children || ellipsis.rows !== prevEllipsis.rows) { this.resizeOnNextFrame(); } + + // If use native ellipsis, we should check if ellipsis changed + const textEle = this.contentRef.current; + if (this.canUseCSSEllipsis() && textEle) { + const currentEllipsis = textEle.offsetWidth < textEle.scrollWidth; + if (isNativeEllipsis !== currentEllipsis) { + // eslint-disable-next-line react/no-did-update-set-state + this.setState({ + isNativeEllipsis: currentEllipsis, + }); + } + } } componentWillUnmount() { @@ -297,9 +314,9 @@ class Base extends React.Component { canUseCSSEllipsis(): boolean { const { clientRendered } = this.state; const { editable, copyable } = this.props; - const { rows, expandable, suffix, onEllipsis, tooltip } = this.getEllipsis(); + const { rows, expandable, suffix, onEllipsis } = this.getEllipsis(); - if (suffix || tooltip) return false; + if (suffix) return false; // Can't use css ellipsis since we need to provide the place for button if (editable || copyable || expandable || !clientRendered || onEllipsis) { return false; @@ -458,7 +475,7 @@ class Base extends React.Component { } renderContent() { - const { ellipsisContent, isEllipsis, expanded } = this.state; + const { ellipsisContent, isEllipsis, isNativeEllipsis, expanded } = this.state; const { component, children, className, type, disabled, style, ...restProps } = this.props; const { direction } = this.context; const { rows, suffix, tooltip } = this.getEllipsis(); @@ -508,15 +525,6 @@ class Base extends React.Component { {suffix} ); - - // If provided tooltip, we need wrap with span to let Tooltip inject events - if (tooltip) { - textNode = ( - - {textNode} - - ); - } } else { textNode = ( <> @@ -538,31 +546,44 @@ class Base extends React.Component { return ( - {}} - {...textProps} - > - {textNode} - {this.renderOperations()} - + {resizeRef => { + let typography = ( + {}} + {...textProps} + > + {textNode} + {this.renderOperations()} + + ); + + // If provided tooltip, we need wrap with span to let Tooltip inject events + if (cssEllipsis ? isNativeEllipsis : isEllipsis) { + typography = ( + {typography} + ); + } + + return typography; + }} ); }} diff --git a/components/typography/__tests__/index.test.js b/components/typography/__tests__/index.test.js index d692a29a3e..8c726d92f2 100644 --- a/components/typography/__tests__/index.test.js +++ b/components/typography/__tests__/index.test.js @@ -3,7 +3,7 @@ import { mount } from 'enzyme'; import { SmileOutlined, LikeOutlined, HighlightOutlined, CheckOutlined } from '@ant-design/icons'; import KeyCode from 'rc-util/lib/KeyCode'; import { resetWarned } from 'rc-util/lib/warning'; -import { spyElementPrototype } from 'rc-util/lib/test/domHook'; +import { spyElementPrototype, spyElementPrototypes } from 'rc-util/lib/test/domHook'; import copy from 'copy-to-clipboard'; import Title from '../Title'; import Link from '../Link'; @@ -258,6 +258,23 @@ describe('Typography', () => { }); describe('should tooltip support', () => { + let domSpy; + + beforeAll(() => { + domSpy = spyElementPrototypes(HTMLElement, { + offsetWidth: { + get: () => 100, + }, + scrollWidth: { + get: () => 200, + }, + }); + }); + + afterAll(() => { + domSpy.mockRestore(); + }); + function getWrapper(tooltip) { return mount( diff --git a/package.json b/package.json index e7ab3da204..9aa7e56850 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "rc-picker": "~2.5.17", "rc-progress": "~3.2.1", "rc-rate": "~2.9.0", - "rc-resize-observer": "^1.1.2", + "rc-resize-observer": "^1.2.0", "rc-select": "~14.0.0-alpha.15", "rc-slider": "~9.7.4", "rc-steps": "~4.1.0",