Skip to content

Commit

Permalink
[ui] Directly set MiddleTruncate truncated text to fix flicker (#26888)
Browse files Browse the repository at this point in the history
## Summary & Motivation

This is a small follow-up to
#26834

I've noticed that sometimes with MiddleTruncate, there is a very slight
flicker when the text is first rendered. There's a single frame where
the rendered text is `null`, and you can see it before the text appears.

I'm not sure if my computer is just running slow today (looking for
excuses to get an M4 now...), or if it's the volume of MiddleTruncates
on this page (there are at least 50 rendering all at the same time), but
here's an example if you watch the tag on the right:


https://github.com/user-attachments/assets/4a05049d-9e70-4aaf-883a-eb448a905b01

Looking at the code for this, I don't think there's a reason for the
sizing to update React state and set the text through a React render.
The text is just used to set the span content, and the component doesn't
re-render unless the text changes (in which case `calculateTargetStyle`
changes and the effect runs again.) Setting the textContent directly
removes the flicker shown in the video.

## How I Tested These Changes

Tested in FF + Chrome manually

---------

Co-authored-by: bengotow <[email protected]>
  • Loading branch information
bengotow and bengotow authored Jan 7, 2025
1 parent 0eec862 commit 194ba27
Showing 1 changed file with 6 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,17 @@ interface Props {
*
* When the DOM element resizes, the measurement and calculation steps will occur again.
*/
export const MiddleTruncate = ({text, showTitle = true}: Props) => {
// Track the font style and target maximum width. `null` means no measurement has
// taken place yet.
const [truncatedText, setTruncatedText] = React.useState<string | null>(null);

export const MiddleTruncate = React.memo(({text, showTitle = true}: Props) => {
// An element that renders the full text into the container, for the purpose of
// measuring the maximum available/necessary width for our truncated string.
const measure = React.useRef<HTMLDivElement>(null);
const truncated = React.useRef<HTMLDivElement>(null);

// Given the target font style and allotted width, calculate the largest possible middle-
// truncated string.
const calculateTargetStyle = React.useCallback(() => {
if (measure.current) {
setTruncatedText(calculateMiddleTruncatedText(measure.current, text));
if (measure.current && truncated.current) {
truncated.current.textContent = calculateMiddleTruncatedText(measure.current, text);
}
}, [text]);

Expand All @@ -59,11 +56,11 @@ export const MiddleTruncate = ({text, showTitle = true}: Props) => {

return (
<Container onCopy={handleCopy} title={showTitle ? text : undefined}>
<span>{truncatedText}</span>
<span ref={truncated}></span>
<MeasureWidth ref={measure}>{text}</MeasureWidth>
</Container>
);
};
});

// An invisible target element that contains the full, no-wrapped text. This is used
// to measure the maximum available width for our truncated string.
Expand Down

1 comment on commit 194ba27

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for dagit-storybook ready!

✅ Preview
https://dagit-storybook-qly00ca0u-elementl.vercel.app

Built with commit 194ba27.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.