A component that swaps text on click or hover.
tailwind.config.js
theme: { extend: { colors: { foreground: "hsl(var(--foreground))", }, transitionTimingFunction: { slow: "cubic-bezier(.405, 0, .025, 1)", "minor-spring": "cubic-bezier(0.18,0.89,0.82,1.04)", } }, },
It will create a new file called swap-text.tsx inside the components/animata/text directory.
swap-text.tsx
components/animata/text
touch components/animata/text/swap-text.tsx
Open the newly created file and paste the following code:
import { useState } from "react"; import { cn } from "@/lib/utils"; interface SwapTextProps extends React.ComponentPropsWithoutRef<"div"> { /** * The initial text to display. */ initialText: string; /** * The final text to display. */ finalText: string; /** * Whether the component should toggle on hover as well as click. */ supportsHover?: boolean; /** * The class name for the text. */ textClassName?: string; /** * The class name for the initial text. */ initialTextClassName?: string; /** * The class name for the final text. */ finalTextClassName?: string; /** * Whether to disable the click interaction. */ disableClick?: boolean; } export default function SwapText({ initialText, finalText, className, supportsHover = true, textClassName, initialTextClassName, finalTextClassName, disableClick, // The rest of the props are passed to the container div. ...props }: SwapTextProps) { const [active, setActive] = useState(false); const common = "block transition-all duration-1000 ease-slow"; const longWord = finalText.length > initialText.length ? finalText : null; return ( <div {...props} className={cn("relative overflow-hidden text-foreground", className)}> <div className={cn("group cursor-pointer select-none text-3xl font-bold", textClassName)} onClick={() => !disableClick && setActive((current) => !current)} > <span className={cn(common, initialTextClassName, { "flex flex-col": true, "-translate-y-full": active, "group-hover:-translate-y-full": supportsHover, })} > {initialText} { /* Trick to make sure it can always fit all available words after transition as the second word is set to absolute*/ Boolean(longWord?.length) && <span className="invisible h-0">{longWord}</span> } </span> <span className={cn(`${common} absolute top-full`, finalTextClassName, { "-translate-y-full": active, "group-hover:-translate-y-full": supportsHover, })} > {finalText} </span> </div> </div> ); }
Built by hari