Skip to content

Commit fa3185e

Browse files
authored
Merge pull request #67 from pras75299/feat/terminal-component
Feat/terminal component
2 parents 0ad4e3f + 92941f7 commit fa3185e

22 files changed

Lines changed: 1616 additions & 1 deletion

apps/www/components/ui/hero-terminal.tsx

Lines changed: 572 additions & 0 deletions
Large diffs are not rendered by default.

apps/www/config/components.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
LucideUserCircle2,
3939
LucideWand2,
4040
LucideWaves,
41+
Terminal,
4142
} from "lucide-react";
4243

4344
export type ComponentVariant = {
@@ -108,6 +109,7 @@ const iconMap = {
108109
LucideUserCircle2,
109110
LucideWand2,
110111
LucideWaves,
112+
Terminal,
111113
} satisfies Record<string, ElementType>;
112114

113115
const componentDefinitions = [
@@ -3309,6 +3311,81 @@ const componentDefinitions = [
33093311
}
33103312
],
33113313
"usageCode": "import { MagneticLettersHero } from \"@/components/ui/hero-magnetic-letters\";\n\nexport default function Hero() {\n return <MagneticLettersHero headline=\"Motion, where it matters.\" />;\n}"
3314+
},
3315+
{
3316+
"slug": "hero-terminal",
3317+
"name": "Terminal Hero",
3318+
"description": "A 'code-builds-the-page' hero: a headline above a macOS-style terminal that types your install commands and prints their output. Ships the reusable Terminal window too, with reduced-motion, in-view triggering, replay, copy, and keystroke sound.",
3319+
"icon": "Terminal",
3320+
"category": "Hero",
3321+
"kind": "block",
3322+
"addedAt": "2026-05-28",
3323+
"props": [
3324+
{
3325+
"name": "children",
3326+
"type": "ReactNode",
3327+
"description": "Slotted hero content above the terminal (headline / subhead / CTAs). When omitted, a default composition renders."
3328+
},
3329+
{
3330+
"name": "commands",
3331+
"type": "string[]",
3332+
"description": "Commands typed out sequentially in the terminal. Defaults to a shadcn init/install sequence."
3333+
},
3334+
{
3335+
"name": "outputs",
3336+
"type": "Record<number, string[]>",
3337+
"default": "{}",
3338+
"description": "Output lines printed after a command finishes typing, keyed by the command's index."
3339+
},
3340+
{
3341+
"name": "username",
3342+
"type": "string",
3343+
"default": "\"you\"",
3344+
"description": "Name shown highlighted in the shell prompt (renders as `username:~$`)."
3345+
},
3346+
{
3347+
"name": "title",
3348+
"type": "string",
3349+
"default": "\"zsh — your-project\"",
3350+
"description": "Text shown centered in the window title bar."
3351+
},
3352+
{
3353+
"name": "typingSpeed",
3354+
"type": "number",
3355+
"default": "50",
3356+
"description": "Typing speed in milliseconds per character."
3357+
},
3358+
{
3359+
"name": "delayBetweenCommands",
3360+
"type": "number",
3361+
"default": "800",
3362+
"description": "Pause in milliseconds after a command's output before the next command starts."
3363+
},
3364+
{
3365+
"name": "initialDelay",
3366+
"type": "number",
3367+
"default": "500",
3368+
"description": "Delay in milliseconds before the first command begins typing."
3369+
},
3370+
{
3371+
"name": "enableSound",
3372+
"type": "boolean",
3373+
"default": "false",
3374+
"description": "Play a subtle keystroke click on each character via the Web Audio API. Defaults off in the hero to avoid autoplay audio."
3375+
},
3376+
{
3377+
"name": "loop",
3378+
"type": "boolean",
3379+
"default": "false",
3380+
"description": "Restart the typing sequence from the top once it finishes."
3381+
},
3382+
{
3383+
"name": "className",
3384+
"type": "string",
3385+
"description": "Extra classes on the outer `<section>`."
3386+
}
3387+
],
3388+
"usageCode": "import { TerminalHero } from \"@/components/ui/hero-terminal\";\n\nexport default function Hero() {\n return (\n <TerminalHero\n username=\"you\"\n title=\"zsh — your-project\"\n commands={[\n \"npx shadcn@latest init\",\n \"npm install motion\",\n \"npx shadcn@latest add button card\",\n ]}\n outputs={{\n 0: [\n \"✔ Preflight checks passed.\",\n \"✔ Created components.json\",\n \"✔ Initialized project.\",\n ],\n 1: [\"added 1 package in 2s\"],\n 2: [\"✔ Done. Installed button, card.\"],\n }}\n >\n <span className=\"mb-5 inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-3 py-1 text-xs uppercase tracking-[0.18em] text-white/70 backdrop-blur\">\n One command to ship\n </span>\n <h1 className=\"text-balance text-4xl font-semibold tracking-tight sm:text-6xl\">\n Watch your stack build itself.\n </h1>\n <p className=\"mt-5 max-w-xl text-pretty text-base text-white/65 sm:text-lg\">\n Copy-paste components, zero config — production-ready before the cursor\n stops blinking.\n </p>\n </TerminalHero>\n );\n}"
33123389
}
33133390
] satisfies ComponentDefinition[];
33143391

