Skip to content

Commit b1bd5cb

Browse files
committed
typewriter effecte udpated
1 parent 2e2496f commit b1bd5cb

File tree

3 files changed

+78
-104
lines changed

3 files changed

+78
-104
lines changed

app/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { cn } from "@/lib/utils";
1010
import metadata from "./metadata";
1111
import "../style/globals.css";
1212
import Footer from "@/components/layout/Footer";
13+
import { memo } from "react";
1314

1415
const layout = ({ children }: Readonly<RootLayoutProps>) => {
1516
return (
@@ -30,7 +31,7 @@ const layout = ({ children }: Readonly<RootLayoutProps>) => {
3031
personSchema,
3132
websiteSchema
3233
]
33-
}, null, 2)
34+
})
3435
}}
3536
/>
3637
<ThemeProvider
@@ -51,4 +52,4 @@ const layout = ({ children }: Readonly<RootLayoutProps>) => {
5152
};
5253
export { metadata };
5354

54-
export default layout;
55+
export default memo(layout);

app/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import TypewriterEffect from '@/components/ui/typewriter-effect';
12
import { TYPEWRITER_WORDS } from '@/constants';
23
import About from '@/components/home/About';
34
import Name from '@/components/home/Name';
4-
import { memo } from 'react';
55
import Image from 'next/image';
6-
import TypewriterEffect from '@/components/ui/typewriter-effect';
6+
import { memo } from 'react';
77

88

