mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
fix errors
This commit is contained in:
@@ -1,22 +1,26 @@
|
|||||||
|
|
||||||
interface ShinyTextProps {
|
interface ShinyTextProps {
|
||||||
text: string;
|
text: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
speed?: number;
|
speed?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShinyText = ({ text, disabled = false, speed = 5, className = '' }: ShinyTextProps) => {
|
const ShinyText = ({
|
||||||
const animationDuration = `${speed}s`;
|
text,
|
||||||
|
disabled = false,
|
||||||
|
speed = 5,
|
||||||
|
className = "",
|
||||||
|
}: ShinyTextProps) => {
|
||||||
|
const animationDuration = `${speed}s`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`shiny-text ${disabled ? 'disabled' : ''} ${className}`}
|
className={`shiny-text ${disabled ? "disabled" : ""} ${className}`}
|
||||||
style={{ animationDuration }}
|
style={{ animationDuration }}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShinyText;
|
export default ShinyText;
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
|
|
||||||
const CenterLines = () => {
|
const CenterLines = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='absolute top-3/4 -translate-y-1/2 left-0 w-80 h-14
|
<div
|
||||||
|
className="absolute top-3/4 -translate-y-1/2 left-0 w-80 h-14
|
||||||
rounded-bl-3xl transform rotate-180
|
rounded-bl-3xl transform rotate-180
|
||||||
border-b-2 border-l-2 border-slate-700
|
border-b-2 border-l-2 border-slate-700
|
||||||
shadow-lg backdrop-blur-sm' />
|
shadow-lg backdrop-blur-sm"
|
||||||
<div className='absolute top-3/4 -translate-y-1/2 right-0 w-80 h-14
|
/>
|
||||||
|
<div
|
||||||
|
className="absolute top-3/4 -translate-y-1/2 right-0 w-80 h-14
|
||||||
rounded-br-3xl transform rotate-180
|
rounded-br-3xl transform rotate-180
|
||||||
border-b-2 border-r-2 border-slate-700
|
border-b-2 border-r-2 border-slate-700
|
||||||
shadow-lg backdrop-blur-sm' />
|
shadow-lg backdrop-blur-sm"
|
||||||
</>
|
/>
|
||||||
)
|
</>
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default CenterLines
|
export default CenterLines;
|
||||||
|
|||||||
@@ -1,123 +1,131 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from "react";
|
|
||||||
import { ChevronRight } from "lucide-react";
|
import { ChevronRight } from "lucide-react";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
import PackageIcon from "./Icons";
|
import PackageIcon from "./Icons";
|
||||||
|
|
||||||
const CodeContainer = () => {
|
const CodeContainer = () => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [selectedPM, setSelectedPM] = useState<"npm" | "yarn" | "pnpm" | "bun">("npm");
|
const [selectedPM, setSelectedPM] = useState<"npm" | "yarn" | "pnpm" | "bun">(
|
||||||
const [copied, setCopied] = useState(false);
|
"npm",
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const commands = {
|
const commands = {
|
||||||
npm: "npx create-better-t-stack@latest",
|
npm: "npx create-better-t-stack@latest",
|
||||||
yarn: "yarn dlx create better-t-stack",
|
yarn: "yarn dlx create better-t-stack",
|
||||||
pnpm: "pnpm dlx create better-t-stack",
|
pnpm: "pnpm dlx create better-t-stack",
|
||||||
bun: "bunx create-better-t-stack"
|
bun: "bunx create-better-t-stack",
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyToClipboard = async (pm: "npm" | "yarn" | "pnpm" | "bun") => {
|
const copyToClipboard = async (pm: "npm" | "yarn" | "pnpm" | "bun") => {
|
||||||
await navigator.clipboard.writeText(commands[pm]);
|
await navigator.clipboard.writeText(commands[pm]);
|
||||||
setSelectedPM(pm);
|
setSelectedPM(pm);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-3xl mx-auto mt-12">
|
<div className="w-full max-w-3xl mx-auto mt-12">
|
||||||
<div className="relative group">
|
<div className="relative group">
|
||||||
<div className="absolute -inset-1 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg backdrop-blur-lg opacity-25 transition duration-1000 group-hover:duration-200"></div>
|
<div className="absolute -inset-1 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg backdrop-blur-lg opacity-25 transition duration-1000 group-hover:duration-200" />
|
||||||
<div className="relative rounded-lg p-1 bg-slate-900/30 backdrop-blur-xl">
|
<div className="relative rounded-lg p-1 bg-slate-900/30 backdrop-blur-xl">
|
||||||
<div className="p-4 font-mono text-gray-300 text-sm bg-black/20 rounded-lg flex items-center justify-between">
|
<div className="p-4 font-mono text-gray-300 text-sm bg-black/20 rounded-lg flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<ChevronRight />
|
<ChevronRight />
|
||||||
<span className="text-base bg-clip-text text-transparent bg-gradient-to-br from-purple-400 via-pink-400 to-yellow-400">
|
<span className="text-base bg-clip-text text-transparent bg-gradient-to-br from-purple-400 via-pink-400 to-yellow-400">
|
||||||
{commands[selectedPM]}
|
{commands[selectedPM]}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative" ref={menuRef}>
|
<div className="relative" ref={menuRef}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsOpen(!isOpen)}
|
type="button"
|
||||||
className="flex items-center space-x-2 px-3 py-2 w-10 justify-center rounded-md cursor-pointer hover:bg-white/10 transition-colors text-gray-300 hover:text-white relative"
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
>
|
className="flex items-center space-x-2 px-3 py-2 w-10 justify-center rounded-md cursor-pointer hover:bg-white/10 transition-colors text-gray-300 hover:text-white relative"
|
||||||
{copied ? (
|
>
|
||||||
<span className="flex items-center space-x-2">
|
{copied ? (
|
||||||
<CheckIcon className="w-5 h-5" />
|
<span className="flex items-center space-x-2">
|
||||||
</span>
|
<CheckIcon className="w-5 h-5" />
|
||||||
) : (
|
</span>
|
||||||
<span className="flex items-center space-x-2">
|
) : (
|
||||||
<CopyIcon className="w-5 h-5" />
|
<span className="flex items-center space-x-2">
|
||||||
</span>
|
<CopyIcon className="w-5 h-5" />
|
||||||
)}
|
</span>
|
||||||
</button>
|
)}
|
||||||
{isOpen && (
|
</button>
|
||||||
<div className="absolute right-6 top-8 mt-2 w-24 rounded-lg backdrop-blur-lg bg-violet-950/10 shadow-xl ring-1 ring-white/10 divide-y divide-gray-700/30 transition-all duration-200">
|
{isOpen && (
|
||||||
{(["npm", "yarn", "pnpm", "bun"] as const).map((pm) => (
|
<div className="absolute right-6 top-8 mt-2 w-24 rounded-lg backdrop-blur-lg bg-violet-950/10 shadow-xl ring-1 ring-white/10 divide-y divide-gray-700/30 transition-all duration-200">
|
||||||
<button
|
{(["npm", "yarn", "pnpm", "bun"] as const).map((pm) => (
|
||||||
key={pm}
|
<button
|
||||||
onClick={() => copyToClipboard(pm)}
|
type="button"
|
||||||
className="group cursor-pointer flex items-center w-full px-4 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 transition-all duration-200 first:rounded-t-lg last:rounded-b-lg"
|
key={pm}
|
||||||
>
|
onClick={() => copyToClipboard(pm)}
|
||||||
<PackageIcon className="h-4 w-4 mr-2 group-hover:scale-110 transition-transform" pm={pm} /> {pm}
|
className="group cursor-pointer flex items-center w-full px-4 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 transition-all duration-200 first:rounded-t-lg last:rounded-b-lg"
|
||||||
</button>
|
>
|
||||||
))}
|
<PackageIcon
|
||||||
</div>
|
className="h-4 w-4 mr-2 group-hover:scale-110 transition-transform"
|
||||||
)}
|
pm={pm}
|
||||||
</div>
|
/>{" "}
|
||||||
|
{pm}
|
||||||
</div>
|
</button>
|
||||||
</div>
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
);
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const CopyIcon = ({ className = "" }) => (
|
const CopyIcon = ({ className = "" }) => (
|
||||||
<svg
|
<svg
|
||||||
className={className}
|
className={className}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<title>copy</title>
|
||||||
strokeLinecap="round"
|
<path
|
||||||
strokeLinejoin="round"
|
strokeLinecap="round"
|
||||||
strokeWidth={2}
|
strokeLinejoin="round"
|
||||||
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
strokeWidth={2}
|
||||||
/>
|
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
||||||
</svg>
|
/>
|
||||||
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
const CheckIcon = ({ className = "" }) => (
|
const CheckIcon = ({ className = "" }) => (
|
||||||
<svg
|
<svg
|
||||||
className={className}
|
className={className}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<title>check</title>
|
||||||
strokeLinecap="round"
|
<path
|
||||||
strokeLinejoin="round"
|
strokeLinecap="round"
|
||||||
strokeWidth={2}
|
strokeLinejoin="round"
|
||||||
d="M5 13l4 4L19 7"
|
strokeWidth={2}
|
||||||
/>
|
d="M5 13l4 4L19 7"
|
||||||
</svg>
|
/>
|
||||||
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default CodeContainer;
|
export default CodeContainer;
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
/** eslint-disable react/jsx-no-comment-textnodes */
|
/** eslint-disable react/jsx-no-comment-textnodes */
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
|
|
||||||
const CodeExample = () => {
|
const CodeExample = () => {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-2xl mx-auto mt-8 rounded-lg overflow-hidden bg-slate-900 border border-slate-700">
|
<div className="max-w-2xl mx-auto mt-8 rounded-lg overflow-hidden bg-slate-900 border border-slate-700">
|
||||||
<div className="flex items-center px-4 py-2 bg-slate-800">
|
<div className="flex items-center px-4 py-2 bg-slate-800">
|
||||||
<div className="flex space-x-2">
|
<div className="flex space-x-2">
|
||||||
<div className="w-3 h-3 rounded-full bg-red-500" />
|
<div className="w-3 h-3 rounded-full bg-red-500" />
|
||||||
<div className="w-3 h-3 rounded-full bg-yellow-500" />
|
<div className="w-3 h-3 rounded-full bg-yellow-500" />
|
||||||
<div className="w-3 h-3 rounded-full bg-green-500" />
|
<div className="w-3 h-3 rounded-full bg-green-500" />
|
||||||
</div>
|
</div>
|
||||||
<span className="ml-4 text-sm text-slate-400">example.ts</span>
|
<span className="ml-4 text-sm text-slate-400">example.ts</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 font-mono text-sm relative">
|
<div className="p-4 font-mono text-sm relative">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="text-slate-400">{"// ❌ Without Type Safety"}</div>
|
<div className="text-slate-400">{"// ❌ Without Type Safety"}</div>
|
||||||
<div className="text-white">
|
<div className="text-white">
|
||||||
function processUser(user) {
|
function processUser(user){" "}
|
||||||
<span className="text-red-400">console.log(user.namee)</span>
|
{<span className="text-red-400">console.log(user.namee)</span>}
|
||||||
}
|
</div>
|
||||||
</div>
|
<div className="text-red-400 text-xs bg-red-900/30 p-2 rounded">
|
||||||
<div className="text-red-400 text-xs bg-red-900/30 p-2 rounded">
|
Property 'namee' does not exist on type 'User'.
|
||||||
Property 'namee' does not exist on type 'User'.
|
Did you mean 'name'?
|
||||||
Did you mean 'name'?
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-6 text-slate-400">{"// ✅ With Type Safety"}</div>
|
<div className="mt-6 text-slate-400">{"// ✅ With Type Safety"}</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-blue-400">interface</span>
|
<span className="text-blue-400">interface</span>
|
||||||
<span className="text-green-400"> User</span>
|
<span className="text-green-400"> User</span>
|
||||||
<span className="text-white"> {'{'}</span>
|
<span className="text-white"> {"{"}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-4 text-slate-200">
|
<div className="pl-4 text-slate-200">
|
||||||
name: string;
|
name: string;
|
||||||
<br />
|
<br />
|
||||||
age: number;
|
age: number;
|
||||||
</div>
|
</div>
|
||||||
<div className="text-white">{'}'}</div>
|
<div className="text-white">{"}"}</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-blue-400">function</span>
|
<span className="text-blue-400">function</span>
|
||||||
<span className="text-yellow-400"> processUser</span>
|
<span className="text-yellow-400"> processUser</span>
|
||||||
<span className="text-white">(user: </span>
|
<span className="text-white">(user: </span>
|
||||||
<span className="text-green-400">User</span>
|
<span className="text-green-400">User</span>
|
||||||
<span className="text-white">) {'{'}</span>
|
<span className="text-white">) {"{"}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-4 text-slate-200">
|
<div className="pl-4 text-slate-200">
|
||||||
console.log(user.name) <span className="text-slate-400">{"// ✨ Type checked!"}</span>
|
console.log(user.name){" "}
|
||||||
</div>
|
<span className="text-slate-400">{"// ✨ Type checked!"}</span>
|
||||||
<div className="text-white">{'}'}</div>
|
</div>
|
||||||
</div>
|
<div className="text-white">{"}"}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default CodeExample
|
export default CodeExample;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const PackageIcon = ({ pm, className }: { pm: string; className?: string }) => {
|
|||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
strokeMiterlimit="2"
|
strokeMiterlimit="2"
|
||||||
>
|
>
|
||||||
|
<title>yarn</title>
|
||||||
<path
|
<path
|
||||||
d="M256 0c141.344 0 256 114.656 256 256S397.344 512 256 512 0 397.344 0 256 114.656 0 256 0z"
|
d="M256 0c141.344 0 256 114.656 256 256S397.344 512 256 512 0 397.344 0 256 114.656 0 256 0z"
|
||||||
fill="#2c8ebb"
|
fill="#2c8ebb"
|
||||||
@@ -39,7 +40,7 @@ const PackageIcon = ({ pm, className }: { pm: string; className?: string }) => {
|
|||||||
viewBox="0 0 32 32"
|
viewBox="0 0 32 32"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<title>file_type_pnpm</title>
|
<title>pnpm</title>
|
||||||
<path d="M30,10.75H21.251V2H30Z" style={{ fill: "#f9ad00" }} />
|
<path d="M30,10.75H21.251V2H30Z" style={{ fill: "#f9ad00" }} />
|
||||||
<path d="M20.374,10.75h-8.75V2h8.75Z" style={{ fill: "#f9ad00" }} />
|
<path d="M20.374,10.75h-8.75V2h8.75Z" style={{ fill: "#f9ad00" }} />
|
||||||
<path d="M10.749,10.75H2V2h8.749Z" style={{ fill: "#f9ad00" }} />
|
<path d="M10.749,10.75H2V2h8.749Z" style={{ fill: "#f9ad00" }} />
|
||||||
@@ -58,6 +59,7 @@ const PackageIcon = ({ pm, className }: { pm: string; className?: string }) => {
|
|||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 100 100"
|
viewBox="0 0 100 100"
|
||||||
>
|
>
|
||||||
|
<title>bun</title>
|
||||||
<path
|
<path
|
||||||
fill="#000"
|
fill="#000"
|
||||||
d="M89.237 32.3c-.2-.213-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625A33.08 33.08 0 0 1 94.75 51c0 20.712-21.025 37.562-46.875 37.562-14.475 0-27.425-5.287-36.038-13.575l.625.625.625.625.625.625.625.625.625.625.625.625.625.625c8.6 8.638 21.838 14.2 36.663 14.2 25.85 0 46.875-16.85 46.875-37.5 0-8.825-3.8-17.187-10.513-23.762"
|
d="M89.237 32.3c-.2-.213-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625-.212-.2-.412-.425-.625-.625A33.08 33.08 0 0 1 94.75 51c0 20.712-21.025 37.562-46.875 37.562-14.475 0-27.425-5.287-36.038-13.575l.625.625.625.625.625.625.625.625.625.625.625.625.625.625c8.6 8.638 21.838 14.2 36.663 14.2 25.85 0 46.875-16.85 46.875-37.5 0-8.825-3.8-17.187-10.513-23.762"
|
||||||
|
|||||||
@@ -5,20 +5,22 @@ import { useEffect, useState } from "react";
|
|||||||
const NpmPackage = () => {
|
const NpmPackage = () => {
|
||||||
const [version, setVersion] = useState("");
|
const [version, setVersion] = useState("");
|
||||||
|
|
||||||
const getLatestVersion = async () => {
|
|
||||||
const res = await fetch(
|
|
||||||
"https://registry.npmjs.org/create-better-t-stack/latest",
|
|
||||||
);
|
|
||||||
const data = await res.json();
|
|
||||||
setVersion(data.version);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const getLatestVersion = async () => {
|
||||||
|
const res = await fetch(
|
||||||
|
"https://registry.npmjs.org/create-better-t-stack/latest",
|
||||||
|
);
|
||||||
|
const data = await res.json();
|
||||||
|
setVersion(data.version);
|
||||||
|
};
|
||||||
getLatestVersion();
|
getLatestVersion();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className="bg-slate-800 no-underline group cursor-pointer relative shadow-2xl shadow-zinc-900 rounded-full p-px text-xs font-semibold leading-6 text-white inline-block">
|
<button
|
||||||
|
type="button"
|
||||||
|
className="bg-slate-800 no-underline group cursor-pointer relative shadow-2xl shadow-zinc-900 rounded-full p-px text-xs font-semibold leading-6 text-white inline-block"
|
||||||
|
>
|
||||||
<span className="absolute inset-0 overflow-hidden rounded-full">
|
<span className="absolute inset-0 overflow-hidden rounded-full">
|
||||||
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
|
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
|
||||||
</span>
|
</span>
|
||||||
@@ -31,6 +33,7 @@ const NpmPackage = () => {
|
|||||||
width="16"
|
width="16"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
|
<title>arrow</title>
|
||||||
<path
|
<path
|
||||||
d="M10.75 8.75L14.25 12L10.75 15.25"
|
d="M10.75 8.75L14.25 12L10.75 15.25"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
|
|
||||||
const SafetyMessage = () => {
|
const SafetyMessage = () => {
|
||||||
return (
|
return <div className="relative" />;
|
||||||
<div className="relative">
|
};
|
||||||
|
|
||||||
</div>
|
export default SafetyMessage;
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SafetyMessage
|
|
||||||
|
|||||||
@@ -1,53 +1,62 @@
|
|||||||
import React from "react";
|
import ShinyText from "components/ShinyText/ShinyText";
|
||||||
import { Poppins } from "next/font/google";
|
import { Poppins } from "next/font/google";
|
||||||
|
import React from "react";
|
||||||
import BackgroundGradients from "./_components/BackgroundGradients";
|
import BackgroundGradients from "./_components/BackgroundGradients";
|
||||||
import Spotlight from "./_components/Spotlight";
|
import CodeContainer from "./_components/CodeContainer";
|
||||||
import NpmPackage from "./_components/NpmPackage";
|
import NpmPackage from "./_components/NpmPackage";
|
||||||
import SideCircles from "./_components/SideCircles";
|
import SideCircles from "./_components/SideCircles";
|
||||||
import CodeContainer from "./_components/CodeContainer";
|
import Spotlight from "./_components/Spotlight";
|
||||||
import ShinyText from "components/ShinyText/ShinyText";
|
|
||||||
|
|
||||||
const poppins = Poppins({
|
const poppins = Poppins({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
weight: ["400", "500", "600", "700"],
|
weight: ["400", "500", "600", "700"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
return (
|
||||||
<main className="min-h-screen flex flex-col items-center justify-start p-8" style={poppins.style}>
|
<main
|
||||||
<BackgroundGradients />
|
className="min-h-screen flex flex-col items-center justify-start p-8"
|
||||||
<Spotlight />
|
style={poppins.style}
|
||||||
<SideCircles />
|
>
|
||||||
<div className="max-w-6xl mx-auto text-center mb-16 relative z-50">
|
<BackgroundGradients />
|
||||||
<div className="relative z-10">
|
<Spotlight />
|
||||||
<div className="flex flex-col items-center justify-center space-y-4 text-center">
|
<SideCircles />
|
||||||
<NpmPackage />
|
<div className="max-w-6xl mx-auto text-center mb-16 relative z-50">
|
||||||
<h1 className="text-6xl font-extrabold text-white">
|
<div className="relative z-10">
|
||||||
<span className="block text-7xl bg-clip-text text-transparent bg-gradient-to-r from-purple-500 via-pink-400 to-yellow-200">Better-T Stack</span>
|
<div className="flex flex-col items-center justify-center space-y-4 text-center">
|
||||||
<span className="relative">
|
<NpmPackage />
|
||||||
<span className="absolute -bottom-1 left-0 right-0 h-1 bg-gradient-to-r from-purple-400 via-pink-500 to-rose-500 transform origin-left transition-transform duration-300 ease-out scale-x-0 group-hover:scale-x-100" />
|
<h1 className="text-6xl font-extrabold text-white">
|
||||||
</span>
|
<span className="block text-7xl bg-clip-text text-transparent bg-gradient-to-r from-purple-500 via-pink-400 to-yellow-200">
|
||||||
</h1>
|
Better-T Stack
|
||||||
|
</span>
|
||||||
|
<span className="relative">
|
||||||
|
<span className="absolute -bottom-1 left-0 right-0 h-1 bg-gradient-to-r from-purple-400 via-pink-500 to-rose-500 transform origin-left transition-transform duration-300 ease-out scale-x-0 group-hover:scale-x-100" />
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
<p className="text-2xl font-medium text-gray-300 max-w-2xl">
|
<p className="text-2xl font-medium text-gray-300 max-w-2xl">
|
||||||
<span className="inline-block transform hover:scale-105 transition-transform duration-200">
|
<span className="inline-block transform hover:scale-105 transition-transform duration-200">
|
||||||
Scaffold
|
Scaffold
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-emerald-400">
|
<span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-emerald-400">
|
||||||
production-ready
|
production-ready
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span className="inline-block transition-transform duration-200">
|
<span className="inline-block transition-transform duration-200">
|
||||||
Better-T projects in seconds
|
Better-T projects in seconds
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<CodeContainer />
|
<CodeContainer />
|
||||||
<ShinyText text="Be the safest developer with typesafe Typescript" speed={3} className="text-lg" />
|
<ShinyText
|
||||||
</div>
|
text="Be the safest developer with typesafe Typescript"
|
||||||
</div>
|
speed={3}
|
||||||
<div className="absolute inset-0 -z-10">
|
className="text-lg"
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-purple-500/20 to-pink-500/20 blur-3xl transform -skew-y-12" />
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
<div className="absolute inset-0 -z-10">
|
||||||
);
|
<div className="absolute inset-0 bg-gradient-to-r from-purple-500/20 to-pink-500/20 blur-3xl transform -skew-y-12" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,32 +5,34 @@
|
|||||||
@source '../../../../node_modules/fumadocs-ui/dist/**/*.js';
|
@source '../../../../node_modules/fumadocs-ui/dist/**/*.js';
|
||||||
|
|
||||||
.bg-noise {
|
.bg-noise {
|
||||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%' height='100%' filter='url(%23noise)' opacity='0.4'/%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%' height='100%' filter='url(%23noise)' opacity='0.4'/%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
|
|
||||||
.shiny-text {
|
.shiny-text {
|
||||||
color: #b5b5b5a4;
|
color: #b5b5b5a4;
|
||||||
background: linear-gradient(120deg,
|
background: linear-gradient(
|
||||||
rgba(255, 255, 255, 0) 40%,
|
120deg,
|
||||||
rgba(255, 255, 255, 0.8) 50%,
|
rgba(255, 255, 255, 0) 40%,
|
||||||
rgba(255, 255, 255, 0) 60%);
|
rgba(255, 255, 255, 0.8) 50%,
|
||||||
background-size: 200% 100%;
|
rgba(255, 255, 255, 0) 60%
|
||||||
-webkit-background-clip: text;
|
);
|
||||||
background-clip: text;
|
background-size: 200% 100%;
|
||||||
display: inline-block;
|
-webkit-background-clip: text;
|
||||||
animation: shine 5s linear infinite;
|
background-clip: text;
|
||||||
|
display: inline-block;
|
||||||
|
animation: shine 5s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shine {
|
@keyframes shine {
|
||||||
0% {
|
0% {
|
||||||
background-position: 100%;
|
background-position: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
background-position: -100%;
|
background-position: -100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shiny-text.disabled {
|
.shiny-text.disabled {
|
||||||
animation: none;
|
animation: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,32 @@
|
|||||||
import "./global.css";
|
import "./global.css";
|
||||||
import { RootProvider } from "fumadocs-ui/provider";
|
import { RootProvider } from "fumadocs-ui/provider";
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import { Suspense, type ReactNode } from "react";
|
import { type ReactNode, Suspense } from "react";
|
||||||
import Navbar from "./(home)/_components/Navbar";
|
import Navbar from "./(home)/_components/Navbar";
|
||||||
|
|
||||||
const inter = Inter({
|
const inter = Inter({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function Layout({ children }: { children: ReactNode }) {
|
export default function Layout({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={inter.className} suppressHydrationWarning>
|
<html lang="en" className={inter.className} suppressHydrationWarning>
|
||||||
<body className="flex flex-col min-h-screen relative bg-black">
|
<body className="flex flex-col min-h-screen relative bg-black">
|
||||||
<RootProvider>
|
<RootProvider>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div className="relative z-10 bg-zinc-50 dark:bg-zinc-950 pt-20 transition-colors duration-300 overflow-hidden">
|
<div className="relative z-10 bg-zinc-50 dark:bg-zinc-950 pt-20 transition-colors duration-300 overflow-hidden">
|
||||||
<Suspense fallback={<LoadingSpinner />}>
|
<Suspense fallback={<LoadingSpinner />}>{children}</Suspense>
|
||||||
{children}
|
</div>
|
||||||
</Suspense>
|
</RootProvider>
|
||||||
</div>
|
</body>
|
||||||
</RootProvider>
|
</html>
|
||||||
</body>
|
);
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function LoadingSpinner() {
|
function LoadingSpinner() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center min-h-[200px]">
|
<div className="flex items-center justify-center min-h-[200px]">
|
||||||
<div className="w-8 h-8 border-4 border-zinc-300 border-t-zinc-800 rounded-full animate-spin" />
|
<div className="w-8 h-8 border-4 border-zinc-300 border-t-zinc-800 rounded-full animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user