DEV Community

Cover image for How I Built a Retro Terminal Panel in React
Ngawang Tenzin
Ngawang Tenzin

Posted on

How I Built a Retro Terminal Panel in React

After sharing my portfolio project on DEV, a fellow community member commented asking how I built the retro terminal panel. So, I decided to break down the logic and share the details here!

The goal was to show a series of commands and outputs, just like a real terminal, and animate them. I also wanted a blinking cursor and a “reset” effect after all lines are shown.

The State
I used React’s useState to keep track of the lines currently displayed in the terminal:

const [terminalLines, setTerminalLines] = useState([] as string[]);
Enter fullscreen mode Exit fullscreen mode

The Commands
I defined the commands and outputs as an array:

const terminalCommands = [
  '> whoami',
  'ngawang_tenzin',
  '> cat skills.txt',
  'React.js | Node.js | Python | TypeScript',
  '> ls projects/',
  'barma-sorig-web-app/ | quiz-mobile-app/ | portfolio-website/',
  '> status',
  'AVAILABLE FOR HIRE',
  '> echo "Let\'s build something amazing!"',
  "Let's build something amazing!"
];
Enter fullscreen mode Exit fullscreen mode

The Animation Logic
I used useEffect to set up an interval that adds one line at a time to the terminal. Here’s the core logic:

useEffect(() => {
  let terminalInterval: ReturnType<typeof setInterval> | undefined;
  let lineIndex = 0;
  if (isRetroMode) {
    terminalInterval = setInterval(() => {
      if (lineIndex < terminalCommands.length && terminalCommands[lineIndex]) {
        setTerminalLines(prev => {
          const newLines = prev.slice();
          newLines.push(terminalCommands[lineIndex]);
          return newLines;
        });
        lineIndex++;
      } else {
        setTimeout(() => {
          setTerminalLines([]);
          lineIndex = 0;
        }, 3000);
      }
    }, 800);
  } else {
    setTerminalLines([]);
  }
  return () => {
    if (terminalInterval) clearInterval(terminalInterval);
  };
}, [isRetroMode]);
Enter fullscreen mode Exit fullscreen mode
  • Every 800ms, a new line is added.
  • When all lines are shown, it waits 3 seconds, then resets the terminal.

The Styling
I used CSS to get the neon green text, dark background, and blinking cursor. Here’s a snippet:

.terminal-line.command {
  color: #00ff41;
}
.terminal-line.output {
  color: #cccccc;
  margin-left: 1rem;
}
.terminal-cursor {
  color: #00ff41;
  animation: blink 1s infinite;
}
@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}
Enter fullscreen mode Exit fullscreen mode

Result
The result is a dynamic, animated terminal panel that brings a retro vibe to my portfolio. It’s all handled with React state and effects, making it easy to customize and integrate with the rest of my site.

Top comments (1)

Collapse
 
masterdevsabith profile image
Muhammed Sabith

🔥❤️ cool