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

feat: create a custom hook to handle tooltip display on headings #4557

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 9 additions & 3 deletions src/components/Column/Column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {Droppable} from "components/DragAndDrop/Droppable";
import {useStripeOffset} from "utils/hooks/useStripeOffset";
import {EmojiSuggestions} from "components/EmojiSuggestions";
import {useEmojiAutocomplete} from "utils/hooks/useEmojiAutocomplete";
import {useTextOverflow} from "utils/hooks/useTextOverflow";
import {Note} from "../Note";
import {ColumnSettings} from "./ColumnSettings";
import {createColumn, deleteColumnOptimistically, editColumn, editColumnOptimistically} from "../../store/features";
Expand All @@ -31,6 +32,8 @@ export const Column = ({id, name, color, visible, index}: ColumnProps) => {
const {t} = useTranslation();
const dispatch = useAppDispatch();

const {isTextTruncated, textRef} = useTextOverflow<HTMLHeadingElement>(name);

const notes = useAppSelector(
(state) =>
state.notes
Expand Down Expand Up @@ -126,6 +129,7 @@ export const Column = ({id, name, color, visible, index}: ColumnProps) => {
<div className={classNames("column__header-text-wrapper", {"column__header-text-wrapper--hidden": !visible})}>
{!visible && <Hidden className="column__header-hidden-icon" title={t("Column.hiddenColumn")} onClick={toggleVisibilityHandler} />}
<h2
ref={textRef}
id={`column-${id}`}
onDoubleClick={() => {
if (isModerator) {
Expand All @@ -136,9 +140,11 @@ export const Column = ({id, name, color, visible, index}: ColumnProps) => {
>
{name}
</h2>
<Tooltip className="column__tooltip" anchorSelect={`#column-${id}`}>
{name}
</Tooltip>
{isTextTruncated && (
<Tooltip className="column__tooltip" anchorSelect={`#column-${id}`}>
{name}
</Tooltip>
)}
</div>
) : (
<>
Expand Down
47 changes: 47 additions & 0 deletions src/utils/hooks/useTextOverflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {useState, useEffect, useRef} from "react";

/**
* Custom hook to detect whether the text within a referenced container is truncated (ellipsis).
* It can be used to determine if a tooltip should be displayed based on text visibility.
*
* @template T
* @param {string} label - The text to monitor for overflow.
* @returns {Object} An object containing:
* @returns {boolean} isTextTruncated - A boolean indicating if the text is truncated.
* @returns {React.RefObject<RefElement>} textRef - A ref to be attached to the text element to measure its dimensions.
*
* @example
* const MyComponent = () => {
* const { isTextTruncated, textRef } = useTextOverflow<string>('Some text that might be truncated');
*
* return (
* <div>
* <h2 ref={textRef}>Some text that might be truncated</h2>
* {isTextTruncated && <div className="tooltip">Some text that might be truncated</div>}
* </div>
* );
* };
*/
export const useTextOverflow = <RefElement extends HTMLElement>(label: string) => {
const [isTextTruncated, setIsTextTruncated] = useState<boolean>(false);
const textRef = useRef<RefElement | null>(null);

const detectTextOverflow = () => {
if (textRef.current) {
const isTextEllipsis = textRef.current.scrollWidth > textRef.current.clientWidth;
setIsTextTruncated(isTextEllipsis);
}
};

useEffect(() => {
detectTextOverflow();

// Add event listener to detect text overflow changes on window resize
window.addEventListener("resize", detectTextOverflow);

// Cleanup function to remove the event listener when the component unmounts
return () => window.removeEventListener("resize", detectTextOverflow);
}, [label]);

return {isTextTruncated, textRef};
};
Loading