Back to Component Explorer

Interactive Terminal

effects

Developer macOS style terminal command prompt with execution output logs and one-click copy.

#terminal#bash#developer#command#prompt
Live Interactive Preview
bash ~ interactive
~npx aurenza-ui init

✔ Ready! Aurenza UI setup complete.

Type 'help' to view all available commands.

~

Component Source Code

Select language in the dropdown
TerminalCard.tsx
1'use client';
2
3import React, { useState, useRef, useEffect } from 'react';
4import { Check, Copy, CornerDownLeft } from 'lucide-react';
5
6interface CommandHistory {
7 command: string;
8 output: string | React.ReactNode;
9}
10
11export default function TerminalCard() {
12 const [copied, setCopied] = useState(false);
13 const [inputVal, setInputVal] = useState('');
14 const [history, setHistory] = useState<CommandHistory[]>([
15 {
16 command: 'npx aurenza-ui init',
17 output: (
18 <div className="text-slate-400 text-[11px] space-y-0.5 font-mono">
19 <p className="text-emerald-400">✔ Ready! Aurenza UI setup complete.</p>
20 <p className="text-slate-500">Type 'help' to view all available commands.</p>
21 </div>
22 )
23 }
24 ]);
25 const bottomRef = useRef<HTMLDivElement>(null);
26 const inputRef = useRef<HTMLInputElement>(null);
27
28 const copy = () => {
29 navigator.clipboard.writeText('npx aurenza-ui init');
30 setCopied(true);
31 setTimeout(() => setCopied(false), 2000);
32 };
33
34 const handleCommand = (e: React.FormEvent) => {
35 e.preventDefault();
36 const cmd = inputVal.trim();
37 if (!cmd) return;
38
39 let out: React.ReactNode = '';
40 const lower = cmd.toLowerCase();
41
42 if (lower === 'help') {
43 out = (
44 <div className="text-[11px] text-slate-300 space-y-1">
45 <p><span className="text-cyan-400 font-bold">components</span> - List top UI components</p>
46 <p><span className="text-cyan-400 font-bold">version</span> - Display Aurenza UI release version</p>
47 <p><span className="text-cyan-400 font-bold">theme</span> - Toggle spatial cyber matrix tokens</p>
48 <p><span className="text-cyan-400 font-bold">clear</span> - Clear terminal session</p>
49 </div>
50 );
51 } else if (lower === 'clear') {
52 setHistory([]);
53 setInputVal('');
54 return;
55 } else if (lower === 'components') {
56 out = <div className="text-[11px] text-emerald-300">Available: 3D Spatial Globe, 5-Layer Orbit, Infinite Marquee, Bento Grid...</div>;
57 } else if (lower === 'version') {
58 out = <span className="text-blue-400 text-[11px]">aurenza-ui v2.4.0 (Turbopack + Tailwind v4)</span>;
59 } else if (lower === 'theme') {
60 out = <span className="text-purple-400 text-[11px]">✨ Spatial Dark Theme active</span>;
61 } else {
62 out = <span className="text-rose-400 text-[11px]">command not found: {cmd}. Type 'help' for list.</span>;
63 }
64
65 setHistory((prev) => [...prev, { command: cmd, output: out }]);
66 setInputVal('');
67 };
68
69 const terminalBodyRef = useRef<HTMLDivElement>(null);
70
71 useEffect(() => {
72 if (terminalBodyRef.current) {
73 terminalBodyRef.current.scrollTop = terminalBodyRef.current.scrollHeight;
74 }
75 }, [history]);
76
77 return (
78 <div
79 onClick={() => inputRef.current?.focus()}
80 className="w-full max-w-lg overflow-hidden rounded-3xl border border-slate-800 bg-slate-950 font-mono text-xs text-slate-100 shadow-2xl transition-all"
81 >
82 <div className="flex items-center justify-between border-b border-slate-800 bg-slate-900/80 px-4 py-2.5">
83 <div className="flex items-center gap-2">
84 <span className="h-3 w-3 rounded-full bg-rose-500/80 cursor-pointer" />
85 <span className="h-3 w-3 rounded-full bg-amber-500/80 cursor-pointer" />
86 <span className="h-3 w-3 rounded-full bg-emerald-500/80 cursor-pointer" />
87 <span className="ml-2 font-sans text-xs text-slate-400 font-medium">bash ~ interactive</span>
88 </div>
89 <button
90 onClick={(e) => {
91 e.stopPropagation();
92 copy();
93 }}
94 className="flex items-center gap-1 text-slate-400 hover:text-white transition cursor-pointer"
95 >
96 {copied ? <Check className="h-3.5 w-3.5 text-emerald-400" /> : <Copy className="h-3.5 w-3.5" />}
97 <span>{copied ? 'Copied' : 'Copy'}</span>
98 </button>
99 </div>
100
101 <div className="p-4 sm:p-5 max-h-64 overflow-y-auto space-y-3">
102 {history.map((h, i) => (
103 <div key={i} className="space-y-1">
104 <div className="flex items-center gap-2 text-emerald-400 font-bold">
105 <span>➜</span>
106 <span className="text-cyan-400">~</span>
107 <span className="text-white font-normal">{h.command}</span>
108 </div>
109 <div>{h.output}</div>
110 </div>
111 ))}
112
113 <form onSubmit={handleCommand} className="flex items-center gap-2 pt-1">
114 <span className="text-emerald-400 font-bold">➜</span>
115 <span className="text-cyan-400 font-bold">~</span>
116 <input
117 ref={inputRef}
118 type="text"
119 value={inputVal}
120 onChange={(e) => setInputVal(e.target.value)}
121 placeholder="Type 'help' or any command..."
122 className="flex-1 bg-transparent text-white placeholder:text-slate-600 outline-none font-mono text-xs caret-cyan-400"
123 />
124 <button type="submit" className="text-slate-500 hover:text-cyan-400 transition cursor-pointer">
125 <CornerDownLeft className="h-3 w-3" />
126 </button>
127 </form>
128 <div ref={bottomRef} />
129 </div>
130 </div>
131 );
132}

Installation & Integration Guide

Step 1: Tailwind CSS v4 Setup
Tailwind Docs

If you do not have Tailwind installed yet, run this installation command:

Terminal
npm install tailwindcss @tailwindcss/postcss postcss

Then add the Tailwind directive to your main stylesheet (globals.css):

@import "tailwindcss";

Step 2: Install Icon Dependencies

npm install lucide-react react-icons

Step 3: Add Component File

Create a new file in your project at src/components/effects/TerminalCard.tsx and paste the copied code from the source viewer above.

Step 4: Usage Example

ExamplePage.tsx
1import InteractiveTerminal from '@/components/effects/TerminalCard';
2
3export default function ExamplePage() {
4 return (
5 <main className="p-8 flex items-center justify-center min-h-screen">
6 <InteractiveTerminal />
7 </main>
8 );
9}