Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/crl-icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet" />
<title>Github Tracker</title>
</head>
<body>
Expand Down
156 changes: 141 additions & 15 deletions src/components/Features.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,91 @@
import { BarChart3, Users, Search, Zap, Shield, Globe } from 'lucide-react';
import type { ReactNode } from 'react';

type TerminalHeadingProps = {
title: string;
as?: 'h2' | 'h3' | 'h4';
className?: string;
promptClassName?: string;
titleClassName?: string;
animated?: boolean;
};

type TerminalCardProps = {
label: string;
children: ReactNode;
className?: string;
contentClassName?: string;
accent?: 'blue' | 'green';
};

const headingSizes: Record<NonNullable<TerminalHeadingProps['as']>, string> = {
h2: 'text-3xl md:text-4xl',
h3: 'text-xl md:text-2xl',
h4: 'text-lg md:text-xl',
};

const TerminalHeading = ({
title,
as: HeadingTag = 'h2',
className = '',
promptClassName = '',
titleClassName = '',
animated = false,
}: TerminalHeadingProps) => {
const chars = title.length + 2;

return (
<HeadingTag
className={`inline-flex items-center gap-2 text-balance text-[#c9d1d9] ${headingSizes[HeadingTag]} ${className}`}
style={animated ? ({ '--terminal-chars': chars } as React.CSSProperties) : undefined}
>
<span
className={`font-["VT323"] text-[#58a6ff] ${animated ? 'terminal-typewriter inline-block' : ''} ${promptClassName}`}
>
&gt;
</span>
<span
className={`font-["VT323"] tracking-[0.03em] ${animated ? 'terminal-typewriter inline-block' : ''} ${titleClassName}`}
>
{title}
</span>
</HeadingTag>
);
};

const TerminalCard = ({
label,
children,
className = '',
contentClassName = '',
accent = 'blue',
}: TerminalCardProps) => {
const accentClasses = accent === 'green' ? 'text-[#3fb950] border-[#3fb950]/30' : 'text-[#58a6ff] border-[#58a6ff]/30';

return (
<article
className={`group relative overflow-hidden rounded-2xl border border-[#30363d] bg-[#161b22] shadow-[0_12px_30px_rgba(1,4,9,0.22)] transition-all duration-300 ease-out hover:-translate-y-1 hover:border-[#58a6ff]/40 hover:shadow-[0_18px_38px_rgba(1,4,9,0.35)] ${className}`}
>
<div className="flex items-center justify-between gap-4 border-b border-[#30363d] bg-[#0d1117]/90 px-4 py-3">
<div className="flex items-center gap-1.5" aria-hidden="true">
<span className="h-2.5 w-2.5 rounded-full bg-[#f85149]/80" />
<span className="h-2.5 w-2.5 rounded-full bg-[#d29922]/80" />
<span className="h-2.5 w-2.5 rounded-full bg-[#3fb950]/80" />
</div>

<div className={`flex items-center gap-2 font-["VT323"] text-sm uppercase tracking-[0.22em] ${accentClasses}`}>
<span>{label}</span>
<span className="terminal-card-cursor opacity-0 transition-opacity duration-200 group-hover:opacity-100">_</span>
</div>
</div>

<div className={`relative px-5 py-5 sm:px-6 sm:py-6 ${contentClassName}`}>
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/5 to-transparent" />
{children}
</div>
</article>
);
};

