refactor(ui): simplify OverflowTooltip and improve render performance

- Inline styles from useMenuTooltipStyles into OverflowTooltip (single consumer)
- Use MUI named colors (grey[700]/grey[300] with alpha) instead of raw rgba
- Stabilize ref callback with useCallback to avoid unnecessary ref churn
- Memoize Tooltip classes and hoist TransitionProps to module level
- Fix useLayoutEffect dependency: observe DOM size, not title string
This commit is contained in:
Deluan 2026-03-15 14:50:33 -04:00
parent 5e9c644c03
commit 834d5f5da5
2 changed files with 47 additions and 40 deletions

View File

@ -1,16 +1,43 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Tooltip } from '@material-ui/core'
import useMenuTooltipStyles from './useMenuTooltipStyles'
import { makeStyles, alpha } from '@material-ui/core/styles'
import grey from '@material-ui/core/colors/grey'
const useStyles = makeStyles(
(theme) => ({
tooltip: {
backgroundColor:
theme.palette.type === 'dark'
? alpha(grey[700], 0.92)
: alpha(grey[300], 0.92),
color:
theme.palette.type === 'dark'
? theme.palette.common.white
: theme.palette.common.black,
borderRadius: theme.shape.borderRadius,
...theme.typography.body2,
padding: theme.spacing(0.5, 1),
maxWidth: 300,
},
}),
{ name: 'NDOverflowTooltip' },
)
const transitionProps = { timeout: 0 }
export const OverflowTooltip = ({
children,
title,
placement = 'bottom-start',
}) => {
const classes = useMenuTooltipStyles()
const classes = useStyles()
const textRef = React.useRef(null)
const [isOverflowing, setIsOverflowing] = React.useState(false)
const tooltipClasses = React.useMemo(
() => ({ tooltip: classes.tooltip }),
[classes.tooltip],
)
React.useLayoutEffect(() => {
const el = textRef.current
@ -26,7 +53,21 @@ export const OverflowTooltip = ({
checkOverflow()
return () => resizeObserver.disconnect()
}, [title])
}, [])
const mergedRef = React.useCallback(
(el) => {
textRef.current = el
const { ref } = children
if (typeof ref === 'function') {
ref(el)
} else if (ref && typeof ref === 'object') {
ref.current = el
}
},
[children],
)
return (
<Tooltip
@ -34,21 +75,10 @@ export const OverflowTooltip = ({
disableHoverListener={!isOverflowing}
disableTouchListener
placement={placement}
TransitionProps={{ timeout: 0 }}
classes={{ tooltip: classes.tooltip }}
TransitionProps={transitionProps}
classes={tooltipClasses}
>
{React.cloneElement(children, {
ref: (el) => {
textRef.current = el
const { ref } = children
if (typeof ref === 'function') {
ref(el)
} else if (ref && typeof ref === 'object') {
ref.current = el
}
},
})}
{React.cloneElement(children, { ref: mergedRef })}
</Tooltip>
)
}

View File

@ -1,23 +0,0 @@
import { makeStyles } from '@material-ui/core/styles'
const useMenuTooltipStyles = makeStyles(
(theme) => ({
tooltip: {
backgroundColor:
theme.palette.type === 'dark'
? 'rgba(97, 97, 97, 0.92)'
: 'rgba(224, 224, 224, 0.92)',
color:
theme.palette.type === 'dark'
? theme.palette.common.white
: theme.palette.common.black,
borderRadius: theme.shape.borderRadius,
...theme.typography.body2,
padding: theme.spacing(0.5, 1),
maxWidth: 300,
},
}),
{ name: 'NDOverflowTooltip' },
)
export default useMenuTooltipStyles