99
const HomePage = () => {
@@ -16,7 +16,7 @@ const HomePage = () => {
1616
alt="Muhammed sinan - Mern stack developer"
1717
width={1}
1818
height={1}
19-
priority={false}
19+
loading='lazy'
2020
className="opacity-0"
2121
/>
2222
</div>

components/ui/typewriter-effect.tsx

Lines changed: 72 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { cn } from "@/lib/utils";
44
import { motion, stagger, useAnimate, useInView } from "framer-motion";
5-
import { memo, useEffect } from "react";
5+
import { memo, useEffect, useMemo, useCallback } from "react";
66

77
const TypewriterEffect = ({
88
words,
@@ -16,16 +16,14 @@ const TypewriterEffect = ({
1616
className?: string;
1717
cursorClassName?: string;
1818
}) => {
19-
20-
const wordsArray = words.map((word) => {
21-
return {
22-
...word,
23-
text: word.text.split(""),
24-
};
25-
});
19+
const wordsArray = useMemo(() => words.map((word) => ({
20+
...word,
21+
text: word.text.split(""),
22+
})), [words]);
2623

2724
const [scope, animate] = useAnimate();
28-
const isInView = useInView(scope);
25+
const isInView = useInView(scope, { once: true });
26+
2927
useEffect(() => {
3028
if (isInView) {
3129
animate(
@@ -36,53 +34,44 @@ const TypewriterEffect = ({
3634
width: "fit-content",
3735
},
3836
{
39-
delay: stagger(0.1),
40-
ease: "easeInOut",
37+
duration: 0.2,
38+
delay: stagger(0.1, { startDelay: 0.3 }),
39+
ease: "linear",
4140
}
4241
);
4342
}
4443
}, [isInView, animate]);
4544

46-
const renderWords = () => {
47-
return (
48-
<motion.div ref={scope} className="inline">
49-
{wordsArray.map((word, idx) => {
50-
return (
51-
<div key={`word-${idx}`} className="inline-block">
52-
{word.text.map((char, index) => (
53-
<motion.span
54-
initial={{}}
55-
key={`char-${index}`}
56-
className={cn(
57-
`dark:text-white text-black opacity-0 hidden`,
58-
word.className
59-
)}
60-
>
61-
{char}
62-
</motion.span>
63-
))}
64-
&nbsp;
65-
</div>
66-
);
67-
})}
68-
</motion.div>
69-
);
70-
};
45+
const renderWords = useCallback(() => (
46+
<motion.div ref={scope} className="inline">
47+
{wordsArray.map((word, idx) => (
48+
<div key={`word-${idx}`} className="inline-block">
49+
{word.text.map((char, index) => (
50+
<motion.span
51+
key={`char-${index}`}
52+
className={cn(
53+
`dark:text-white text-black opacity-0 hidden`,
54+
word.className
55+
)}
56+
>
57+
{char}
58+
</motion.span>
59+
))}
60+
&nbsp;
61+
</div>
62+
))}
63+
</motion.div>
64+
), [wordsArray, scope]);
65+
7166
return (
72-
<div
73-
className={cn(
74-
"text-base sm:text-xl md:text-1xl lg:text-4xl font-bold text-center",
75-
className
76-
)}
77-
>
67+
<div className={cn(
68+
"text-base sm:text-xl md:text-1xl lg:text-4xl font-bold text-center",
69+
className
70+
)}>
7871
{renderWords()}
7972
<motion.span
80-
initial={{
81-
opacity: 0,
82-
}}
83-
animate={{
84-
opacity: 1,
85-
}}
73+
initial={{ opacity: 0 }}
74+
animate={{ opacity: 1 }}
8675
transition={{
8776
duration: 0.8,
8877
repeat: Infinity,
@@ -92,12 +81,12 @@ const TypewriterEffect = ({
9281
"inline-block rounded-sm w-[4px] h-4 md:h-6 lg:h-10 bg-blue-500",
9382
cursorClassName
9483
)}
95-
></motion.span>
84+
/>
9685
</div>
9786
);
9887
};
9988

100-
export const TypewriterEffectSmooth = ({
89+
export const TypewriterEffectSmooth = memo(({
10190
words,
10291
className,
10392
cursorClassName,
@@ -109,45 +98,36 @@ export const TypewriterEffectSmooth = ({
10998
className?: string;
11099
cursorClassName?: string;
111100
}) => {
112-
// split text inside of words into array of characters
113-
const wordsArray = words.map((word) => {
114-
return {
115-
...word,
116-
text: word.text.split(""),
117-
};
118-
});
119-
const renderWords = () => {
120-
return (
121-
<div>
122-
{wordsArray.map((word, idx) => {
123-
return (
124-
<div key={`word-${idx}`} className="inline-block">
125-
{word.text.map((char, index) => (
126-
<span
127-
key={`char-${index}`}
128-
className={cn(`text-white `, word.className)}
129-
>
130-
{char}
131-
</span>
132-
))}
133-
&nbsp;
134-
</div>
135-
);
136-
})}
137-
</div>
138-
);
139-
};
101+
const wordsArray = useMemo(() => words.map((word) => ({
102+
...word,
103+
text: word.text.split(""),
104+
})), [words]);
105+
106+
const renderWords = useCallback(() => (
107+
<div>
108+
{wordsArray.map((word, idx) => (
109+
<div key={`word-${idx}`} className="inline-block">
110+
{word.text.map((char, index) => (
111+
<span
112+
key={`char-${index}`}
113+
className={cn(`text-white`, word.className)}
114+
>
115+
{char}
116+
</span>
117+
))}
118+
&nbsp;
119+
</div>
120+
))}
121+
</div>
122+
), [wordsArray]);
140123

141124
return (
142125
<div className={cn("flex space-x-1 my-6", className)}>
143126
<motion.div
144127
className="overflow-hidden pb-2"
145-
initial={{
146-
width: "0%",
147-
}}
148-
whileInView={{
149-
width: "fit-content",
150-
}}
128+
initial={{ width: "0%" }}
129+
whileInView={{ width: "fit-content" }}
130+
viewport={{ once: true }}
151131
transition={{
152132
duration: 2,
153133
ease: "linear",
@@ -156,33 +136,26 @@ export const TypewriterEffectSmooth = ({
156136
>
157137
<div
158138
className="text-xs sm:text-base md:text-xl lg:text:3xl xl:text-5xl font-bold"
159-
style={{
160-
whiteSpace: "nowrap",
161-
}}
139+
style={{ whiteSpace: "nowrap" }}
162140
>
163-
{renderWords()}{" "}
164-
</div>{" "}
141+
{renderWords()}
142+
</div>
165143
</motion.div>
166144
<motion.span
167-
initial={{
168-
opacity: 0,
169-
}}
170-
animate={{
171-
opacity: 1,
172-
}}
145+
initial={{ opacity: 0 }}
146+
animate={{ opacity: 1 }}
173147
transition={{
174148
duration: 0.8,
175-
176149
repeat: Infinity,
177150
repeatType: "reverse",
178151
}}
179152
className={cn(
180153
"block rounded-sm w-[4px] h-5 sm:h-6 xl:h-12 bg-blue-500",
181154
cursorClassName
182155
)}
183-
></motion.span>
156+
/>
184157
</div>
185158
);
186-
};
159+
});
187160

188-
export default memo(TypewriterEffect)
161+
export default memo(TypewriterEffect);

0 commit comments

Comments
 (0)