Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui] Fix unnecessary middle truncation occurring in dialogs #26086

Merged
merged 1 commit into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const MiddleTruncate = ({text, showTitle = true}: Props) => {

// Use a layout effect to trigger the process of calculating the truncated text, for the
// initial render.
React.useLayoutEffect(() => {
calculateTargetStyle();
React.useEffect(() => {
window.requestAnimationFrame(calculateTargetStyle);
}, [calculateTargetStyle]);

// If the container has just been resized, recalculate.
Expand Down Expand Up @@ -87,7 +87,9 @@ const Container = styled.div`
*/
const calculateMiddleTruncatedText = (container: HTMLDivElement, text: string) => {
const font = getComputedStyle(container).font;
const width = container.getBoundingClientRect().width;

// https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements#how_much_room_does_it_use_up
const width = container.offsetWidth;
Copy link
Contributor

Choose a reason for hiding this comment

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

Not caused by your PR but can we wrap the usage of calculateMiddleTruncatedText in a requestAnimationFrame since accessing offsetWidth triggers a forced layout.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm it looks like this fn is called in two places - one in a useLayoutEffect and one in a resize observer. I think in the resizeObserver case the layout is fresh so it's best to read it immediately vs allowing to change and then requesting it again, but I'm not sure about the useLayoutEffect callsite.

It looks like using useLayoutEffect instead of useEffect is the preferred way to implement this without an empty frame where the text was null while we were waiting to determine it's size, but if we're ok with the empty frame + not forcing a render, i think we switch that to useEffect and add a window.requestAnimationFrame.

I don't think it'll be that bad to have the null text for a single frame, I'll switch it and we can see if it's noticeable 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Delay of doing it in a requestAnimationFrame isn't noticeable as far as I can tell - switched!


const body = document.body;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,36 @@ export const Simple = () => {
);
};

export const TransformedContainerUsage = () => {
return (
<Box>
<em style={{display: 'block', marginBottom: 10}}>
Note: Only the first item should appear truncated. This use case is based on our usage of
MiddleTruncate in modals that animate in.
</em>
{[
'asset_that_supports_partition_ranges',
'asset_downstream',
'asset_weekly_root',
'asset_weekly',
].map((text) => (
<Box
key={text}
style={{maxWidth: 200, transform: 'scale(0.8)'}}
flex={{direction: 'row', gap: 8}}
>
<Box>
<Icon name="asset_non_sda" />
</Box>
<a style={{overflow: 'hidden'}} href="#/">
<MiddleTruncate text={text} />
</a>
</Box>
))}
</Box>
);
};

export const FlexboxContainerUsage = () => {
return (
<Box>
Expand Down Expand Up @@ -85,6 +115,7 @@ export const FlexboxContainerUsage = () => {
</Box>
);
};

export const TagUsage = () => {
return (
<Tag icon="job">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const AssetKeysDialog = (props: Props) => {
<Dialog
isOpen={isOpen}
onClose={() => setIsOpen(false)}
style={{width: '750px', maxWidth: '80vw', minWidth: '500px', transform: 'scale(1)'}}
style={{width: '750px', maxWidth: '80vw', minWidth: '500px'}}
canOutsideClickClose
canEscapeKeyClose
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,12 @@ export const BackfillPreviewModal = ({
);
}, [data]);

// BG Note: The transform: scale(1) below fixes a bug with MiddleTruncate where the text size
// is measured while the dialog is animating open and the scale is < 1, causing it to think
// it needs to truncate. A more general fix for this seems like it'll require a lot of testing.

return (
<Dialog
title="Backfill preview"
isOpen={isOpen}
onClose={() => setOpen(false)}
style={{width: '90vw', maxWidth: 1100, transform: 'scale(1)'}}
style={{width: '90vw', maxWidth: 1100}}
>
<Container
ref={parentRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const TickDetailsDialog = ({
<Dialog
isOpen={isOpen}
onClose={onClose}
style={{width: '80vw', maxWidth: '1200px', minWidth: '600px', transform: 'scale(1)'}}
style={{width: '80vw', maxWidth: '1200px', minWidth: '600px'}}
>
<TickDetailsDialogImpl
tickId={tickId}
Expand Down