New

RetroTerminal

Terminal-style component with green phosphor text, blinking cursor, scan lines, and typed output effect.

Creative & Uniqueterminalretrohackertypingconsole

Dependencies

No additional dependencies needed.

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client";
2
3import { useState, useEffect, useRef } from "react";
4
5const lines = [
6 "$ initializing system...",
7 "> Loading modules: [OK]",
8 "> Connecting to mainframe: [OK]",
9 "> Authenticating user: admin",
10 "> Access granted.",
11 "",
12 "$ fetch --status",
13 "> Uptime: 99.97%",
14 "> Memory: 4.2GB / 16GB",
15 "> CPU: 23% utilization",
16 "> All systems nominal.",
17 "",
18 "$ _",
19];
20
21export default function RetroTerminal() {
22 const [displayedLines, setDisplayedLines] = useState<string[]>([]);
23 const [currentLine, setCurrentLine] = useState(0);
24 const [currentChar, setCurrentChar] = useState(0);
25 const containerRef = useRef<HTMLDivElement>(null);
26
27 useEffect(() => {
28 if (currentLine >= lines.length) return;
29 const line = lines[currentLine];
30
31 if (currentChar <= line.length) {
32 const timeout = setTimeout(() => {
33 setDisplayedLines((prev) => {
34 const next = [...prev];
35 next[currentLine] = line.slice(0, currentChar);
36 return next;
37 });
38 setCurrentChar(currentChar + 1);
39 }, 30 + Math.random() * 40);
40 return () => clearTimeout(timeout);
41 } else {
42 const timeout = setTimeout(() => {
43 setCurrentLine(currentLine + 1);
44 setCurrentChar(0);
45 }, 200);
46 return () => clearTimeout(timeout);
47 }
48 }, [currentLine, currentChar]);
49
50 useEffect(() => {
51 containerRef.current?.scrollTo(0, containerRef.current.scrollHeight);
52 }, [displayedLines]);
53
54 return (
55 <div className="mx-auto w-full max-w-lg overflow-hidden rounded-2xl border border-zinc-800 bg-zinc-950 shadow-2xl shadow-green-500/5">
56 {/* Title bar */}
57 <div className="flex items-center gap-2 border-b border-zinc-800 bg-zinc-900 px-4 py-3">
58 <div className="h-3 w-3 rounded-full bg-red-500" />
59 <div className="h-3 w-3 rounded-full bg-yellow-500" />
60 <div className="h-3 w-3 rounded-full bg-green-500" />
61 <span className="ml-2 font-mono text-xs text-zinc-500">terminal@ui-anvil ~ %</span>
62 </div>
63
64 {/* Terminal body */}
65 <div ref={containerRef} className="relative h-72 overflow-y-auto p-4 font-mono text-sm leading-relaxed">
66 {/* Scan lines overlay */}
67 <div className="pointer-events-none absolute inset-0 bg-[repeating-linear-gradient(0deg,transparent,transparent_2px,rgba(0,0,0,0.1)_2px,rgba(0,0,0,0.1)_4px)]" />
68
69 {displayedLines.map((line, i) => (
70 <div key={i} className="whitespace-pre-wrap">
71 <span className={line.startsWith("$") ? "text-green-400" : line.startsWith(">") ? "text-green-300/80" : "text-green-200/60"}>
72 {line}
73 </span>
74 {i === currentLine && currentLine < lines.length && (
75 <span className="ml-0.5 inline-block h-4 w-2 animate-pulse bg-green-400" />
76 )}
77 </div>
78 ))}
79 {currentLine >= lines.length && (
80 <span className="ml-0.5 inline-block h-4 w-2 animate-pulse bg-green-400" />
81 )}
82 </div>
83 </div>
84 );
85}

Related Creative & Unique Components

Command Palette

Search for a command to run...