add ascii background sections on home page
This commit is contained in:
parent
a0dab9089d
commit
e5010d05b6
@ -15,6 +15,7 @@ import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { montserrat, spaceGrotesk } from "@/app/fonts";
|
||||
import { PrivyInterface, usePrivy } from "@privy-io/react-auth";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { LetterGlitch } from "@/components/letter-glitch";
|
||||
|
||||
function HeroPill() {
|
||||
return (
|
||||
@ -74,8 +75,8 @@ function HeroTitles() {
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
className={cn(
|
||||
"mx-auto max-w-3xl text-center text-sm leading-7 text-muted-foreground sm:text-lg sm:leading-9 text-balance"
|
||||
// montserrat.className
|
||||
"mx-auto max-w-4xl text-center text-sm leading-7 text-muted-foreground sm:text-lg sm:leading-9 text-balance",
|
||||
"text-[#222222] font-semibold"
|
||||
)}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
@ -207,11 +208,23 @@ export function Hero() {
|
||||
const privyAuth = usePrivy();
|
||||
|
||||
return (
|
||||
<section id="hero" className="">
|
||||
<div className="pt-8 px-3 sm:px-6 layout flex flex-col justify-center items-center border-x">
|
||||
<HeroPill />
|
||||
<HeroTitles />
|
||||
<HeroCTA privyAuth={privyAuth} />
|
||||
<section id="hero">
|
||||
<div className="relative">
|
||||
<div className="relative z-20">
|
||||
<div className="pt-8 px-3 sm:px-6 layout flex flex-col justify-center items-center border-x">
|
||||
<HeroPill />
|
||||
<HeroTitles />
|
||||
<HeroCTA privyAuth={privyAuth} />
|
||||
</div>
|
||||
</div>
|
||||
<LetterGlitch
|
||||
glitchSpeed={50}
|
||||
centerVignette={false}
|
||||
outerVignette={false}
|
||||
smooth={true}
|
||||
glitchColors={["#222222", "#BEBDBD"]}
|
||||
className="absolute top-0 left-0 right-0 bottom-0 bg-transparent opacity-20"
|
||||
/>
|
||||
</div>
|
||||
<HeroMarquee />
|
||||
</section>
|
||||
|
@ -9,25 +9,20 @@ import { spaceGrotesk } from "@/app/fonts";
|
||||
import Link from "next/link";
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import Image from "next/image";
|
||||
import { LetterGlitch } from "@/components/letter-glitch";
|
||||
import { SevenSegmentDigit } from "@/components/seven-segment-digit";
|
||||
|
||||
const ROADMAPS = [
|
||||
"Lorem ipsum dolor sit amet consectetur. Et dictum at egestas nisl. Aenean ut a augue viverra adipiscing mi nisl ullamcorper mauris. Ipsum varius ullamcorper mi suscipit. Justo eget faucibus aliquet dui pellentesque sit vitae pellentesque.",
|
||||
"Lorem ipsum dolor sit amet consectetur. Et dictum at egestas nisl. Aenean ut a augue viverra adipiscing mi nisl ullamcorper mauris. Ipsum varius ullamcorper mi suscipit. Justo eget faucibus aliquet dui pellentesque sit vitae pellentesque.",
|
||||
"Lorem ipsum dolor sit amet consectetur. Et dictum at egestas nisl. Aenean ut a augue viverra adipiscing mi nisl ullamcorper mauris. Ipsum varius ullamcorper mi suscipit. Justo eget faucibus aliquet dui pellentesque sit vitae pellentesque.",
|
||||
"Lorem ipsum dolor sit amet consectetur. Et dictum at egestas nisl. Aenean ut a augue viverra adipiscing mi nisl ullamcorper mauris. Ipsum varius ullamcorper mi suscipit. Justo eget faucibus aliquet dui pellentesque sit vitae pellentesque.",
|
||||
"Optimize inference pipelines to reduce latency and enhance memory efficiency. Introduce dynamic model selection for improved performance. Develop stateful agents capable of maintaining context across interactions.",
|
||||
"Enable multi-agent collaboration for task delegation and workflow automation. Integrate knowledge graphs to enhance reasoning and decision-making. Develop an interactive agent dashboard for better visualization and control.",
|
||||
"Strengthen data security with access controls and compliance measures. Expand deployment flexibility with on-premises and cloud options. Enhance API capabilities for seamless third-party integration.",
|
||||
"Launch a plugin marketplace for custom agent extensions. Develop low-code/no-code tools for easy deployment. Explore AI-driven automation in robotics and IoT applications.",
|
||||
];
|
||||
|
||||
export function Roadmap() {
|
||||
return (
|
||||
<section className="">
|
||||
<div
|
||||
className="layout"
|
||||
style={{
|
||||
backgroundImage: "url(/background-4.png)",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.75)",
|
||||
backgroundBlendMode: "lighten",
|
||||
}}
|
||||
>
|
||||
<div className="layout relative">
|
||||
<div className="border-x border-b">
|
||||
<BlurFade className="p-6" inView>
|
||||
<Badge className="hover:bg-primary rounded-md font-light mb-6">
|
||||
@ -82,15 +77,23 @@ export function Roadmap() {
|
||||
>
|
||||
<li>
|
||||
<div className="flex items-center gap-3">
|
||||
<p className="text-5xl">{idx + 1}</p>
|
||||
<p className="text-lg">Q{idx + 1} 2025</p>
|
||||
<SevenSegmentDigit digit={`${idx + 1}`} />
|
||||
<p className="text-lg font-semibold">Q{idx + 1} 2025</p>
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold">Phase 0{idx + 1}</h2>
|
||||
<p className="text-muted-foreground">{roadmap}</p>
|
||||
<p className="text-[#222222]">{roadmap}</p>
|
||||
</li>
|
||||
</BlurFade>
|
||||
))}
|
||||
</ul>
|
||||
<LetterGlitch
|
||||
glitchSpeed={50}
|
||||
centerVignette={false}
|
||||
outerVignette={false}
|
||||
smooth={true}
|
||||
glitchColors={["#222222", "#BEBDBD"]}
|
||||
className="absolute top-0 left-0 right-0 bottom-0 bg-transparent opacity-10"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
@ -9,7 +9,7 @@ import { Footer } from "@/components/footer";
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div className="bg-[url(/background-1.png)]">
|
||||
<div >
|
||||
<Hero />
|
||||
<Features />
|
||||
<hr className="" />
|
||||
|
301
src/components/letter-glitch.tsx
Normal file
301
src/components/letter-glitch.tsx
Normal file
@ -0,0 +1,301 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useRef, useEffect } from "react";
|
||||
|
||||
export function LetterGlitch({
|
||||
glitchColors = ["#2b4539", "#61dca3", "#61b3dc"],
|
||||
glitchSpeed = 50,
|
||||
centerVignette = false,
|
||||
outerVignette = true,
|
||||
smooth = true,
|
||||
className,
|
||||
}: {
|
||||
glitchColors?: string[];
|
||||
glitchSpeed: number;
|
||||
centerVignette: boolean;
|
||||
outerVignette: boolean;
|
||||
smooth: boolean;
|
||||
className: string;
|
||||
}) {
|
||||
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||
const animationRef = useRef<number | null>(null);
|
||||
const letters = useRef<
|
||||
{
|
||||
char: string;
|
||||
color: string;
|
||||
targetColor: string;
|
||||
colorProgress: number;
|
||||
}[]
|
||||
>([]);
|
||||
const grid = useRef({ columns: 0, rows: 0 });
|
||||
const context = useRef<CanvasRenderingContext2D | null>(null);
|
||||
const lastGlitchTime = useRef(Date.now());
|
||||
|
||||
const fontSize = 16;
|
||||
const charWidth = 10;
|
||||
const charHeight = 20;
|
||||
|
||||
const lettersAndSymbols = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"!",
|
||||
"@",
|
||||
"#",
|
||||
"$",
|
||||
"&",
|
||||
"*",
|
||||
"(",
|
||||
")",
|
||||
"-",
|
||||
"_",
|
||||
"+",
|
||||
"=",
|
||||
"/",
|
||||
"[",
|
||||
"]",
|
||||
"{",
|
||||
"}",
|
||||
";",
|
||||
":",
|
||||
"<",
|
||||
">",
|
||||
",",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
];
|
||||
|
||||
const getRandomChar = () => {
|
||||
return lettersAndSymbols[
|
||||
Math.floor(Math.random() * lettersAndSymbols.length)
|
||||
];
|
||||
};
|
||||
|
||||
const getRandomColor = () => {
|
||||
return glitchColors[Math.floor(Math.random() * glitchColors.length)];
|
||||
};
|
||||
|
||||
const hexToRgb = (hex: string) => {
|
||||
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||
hex = hex.replace(shorthandRegex, (m, r, g, b) => {
|
||||
return r + r + g + g + b + b;
|
||||
});
|
||||
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result
|
||||
? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16),
|
||||
}
|
||||
: null;
|
||||
};
|
||||
|
||||
const interpolateColor = (
|
||||
start: { r: number; g: number; b: number },
|
||||
end: { r: number; g: number; b: number },
|
||||
factor: number
|
||||
) => {
|
||||
const result = {
|
||||
r: Math.round(start.r + (end.r - start.r) * factor),
|
||||
g: Math.round(start.g + (end.g - start.g) * factor),
|
||||
b: Math.round(start.b + (end.b - start.b) * factor),
|
||||
};
|
||||
return `rgb(${result.r}, ${result.g}, ${result.b})`;
|
||||
};
|
||||
|
||||
const calculateGrid = (width: number, height: number) => {
|
||||
const columns = Math.ceil(width / charWidth);
|
||||
const rows = Math.ceil(height / charHeight);
|
||||
return { columns, rows };
|
||||
};
|
||||
|
||||
const initializeLetters = (columns: number, rows: number) => {
|
||||
grid.current = { columns, rows };
|
||||
const totalLetters = columns * rows;
|
||||
letters.current = Array.from({ length: totalLetters }, () => ({
|
||||
char: getRandomChar(),
|
||||
color: getRandomColor(),
|
||||
targetColor: getRandomColor(),
|
||||
colorProgress: 1,
|
||||
}));
|
||||
};
|
||||
|
||||
const resizeCanvas = () => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const parent = canvas.parentElement;
|
||||
if (!parent) return;
|
||||
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
const rect = parent.getBoundingClientRect();
|
||||
|
||||
canvas.width = rect.width * dpr;
|
||||
canvas.height = rect.height * dpr;
|
||||
|
||||
canvas.style.width = `${rect.width}px`;
|
||||
canvas.style.height = `${rect.height}px`;
|
||||
|
||||
if (context.current) {
|
||||
context.current.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
}
|
||||
|
||||
const { columns, rows } = calculateGrid(rect.width, rect.height);
|
||||
initializeLetters(columns, rows);
|
||||
drawLetters();
|
||||
};
|
||||
|
||||
const drawLetters = () => {
|
||||
if (!context.current || letters.current.length === 0) return;
|
||||
const ctx = context.current;
|
||||
const { width, height } = canvasRef.current!.getBoundingClientRect();
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.font = `${fontSize}px monospace`;
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
letters.current.forEach((letter, index) => {
|
||||
const x = (index % grid.current.columns) * charWidth;
|
||||
const y = Math.floor(index / grid.current.columns) * charHeight;
|
||||
ctx.fillStyle = letter.color;
|
||||
ctx.fillText(letter.char, x, y);
|
||||
});
|
||||
};
|
||||
|
||||
const updateLetters = () => {
|
||||
if (!letters.current || letters.current.length === 0) return; // Prevent accessing empty array
|
||||
|
||||
const updateCount = Math.max(1, Math.floor(letters.current.length * 0.05));
|
||||
|
||||
for (let i = 0; i < updateCount; i++) {
|
||||
const index = Math.floor(Math.random() * letters.current.length);
|
||||
if (!letters.current[index]) continue; // Skip if index is invalid
|
||||
|
||||
letters.current[index].char = getRandomChar();
|
||||
letters.current[index].targetColor = getRandomColor();
|
||||
|
||||
if (!smooth) {
|
||||
letters.current[index].color = letters.current[index].targetColor;
|
||||
letters.current[index].colorProgress = 1;
|
||||
} else {
|
||||
letters.current[index].colorProgress = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleSmoothTransitions = () => {
|
||||
let needsRedraw = false;
|
||||
letters.current.forEach((letter) => {
|
||||
if (letter.colorProgress < 1) {
|
||||
letter.colorProgress += 0.05;
|
||||
if (letter.colorProgress > 1) letter.colorProgress = 1;
|
||||
|
||||
const startRgb = hexToRgb(letter.color);
|
||||
const endRgb = hexToRgb(letter.targetColor);
|
||||
if (startRgb && endRgb) {
|
||||
letter.color = interpolateColor(
|
||||
startRgb,
|
||||
endRgb,
|
||||
letter.colorProgress
|
||||
);
|
||||
needsRedraw = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (needsRedraw) {
|
||||
drawLetters();
|
||||
}
|
||||
};
|
||||
|
||||
const animate = () => {
|
||||
const now = Date.now();
|
||||
if (now - lastGlitchTime.current >= glitchSpeed) {
|
||||
updateLetters();
|
||||
drawLetters();
|
||||
lastGlitchTime.current = now;
|
||||
}
|
||||
|
||||
if (smooth) {
|
||||
handleSmoothTransitions();
|
||||
}
|
||||
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
context.current = canvas.getContext("2d");
|
||||
resizeCanvas();
|
||||
animate();
|
||||
|
||||
let resizeTimeout: NodeJS.Timeout;
|
||||
|
||||
const handleResize = () => {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(() => {
|
||||
cancelAnimationFrame(animationRef.current as number);
|
||||
resizeCanvas();
|
||||
animate();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(animationRef.current!);
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [glitchSpeed, smooth]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full h-full bg-black overflow-hidden",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<canvas ref={canvasRef} className="block w-full h-full" />
|
||||
{outerVignette && (
|
||||
<div className="absolute top-0 left-0 w-full h-full pointer-events-none bg-[radial-gradient(circle,_rgba(0,0,0,0)_60%,_rgba(0,0,0,1)_100%)]"></div>
|
||||
)}
|
||||
{centerVignette && (
|
||||
<div className="absolute top-0 left-0 w-full h-full pointer-events-none bg-[radial-gradient(circle,_rgba(0,0,0,0.8)_0%,_rgba(0,0,0,0)_60%)]"></div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
51
src/components/seven-segment-digit.tsx
Normal file
51
src/components/seven-segment-digit.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
export function SevenSegmentDigit({ digit }: { digit: string }) {
|
||||
const segmentMap: Record<string, string[]> = {
|
||||
"0": [
|
||||
"top",
|
||||
"top-left",
|
||||
"top-right",
|
||||
"bottom-left",
|
||||
"bottom-right",
|
||||
"bottom",
|
||||
],
|
||||
"1": ["top-right", "bottom-right"],
|
||||
"2": ["top", "top-right", "middle", "bottom-left", "bottom"],
|
||||
"3": ["top", "top-right", "middle", "bottom-right", "bottom"],
|
||||
"4": ["top-left", "top-right", "middle", "bottom-right"],
|
||||
"5": ["top", "top-left", "middle", "bottom-right", "bottom"],
|
||||
"6": ["top", "top-left", "middle", "bottom-left", "bottom-right", "bottom"],
|
||||
"7": ["top", "top-right", "bottom-right"],
|
||||
"8": [
|
||||
"top",
|
||||
"top-left",
|
||||
"top-right",
|
||||
"middle",
|
||||
"bottom-left",
|
||||
"bottom-right",
|
||||
"bottom",
|
||||
],
|
||||
"9": ["top", "top-left", "top-right", "middle", "bottom-right", "bottom"],
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative w-12 h-20 flex flex-col items-center justify-center">
|
||||
{/* Define segments */}
|
||||
{[
|
||||
{ name: "top", className: "w-8 h-1 -top-0 left-2" },
|
||||
{ name: "top-left", className: "w-1 h-8 top-1 left-1" },
|
||||
{ name: "top-right", className: "w-1 h-8 top-1 right-1" },
|
||||
{ name: "middle", className: "w-8 h-1 top-9 left-2" },
|
||||
{ name: "bottom-left", className: "w-1 h-8 bottom-2 left-1" },
|
||||
{ name: "bottom-right", className: "w-1 h-8 bottom-2 right-1" },
|
||||
{ name: "bottom", className: "w-8 h-1 bottom-1 left-2" },
|
||||
].map((seg) => (
|
||||
<div
|
||||
key={seg.name}
|
||||
className={`absolute rounded-full ${seg.className} ${
|
||||
segmentMap[digit]?.includes(seg.name) ? "bg-black" : "bg-gray-400"
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user