Skip to content

Commit

Permalink
builderkit landing page and docs (#2058)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xstt authored Feb 7, 2025
1 parent d05ea7d commit 7a82df3
Show file tree
Hide file tree
Showing 64 changed files with 5,943 additions and 1,717 deletions.
69 changes: 69 additions & 0 deletions app/(home)/builderkit/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use client'

import { useTheme } from 'next-themes';
import { AnimatedBackground } from '@/components/builderkit/animated-background';
import { AnimatedWords } from '@/components/builderkit/animated-words';
import { InstallCommand } from '@/components/builderkit/install-command';
import Link from 'next/link';
import { ComponentShowcase } from '@/components/builderkit/sections/component-showcase';
import { PainPoints } from '@/components/builderkit/sections/pain-points';
import { useState, useEffect } from 'react';

export default function Page() {
const { resolvedTheme } = useTheme();
const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
setIsMounted(true);
}, []);

const logo = isMounted ? (resolvedTheme === "dark" ? "/logo-white.png" : "/logo-black.png") : null;

return (
<div className="min-h-screen bg-background text-foreground overflow-hidden">
<AnimatedBackground />
<section className="min-h-screen flex items-center justify-center px-4">
<div className="text-center max-w-4xl">
<h1 className="text-7xl font-bold mb-8">
<div className="flex items-center justify-center gap-3 mb-2">
Build <AnimatedWords words={['Better', 'Faster', 'Simpler', 'Modern', 'Secure']} />
</div>
<div>User Interfaces</div>
</h1>
<p className="text-lg text-foreground mb-12 max-w-3xl mx-auto">
A comprehensive suite of React components designed for modern web applications.
Build beautiful, accessible, and performant user interfaces with our type-safe and customizable components.
</p>
<InstallCommand className="mb-8" />
<div className="flex gap-4 justify-center mb-16">
<Link
href="/docs/builderkit"
className="bg-black hover:bg-black/75 dark:bg-white dark:hover:bg-white/75 text-white dark:text-black px-4 py-2 rounded-lg text-sm font-semibold transition-colors dark:bg-opacity-90"
>
Get Started
</Link>
<a
href="https://github.com/ava-labs/builderkit"
className="bg-white dark:bg-black border border-[0.5] border-black/25 dark:border-white/25 dark:hover:border-white/50 hover:border-black/50 dark:text-white px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</a>
</div>
<div className="flex justify-center">
{logo && (
<img
src={logo}
alt="Avalanche Logo"
className="h-10 opacity-80 hover:opacity-100 transition-opacity"
/>
)}
</div>
</div>
</section>
<ComponentShowcase />
<PainPoints />
</div>
)
}
11 changes: 11 additions & 0 deletions app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,15 @@ nav a:not(:first-child) {

.tools-page svg.lucide {
color: #EB4C50 !important;
}

/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}

/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
8 changes: 7 additions & 1 deletion app/layout.config.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type LinkItemType } from 'fumadocs-ui/layouts/docs';
import { type BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
import { AvalancheLogo } from '@/components/navigation/avalanche-logo';
import { Workflow, Sprout, Logs, MonitorCheck, ArrowUpRight, SendHorizontal, Cable, Bot, Cpu, Cog, Snowflake, BriefcaseBusiness,MessageSquareQuote, Server, Github, Waypoints, HandCoins, Ticket, Handshake, HardDrive } from 'lucide-react';
import { Workflow, Sprout, Logs, MonitorCheck, ArrowUpRight, SendHorizontal, Cable, Bot, Cpu, Cog, Snowflake, BriefcaseBusiness,MessageSquareQuote, Server, Github, Waypoints, HandCoins, Ticket, Handshake, HardDrive, LayoutTemplate } from 'lucide-react';
import Image from 'next/image';
import Preview9000 from '@/public/nav-banner/9000-logo.png';
import CoursePreview from '@/public/nav-banner/course-preview.png';
Expand All @@ -20,6 +20,12 @@ export const linkItems: LinkItemType[] = [
text: 'Hackathon',
url: '/hackathon',
active: 'nested-url',
},
{
icon: <LayoutTemplate />,
text: 'Builder Kit',
url: '/builderkit',
active: 'nested-url',
}
];

Expand Down
36 changes: 36 additions & 0 deletions components/builderkit/animated-background.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useEffect, useState } from 'react';
import { useTheme } from 'next-themes';

export const AnimatedBackground = () => {
const { resolvedTheme } = useTheme();
const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
setIsMounted(true);
}, []);

