diff --git a/src/components/CompanyInfoMockup.tsx b/src/components/CompanyInfoMockup.tsx index 6cfc34f..6ca5a1b 100644 --- a/src/components/CompanyInfoMockup.tsx +++ b/src/components/CompanyInfoMockup.tsx @@ -4,7 +4,7 @@ const CompanyInfoMockup = ({ children }: PropsWithChildren) => { return ( -
+
diff --git a/src/components/DirectorSection.tsx b/src/components/DirectorSection.tsx index 3a37a4d..af13c47 100644 --- a/src/components/DirectorSection.tsx +++ b/src/components/DirectorSection.tsx @@ -24,8 +24,8 @@ const DirectorSection = () => { Нашей стратегией является превращать сложные задачи сферы ЖКХ в эффективные цифровые решения. Мы разрабатываем автоматизацию для жизненно важной отрасли. -
-
+
+
diff --git a/src/components/TypingEffect.tsx b/src/components/TypingEffect.tsx index 1a04628..86e78c1 100644 --- a/src/components/TypingEffect.tsx +++ b/src/components/TypingEffect.tsx @@ -1,48 +1,47 @@ import { useInView } from "motion/react"; import { useRef, useEffect, useState } from "react"; -export default function TypingEffect({ text = 'Typing Effect', speed = 0.1 }: { text: string, speed?: number }) { +export default function TypingEffect({ + text = "Typing Effect", + speed = 0.05, +}: { + text: string; + speed?: number; +}) { const ref = useRef(null); const isInView = useInView(ref, { once: true }); + const [visibleChars, setVisibleChars] = useState(0); - - // Split text into lines - const lines = text.split('\n'); - + + const lines = text.split("\n"); + const totalChars = text.replace(/\n/g, "").length; + useEffect(() => { if (!isInView) return; - - let currentIndex = 0; - const totalChars = text.replace(/\n/g, '').length; - + const interval = setInterval(() => { - if (currentIndex < totalChars) { - currentIndex++; - setVisibleChars(currentIndex); - } else { - clearInterval(interval); - } + setVisibleChars((prev) => { + if (prev >= totalChars) return 0; // loop + return prev + 1; + }); }, speed * 1000); - + return () => clearInterval(interval); - }, [isInView, text, speed]); - - // Build visible text based on visible characters + }, [isInView, totalChars, speed]); + + // Build visible overlay text let charsProcessed = 0; const visibleLines: string[] = []; - + for (const line of lines) { const lineLength = line.length; + if (charsProcessed + lineLength <= visibleChars) { - // Full line is visible visibleLines.push(line); charsProcessed += lineLength; } else { - // Partial line - const remainingChars = visibleChars - charsProcessed; - if (remainingChars > 0) { - visibleLines.push(line.slice(0, remainingChars)); - } + const remaining = visibleChars - charsProcessed; + if (remaining > 0) visibleLines.push(line.slice(0, remaining)); break; } } @@ -53,11 +52,11 @@ export default function TypingEffect({ text = 'Typing Effect', speed = 0.1 }: { ref={ref} className="text-sm text-left font-mono text-base-content/70 tracking-tighter absolute bottom-0" > + {lines.map((line, i) => ( +
{line}
+ ))} {visibleLines.map((line, index) => ( -
- {line} - {index < visibleLines.length - 1 &&
} -
+
{line}
))}