Draft
Write your dreams
Writing is the best way to express your thoughts
Installation
1. Install the following packages
npm
npm install @hugeicons/react @hugeicons/core-free-icons motion2. Copy and paste the following code into your project
typewriter.tsx
1"use client";
2
3import { Edit02Icon } from "@hugeicons/core-free-icons";
4import { HugeiconsIcon } from "@hugeicons/react";
5import { motion } from "motion/react";
6import { useEffect, useState } from "react";
7
8function TypewriterEffect() {
9 const textToType = "Building something beautiful together...";
10
11 const [currentText, setCurrentText] = useState("");
12 const [isDeleting, setIsDeleting] = useState(false);
13
14 useEffect(() => {
15 const timeout = setTimeout(
16 () => {
17 if (!isDeleting) {
18 if (currentText.length < textToType.length) {
19 setCurrentText(textToType.slice(0, currentText.length + 1));
20 } else {
21 // Wait before starting to delete
22 setTimeout(() => setIsDeleting(true), 2000);
23 }
24 } else {
25 if (currentText.length > 0) {
26 setCurrentText(currentText.slice(0, -1));
27 } else {
28 setIsDeleting(false);
29 }
30 }
31 },
32 isDeleting ? 30 : 70 + Math.random() * 30,
33 );
34
35 return () => clearTimeout(timeout);
36 }, [currentText, isDeleting, textToType]);
37
38 return (
39 <div className="relative w-full max-w-[280px] bg-white/40 dark:bg-black/20 rounded-xl p-4 min-h-[140px] overflow-hidden">
40 <div className="flex items-center gap-2 mb-3 border-b border-black/5 dark:border-white/5 pb-2">
41 <HugeiconsIcon icon={Edit02Icon} size={12} className="text-muted-foreground" />
42 <span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wider">Draft</span>
43 </div>
44
45 <div className="relative text-sm leading-relaxed text-black/80 dark:text-white/80 wrap-break-word">
46 <span className="inline-block">
47 {currentText}
48 <motion.span
49 animate={{ opacity: [1, 0] }}
50 transition={{
51 duration: 0.5,
52 repeat: Infinity,
53 repeatType: "reverse",
54 }}
55 className="ml-0.5 inline-block h-[1em] w-[2px] bg-violet-500 align-middle"
56 />
57 </span>
58 </div>
59 </div>
60 );
61}
62
63export function Typewriter() {
64 return (
65 <motion.div
66 className="bg-white/50 dark:bg-black/40 rounded-md p-8 border border-gray-200/50 dark:border-white/10 min-h-[300px] flex flex-col shadow-[inset_-12px_-8px_40px_#46464620] max-w-[400px]"
67 initial={{ opacity: 0, y: 30 }}
68 whileInView={{ opacity: 1, y: 0 }}
69 viewport={{ once: true }}
70 transition={{ duration: 0.4, ease: "circOut" }}
71 data-clickable
72 >
73 <div className="flex-1 flex items-center justify-center">
74 <TypewriterEffect />
75 </div>
76 <div className="mt-6 flex flex-col">
77 <div className="flex items-center gap-2 mb-1">
78 <h3 className="font-semibold text-lg text-black dark:text-white">Write your dreams</h3>
79 </div>
80 <p className="text-muted-foreground text-sm leading-snug">Writing is the best way to express your thoughts</p>
81 </div>
82 </motion.div>
83 );
84}
85
86export default Typewriter;
87