Initial commit: CHORUS Services marketing website
Complete Next.js website with Docker containerization: - Next.js 14 with TypeScript and Tailwind CSS - Responsive design with modern UI components - Hero section, features showcase, testimonials - FAQ section with comprehensive content - Contact forms and newsletter signup - Docker production build with Nginx - Health checks and monitoring support - SEO optimization and performance tuning Ready for integration as git submodule in main CHORUS project. Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
101
components/ui/ProgressIndicator.tsx
Normal file
101
components/ui/ProgressIndicator.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Progress } from 'antd';
|
||||
|
||||
interface ProgressIndicatorProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const sections = ['hero', 'whoosh', 'bzzz', 'slurp', 'cooee', 'integration'];
|
||||
|
||||
export default function ProgressIndicator({ className = '' }: ProgressIndicatorProps) {
|
||||
const [progress, setProgress] = useState(0);
|
||||
const [currentSection, setCurrentSection] = useState('');
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
const scrollY = window.scrollY;
|
||||
const documentHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||
const scrollProgress = Math.min((scrollY / documentHeight) * 100, 100);
|
||||
|
||||
setProgress(scrollProgress);
|
||||
setIsVisible(scrollY > 200);
|
||||
|
||||
// Find current section
|
||||
const sectionElements = sections.map(section =>
|
||||
document.getElementById(section) || document.querySelector('.hero-section')
|
||||
).filter(Boolean);
|
||||
|
||||
for (let i = sectionElements.length - 1; i >= 0; i--) {
|
||||
const element = sectionElements[i];
|
||||
if (element && element.offsetTop <= scrollY + 300) {
|
||||
setCurrentSection(sections[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
handleScroll(); // Check initial position
|
||||
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
const getSectionTitle = (section: string) => {
|
||||
switch (section) {
|
||||
case 'hero': return 'Welcome to CHORUS';
|
||||
case 'whoosh': return 'WHOOSH - Orchestration Engine';
|
||||
case 'bzzz': return 'BZZZ - P2P Coordination';
|
||||
case 'slurp': return 'SLURP - Context Curator';
|
||||
case 'cooee': return 'COOEE - Feedback & Learning';
|
||||
case 'integration': return 'Complete Ecosystem';
|
||||
default: return 'CHORUS Services';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isVisible && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -50 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -50 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className={`fixed top-0 left-0 right-0 z-40 ${className}`}
|
||||
>
|
||||
<div className="glass-effect border-b border-gray-600">
|
||||
<div className="container-chorus py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<div className="text-sm text-gray-300 mb-1">
|
||||
{getSectionTitle(currentSection)}
|
||||
</div>
|
||||
<Progress
|
||||
percent={progress}
|
||||
strokeColor={{
|
||||
'0%': '#007aff',
|
||||
'25%': '#30d158',
|
||||
'50%': '#eab308',
|
||||
'75%': '#a855f7',
|
||||
'100%': '#f97316',
|
||||
}}
|
||||
trailColor="rgba(255, 255, 255, 0.1)"
|
||||
showInfo={false}
|
||||
strokeWidth={3}
|
||||
className="max-w-md"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400 ml-4">
|
||||
{Math.round(progress)}% complete
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user