apps/www/config/demos.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import { LiquidAuroraMeshHero } from "@/components/ui/hero-liquid-aurora-mesh";
7777
import { NoiseDotFieldHero } from "@/components/ui/hero-noise-dot-field";
7878
import { LogoMarqueeHero } from "@/components/ui/hero-logo-marquee";
7979
import { MagneticLettersHero } from "@/components/ui/hero-magnetic-letters";
80+
import { TerminalHero } from "@/components/ui/hero-terminal";
8081
import { motion } from "motion/react";
8182
import { useRef, useState } from "react";
8283
import {
@@ -3828,4 +3829,5 @@ export const componentDemos: Record<string, DemoComponent> = {
38283829
</LogoMarqueeHero>
38293830
),
38303831
"hero-magnetic-letters": () => <MagneticLettersHero />,
3832+
"hero-terminal": () => <TerminalHero />,
38313833
};

apps/www/config/docs-scenarios.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,5 +1116,10 @@ export const docsScenarios: Record<string, ComponentDocs> = {
11161116
"slug": "hero-magnetic-letters",
11171117
"overview": "Per-glyph cursor-tracking hero. The headline reads as a normal h1 to screen readers (aria-label on the wrapper, aria-hidden on each animated span), so accessibility is preserved despite the per-letter wrapping.",
11181118
"scenarios": []
1119+
},
1120+
"hero-terminal": {
1121+
"slug": "hero-terminal",
1122+
"overview": "TerminalHero pairs a headline with a live terminal that types your getting-started commands and prints their output — a high-conversion 'see it work' pattern for landing pages. The standalone `Terminal` window is exported from the same file for reuse elsewhere. The animation starts when the hero scrolls into view, respects `prefers-reduced-motion` (rendering the finished transcript instantly), and exposes copy + replay controls. The animated transcript is `aria-hidden` while a screen-reader-only copy carries the real content.",
1123+
"scenarios": []
11191124
}
11201125
};

apps/www/public/r/hero-terminal.json

Lines changed: 20 additions & 0 deletions
Large diffs are not rendered by default.

apps/www/public/r/registry.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,24 @@
11441144
}
11451145
]
11461146
},
1147+
{
1148+
"name": "hero-terminal",
1149+
"type": "registry:ui",
1150+
"title": "Terminal Hero",
1151+
"description": "A 'code-builds-the-page' hero: a headline above a macOS-style terminal that types your install commands and prints their output. Ships the reusable Terminal window too, with reduced-motion, in-view triggering, replay, copy, and keystroke sound.",
1152+
"dependencies": [
1153+
"motion",
1154+
"clsx",
1155+
"tailwind-merge"
1156+
],
1157+
"files": [
1158+
{
1159+
"path": "components/ui/hero-terminal.tsx",
1160+
"type": "registry:component",
1161+
"target": "components/ui/hero-terminal.tsx"
1162+
}
1163+
]
1164+
},
11471165
{
11481166
"name": "magnetic-text",
11491167
"type": "registry:ui",

apps/www/public/registry.json

Lines changed: 68 additions & 0 deletions
Large diffs are not rendered by default.

apps/www/public/registry/changelogs.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,23 @@
625625
]
626626
}
627627
],
628+
"hero-terminal": [
629+
{
630+
"version": "1.0.1",
631+
"date": "2026-05-29",
632+
"changes": [
633+
"Stop the prompt cursor from blinking under prefers-reduced-motion to honor the full reduced-motion claim.",
634+
"Add a focus-visible ring to the copy and replay controls for keyboard users."
635+
]
636+
},
637+
{
638+
"version": "1.0.0",
639+
"date": "2026-05-28",
640+
"changes": [
641+
"Initial release."
642+
]
643+
}
644+
],
628645
"magnetic-text": [
629646
{
630647
"version": "1.0.0",

apps/www/public/registry/hero-terminal.json

Lines changed: 68 additions & 0 deletions
Large diffs are not rendered by default.

apps/www/public/registry/index.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"hero-noise-dot-field",
6262
"hero-logo-marquee",
6363
"hero-magnetic-letters",
64+
"hero-terminal",
6465
"magnetic-text"
6566
]
6667
}

0 commit comments

Comments
 (0)