diff --git a/remotion-composer/src/components/HeroTitle.tsx b/remotion-composer/src/components/HeroTitle.tsx index 381dd1732..538641f03 100644 --- a/remotion-composer/src/components/HeroTitle.tsx +++ b/remotion-composer/src/components/HeroTitle.tsx @@ -17,6 +17,9 @@ export const HeroTitle: React.FC = ({ title, subtitle }) => { // Staggered letter-by-letter spring const titleChars = title.split(""); + // Group characters into words so each word wraps as an unbreakable unit + // (per-character flex items would otherwise break mid-word at the line edge). + const titleWords = title.split(" "); return ( = ({ title, subtitle }) => { display: "flex", justifyContent: "center", flexWrap: "wrap", - gap: 0, + columnGap: "0.28em", + rowGap: "0.1em", }} > - {titleChars.map((char, i) => { - const delay = i * 1.2; - const charSpring = spring({ - frame: frame - delay, - fps, - config: { damping: 12, stiffness: 150 }, + {(() => { + let charIndex = 0; + return titleWords.map((word, wIdx) => { + const wordSpan = ( +
+ {word.split("").map((char) => { + const i = charIndex++; + const delay = i * 1.2; + const charSpring = spring({ + frame: frame - delay, + fps, + config: { damping: 12, stiffness: 150 }, + }); + return ( + + {char} + + ); + })} +
+ ); + charIndex++; // account for the inter-word space in stagger timing + return wordSpan; }); - - return ( - - {char} - - ); - })} + })()} {/* Subtitle */}