mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
add new stack builder page
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { Github, Menu, X } from "lucide-react";
|
import { Github, Maximize2, Menu, X } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import PackageIcon from "./Icons";
|
import PackageIcon from "./Icons";
|
||||||
@@ -47,10 +47,10 @@ const Navbar = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<nav
|
<nav
|
||||||
className={`z-[100] flex w-screen items-center justify-between px-4 py-4 transition-all duration-300 sm:px-8 ${
|
className={`fixed top-0 z-[100] flex w-full items-center justify-between px-4 py-4 transition-all duration-300 sm:px-8 ${
|
||||||
scrolled
|
scrolled
|
||||||
? "border-transparent bg-transparent"
|
? "bg-transparent"
|
||||||
: "border-gray-200 border-b bg-gray-50/80 backdrop-blur-xl dark:border-gray-800/50 dark:bg-gray-950/80"
|
: "bg-gray-50/80 backdrop-blur-xl dark:bg-gray-950/80"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -138,10 +138,17 @@ const Navbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`hidden justify-end transition-opacity duration-300 md:flex ${
|
className={`hidden justify-end gap-2 transition-opacity duration-300 md:flex ${
|
||||||
scrolled ? "pointer-events-none opacity-0" : "opacity-100"
|
scrolled ? "pointer-events-none opacity-0" : "opacity-100"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<Link
|
||||||
|
href="/new"
|
||||||
|
className="inline-flex items-center rounded-lg border border-blue-300 bg-blue-100/90 px-4 py-1 font-mono text-blue-700 text-sm backdrop-blur-sm transition-colors hover:bg-blue-200 dark:border-blue-800 dark:bg-blue-900/90 dark:text-blue-300 dark:hover:bg-blue-800/50"
|
||||||
|
>
|
||||||
|
<Maximize2 className="mr-2 size-4" />
|
||||||
|
Stack Builder
|
||||||
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="https://www.github.com/better-t-stack/create-better-t-stack"
|
href="https://www.github.com/better-t-stack/create-better-t-stack"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -169,7 +176,6 @@ const Navbar = () => {
|
|||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Mobile Menu - Terminal Style */}
|
|
||||||
<div
|
<div
|
||||||
className={`fixed inset-0 z-[99] pt-16 backdrop-blur-md transition-all duration-300 ease-in-out md:hidden ${
|
className={`fixed inset-0 z-[99] pt-16 backdrop-blur-md transition-all duration-300 ease-in-out md:hidden ${
|
||||||
mobileMenuOpen
|
mobileMenuOpen
|
||||||
@@ -178,7 +184,6 @@ const Navbar = () => {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="mx-4 mt-4 overflow-hidden rounded-lg border border-gray-300 bg-gray-100/95 shadow-lg dark:border-gray-700 dark:bg-gray-900/95">
|
<div className="mx-4 mt-4 overflow-hidden rounded-lg border border-gray-300 bg-gray-100/95 shadow-lg dark:border-gray-700 dark:bg-gray-900/95">
|
||||||
{/* Terminal Header */}
|
|
||||||
<div className="flex items-center bg-gray-200 px-4 py-2 dark:bg-gray-800">
|
<div className="flex items-center bg-gray-200 px-4 py-2 dark:bg-gray-800">
|
||||||
<div className="mr-4 flex space-x-2">
|
<div className="mr-4 flex space-x-2">
|
||||||
<div className="h-3 w-3 rounded-full bg-red-500" />
|
<div className="h-3 w-3 rounded-full bg-red-500" />
|
||||||
@@ -190,7 +195,6 @@ const Navbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Terminal Body */}
|
|
||||||
<div className="p-4 font-mono text-sm">
|
<div className="p-4 font-mono text-sm">
|
||||||
<div className="pb-3">
|
<div className="pb-3">
|
||||||
<span className="text-green-600 dark:text-green-500">
|
<span className="text-green-600 dark:text-green-500">
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ import {
|
|||||||
ClipboardCopy,
|
ClipboardCopy,
|
||||||
HelpCircle,
|
HelpCircle,
|
||||||
InfoIcon,
|
InfoIcon,
|
||||||
|
Maximize2,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
Settings,
|
Settings,
|
||||||
Star,
|
Star,
|
||||||
Terminal,
|
Terminal,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
const validateProjectName = (name: string): string | undefined => {
|
const validateProjectName = (name: string): string | undefined => {
|
||||||
@@ -46,7 +48,11 @@ const validateProjectName = (name: string): string | undefined => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StackArchitect = () => {
|
const StackArchitect = ({
|
||||||
|
fullscreen = false,
|
||||||
|
}: {
|
||||||
|
fullscreen?: boolean;
|
||||||
|
}) => {
|
||||||
const [stack, setStack] = useState<StackState>(DEFAULT_STACK);
|
const [stack, setStack] = useState<StackState>(DEFAULT_STACK);
|
||||||
const [command, setCommand] = useState(
|
const [command, setCommand] = useState(
|
||||||
"npx create-better-t-stack@latest my-better-t-app --yes",
|
"npx create-better-t-stack@latest my-better-t-app --yes",
|
||||||
@@ -520,7 +526,7 @@ const StackArchitect = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full">
|
<div className={`mx-auto w-full ${fullscreen ? "max-w-none" : ""}`}>
|
||||||
<div className="overflow-hidden rounded-xl border border-gray-300 bg-gray-100 text-gray-800 shadow-xl dark:border-gray-700 dark:bg-gray-900 dark:text-white">
|
<div className="overflow-hidden rounded-xl border border-gray-300 bg-gray-100 text-gray-800 shadow-xl dark:border-gray-700 dark:bg-gray-900 dark:text-white">
|
||||||
<div className="flex items-center justify-between bg-gray-200 px-2 py-2 sm:px-4 dark:bg-gray-800">
|
<div className="flex items-center justify-between bg-gray-200 px-2 py-2 sm:px-4 dark:bg-gray-800">
|
||||||
<div className="flex space-x-2">
|
<div className="flex space-x-2">
|
||||||
@@ -548,6 +554,13 @@ const StackArchitect = () => {
|
|||||||
>
|
>
|
||||||
<Star className="h-4 w-4" />
|
<Star className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
|
<Link
|
||||||
|
href={fullscreen ? "/" : "/new"}
|
||||||
|
className="text-gray-600 transition-colors hover:text-gray-800 dark:text-gray-400 dark:hover:text-white"
|
||||||
|
title={fullscreen ? "Exit Fullscreen" : "Open Fullscreen"}
|
||||||
|
>
|
||||||
|
<Maximize2 className="h-4 w-4" />
|
||||||
|
</Link>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={copyToClipboard}
|
onClick={copyToClipboard}
|
||||||
@@ -704,7 +717,7 @@ const StackArchitect = () => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4 grid grid-cols-1 gap-2 sm:grid-cols-2">
|
<div className="mb-4 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3">
|
||||||
{TECH_OPTIONS[activeTab as keyof typeof TECH_OPTIONS].map(
|
{TECH_OPTIONS[activeTab as keyof typeof TECH_OPTIONS].map(
|
||||||
(tech) => {
|
(tech) => {
|
||||||
let isSelected = false;
|
let isSelected = false;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|||||||
return (
|
return (
|
||||||
<main className="relative z-10 grid min-h-svh grid-cols-1 grid-rows-[auto_1fr_auto] overflow-hidden bg-gradient-to-b from-gray-50 to-gray-100 transition-color duration-300 dark:from-gray-950 dark:to-black">
|
<main className="relative z-10 grid min-h-svh grid-cols-1 grid-rows-[auto_1fr_auto] overflow-hidden bg-gradient-to-b from-gray-50 to-gray-100 transition-color duration-300 dark:from-gray-950 dark:to-black">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
{children}
|
<div className="pt-16">{children}</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|||||||
56
apps/web/src/app/(home)/new/page.tsx
Normal file
56
apps/web/src/app/(home)/new/page.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import StackArchitect from "../_components/StackArchitech";
|
||||||
|
|
||||||
|
export default function FullScreenStackArchitect() {
|
||||||
|
useEffect(() => {
|
||||||
|
const setVh = () => {
|
||||||
|
const vh = window.innerHeight * 0.01;
|
||||||
|
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
||||||
|
};
|
||||||
|
|
||||||
|
setVh();
|
||||||
|
window.addEventListener("resize", setVh);
|
||||||
|
return () => window.removeEventListener("resize", setVh);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-[calc(var(--vh,1vh)*100)] flex-col bg-gradient-to-b from-white to-gray-50 dark:from-gray-950 dark:to-gray-900">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
className="flex-1 px-4 py-8"
|
||||||
|
>
|
||||||
|
<div className="mx-auto max-w-6xl">
|
||||||
|
<div className="mb-8 max-w-3xl">
|
||||||
|
<h1 className="mb-3 font-bold font-mono text-2xl sm:text-3xl md:text-4xl">
|
||||||
|
Design Your Ideal Full Stack
|
||||||
|
</h1>
|
||||||
|
<p className="text-gray-700 text-lg dark:text-gray-300">
|
||||||
|
Configure every aspect of your TypeScript application with the
|
||||||
|
interactive stack architect. Choose your technologies, add
|
||||||
|
features, and generate your startup command.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<StackArchitect fullscreen={true} />
|
||||||
|
|
||||||
|
<div className="mt-8 rounded-lg border border-blue-100 bg-blue-50 p-4 dark:border-blue-900 dark:bg-blue-900/20">
|
||||||
|
<h3 className="mb-2 font-medium text-blue-800 dark:text-blue-300">
|
||||||
|
Need help getting started?
|
||||||
|
</h3>
|
||||||
|
<p className="text-blue-700 dark:text-blue-400">
|
||||||
|
Select a preset template for common configurations, or customize
|
||||||
|
each component of your stack. When you are ready, copy the
|
||||||
|
generated command and run it in your terminal to create your
|
||||||
|
project.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user