Aa
Typography
Responsive and beautiful type systems that scale perfectly across all viewports.
Installation
1. Install the following packages
npm
npm install motion2. Add cn utility function to your project
@/lib/utils/utils.ts
1import { clsx, type ClassValue } from "clsx"
2import { twMerge } from "tailwind-merge"
3
4export function cn(...inputs: ClassValue[]) {
5 return twMerge(clsx(inputs))
6}3. Copy and paste the following code into your project
typography.tsx
1"use client";
2
3import { cn } from "@/lib/utils";
4import { motion } from "motion/react";
5import { useEffect, useState } from "react";
6
7const characters = [
8 { char: "Aa", font: "font-serif" },
9 { char: "Gg", font: "font-sans" },
10 { char: "Rr", font: "font-serif" },
11 { char: "Tt", font: "font-mono" },
12];
13
14function TypeTester() {
15 const [index, setIndex] = useState(0);
16
17 useEffect(() => {
18 const interval = setInterval(() => {
19 setIndex((prev) => (prev + 1) % characters.length);
20 }, 3000);
21 return () => clearInterval(interval);
22 }, []);
23
24 return (
25 <div className="flex items-center justify-center h-full min-h-[160px]">
26 <motion.div
27 key={index}
28 initial={{ opacity: 0, y: 10, filter: "blur(8px)" }}
29 animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
30 exit={{ opacity: 0, y: -10, filter: "blur(8px)" }}
31 transition={{ duration: 0.8, ease: [0.23, 1, 0.32, 1] }}
32 className="flex flex-col items-center gap-2"
33 >
34 <span className={cn(characters[index].font, "text-7xl md:text-8xl text-black dark:text-white tracking-tighter")}>{characters[index].char}</span>
35 <motion.div initial={{ width: 0 }} animate={{ width: "100%" }} transition={{ duration: 2, ease: "easeInOut" }} className="h-px bg-primary/20 w-full" />
36 </motion.div>
37 </div>
38 );
39}
40
41export function Typography() {
42 return (
43 <motion.div
44 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]"
45 initial={{ opacity: 0, y: 30 }}
46 whileInView={{ opacity: 1, y: 0 }}
47 viewport={{ once: true }}
48 transition={{ duration: 0.4, ease: "circOut" }}
49 data-clickable
50 >
51 <div className="flex-1">
52 <TypeTester />
53 </div>
54 <div className="mt-6 flex flex-col">
55 <h3 className="font-semibold text-lg text-black dark:text-white">Typography</h3>
56 <p className="text-muted-foreground text-sm">Responsive and beautiful type systems that scale perfectly across all viewports.</p>
57 </div>
58 </motion.div>
59 );
60}
61