Files
explore/ui/shared/TruncatedTextTooltip.tsx
T
tom goriunovandGitHub 802fe6c41f Public tags: display name tags for addresses (#1877)
* refactor EntityTags component to work with metadata API format

* hook for API metadata info query

* make EntityTag component

* make EntityTag component

* display custom tag colors and sort tags by ordinal field

* add tag popover

* refactoring

* display name tag in the lists

* add mixpanel event and disable link for protocol and generic tags

* adjust demo ENVs

* tests

* fix tests

* change actionURL to tagUrl
2024-05-06 19:38:44 +02:00

72 lines
2.2 KiB
TypeScript

import type { PlacementWithLogical } from '@chakra-ui/react';
import { Tooltip } from '@chakra-ui/react';
import debounce from 'lodash/debounce';
import React from 'react';
import useFontFaceObserver from 'use-font-face-observer';
import { BODY_TYPEFACE } from 'theme/foundations/typography';
interface Props {
children: React.ReactNode;
label: string;
placement?: PlacementWithLogical;
}
const TruncatedTextTooltip = ({ children, label, placement }: Props) => {
const childRef = React.useRef<HTMLElement>(null);
const [ isTruncated, setTruncated ] = React.useState(false);
const isFontFaceLoaded = useFontFaceObserver([
{ family: BODY_TYPEFACE },
]);
const updatedTruncateState = React.useCallback(() => {
if (childRef.current) {
const scrollWidth = childRef.current.scrollWidth;
const clientWidth = childRef.current.clientWidth;
if (scrollWidth > clientWidth) {
setTruncated(true);
} else {
setTruncated(false);
}
}
}, []);
// FIXME: that should be useLayoutEffect, but it keeps complaining about SSR
// let's keep it as it is until the first issue
React.useEffect(() => {
updatedTruncateState();
}, [ updatedTruncateState, isFontFaceLoaded ]);
// we want to do recalculation when isFontFaceLoaded flag is changed
// but we don't want to create more resize event listeners
// that's why there are separate useEffect hooks
React.useEffect(() => {
const handleResize = debounce(updatedTruncateState, 1000);
window.addEventListener('resize', handleResize);
return function cleanup() {
window.removeEventListener('resize', handleResize);
};
}, [ updatedTruncateState ]);
// as for now it supports only one child
// and it is not cleared how to manage case with two or more children
const child = React.Children.only(children) as React.ReactElement & {
ref?: React.Ref<React.ReactNode>;
};
const modifiedChildren = React.cloneElement(
child,
{ ref: childRef },
);
if (isTruncated) {
return <Tooltip label={ label } maxW={{ base: '100vw', lg: '400px' }} placement={ placement }>{ modifiedChildren }</Tooltip>;
}
return modifiedChildren;
};
export default React.memo(TruncatedTextTooltip);