fleet/frontend/hooks/useCheckTruncatedElement.ts
jacobshandling 19fe0ff5ce
UI: Improve TooltipTruncatedText and now underlying useCheckTruncatedElement (#29232)
## For #27667 

- Have `TooltipTruncatedText` component use `useCheckTruncatedElement`
to track its current state of truncation.
- Update `useCheckTruncatedElement` to re-evaluate truncation state
based on changes to the width of
the element itself as opposed to changes to viewport width. This
facilitates truncation when the
width of the element is updated due to user interaction / change in UI
state other than window resize, e.g. checking a policy in the policy
software automations modal (see issue description for details
reproduction instructions there).

**Truncation with tooltip successful for UI state changes:**

![ezgif-27969fb4a17d3e](https://github.com/user-attachments/assets/66156bd5-7948-4e73-9c11-4a08fde44189)

Truncation with tooltip successful for viewport resizing:

![ezgif-2515f715b05436](https://github.com/user-attachments/assets/8ef70579-1e89-4a4b-9fd0-93a4776d3151)

![ezgif-24a953c65500d9](https://github.com/user-attachments/assets/fc2f302b-6f7e-463e-97d2-9978b97c5601)

- [x] Changes file added for user-visible changes in `changes/⁄
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-05-20 15:41:53 -07:00

36 lines
991 B
TypeScript

import { useLayoutEffect, useState } from "react";
/**
* This hook checks if an element is truncated and returns a boolean value.
*/
// eslint-disable-next-line import/prefer-default-export
export const useCheckTruncatedElement = <T extends HTMLElement>(
ref: React.RefObject<T>
) => {
const [isTruncated, setIsTruncated] = useState(false);
const updateIsTruncated = (element: HTMLElement) => {
const { scrollWidth, clientWidth } = element;
setIsTruncated(scrollWidth > clientWidth);
};
useLayoutEffect(() => {
const resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
updateIsTruncated(entry.target as HTMLElement);
});
});
const element = ref.current;
if (element) {
updateIsTruncated(element);
resizeObserver.observe(ref.current as HTMLElement);
}
return () => {
if (element) {
resizeObserver.unobserve(element);
}
};
}, [ref]);
return isTruncated;
};