const gridColor = isMounted ? (resolvedTheme === "dark" ? "rgba(255,255,255,.05)" : "rgba(0,0,0,.05)") : "transparent";

return (
<div className="fixed inset-0 -z-10">
<div className="absolute inset-0">
{/* Geometric shapes */}
<div className="absolute w-[500px] h-[500px] bg-[#1f66f4]/5 rounded-full blur-3xl animate-blob1 top-0 left-0" />
<div className="absolute w-[400px] h-[400px] bg-[#1f66f4]/10 rounded-full blur-3xl animate-blob2 bottom-0 right-0" />
<div className="absolute w-[300px] h-[300px] bg-[#1f66f4]/5 rounded-full blur-3xl animate-blob3 top-1/2 left-1/2" />

{/* Grid overlay */}
<div
className="absolute inset-0 backdrop-blur-[100px]"
style={{
backgroundImage: `
linear-gradient(to right, ${gridColor} 1px, transparent 1px),
linear-gradient(to bottom, ${gridColor} 1px, transparent 1px)
`,
backgroundSize: '40px 40px'
}}
/>
</div>
</div>
);
};
30 changes: 30 additions & 0 deletions components/builderkit/animated-words.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';

export const AnimatedWords = ({ words }: { words: string[] }) => {
const [index, setIndex] = React.useState(0);

React.useEffect(() => {
const interval = setInterval(() => {
setIndex((prev) => (prev + 1) % words.length);
}, 3000);
return () => clearInterval(interval);
}, []);

return (
<span className="inline-flex h-[1.1em] w-fit items-center justify-center overflow-hidden">
<AnimatePresence mode="wait">
<motion.span
key={words[index]}
initial={{ y: 50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -50, opacity: 0 }}
transition={{ duration: 0.75, ease: "easeOut" }}
className="text-[#1f66f4]"
>
{words[index]}
</motion.span>
</AnimatePresence>
</span>
);
};
37 changes: 37 additions & 0 deletions components/builderkit/code-snippet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { cn } from '@/utils/cn';
import Prism from 'prismjs';
import 'prismjs/components/prism-typescript';
import 'prismjs/themes/prism-tomorrow.css';
import 'prismjs/components/prism-bash';

interface CodeSnippetProps {
code: string;
language?: string;
className?: string;
}

export const CodeSnippet: React.FC<CodeSnippetProps> = ({
code,
language = 'typescript',
className
}) => {
const [isMounted, setIsMounted] = React.useState(false);

React.useEffect(() => {
setIsMounted(true);
}, []);

const highlightedCode = React.useMemo(() => {
return isMounted ? Prism.highlight(code, Prism.languages[language], language) : '';
}, [code, language, isMounted]);

return (
<pre className={cn("text-sm", className)}>
<code
className={isMounted ? `language-${language}` : ''}
dangerouslySetInnerHTML={{ __html: highlightedCode }}
/>
</pre>
);
};
36 changes: 36 additions & 0 deletions components/builderkit/install-command.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client';

import React, { useState } from 'react';
import { cn } from '@/utils/cn';
import { CheckIcon, CopyIcon } from 'lucide-react';
import { CodeSnippet } from './code-snippet';

interface InstallCommandProps {
className?: string;
}

export const InstallCommand: React.FC<InstallCommandProps> = ({ className }) => {
const [copied, setCopied] = useState(false);

const handleCopy = () => {
navigator.clipboard.writeText('npm install @avalabs/builderkit');
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};

return (
<div className={cn("max-w-fit mx-auto", className)}>
<div className="bg-black dark:bg-foreground/[0.1] backdrop-blur-sm border border-foreground/[0.05] rounded-lg overflow-hidden px-4">
<div className="flex items-center justify-center gap-4 p-4 text-sm overflow-x-auto scrollbar-thin">
<CodeSnippet
code="npm install @avalabs/builderkit"
language='bash'
/>
<button onClick={handleCopy} className="p-2 flex items-center">
{copied ? <CheckIcon className="w-4 h-4 !text-green-500" /> : <CopyIcon className="w-4 h-4" />}
</button>
</div>
</div>
</div>
);
};
21 changes: 21 additions & 0 deletions components/builderkit/scroll-animation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { motion } from 'framer-motion';
import { ReactNode } from 'react';

interface ScrollAnimationProps {
children: ReactNode;
className?: string;
}

export const ScrollAnimation = ({ children, className }: ScrollAnimationProps) => {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.5, ease: "easeOut" }}
className={className}
>
{children}
</motion.div>
);
};
Loading

0 comments on commit 7a82df3

Please sign in to comment.