Skip to content

Instantly share code, notes, and snippets.

@acorn1010
Created November 25, 2022 14:44
Show Gist options
  • Save acorn1010/c9241b2d1dd3a926c53fcac4aa6bcdd7 to your computer and use it in GitHub Desktop.
Save acorn1010/c9241b2d1dd3a926c53fcac4aa6bcdd7 to your computer and use it in GitHub Desktop.
OverflowText.tsx
import {
createStyles,
makeStyles,
Tooltip,
Typography,
TypographyProps,
} from '@material-ui/core';
import clsx from 'clsx';
import React, {CSSProperties, useCallback, useState} from 'react';
import useResizeObserver from 'use-resize-observer';
const useStyles = makeStyles(() =>
createStyles({
overflowText: {
maxWidth: 'fit-content !important',
},
})
);
/**
* Returns a <Typography> element wrapped in a tooltip. The tooltip will only be visible when the
* <Typography> element doesn't have enough space (e.g. it has an ellipsis).
*/
export function OverflowText(props: TypographyProps & {center?: boolean, title: string, component?: 'h1'}) {
const {center, className, title, ...rest} = props;
const classes = useStyles();
const [isOpen, setIsOpen] = useState(false);
const {ref} = useResizeObserver<HTMLElement>();
const resizeCallback = useCallback((el: HTMLParagraphElement) => {
if (!el) {
return;
}
// scrollWidth doesn't include margin, so add margin to the child to see if it overflows the
// parent.
const {marginLeft, marginRight} = window.getComputedStyle(el);
const outerChildWidth = el.scrollWidth + parseInt(marginLeft, 10) + parseInt(marginRight, 10);
setIsOpen(!!el.parentElement && outerChildWidth >= el.parentElement.clientWidth);
}, [setIsOpen]);
// We wrap the Typography in a div to ensure that no other child interferes with the width of the
// parent container.
// TODO(acornwall): Replace center prop with a better solution for centering text.
const centerStyle: CSSProperties = center ? {display: 'flex', justifyContent: 'center'} : {};
return (
<Tooltip title={isOpen ? title : ''}>
<div style={{alignSelf: 'center', minWidth: 0, width: '100%', ...centerStyle}}>
<Typography
className={clsx(classes.overflowText, className)}
noWrap
{...rest}
ref={(e: HTMLParagraphElement) => {
ref(e);
resizeCallback(e);
}}>
{title}
</Typography>
</div>
</Tooltip>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment