feat: Implement ScrollReveal animations and sync navigation icons

- Add ScrollReveal component with Intersection Observer API
- Create useIntersectionObserver hook for scroll-based animations
- Implement progressive scroll animations on motion page (200ms-600ms delays)
- Add CSS animation system with prefers-reduced-motion accessibility support
- Update navigation icons for consistency between sidebar and primary nav
- Use Interface/Trending_Up for Motion System and Environment/Puzzle for Components
- Add GPU-accelerated transforms with will-change optimization

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tony
2025-08-26 08:39:48 +10:00
parent 9cf92f9fcf
commit 630d1c26ad
12 changed files with 1009 additions and 810 deletions

View File

@@ -1,4 +1,4 @@
import ScrollReveal from '@/components/ScrollReveal';
export default function ColorsPage() { export default function ColorsPage() {
const lightColorSets = [ const lightColorSets = [
{ {
@@ -170,7 +170,9 @@ export default function ColorsPage() {
<div className="py-chorus-xxl bg-gradient-to-b dark:from-carbon-950 dark:to-mulberry-950 from-white to-sand-200"> <div className="py-chorus-xxl bg-gradient-to-b dark:from-carbon-950 dark:to-mulberry-950 from-white to-sand-200">
<section id="colors" className="pt-chorus-xxl"> <section id="colors" className="pt-chorus-xxl">
<div className="px-chorus-lg max-w-5xl mx-auto"> <div className="px-chorus-lg max-w-5xl mx-auto">
<ScrollReveal delay={300} duration={600} direction="up">
<h2 className="text-h2 mb-chorus-lg">Color Palette</h2> <h2 className="text-h2 mb-chorus-lg">Color Palette</h2>
</ScrollReveal>
<div className="space-y-chorus-lg"> <div className="space-y-chorus-lg">
<div> <div>
@@ -183,6 +185,7 @@ export default function ColorsPage() {
<div className="grid md:grid-cols-2 mb-chorus-lg"> <div className="grid md:grid-cols-2 mb-chorus-lg">
<div className="p-chorus-lg bg-mulberry-900 shadow-lg"> <div className="p-chorus-lg bg-mulberry-900 shadow-lg">
<ScrollReveal delay={300} duration={600} direction="up">
<div className="flex items-center gap-3 mb-chorus-sm"> <div className="flex items-center gap-3 mb-chorus-sm">
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Environment/Moon.png" alt="Dark Mode" className="w-8 h-8" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Environment/Moon.png" alt="Dark Mode" className="w-8 h-8" />
<h4 className="text-h4 text-white">Dark Mode (Default)</h4> <h4 className="text-h4 text-white">Dark Mode (Default)</h4>
@@ -194,9 +197,11 @@ export default function ColorsPage() {
<li><strong>Aesthetic:</strong> Ultra-minimalist with sophisticated mulberry accents</li> <li><strong>Aesthetic:</strong> Ultra-minimalist with sophisticated mulberry accents</li>
<li><strong>Contrast:</strong> WCAG 2.1 AA compliant</li> <li><strong>Contrast:</strong> WCAG 2.1 AA compliant</li>
</ul> </ul>
</ScrollReveal>
<div className="-mr-chorus-lg"> <div className="-mr-chorus-lg">
{darkColorSets.map((colorSet) => ( {darkColorSets.map((colorSet) => (
<div key={colorSet.name} className={`border border-nickel-200 overflow-hidden bg-${colorSet.baseColor}`}> <div key={colorSet.name} className={`border border-nickel-200 overflow-hidden bg-${colorSet.baseColor}`}>
<ScrollReveal delay={300} duration={600} direction="up">
<div className={`p-chorus-lg bg-${colorSet.baseColor}`}> <div className={`p-chorus-lg bg-${colorSet.baseColor}`}>
<div className="flex items-start justify-between mb-chorus-md"> <div className="flex items-start justify-between mb-chorus-md">
<div> <div>
@@ -226,6 +231,7 @@ export default function ColorsPage() {
})} })}
</div> </div>
</div> </div>
</ScrollReveal>
</div> </div>
))} ))}
</div> </div>
@@ -233,6 +239,8 @@ export default function ColorsPage() {
</div> </div>
<div className="p-chorus-lg bg-white shadow-lg"> <div className="p-chorus-lg bg-white shadow-lg">
<ScrollReveal delay={300} duration={600} direction="up">
<div className="flex items-center gap-3 mb-chorus-sm"> <div className="flex items-center gap-3 mb-chorus-sm">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Environment/Sun.png" alt="Light Mode" className="w-8 h-8" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Environment/Sun.png" alt="Light Mode" className="w-8 h-8" />
<h4 className="text-h4 text-carbon-900">Light Mode (Alternative)</h4> <h4 className="text-h4 text-carbon-900">Light Mode (Alternative)</h4>
@@ -244,10 +252,13 @@ export default function ColorsPage() {
<li><strong>Usage:</strong> Print materials, accessibility accommodations</li> <li><strong>Usage:</strong> Print materials, accessibility accommodations</li>
<li><strong>Contrast:</strong> Optimized for readability on warm backgrounds</li> <li><strong>Contrast:</strong> Optimized for readability on warm backgrounds</li>
</ul> </ul>
</ScrollReveal>
<div className="-ml-chorus-lg"> <div className="-ml-chorus-lg">
{lightColorSets.map((colorSet) => ( {lightColorSets.map((colorSet) => (
<div key={colorSet.name} className={`border border-nickel-200 overflow-hidden bg-${colorSet.baseColor}`}> <div key={colorSet.name} className={`border border-nickel-200 overflow-hidden bg-${colorSet.baseColor}`}>
<ScrollReveal delay={300} duration={600} direction="up">
<div className={`p-chorus-lg bg-${colorSet.baseColor}`}> <div className={`p-chorus-lg bg-${colorSet.baseColor}`}>
<div className="flex items-start justify-between mb-chorus-md"> <div className="flex items-start justify-between mb-chorus-md">
<div> <div>
@@ -277,6 +288,7 @@ export default function ColorsPage() {
})} })}
</div> </div>
</div> </div>
</ScrollReveal>
</div> </div>
))} ))}
</div> </div>

View File

@@ -51,30 +51,30 @@ export default function Communications() {
<div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 "> <div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 ">
<h3 className="text-h3 mb-chorus-md">Writing Style</h3> <h3 className="text-h3 mb-chorus-md">Writing Style</h3>
<ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300"> <ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300">
<li> Active voice preferred</li> <li>Active voice preferred</li>
<li> Clear, concise sentences</li> <li>Clear, concise sentences</li>
<li> Technical accuracy</li> <li>Technical accuracy</li>
<li> Inclusive language</li> <li>Inclusive language</li>
</ul> </ul>
</div> </div>
<div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 "> <div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 ">
<h3 className="text-h3 mb-chorus-md">Terminology</h3> <h3 className="text-h3 mb-chorus-md">Terminology</h3>
<ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300"> <ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300">
<li> "AI agents" not "bots"</li> <li>"AI agents" not "bots"</li>
<li> "Context management"</li> <li>"Context management"</li>
<li> "Distributed orchestration"</li> <li>"Distributed orchestration"</li>
<li> "Knowledge fabric"</li> <li>"Knowledge fabric"</li>
</ul> </ul>
</div> </div>
<div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 "> <div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900 ">
<h3 className="text-h3 mb-chorus-md">Localization</h3> <h3 className="text-h3 mb-chorus-md">Localization</h3>
<ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300"> <ul className="space-y-2 text-sm text-carbon-600 dark:text-mulberry-300">
<li> Global-first approach</li> <li>Global-first approach</li>
<li> Cultural sensitivity</li> <li>Cultural sensitivity</li>
<li> Technical term consistency</li> <li>Technical term consistency</li>
<li> Regional adaptations</li> <li>Regional adaptations</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -790,6 +790,10 @@ pre[class*="language-"] {
margin-bottom: 0; margin-bottom: 0;
} }
.secondary-nav {
overflow: hidden !important;
}
.primary-nav { .primary-nav {
position: relative; position: relative;
font-weight: 600; font-weight: 600;
@@ -1104,6 +1108,22 @@ nav button {
&.dark .bg-white { background-color: #ffffff !important; } &.dark .bg-white { background-color: #ffffff !important; }
} }
/* Scroll Animation System */
.scroll-reveal {
/* Base styles for scroll animations */
will-change: opacity, transform;
}
/* Accessibility: respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.scroll-reveal, .scroll-reveal * {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
transform: none !important;
opacity: 1 !important;
}
}
/* Enhanced contrast for accessibility theme selection indicators */ /* Enhanced contrast for accessibility theme selection indicators */
[data-theme="protanopia"] .ring-ocean-500 { box-shadow: 0 0 0 2px #1e40af !important; } [data-theme="protanopia"] .ring-ocean-500 { box-shadow: 0 0 0 2px #1e40af !important; }
[data-theme="deuteranopia"] .ring-eucalyptus-500 { box-shadow: 0 0 0 2px #6b21a8 !important; } [data-theme="deuteranopia"] .ring-eucalyptus-500 { box-shadow: 0 0 0 2px #6b21a8 !important; }

View File

@@ -1,10 +1,12 @@
import { div } from "three/tsl" import { div } from "three/tsl"
import ScrollReveal from '@/components/ScrollReveal';
export default function IconographyPage() { export default function IconographyPage() {
return ( return (
<div className="py-chorus-xxl"> <div className="py-chorus-xxl">
<section> <section>
<div className="max-w-5xl mx-auto px-chorus-lg pt-chorus-xxl"> <div className="max-w-5xl mx-auto px-chorus-lg pt-chorus-xxl">
<ScrollReveal delay={200} duration={600} direction="up">
<div className="mb-chorus-xxl"> <div className="mb-chorus-xxl">
<h1 className="text-h2 mb-chorus-lg">Iconography System</h1> <h1 className="text-h2 mb-chorus-lg">Iconography System</h1>
@@ -15,23 +17,31 @@ export default function IconographyPage() {
</p> </p>
<div className="grid gap-chorus-md md:grid-cols-3 mt-chorus-lg"> <div className="grid gap-chorus-md md:grid-cols-3 mt-chorus-lg">
<ScrollReveal delay={300} duration={600} direction="up">
<div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950"> <div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950">
<h4 className="text-h4 mb-chorus-sm">Clarity & Recognition</h4> <h4 className="text-h4 mb-chorus-sm">Clarity & Recognition</h4>
<p className="text-sm text-carbon-600 dark:text-mulberry-300">Icons communicate instantly without language barriers</p> <p className="text-sm text-carbon-600 dark:text-mulberry-300">Icons communicate instantly without language barriers</p>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={400} duration={600} direction="up">
<div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950"> <div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950">
<h4 className="text-h4 mb-chorus-sm">Theme Adaptive</h4> <h4 className="text-h4 mb-chorus-sm">Theme Adaptive</h4>
<p className="text-sm text-carbon-600 dark:text-mulberry-300">Black and white variants ensure perfect contrast in all modes</p> <p className="text-sm text-carbon-600 dark:text-mulberry-300">Black and white variants ensure perfect contrast in all modes</p>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
<div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950"> <div className="border border-nickel-200 p-chorus-md dark:border-nickel-900 bg-white dark:bg-mulberry-950">
<h4 className="text-h4 mb-chorus-sm">Consistent Scale</h4> <h4 className="text-h4 mb-chorus-sm">Consistent Scale</h4>
<p className="text-sm text-carbon-600 dark:text-mulberry-300">Standardized sizing maintains visual harmony</p> <p className="text-sm text-carbon-600 dark:text-mulberry-300">Standardized sizing maintains visual harmony</p>
</div> </div>
</div> </ScrollReveal>
</div> </div>
</div> </div>
</div>
</ScrollReveal>
{/* Icon Categories */} {/* Icon Categories */}
<section className="mb-chorus-xxl"> <section className="mb-chorus-xxl">
<h2 className="text-h3 mb-chorus-md">Icon Categories</h2> <h2 className="text-h3 mb-chorus-md">Icon Categories</h2>
<p className="mb-chorus-md"> <p className="mb-chorus-md">
@@ -39,6 +49,7 @@ export default function IconographyPage() {
</p> </p>
<div className="space-y-chorus-lg"> <div className="space-y-chorus-lg">
<ScrollReveal delay={500} duration={600} direction="up">
{/* Interface Icons */} {/* Interface Icons */}
<div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800"> <div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800">
<h4 className="text-h4 mb-chorus-md">Interface & Navigation</h4> <h4 className="text-h4 mb-chorus-md">Interface & Navigation</h4>
@@ -86,7 +97,9 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
{/* Navigation Icons */} {/* Navigation Icons */}
<div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800"> <div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800">
<h4 className="text-h4 mb-chorus-md">Navigation & Direction</h4> <h4 className="text-h4 mb-chorus-md">Navigation & Direction</h4>
@@ -134,7 +147,8 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
{/* File & System Icons */} {/* File & System Icons */}
<div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800"> <div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800">
<h4 className="text-h4 mb-chorus-md">File & System Operations</h4> <h4 className="text-h4 mb-chorus-md">File & System Operations</h4>
@@ -182,7 +196,8 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
{/* Communication Icons */} {/* Communication Icons */}
<div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800"> <div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800">
<h4 className="text-h4 mb-chorus-md">Communication & Social</h4> <h4 className="text-h4 mb-chorus-md">Communication & Social</h4>
@@ -230,7 +245,8 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
{/* Status & Warning Icons */} {/* Status & Warning Icons */}
<div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800"> <div className="shadow-lg bg-white dark:bg-mulberry-900 border border-nickel-200 p-chorus-lg dark:border-nickel-800">
<h4 className="text-h4 mb-chorus-md">Status & Feedback</h4> <h4 className="text-h4 mb-chorus-md">Status & Feedback</h4>
@@ -278,9 +294,11 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
</div> </div>
</section> </section>
<ScrollReveal delay={200} duration={600} direction="up">
{/* Usage Guidelines */} {/* Usage Guidelines */}
<section className="mb-chorus-xxl"> <section className="mb-chorus-xxl">
<h2 className="text-h3 mb-chorus-md">Usage Guidelines</h2> <h2 className="text-h3 mb-chorus-md">Usage Guidelines</h2>
@@ -360,7 +378,9 @@ export default function IconographyPage() {
</div> </div>
</div> </div>
</section> </section>
</ScrollReveal>
<ScrollReveal delay={200} duration={600} direction="up">
{/* Implementation Guide */} {/* Implementation Guide */}
<section> <section>
<h2 className="text-h3 mb-chorus-md">Implementation Guide</h2> <h2 className="text-h3 mb-chorus-md">Implementation Guide</h2>
@@ -383,12 +403,12 @@ export default function IconographyPage() {
</h5> </h5>
<div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto"> <div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto">
<pre>{`<!-- Light theme icon (visible in light mode) --> <pre>{`<!-- Light theme icon (visible in light mode) -->
<img src="icons/coolicons.v4.1/coolicons PNG/Black/Interface/Settings.png" <img src="icons/coolicons.v4.1/coolicons PNG/Black/Interface/Settings.png"
alt="Settings" alt="Settings"
className="w-6 h-6 dark:hidden" /> className="w-6 h-6 dark:hidden" />
<!-- Dark theme icon (visible in dark mode) --> <!-- Dark theme icon (visible in dark mode) -->
<img src="icons/coolicons.v4.1/coolicons PNG/White/Interface/Settings.png" <img src="icons/coolicons.v4.1/coolicons PNG/White/Interface/Settings.png"
alt="Settings" alt="Settings"
className="w-6 h-6 hidden dark:block" />`}</pre> className="w-6 h-6 hidden dark:block" />`}</pre>
</div> </div>
@@ -400,10 +420,10 @@ export default function IconographyPage() {
</h5> </h5>
<div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto"> <div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto">
<pre>{`/* Standard icon sizes following CHORUS spacing system */ <pre>{`/* Standard icon sizes following CHORUS spacing system */
.icon-sm { width: 1rem; height: 1rem; } /* 16px */ .icon-sm { width: 1rem; height: 1rem; } /* 16px */
.icon-md { width: 1.25rem; height: 1.25rem; } /* 20px */ .icon-md { width: 1.25rem; height: 1.25rem; } /* 20px */
.icon-lg { width: 1.5rem; height: 1.5rem; } /* 24px */ .icon-lg { width: 1.5rem; height: 1.5rem; } /* 24px */
.icon-xl { width: 2rem; height: 2rem; } /* 32px */`}</pre> .icon-xl { width: 2rem; height: 2rem; } /* 32px */`}</pre>
</div> </div>
</div> </div>
@@ -413,16 +433,17 @@ export default function IconographyPage() {
</h5> </h5>
<div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto"> <div className="bg-white dark:bg-carbon-950 p-chorus-md border border-gray-200 dark:border-mulberry-700 font-mono text-sm overflow-x-auto">
<pre>{`public/icons/coolicons.v4.1/ <pre>{`public/icons/coolicons.v4.1/
├── coolicons PNG/ ├── coolicons PNG/
│ ├── Black/ # Light theme icons │ ├── Black/ # Light theme icons
│ └── White/ # Dark theme icons │ └── White/ # Dark theme icons
├── coolicons SVG/ # Vector versions ├── coolicons SVG/ # Vector versions
└── Webfont/ # Icon font (optional)`}</pre> └── Webfont/ # Icon font (optional)`}</pre>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</ScrollReveal>
</div> </div>
</section> </section>
</div> </div>

View File

@@ -1,26 +1,36 @@
import ThreeLogo from '@/components/ThreeLogo'; import ThreeLogo from '@/components/ThreeLogo';
import ScrollReveal from '@/components/ScrollReveal';
export default function LogoPage() { export default function LogoPage() {
return ( return (
<div className="py-chorus-xxl bg-gradient-to-b dark:from-mulberry-700 dark:to-mulberry-950 to-white from-sand-400 "> <div className="relative">
{/* Full-width Hero Section with 3D Logo */} {/* Fixed Hero Section with 3D Logo */}
<section id="logo-hero" className="mb-chorus-lg pt-chorus-xl"> <section
id="logo-hero"
className="fixed top-0 left-0 right-0 bottom-0 md:left-64 flex items-center justify-center bg-gradient-to-b dark:from-mulberry-700 dark:to-mulberry-950 to-white from-sand-400"
>
<ScrollReveal delay={300} duration={600} direction="up">
{/* Logo Section */} {/* Logo Section */}
<div className="pt-chorus-xs logo-group-circular mx-auto"> <div className="logo-group-circular">
<div className="pb-chorus-md item mx-auto logo-group-circular"> <div className="item logo-group-circular">
<ThreeLogo width={512} height={512} /> <ThreeLogo width={512} height={512} />
<h4 className="text-h4 font-logo">CHORUS</h4> <h4 className="text-h4 font-logo">CHORUS</h4>
</div> </div>
</div> </div>
</ScrollReveal>
</section> </section>
{/* Spacer to create scroll space */}
<div className="h-screen"></div>
{/* Sliding Content Overlay */}
<div className="relative z-10 bg-white dark:bg-transparent shadow-2xl">
<div className="max-w-5xl mx-auto px-chorus-lg py-chorus-xxl"> <div className="max-w-5xl mx-auto px-chorus-lg py-chorus-xxl">
{/* Logo System Content */} {/* Logo System Content */}
<div className="space-y-chorus-xxl"> <div className="space-y-chorus-xxl">
{/* Primary Logo Description */} {/* Primary Logo Description */}
<ScrollReveal delay={300} duration={600} direction="up">
<section> <section>
<h2 className="text-h2 mb-chorus-lg">Logo System</h2> <h2 className="text-h2 mb-chorus-lg">Logo System</h2>
@@ -65,7 +75,7 @@ export default function LogoPage() {
</div> </div>
</div> </div>
</section> </section>
</ScrollReveal>
{/* Logo Orientations */} {/* Logo Orientations */}
<section> <section>
<h3 className="text-h3 mb-chorus-md">Logo Orientations</h3> <h3 className="text-h3 mb-chorus-md">Logo Orientations</h3>
@@ -263,5 +273,6 @@ export default function LogoPage() {
</div> </div>
</div> </div>
</div> </div>
</div>
); );
} }

View File

@@ -1,3 +1,5 @@
import ScrollReveal from '@/components/ScrollReveal';
export default function Motion() { export default function Motion() {
return ( return (
<div className="py-chorus-xxl bg-gradient-to-b dark:from-mulberry-950 dark:to-carbon-950 from-white to-sand-200"> <div className="py-chorus-xxl bg-gradient-to-b dark:from-mulberry-950 dark:to-carbon-950 from-white to-sand-200">
@@ -6,6 +8,7 @@ export default function Motion() {
<h2 className="text-h2 mb-chorus-lg">Motion System</h2> <h2 className="text-h2 mb-chorus-lg">Motion System</h2>
<div className="py-chorus-lg space-y-chorus-lg"> <div className="py-chorus-lg space-y-chorus-lg">
<ScrollReveal delay={200} duration={600} direction="up">
<div className="mb-chorus-lg"> <div className="mb-chorus-lg">
<p className="text-lg mb-chorus-md"> <p className="text-lg mb-chorus-md">
The CHORUS motion system creates sophisticated, purposeful animations that enhance usability without overwhelming users. The CHORUS motion system creates sophisticated, purposeful animations that enhance usability without overwhelming users.
@@ -14,7 +17,9 @@ export default function Motion() {
Our implementation focuses on performance, accessibility, and consistent timing that reinforces the premium CHORUS brand personality. Our implementation focuses on performance, accessibility, and consistent timing that reinforces the premium CHORUS brand personality.
</p> </p>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={300} duration={600} direction="up">
<div className="grid gap-chorus-lg md:grid-cols-3"> <div className="grid gap-chorus-lg md:grid-cols-3">
<div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900"> <div className="border border-nickel-200 p-chorus-lg dark:border-nickel-900">
<h3 className="text-h3 mb-chorus-md">Timing Scale</h3> <h3 className="text-h3 mb-chorus-md">Timing Scale</h3>
@@ -62,7 +67,9 @@ export default function Motion() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={400} duration={600} direction="up">
<div className="grid gap-chorus-lg md:grid-cols-2"> <div className="grid gap-chorus-lg md:grid-cols-2">
<div className="bg-sand-50 dark:bg-mulberry-900 p-chorus-lg border border-sand-200 dark:border-mulberry-800"> <div className="bg-sand-50 dark:bg-mulberry-900 p-chorus-lg border border-sand-200 dark:border-mulberry-800">
<h3 className="text-h3 mb-chorus-md">Interactive Elements</h3> <h3 className="text-h3 mb-chorus-md">Interactive Elements</h3>
@@ -113,7 +120,9 @@ export default function Motion() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
<div className="bg-white dark:bg-carbon-900 p-chorus-lg border border-nickel-200 dark:border-carbon-800"> <div className="bg-white dark:bg-carbon-900 p-chorus-lg border border-nickel-200 dark:border-carbon-800">
<h3 className="text-h3 mb-chorus-md">CSS Implementation</h3> <h3 className="text-h3 mb-chorus-md">CSS Implementation</h3>
<div className="grid gap-chorus-md md:grid-cols-2"> <div className="grid gap-chorus-md md:grid-cols-2">
@@ -145,7 +154,9 @@ export default function Motion() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={600} duration={600} direction="up">
<div className="bg-sand-50 dark:bg-mulberry-900 p-chorus-lg border border-sand-200 dark:border-mulberry-800"> <div className="bg-sand-50 dark:bg-mulberry-900 p-chorus-lg border border-sand-200 dark:border-mulberry-800">
<h3 className="text-h3 mb-chorus-md">Motion Principles</h3> <h3 className="text-h3 mb-chorus-md">Motion Principles</h3>
<div className="grid gap-chorus-md md:grid-cols-2"> <div className="grid gap-chorus-md md:grid-cols-2">
@@ -171,6 +182,7 @@ export default function Motion() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
</div> </div>
</div> </div>
</section> </section>

View File

@@ -1,9 +1,11 @@
import ScrollReveal from '@/components/ScrollReveal';
export default function TypographyPage() { export default function TypographyPage() {
return ( return (
<div className="py-chorus-xxl"> <div className="py-chorus-xxl">
<section className="mb-chorus-xxl pt-chorus-xxl"> <section className="mb-chorus-xxl pt-chorus-xxl">
<div className="mb-chorus-xxl max-w-5xl mx-auto px-chorus-lg "> <div className="mb-chorus-xxl max-w-5xl mx-auto px-chorus-lg ">
<ScrollReveal delay={300} duration={600} direction="up">
<h1 className="text-h2 mb-chorus-md">Typography</h1> <h1 className="text-h2 mb-chorus-md">Typography</h1>
<p className="text-carbon-600 dark:text-mulberry-300 mb-chorus-md"> <p className="text-carbon-600 dark:text-mulberry-300 mb-chorus-md">
@@ -16,7 +18,9 @@ export default function TypographyPage() {
All spacing, sizing, and proportions automatically scale with the 18px base. CHORUS spacing system (chorus-xs, chorus-md, etc.) maintains perfect proportional relationships. All spacing, sizing, and proportions automatically scale with the 18px base. CHORUS spacing system (chorus-xs, chorus-md, etc.) maintains perfect proportional relationships.
</p> </p>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={400} duration={600} direction="up">
{/* Font Families */} {/* Font Families */}
<div className="py-chorus-xl"> <div className="py-chorus-xl">
<h2 className="text-h3 mb-chorus-md">Font Families</h2> <h2 className="text-h3 mb-chorus-md">Font Families</h2>
@@ -64,8 +68,9 @@ export default function TypographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={500} duration={600} direction="up">
{/* Typography Examples - DO vs DON'T */} {/* Typography Examples - DO vs DON'T */}
<div className="py-chorus-xl"> <div className="py-chorus-xl">
<div className="grid gap-chorus-lg md:grid-cols-2"> <div className="grid gap-chorus-lg md:grid-cols-2">
@@ -189,14 +194,19 @@ export default function TypographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={600} duration={600} direction="up">
{/* Typography Scale */} {/* Typography Scale */}
<h2 className="text-h3 mb-chorus-md">Proportional Font Scale</h2> <h2 className="text-h3 mb-chorus-md">Proportional Font Scale</h2>
<p className="text-sm text-carbon-500 dark:text-mulberry-300 mb-chorus-lg"> <p className="text-sm text-carbon-500 dark:text-mulberry-300 mb-chorus-lg">
Based on Major Third (1.25×) ratio with 18px foundation for enhanced readability Based on Major Third (1.25×) ratio with 18px foundation for enhanced readability
</p> </p>
</ScrollReveal>
<ScrollReveal delay={700} duration={600} direction="up">
<div className="bg-white dark:bg-mulberry-950 border border-nickel-200 dark:border-mulberry-800 p-chorus-lg"> <div className="bg-white dark:bg-mulberry-950 border border-nickel-200 dark:border-mulberry-800 p-chorus-lg">
<div className="grid gap-chorus-sm md:grid-cols-2"> <div className="grid gap-chorus-sm md:grid-cols-2">
<div> <div>
@@ -219,8 +229,10 @@ export default function TypographyPage() {
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
<ScrollReveal delay={800} duration={600} direction="up">
<div className="pt-chorus-xl"> <div className="pt-chorus-xl">
<h2 className="text-h3 mb-chorus-md">Implementation Guide</h2> <h2 className="text-h3 mb-chorus-md">Implementation Guide</h2>
<p className="text-carbon-600 dark:text-mulberry-300 mb-chorus-lg"> <p className="text-carbon-600 dark:text-mulberry-300 mb-chorus-lg">
@@ -261,7 +273,9 @@ export default function TypographyPage() {
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</ScrollReveal>
</div> </div>
</section> </section>
</div> </div>

View File

@@ -25,10 +25,8 @@ export default function Footer() {
<h4 className="text-h4 text-carbon-950 dark:text-white mb-chorus-md">Brand Guide</h4> <h4 className="text-h4 text-carbon-950 dark:text-white mb-chorus-md">Brand Guide</h4>
<ul className="space-y-chorus-xs text-sm"> <ul className="space-y-chorus-xs text-sm">
<li><Link href="/" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Overview</Link></li> <li><Link href="/" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Overview</Link></li>
<li><Link href="/identity" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Brand Identity</Link></li> <li><Link href="/visual-identity" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Visual Identity</Link></li>
<li><Link href="/colors" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Color Palette</Link></li> <li><Link href="/communications" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Communications</Link></li>
<li><Link href="/typography" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Typography</Link></li>
<li><Link href="/logo" className="text-carbon-600 dark:text-mulberry-300 hover:text-carbon-950 dark:hover:text-white transition-colors">Logo System</Link></li>
</ul> </ul>
</div> </div>
<div> <div>

View File

@@ -39,8 +39,8 @@ const MobileAccordionMenu = ({ onClose }: MobileAccordionMenuProps) => {
{ href: '/colors', section: 'colors', icon: 'Edit/Swatches_Palette', label: 'Color Palette' }, { href: '/colors', section: 'colors', icon: 'Edit/Swatches_Palette', label: 'Color Palette' },
{ href: '/iconography', section: 'iconography', icon: 'Interface/Main_Component', label: 'Iconography' }, { href: '/iconography', section: 'iconography', icon: 'Interface/Main_Component', label: 'Iconography' },
{ href: '/accessibility', section: 'accessibility', icon: 'Interface/Heart_01', label: 'Accessibility' }, { href: '/accessibility', section: 'accessibility', icon: 'Interface/Heart_01', label: 'Accessibility' },
{ href: '/components', section: 'components', icon: 'Interface/Settings', label: 'Components' }, { href: '/components', section: 'components', icon: 'Environment/Puzzle', label: 'Components' },
{ href: '/motion', section: 'motion', icon: 'Interface/Link', label: 'Motion System' }, { href: '/motion', section: 'motion', icon: 'Interface/Trending_Up', label: 'Motion System' },
{ href: '/implementation', section: 'implementation', icon: 'File/File_Code', label: 'Implementation' }, { href: '/implementation', section: 'implementation', icon: 'File/File_Code', label: 'Implementation' },
] ]
}, },
@@ -95,7 +95,7 @@ const MobileAccordionMenu = ({ onClose }: MobileAccordionMenuProps) => {
className={`w-full group flex items-center justify-between gap-2 px-chorus-sm py-chorus-xs text-left transition-all duration-300 ease-out hover:bg-sand-50 hover:bg-opacity-30 hover:text-mulberry-950 dark:hover:bg-mulberry-900 dark:hover:bg-opacity-40 dark:hover:text-white ${ className={`w-full group flex items-center justify-between gap-2 px-chorus-sm py-chorus-xs text-left transition-all duration-300 ease-out hover:bg-sand-50 hover:bg-opacity-30 hover:text-mulberry-950 dark:hover:bg-mulberry-900 dark:hover:bg-opacity-40 dark:hover:text-white ${
isActive isActive
? 'bg-sand-100 text-mulberry-950 dark:bg-mulberry-800 dark:text-white font-medium' ? 'bg-sand-100 text-mulberry-950 dark:bg-mulberry-800 dark:text-white font-medium'
: 'text-carbon-700 dark:text-mulberry-300' : 'transparent'
}`} }`}
aria-expanded={isExpanded} aria-expanded={isExpanded}
> >
@@ -131,7 +131,7 @@ const MobileAccordionMenu = ({ onClose }: MobileAccordionMenuProps) => {
onClick={onClose} onClick={onClose}
className={`p-chorus-sm flex items-center gap-2 px-chorus-sm transition-all duration-300 ease-out hover:bg-sand-50 hover:bg-opacity-30 hover:text-mulberry-950 dark:hover:bg-mulberry-900 dark:hover:bg-opacity-40 dark:hover:text-white ${ className={`p-chorus-sm flex items-center gap-2 px-chorus-sm transition-all duration-300 ease-out hover:bg-sand-50 hover:bg-opacity-30 hover:text-mulberry-950 dark:hover:bg-mulberry-900 dark:hover:bg-opacity-40 dark:hover:text-white ${
isCurrentPage(item.href) isCurrentPage(item.href)
? 'bg-sand-50 text-mulberry-950 dark:bg-mulberry-900 dark:text-white font-medium border-l-2 border-mulberry-600 dark:border-mulberry-400' ? 'transparent text-mulberry-950 dark:text-white font-medium border-l-2 border-mulberry-600 dark:border-mulberry-400'
: 'text-carbon-600 dark:text-mulberry-400' : 'text-carbon-600 dark:text-mulberry-400'
}`} }`}
> >
@@ -266,7 +266,7 @@ const Header = () => {
{/* Desktop primary navigation - hidden on mobile */} {/* Desktop primary navigation - hidden on mobile */}
<nav className="primary-nav hidden lg:block"> <nav className="primary-nav hidden lg:block">
<ul className="horizontal-menu"> <ul className="horizontal-menu">
<li className="dark:hover:bg-mulberry-700 hover:bg-sand-300 backdrop-blur"> <li className="item">
<div className="flex items-center gap-2 ml-chorus-sm"> <div className="flex items-center gap-2 ml-chorus-sm">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Navigation/House_01.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Navigation/House_01.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" />
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Navigation/House_01.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Navigation/House_01.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" />
@@ -296,7 +296,7 @@ const Header = () => {
</li> </li>
</ul> </ul>
</li> </li>
<li className="dark:hover:bg-mulberry-700 hover:bg-sand-300 backdrop-blur"> <li className="item">
<div className="flex items-center gap-2 ml-chorus-sm"> <div className="flex items-center gap-2 ml-chorus-sm">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Shape/Circle.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Shape/Circle.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" />
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Shape/Circle.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Shape/Circle.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" />
@@ -348,15 +348,15 @@ const Header = () => {
</li> </li>
<li className="item"> <li className="item">
<Link href="/components" className="dark:hover:bg-mulberry-700 hover:bg-sand-300 transition-all duration-300 ease-out flex items-center gap-2"> <Link href="/components" className="dark:hover:bg-mulberry-700 hover:bg-sand-300 transition-all duration-300 ease-out flex items-center gap-2">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Interface/Settings.png" alt="" className="icon py-chous-sm h-3 w-3 dark:hidden" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Environment/Puzzle.png" alt="" className="icon py-chous-sm h-3 w-3 dark:hidden" />
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Interface/Settings.png" alt="" className="icon py-chous-sm hidden h-3 w-3 dark:inline-flex" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Environment/Puzzle.png" alt="" className="icon py-chous-sm hidden h-3 w-3 dark:inline-flex" />
<span>Components</span> <span>Components</span>
</Link> </Link>
</li> </li>
<li className="item"> <li className="item">
<Link href="/motion" className="dark:hover:bg-mulberry-700 hover:bg-sand-300 transition-all duration-300 ease-out flex items-center gap-2"> <Link href="/motion" className="dark:hover:bg-mulberry-700 hover:bg-sand-300 transition-all duration-300 ease-out flex items-center gap-2">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Interface/Link.png" alt="" className="icon py-chous-sm h-3 w-3 dark:hidden" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Interface/Trending_Up.png" alt="" className="icon py-chous-sm h-3 w-3 dark:hidden" />
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Interface/Link.png" alt="" className="icon py-chous-sm hidden h-3 w-3 dark:inline-flex" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Interface/Trending_Up.png" alt="" className="icon py-chous-sm hidden h-3 w-3 dark:inline-flex" />
<span>Motion System</span> <span>Motion System</span>
</Link> </Link>
</li> </li>
@@ -369,7 +369,7 @@ const Header = () => {
</li> </li>
</ul> </ul>
</li> </li>
<li className="dark:hover:bg-mulberry-700 hover:bg-sand-300"> <li className="item">
<div className="flex items-center gap-2 ml-chorus-sm"> <div className="flex items-center gap-2 ml-chorus-sm">
<img src="/icons/coolicons.v4.1/coolicons PNG/Black/Communication/Chat.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" /> <img src="/icons/coolicons.v4.1/coolicons PNG/Black/Communication/Chat.png" alt="" className="icon py-chous-sm h-4 w-4 dark:hidden" />
<img src="/icons/coolicons.v4.1/coolicons PNG/White/Communication/Chat.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" /> <img src="/icons/coolicons.v4.1/coolicons PNG/White/Communication/Chat.png" alt="" className="icon py-chous-sm hidden h-4 w-4 dark:inline-flex" />

View File

@@ -0,0 +1,62 @@
'use client';
import React from 'react';
import { useIntersectionObserver } from '@/hooks/useIntersectionObserver';
interface ScrollRevealProps {
children: React.ReactNode;
delay?: number;
duration?: number;
direction?: 'up' | 'down' | 'left' | 'right';
distance?: number;
className?: string;
}
export default function ScrollReveal({
children,
delay = 0,
duration = 600,
direction = 'up',
distance = 24,
className = '',
}: ScrollRevealProps) {
const { elementRef, isVisible } = useIntersectionObserver({
threshold: 0.1,
rootMargin: '0px 0px -100px 0px',
triggerOnce: true,
});
const getTransform = (visible: boolean) => {
if (visible) return 'translate3d(0, 0, 0)';
switch (direction) {
case 'up':
return `translate3d(0, ${distance}px, 0)`;
case 'down':
return `translate3d(0, -${distance}px, 0)`;
case 'left':
return `translate3d(${distance}px, 0, 0)`;
case 'right':
return `translate3d(-${distance}px, 0, 0)`;
default:
return `translate3d(0, ${distance}px, 0)`;
}
};
const revealStyle = {
opacity: isVisible ? 1 : 0,
transform: getTransform(isVisible),
transition: `opacity ${duration}ms ease-out ${delay}ms, transform ${duration}ms ease-out ${delay}ms`,
willChange: 'opacity, transform',
};
return (
<div
ref={elementRef}
style={revealStyle}
className={`scroll-reveal ${className}`}
>
{children}
</div>
);
}

View File

@@ -22,7 +22,7 @@ export default function ThreeLogo({ width = 64, height = 64, className = "" }: T
// Scene / Renderer / Camera // Scene / Renderer / Camera
const scene = new THREE.Scene(); const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100); const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 0, 2.2); // Move camera back to prevent clipping camera.position.set(0, 0, 3.0); // Move camera back to prevent clipping
camera.lookAt(0, 0, 0); // Ensure camera looks at exact center camera.lookAt(0, 0, 0); // Ensure camera looks at exact center
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

View File

@@ -0,0 +1,49 @@
'use client';
import { useEffect, useRef, useState } from 'react';
interface IntersectionObserverOptions {
threshold?: number;
rootMargin?: string;
triggerOnce?: boolean;
}
export function useIntersectionObserver(
options: IntersectionObserverOptions = {}
) {
const { threshold = 0.1, rootMargin = '0px 0px -100px 0px', triggerOnce = true } = options;
const [isIntersecting, setIsIntersecting] = useState(false);
const [hasIntersected, setHasIntersected] = useState(false);
const elementRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const element = elementRef.current;
if (!element) return;
const observer = new IntersectionObserver(
([entry]) => {
const isVisible = entry.isIntersecting;
setIsIntersecting(isVisible);
if (isVisible && !hasIntersected) {
setHasIntersected(true);
}
},
{
threshold,
rootMargin,
}
);
observer.observe(element);
return () => {
observer.unobserve(element);
};
}, [threshold, rootMargin, hasIntersected]);
return {
elementRef,
isVisible: triggerOnce ? hasIntersected : isIntersecting,
};
}