const Features = () => {
const features = [
Expand Down Expand Up @@ -59,28 +146,67 @@ const Features = () => {
];

return (
<section id="features" className="px-6 py-6 bg-white dark:bg-gray-900 transition-colors duration-300">
<div className="mx-auto">
<div className="text-center mb-16">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">Powerful Features</h2>
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
Everything you need to track, analyze, and understand GitHub activity patterns
<section
id="features"
className="relative left-1/2 right-1/2 w-screen -mx-[50vw] overflow-hidden bg-[linear-gradient(to_bottom,#f8fafc_0%,#dbe7f5_20%,#0d1117_100%)] px-6 py-16 text-[#c9d1d9] transition-colors duration-300 sm:py-20"
style={{
boxShadow: '0 -40px 80px rgba(88,166,255,0.08), 0 40px 80px rgba(88,166,255,0.05)',
}}
>
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(88,166,255,0.08),_transparent_32%),radial-gradient(circle_at_bottom_right,_rgba(63,185,80,0.05),_transparent_28%)] pointer-events-none" />
<div className="absolute inset-x-0 top-0 h-28 bg-gradient-to-b from-[#f8fafc]/75 via-[#dbe7f5]/20 to-transparent pointer-events-none" />
<div className="absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-[#0d1117] via-[#0d1117]/70 to-transparent pointer-events-none" />
<div className="mx-auto max-w-7xl relative">
<div className="mx-auto mb-10 max-w-3xl text-center sm:mb-12">
<p className="font-['VT323'] text-sm uppercase tracking-[0.32em] text-[#58a6ff] sm:text-base">
&gt; initialize tracking capabilities
</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-black md:text-4xl">
Powerful Features
</h2>
<p className="mx-auto mt-4 max-w-2xl text-sm leading-relaxed text-[#8b949e] sm:text-base">
Everything you need to track, analyze, and understand GitHub activity patterns.
</p>
</div>

<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
{features.map((feature, index) => {
const IconComponent = feature.icon;
const promptLabel = `feature-${String(index + 1).padStart(2, '0')}`;
const titleTone = index % 2 === 0 ? 'blue' : 'green';
return (
<div key={index} className={`group h-72 w-full bg-gray-100 dark:bg-gray-800 ${feature.hoverColor} ${feature.borderColor} rounded-2xl shadow-md hover:shadow-2xl hover:shadow-blue-500/20 border dark:border-gray-800 transform hover:-translate-y-3 hover:scale-105 backdrop-blur-sm transition-all duration-300 ease-linear p-6`}>
<div className={`${feature.bgColor} w-12 h-12 rounded-lg flex items-center justify-center mb-6 transition-transform duration-300 group-hover:rotate-6 group-hover:scale-110`}>
<IconComponent className={`h-6 w-6 ${feature.iconColor}`} />
<TerminalCard key={index} label={promptLabel} accent={titleTone} className="h-full">
<div className="flex h-full flex-col gap-4">
<div className="flex items-start gap-4">
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl border border-[#30363d] bg-[#0d1117] text-[#58a6ff] transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:scale-105">
<IconComponent className="h-5 w-5" />
</div>
<div className="min-w-0 flex-1 space-y-2">
<TerminalHeading
title={feature.title}
as="h3"
className="items-start"
titleClassName="text-[#f0f6fc]"
/>
<div className="flex flex-wrap items-center gap-2 text-[11px] uppercase tracking-[0.24em] text-[#8b949e]">
<span className="rounded-full border border-[#30363d] bg-[#0d1117] px-2.5 py-1 font-['VT323'] text-[#58a6ff]">
cmd
</span>
<span className="font-['VT323']">gh tracker --feature</span>
</div>
</div>
</div>

<p className="text-sm leading-relaxed text-[#8b949e] sm:text-[0.95rem]">
{feature.description}
</p>

<div className="mt-auto flex items-center justify-between border-t border-[#30363d] pt-4 text-xs text-[#8b949e]">
<span className="font-['VT323'] uppercase tracking-[0.2em] text-[#3fb950]">ready</span>
<span className="font-['VT323'] text-[#58a6ff]">{feature.title.toLowerCase().replace(/\s+/g, '-')}</span>
</div>
</div>
<h3 className=" text-2xl font-bold text-gray-900 dark:text-gray-100 group-hover:text-black dark:group-hover:text-white transition-colors duration-300">{feature.title}</h3>
<p className="text-gray-600 dark:text-gray-300 text-base font-semibold leading-relaxed group-hover:text-gray-700 dark:group-hover:text-gray-200 transition-colors duration-300">
{feature.description}
</p>
</div>
</TerminalCard>
);
})}
</div>
Expand Down
111 changes: 48 additions & 63 deletions src/components/HowItWorks.tsx
Original file line number Diff line number Diff line change
@@ -1,107 +1,92 @@
import { useContext } from 'react';
import { ArrowDown, ArrowRight, BarChart3, Activity, Search } from 'lucide-react';
import { ThemeContext } from '../context/ThemeContext';
import type { ThemeContextType } from '../context/ThemeContext';
import { BarChart3, Activity, Search } from 'lucide-react';

const HowItWorks = () => {
const themeContext = useContext(ThemeContext) as ThemeContextType | null;
const mode = themeContext?.mode ?? 'light';

const steps = [
{
number: 1,
title: 'Search Users',
label: 'Discover',
description: 'Enter GitHub usernames or search for users by name. Add them to your tracking dashboard.',
icon: Search,
},
{
number: 2,
title: 'Monitor Activity',
label: 'Observe',
description: 'Watch insights of commits, pull requests, issues, and other GitHub activities.',
icon: Activity,
},
{
number: 3,
title: 'Analyze Insights',
label: 'Review',
description: 'Review detailed analytics, export reports, and gain valuable insights into development patterns.',
icon: BarChart3,
}
];

const sectionBgClass = mode === 'dark'
? 'bg-[#1e2130] text-white'
: 'bg-gradient-to-b from-gray-50 via-white to-slate-100 text-gray-900';
const cardSurfaceClass = mode === 'dark' ? 'bg-white/[0.04]' : 'bg-white';
const cardBorderClass = mode === 'dark' ? 'border-white/10' : 'border-gray-200';
const titleTextClass = mode === 'dark' ? 'text-white' : 'text-gray-900';
const bodyTextClass = mode === 'dark' ? 'text-gray-300' : 'text-gray-600';
const connectorBubbleClass = mode === 'dark'
? 'rounded-full border border-blue-400/25 bg-[#1e2130] p-2 text-blue-300 shadow-[0_0_20px_rgba(59,130,246,0.28)]'
: 'rounded-full border border-blue-200 bg-white p-2 text-blue-600 shadow-[0_0_18px_rgba(59,130,246,0.14)]';
const connectorLineClass = mode === 'dark'
? 'how-it-works-flow-line'
: 'how-it-works-flow-line light';

return (
<section id="how-it-works" className={`relative overflow-hidden px-6 py-20 ${sectionBgClass}`}>
<div className="mx-auto max-w-7xl">
<div className="text-center mb-16">
<h2 className={`text-3xl md:text-4xl font-bold mb-4 ${titleTextClass}`}>How It Works</h2>
<p className={`text-lg md:text-xl max-w-2xl mx-auto ${bodyTextClass}`}>
Get started in minutes with our simple three-step process
</p>
</div>
<section id="how-it-works" className="how-it-works-section relative overflow-hidden px-6 py-20 text-slate-900 md:py-24">
<div className="how-it-works-ambient how-it-works-ambient-left" aria-hidden="true" />
<div className="how-it-works-ambient how-it-works-ambient-right" aria-hidden="true" />
<div className="how-it-works-grid-overlay" aria-hidden="true" />

<div className="relative">
<div className="pointer-events-none absolute left-0 right-0 top-28 hidden md:block">
<div className="relative mx-auto h-10 max-w-6xl">
<span className={`${connectorLineClass} absolute left-16 right-16 top-1/2 -translate-y-1/2`} />
<span className={`absolute left-1/3 top-1/2 -translate-x-1/2 -translate-y-1/2 ${connectorBubbleClass}`}>
<ArrowRight className="h-4 w-4" />
</span>
<span className={`absolute left-2/3 top-1/2 -translate-x-1/2 -translate-y-1/2 ${connectorBubbleClass}`}>
<ArrowRight className="h-4 w-4" />
</span>
</div>
<div className="relative mx-auto max-w-7xl">
<div className="mx-auto max-w-2xl text-center">
<div className="mb-4 inline-flex items-center rounded-full border border-blue-200/80 bg-white/70 px-4 py-2 text-xs font-semibold uppercase tracking-[0.24em] text-blue-600 shadow-[0_10px_30px_rgba(79,124,255,0.08)] backdrop-blur-sm">
Workflow pipeline
</div>
<h2 className="text-3xl font-semibold tracking-tight text-slate-900 md:text-5xl">
How It Works
</h2>
<p className="mx-auto mt-4 max-w-xl text-base leading-7 text-slate-600 md:text-lg">
A clean three-step flow with a horizontal rhythm, subtle hierarchy, and just enough motion to feel polished.
</p>
</div>

<div className="pointer-events-none absolute left-1/2 top-24 bottom-24 flex -translate-x-1/2 flex-col items-center justify-between md:hidden">
<span className={connectorBubbleClass}>
<ArrowDown className="h-4 w-4" />
</span>
<span className={connectorBubbleClass}>
<ArrowDown className="h-4 w-4" />
</span>
<span className={`${connectorLineClass} vertical absolute left-1/2 top-0 h-full -translate-x-1/2`} />
</div>
<div className="relative mt-14 md:mt-16">
<div className="how-it-works-timeline-line pointer-events-none absolute left-6 right-6 top-7 hidden md:block" aria-hidden="true" />

<div className="grid gap-8 md:grid-cols-3 md:gap-6 lg:gap-8">
<ol className="relative grid gap-10 md:grid-cols-3 md:gap-8 lg:gap-10">
{steps.map((step, index) => {
const IconComponent = step.icon;

return (
<article
key={index}
className={`group relative rounded-3xl border p-8 text-center backdrop-blur-sm transition-all duration-300 hover:-translate-y-1 hover:border-blue-400/30 hover:shadow-[0_24px_60px_rgba(46,89,255,0.18)] ${cardBorderClass} ${cardSurfaceClass} ${mode === 'dark' ? 'hover:bg-white/[0.06]' : 'hover:bg-white'}`}
<li
key={step.title}
className="group relative flex flex-col items-center text-center"
>
<div className="mx-auto mb-6 flex h-24 w-24 items-center justify-center rounded-full border border-blue-400/20 bg-blue-500/10 shadow-[0_0_38px_rgba(46,89,255,0.35)] ring-1 ring-blue-400/15 transition-transform duration-300 group-hover:scale-105">
<div className="flex h-16 w-16 items-center justify-center rounded-full border border-blue-300/25 bg-blue-500 text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.2),0_0_24px_rgba(46,89,255,0.38)]">
<span className="text-2xl font-bold leading-none">{step.number}</span>
</div>
<div className="workflow-step-marker relative z-10 flex h-14 w-14 items-center justify-center rounded-[1.25rem] border border-blue-200/80 bg-[linear-gradient(180deg,rgba(255,255,255,0.96),rgba(247,250,255,0.9))] text-blue-600 shadow-[0_14px_30px_rgba(79,124,255,0.14)] transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:shadow-[0_18px_34px_rgba(79,124,255,0.18)]">
<span className="text-[0.95rem] font-semibold tracking-[0.18em] text-blue-600">
{String(step.number).padStart(2, '0')}
</span>
</div>

<div className={`mx-auto mb-5 flex h-11 w-11 items-center justify-center rounded-full border shadow-[0_0_18px_rgba(46,89,255,0.2)] ${mode === 'dark' ? 'border-white/10 bg-white/5 text-blue-300' : 'border-blue-100 bg-blue-50 text-blue-600'}`}>
<IconComponent className="h-5 w-5" />
<div className="mt-5 inline-flex items-center gap-2 rounded-full border border-blue-100/80 bg-white/75 px-3 py-1.5 text-[0.68rem] font-semibold uppercase tracking-[0.2em] text-slate-500 shadow-[0_8px_20px_rgba(15,23,42,0.04)] backdrop-blur-sm">
<span className="workflow-step-icon inline-flex h-7 w-7 items-center justify-center rounded-full border border-blue-100 bg-[linear-gradient(180deg,rgba(255,255,255,0.95),rgba(240,245,255,0.88))] text-blue-600 shadow-[0_8px_16px_rgba(79,124,255,0.08)] transition-transform duration-300 group-hover:scale-105">
<IconComponent className="h-3.5 w-3.5" />
</span>
<span>{step.label}</span>
</div>

<h3 className={`text-xl font-semibold mb-3 ${titleTextClass}`}>{step.title}</h3>
<p className={`text-sm md:text-base leading-relaxed ${bodyTextClass}`}>
<h3 className="mt-4 text-[1.35rem] font-semibold tracking-tight text-slate-900 md:text-[1.5rem]">
{step.title}
</h3>

<p className="mx-auto mt-3 max-w-[18rem] text-sm leading-7 text-slate-600 md:text-[0.98rem]">
{step.description}
</p>
</article>

{index < steps.length - 1 && (
<span
aria-hidden="true"
className="how-it-works-step-link mt-8 hidden w-full md:block"
/>
)}
</li>
);
})}
</div>
</ol>
</div>
</div>
</section>
Expand Down
Loading
Loading