1
3
Block

Terminal

PreviousNext

An implementation of the linux terminal. Used for showcasing a command line interface.

import {
  AnimatedSpan,
  Terminal,
  TypingAnimation,
} from "@/components/ui/terminal"

export function TerminalDemo() {
  return (
    <Terminal>
      <TypingAnimation>
        &gt; npx create-vite@latest my-app --template react-ts
      </TypingAnimation>

      <AnimatedSpan className="text-green-500">
        ✔ Scaffolding project in /path/to/my-app...
      </AnimatedSpan>

      <AnimatedSpan className="text-green-500">✔ Done. Now run:</AnimatedSpan>

      <AnimatedSpan className="ml-4 text-green-500">npm install</AnimatedSpan>

      <AnimatedSpan className="ml-4 text-green-500">npm run dev</AnimatedSpan>

      <AnimatedSpan className="text-blue-500">
        <span>📁 Created files:</span>
        <span className="block pl-2">- src/App.tsx</span>
        <span className="block pl-2">- vite.config.ts</span>
        <span className="block pl-2">- tsconfig.json</span>
      </AnimatedSpan>

      <TypingAnimation className="text-muted-foreground">
        Your Vite + React + TypeScript project is ready!
      </TypingAnimation>

      <TypingAnimation className="text-muted-foreground">
        Navigate to the project and start building.
      </TypingAnimation>
    </Terminal>
  )
}

Installation

pnpm dlx shadcn@latest add https://ebonui.com/r/terminal.json

Examples

Custom Delays

import {
  AnimatedSpan,
  Terminal,
  TypingAnimation,
} from "@/components/ui/terminal"

export function TerminalDemo2() {
  return (
    <Terminal>
      <TypingAnimation delay={0}>$ git status</TypingAnimation>

      <AnimatedSpan delay={800} className="text-green-500">
        On branch main
      </AnimatedSpan>

      <AnimatedSpan delay={1000} className="text-green-500">
        Your branch is up to date with origin/main.
      </AnimatedSpan>

      <AnimatedSpan delay={1200} className="text-blue-500">
        Changes not staged for commit:
      </AnimatedSpan>

      <AnimatedSpan delay={1400} className="ml-4 text-blue-500">
        modified: src/components/Button.tsx
      </AnimatedSpan>

      <TypingAnimation delay={2000}>$ git add .</TypingAnimation>

      <TypingAnimation delay={2800}>
        $ git commit -m Update Button component
      </TypingAnimation>

      <AnimatedSpan delay={3600} className="text-green-500">
        [main abc1234] Update Button component
      </AnimatedSpan>

      <AnimatedSpan delay={3800} className="text-green-500">
        1 file changed, 5 insertions(+), 2 deletions(-)
      </AnimatedSpan>
    </Terminal>
  )
}

Usage

import {
  AnimatedSpan,
  Terminal,
  TypingAnimation,
} from "@/components/ui/terminal"
<Terminal>
  <TypingAnimation>pnpm dlx shadcn@latest init</TypingAnimation>
  <AnimatedSpan>✔ Preflight checks.</AnimatedSpan>
  <AnimatedSpan>✔ Validating Tailwind CSS.</AnimatedSpan>
  <TypingAnimation>Success! Project initialization completed.</TypingAnimation>
</Terminal>

The terminal sequences its children automatically. Each TypingAnimation or AnimatedSpan starts when the previous finishes. Manual delay props are optional and typically unnecessary.

Props

Terminal

PropTypeDefaultDescription
childrenReactNode-Terminal content: a list of TypingAnimation/AnimatedSpan.
classNamestring-Custom CSS class for styling.
sequencebooleantrueEnable auto sequencing so each line starts after the previous.
startOnViewbooleantrueStart sequencing when the terminal enters the viewport.

AnimatedSpan

PropTypeDefaultDescription
childrenReactNode-Content to be faded in.
classNamestring-Custom CSS class for styling.
delaynumber0Delay in ms before animation starts (used when sequence is false).
startOnViewbooleanfalseIf true, waits for viewport visibility before animating when unsequenced.

TypingAnimation

PropTypeDefaultDescription
childrenstring-Text to be typed.
classNamestring-Custom CSS class for styling.
durationnumber60Milliseconds per character.
delaynumber0Delay in ms before typing starts (used when sequence is false).
asReact.ElementType"span"The component type to render.
startOnViewbooleantrueIf true, waits for viewport visibility before typing when unsequenced.