From fa9eb9718ed6ca30fb2ee80342ea855366e211af Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 04:49:46 +0000 Subject: [PATCH] Switch to version 2: added src/components/shared/FillWidthText/FillWidthText.tsx --- .../shared/FillWidthText/FillWidthText.tsx | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/components/shared/FillWidthText/FillWidthText.tsx diff --git a/src/components/shared/FillWidthText/FillWidthText.tsx b/src/components/shared/FillWidthText/FillWidthText.tsx new file mode 100644 index 0000000..b24b82b --- /dev/null +++ b/src/components/shared/FillWidthText/FillWidthText.tsx @@ -0,0 +1,59 @@ +"use client"; + +import React, { useMemo } from "react"; +import useFillWidthText from "./useFillWidthText"; +import { cls } from "@/lib/utils"; + +type TextElement = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span"; + +// Lowercase characters that have descenders (extend below the baseline) +// Uppercase versions (G, J, P, Q, Y) don't have descenders +const DESCENDER_CHARS = /[gjpqy]/; + +// Utility function to check if text has descender characters +export const hasDescenders = (text: string): boolean => DESCENDER_CHARS.test(text); + +interface FillWidthTextProps { + children: string; + as?: TextElement; + className?: string; +} + +const FillWidthText = ({ + children, + as: Component = "h1", + className = "", +}: FillWidthTextProps) => { + const { containerRef, textRef, fontSize, isReady } = useFillWidthText(children); + + // Use tighter line height if text has no descender characters + const lineHeight = useMemo(() => { + return DESCENDER_CHARS.test(children) ? 1.2 : 0.8; + }, [children]); + + return ( +
+ } + className={cls( + "whitespace-nowrap transition-opacity duration-150", + isReady ? "opacity-100" : "opacity-0", + className + )} + style={{ + fontSize: `${fontSize}px`, + lineHeight, + }} + > + {children} + +
+ ); +}; + +FillWidthText.displayName = "FillWidthText"; + +export default React.memo(FillWidthText);