From ce35f7032625960c7d3ff5f361a3ce44705a4494 Mon Sep 17 00:00:00 2001 From: Ajit Pratap Singh Date: Mon, 13 Apr 2026 22:41:29 +0530 Subject: [PATCH 1/2] fix(website): comprehensive light mode CSS fixes for Tailwind v4 The light mode was broken because Tailwind v4 compiles utilities inside @layer which wins the CSS cascade over unlayered selectors, and many classes use arbitrary values (bg-[#09090b]) or slash-encoded opacities (bg-white/[0.06]) that attribute selectors can't match. Fixes: - Add !important to all html.light overrides for Tailwind v4 cascade - Add direct class selectors for bg-white/[0.06], bg-white/5, etc. - Add bg-[#09090b] override for playground root container - Add bg-slate-900/50, bg-slate-900/30 etc. direct overrides - Add border-white/[0.06], border-white/10 etc. direct overrides - Darken slate text overrides for better playground contrast - Override all select elements for light mode - Add playground-specific overrides (blue tabs, emerald code, dividers) - Keep green parser dot, loading skeletons, hover states correct Co-Authored-By: Claude Opus 4.6 (1M context) --- website/src/app/globals.css | 103 +++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/website/src/app/globals.css b/website/src/app/globals.css index 08b78e10..967b68dd 100644 --- a/website/src/app/globals.css +++ b/website/src/app/globals.css @@ -156,11 +156,11 @@ html.light .text-zinc-600 { color: #4B5563 !important; } html.light .text-indigo-300 { color: #4338CA !important; } html.light .text-emerald-400 { color: #059669 !important; } /* Slate palette (used in playground components) */ -html.light .text-slate-200 { color: #374151 !important; } -html.light .text-slate-300 { color: #4B5563 !important; } -html.light .text-slate-400 { color: #4B5563 !important; } -html.light .text-slate-500 { color: #6B7280 !important; } -html.light .text-slate-600 { color: #4B5563 !important; } +html.light .text-slate-200 { color: #1E293B !important; } +html.light .text-slate-300 { color: #334155 !important; } +html.light .text-slate-400 { color: #475569 !important; } +html.light .text-slate-500 { color: #475569 !important; } +html.light .text-slate-600 { color: #334155 !important; } /* --- Heading gradient: dark gradient on light bg --- */ html.light .from-white { --tw-gradient-from: #0F172A !important; } @@ -180,6 +180,12 @@ html.light .glass-hover:hover { } /* --- Borders (white/opacity → black/opacity) --- */ +html.light .border-white\/\[0\.06\] { border-color: rgba(0, 0, 0, 0.08) !important; } +html.light .border-white\/\[0\.08\] { border-color: rgba(0, 0, 0, 0.08) !important; } +html.light .border-white\/\[0\.1\] { border-color: rgba(0, 0, 0, 0.12) !important; } +html.light .border-white\/\[0\.12\] { border-color: rgba(0, 0, 0, 0.12) !important; } +html.light .border-white\/5 { border-color: rgba(0, 0, 0, 0.06) !important; } +html.light .border-white\/10 { border-color: rgba(0, 0, 0, 0.10) !important; } html.light [class*="border-white\\/"] { border-color: rgba(0, 0, 0, 0.10) !important; } html.light [class*="divide-white\\/"] { border-color: rgba(0, 0, 0, 0.08) !important; } @@ -197,19 +203,30 @@ html.light .bg-surface { background-color: #FFFFFF !important; } html.light .bg-slate-800 { background-color: #E5E7EB !important; } html.light .bg-slate-900 { background-color: #F3F4F6 !important; } html.light .bg-slate-950 { background-color: #F9FAFB !important; } +html.light .bg-slate-800\/80 { background-color: #E5E7EB !important; } +html.light .bg-slate-900\/50 { background-color: rgba(0, 0, 0, 0.03) !important; } +html.light .bg-slate-900\/30 { background-color: rgba(0, 0, 0, 0.02) !important; } +html.light .bg-slate-700\/50 { background-color: rgba(0, 0, 0, 0.05) !important; } +html.light .bg-slate-500\/20 { background-color: rgba(0, 0, 0, 0.06) !important; } +html.light .bg-slate-500\/30 { background-color: rgba(0, 0, 0, 0.06) !important; } +/* Fallback attribute selectors */ html.light [class*="bg-slate-800\\/"] { background-color: rgba(0, 0, 0, 0.04) !important; } html.light [class*="bg-slate-900\\/"] { background-color: rgba(0, 0, 0, 0.03) !important; } html.light [class*="bg-slate-700\\/"] { background-color: rgba(0, 0, 0, 0.05) !important; } html.light [class*="bg-slate-500\\/"] { background-color: rgba(0, 0, 0, 0.06) !important; } /* Slate borders */ -html.light .border-slate-700 { border-color: rgba(0, 0, 0, 0.10) !important; } +html.light .border-slate-700 { border-color: rgba(0, 0, 0, 0.12) !important; } html.light .border-slate-800 { border-color: rgba(0, 0, 0, 0.08) !important; } +html.light .border-slate-500\/30 { border-color: rgba(0, 0, 0, 0.12) !important; } +html.light .border-slate-500\/20 { border-color: rgba(0, 0, 0, 0.10) !important; } html.light [class*="border-slate-500\\/"] { border-color: rgba(0, 0, 0, 0.12) !important; } html.light [class*="border-slate-700\\/"] { border-color: rgba(0, 0, 0, 0.08) !important; } /* Zinc backgrounds */ +html.light .bg-zinc-700 { background-color: #D1D5DB !important; } html.light .bg-zinc-800 { background-color: #E5E7EB !important; } +html.light .bg-zinc-800\/80 { background-color: #E5E7EB !important; } html.light .bg-zinc-900 { background-color: #F3F4F6 !important; } html.light .bg-zinc-950 { background-color: #F9FAFB !important; } @@ -250,25 +267,38 @@ html.light .bg-white.text-zinc-950:hover { background-color: #2D2D44 !important; } -/* Ghost button */ -html.light [class*="bg-white\\/\\[0\\.06\\]"][class*="border"][class*="text-zinc-300"] { - background-color: rgba(0, 0, 0, 0.04); - border-color: rgba(0, 0, 0, 0.12); - color: #374151; +/* Ghost button + hover states for transparent white backgrounds */ +html.light .bg-white\/\[0\.06\] { + background-color: rgba(0, 0, 0, 0.05) !important; + border-color: rgba(0, 0, 0, 0.15) !important; } -html.light [class*="bg-white\\/\\[0\\.06\\]"][class*="border"][class*="text-zinc-300"]:hover { - background-color: rgba(0, 0, 0, 0.08); - color: #1A1A2E; +html.light .bg-white\/\[0\.1\] { + background-color: rgba(0, 0, 0, 0.08) !important; +} +html.light .bg-white\/\[0\.04\] { + background-color: rgba(0, 0, 0, 0.04) !important; +} +html.light .bg-white\/\[0\.03\] { + background-color: rgba(0, 0, 0, 0.03) !important; } /* GitHub star button */ -html.light a[class*="bg-white\\/5"][class*="border-white\\/10"] { - background-color: rgba(0, 0, 0, 0.03); - border-color: rgba(0, 0, 0, 0.10); - color: #374151; +html.light .bg-white\/5 { + background-color: rgba(0, 0, 0, 0.04) !important; +} +html.light .bg-white\/10 { + background-color: rgba(0, 0, 0, 0.06) !important; +} + +/* All select elements in light mode */ +html.light select { + background-color: #F3F4F6 !important; + color: #1E293B !important; + border-color: rgba(0, 0, 0, 0.12) !important; } -html.light a[class*="bg-white\\/5"][class*="border-white\\/10"]:hover { - background-color: rgba(0, 0, 0, 0.06); +html.light select option { + background-color: #FFFFFF; + color: #1A1A2E; } /* --- Version badge --- */ @@ -282,6 +312,39 @@ html.light .border-accent-indigo\\/30 { /* --- Hero background gradients: reduce on light mode --- */ html.light section > [aria-hidden="true"] { opacity: 0.15; } +/* --- Playground: override hardcoded arbitrary bg --- */ +html.light .bg-\[\#09090b\] { background-color: #FAFBFC !important; } +html.light .bg-\[\#0F172A\] { background-color: #FAFBFC !important; } + +/* Playground select element */ +html.light .bg-slate-800.text-slate-200 { + background-color: #F3F4F6 !important; + color: #1E293B !important; + border-color: rgba(0, 0, 0, 0.12) !important; +} + +/* Playground active tab */ +html.light .text-blue-400 { color: #2563EB !important; } +html.light .bg-blue-500 { background-color: #3B82F6 !important; } + +/* Playground emerald code */ +html.light code .text-emerald-400, +html.light code.text-emerald-400 { color: #059669 !important; } +html.light .bg-slate-800.rounded { background-color: #E5E7EB !important; } + +/* Playground divider */ +html.light .bg-slate-700 { background-color: #D1D5DB !important; } + +/* Playground copy/bottom bar hover */ +html.light .hover\:text-white:hover { color: #1A1A2E !important; } +html.light .hover\:border-slate-500:hover { border-color: rgba(0, 0, 0, 0.2) !important; } + +/* Loading skeleton in playground */ +html.light .animate-pulse.bg-zinc-800 { background-color: #E5E7EB !important; } + +/* Green dot (parser ready) — keep green */ +html.light .bg-green-500 { background-color: #22C55E !important; } + /* --- Code blocks / pre elements --- */ html.light pre[class*="font-mono"] { background-color: #1E1E2E; From 205a8c4a139a421f0c9b8a95809d1ba96df3d13b Mon Sep 17 00:00:00 2001 From: Ajit Pratap Singh Date: Wed, 15 Apr 2026 15:55:36 +0530 Subject: [PATCH 2/2] feat(website): migrate to Motion package and add comprehensive animations Replace framer-motion with the canonical motion package (same v12 codebase, cleaner imports from "motion/react"). Consolidate the dual animation system (FadeInCSS + FadeIn) into a single Motion-based FadeIn component with viewport-triggered scroll animations. Key changes: - Package migration: framer-motion -> motion (7 import files updated) - Shared animation infrastructure: motion-variants.ts with reusable variants - FadeIn component: now supports viewport prop for whileInView scroll triggers - ScrollProgressBar: gradient progress indicator at page top - Button: motion.button with spring hover/tap (scale 1.02/0.97) - GlassCard: hover lift (y: -2) + tap feedback (scale 0.99) - ThemeToggle: AnimatePresence icon swap with rotation - CopyButton: AnimatePresence scale-in icon transitions - SearchModal: AnimatePresence overlay fade + modal scale entrance - Benchmarks: animated chevron + AnimatePresence expand/collapse - Docs index: staggered category card entrance - 404 page: staggered entrance animation - All animations: GPU-accelerated (transform/opacity only) - All animations: respect prefers-reduced-motion - All animations: dark/light mode agnostic (pure transforms) Co-Authored-By: Claude Opus 4.6 (1M context) --- website/package-lock.json | 42 ++++++++-- website/package.json | 2 +- .../src/app/benchmarks/BenchmarksContent.tsx | 28 +++++-- website/src/app/blog/BlogList.tsx | 2 +- website/src/app/docs/page.tsx | 50 ++++++------ website/src/app/layout.tsx | 2 + website/src/app/not-found.tsx | 35 +++++--- website/src/components/docs/CopyButton.tsx | 48 +++++++---- website/src/components/home/CodeExamples.tsx | 12 +-- website/src/components/home/CtaBanner.tsx | 6 +- .../src/components/home/DialectShowcase.tsx | 10 +-- website/src/components/home/FeatureGrid.tsx | 10 +-- .../src/components/home/GitHubStarButton.tsx | 10 ++- website/src/components/home/Hero.tsx | 22 ++--- website/src/components/home/McpSection.tsx | 18 ++--- .../components/home/PerformanceSection.tsx | 14 ++-- website/src/components/home/SocialProof.tsx | 6 +- website/src/components/home/StatsBar.tsx | 6 +- website/src/components/home/TrustSection.tsx | 18 ++--- website/src/components/home/VscodeSection.tsx | 10 +-- website/src/components/layout/Navbar.tsx | 2 +- .../src/components/playground/Playground.tsx | 2 +- website/src/components/ui/AnimatedCounter.tsx | 2 +- website/src/components/ui/Button.tsx | 41 +++++++++- website/src/components/ui/FadeIn.tsx | 41 ++++++++-- website/src/components/ui/GlassCard.tsx | 10 ++- .../src/components/ui/ScrollProgressBar.tsx | 25 ++++++ website/src/components/ui/SearchModal.tsx | 26 ++++-- website/src/components/ui/ThemeToggle.tsx | 39 +++++++-- website/src/lib/motion-variants.ts | 80 +++++++++++++++++++ 30 files changed, 449 insertions(+), 170 deletions(-) create mode 100644 website/src/components/ui/ScrollProgressBar.tsx create mode 100644 website/src/lib/motion-variants.ts diff --git a/website/package-lock.json b/website/package-lock.json index 1bc97fb9..c8d5513d 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -18,9 +18,9 @@ "@vercel/analytics": "^2.0.1", "@vercel/speed-insights": "^2.0.0", "codemirror": "^6.0.2", - "framer-motion": "^12.36.0", "fuse.js": "^7.1.0", "gray-matter": "^4.0.3", + "motion": "^12.36.0", "next": "16.1.7", "next-mdx-remote": "^6.0.0", "react": "19.2.3", @@ -4417,12 +4417,12 @@ "license": "MIT" }, "node_modules/framer-motion": { - "version": "12.36.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.36.0.tgz", - "integrity": "sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==", + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz", + "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==", "license": "MIT", "dependencies": { - "motion-dom": "^12.36.0", + "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, @@ -6327,10 +6327,36 @@ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", "license": "MIT" }, + "node_modules/motion": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz", + "integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.38.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/motion-dom": { - "version": "12.36.0", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.36.0.tgz", - "integrity": "sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA==", + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", + "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==", "license": "MIT", "dependencies": { "motion-utils": "^12.36.0" diff --git a/website/package.json b/website/package.json index 697f875b..30c3d921 100644 --- a/website/package.json +++ b/website/package.json @@ -22,7 +22,7 @@ "@vercel/analytics": "^2.0.1", "@vercel/speed-insights": "^2.0.0", "codemirror": "^6.0.2", - "framer-motion": "^12.36.0", + "motion": "^12.36.0", "fuse.js": "^7.1.0", "gray-matter": "^4.0.3", "next": "16.1.7", diff --git a/website/src/app/benchmarks/BenchmarksContent.tsx b/website/src/app/benchmarks/BenchmarksContent.tsx index f847cfe6..80ac936a 100644 --- a/website/src/app/benchmarks/BenchmarksContent.tsx +++ b/website/src/app/benchmarks/BenchmarksContent.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState } from 'react'; +import { motion, AnimatePresence } from 'motion/react'; import { FadeIn } from '@/components/ui/FadeIn'; import { GlassCard } from '@/components/ui/GlassCard'; import { Button } from '@/components/ui/Button'; @@ -41,22 +42,33 @@ function RawDataToggle({ id, children }: { id: string; children: React.ReactNode aria-expanded={open} aria-controls={`raw-data-${id}`} > - - + {open ? 'Hide' : 'View'} raw data - {open && ( -
- {children} -
- )} + + {open && ( + + {children} + + )} + ); } diff --git a/website/src/app/blog/BlogList.tsx b/website/src/app/blog/BlogList.tsx index 181f1099..e7e23198 100644 --- a/website/src/app/blog/BlogList.tsx +++ b/website/src/app/blog/BlogList.tsx @@ -1,7 +1,7 @@ 'use client'; import Link from 'next/link'; -import { motion } from 'framer-motion'; +import { motion } from 'motion/react'; import type { BlogPost } from '@/lib/blog'; export function BlogList({ posts }: { posts: BlogPost[] }) { diff --git a/website/src/app/docs/page.tsx b/website/src/app/docs/page.tsx index c124627e..0aaf9ad6 100644 --- a/website/src/app/docs/page.tsx +++ b/website/src/app/docs/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from 'next'; import Link from 'next/link'; import { DOCS_SIDEBAR } from '@/lib/constants'; import { DocsSearchTrigger } from '@/components/docs/DocsSearchTrigger'; +import { FadeIn } from '@/components/ui/FadeIn'; export const metadata: Metadata = { title: 'Documentation', @@ -43,30 +44,31 @@ export default function DocsPage() {
- {DOCS_SIDEBAR.map((group) => ( - -
- - - -
-

{group.category}

-

- {group.items.length} {group.items.length === 1 ? 'article' : 'articles'} -

-
    - {group.items.slice(0, 3).map((item) => ( -
  • {item.label}
  • - ))} - {group.items.length > 3 && ( -
  • +{group.items.length - 3} more
  • - )} -
- + {DOCS_SIDEBAR.map((group, i) => ( + + +
+ + + +
+

{group.category}

+

+ {group.items.length} {group.items.length === 1 ? 'article' : 'articles'} +

+
    + {group.items.slice(0, 3).map((item) => ( +
  • {item.label}
  • + ))} + {group.items.length > 3 && ( +
  • +{group.items.length - 3} more
  • + )} +
+ +
))}
diff --git a/website/src/app/layout.tsx b/website/src/app/layout.tsx index c2597a7e..03ac377d 100644 --- a/website/src/app/layout.tsx +++ b/website/src/app/layout.tsx @@ -3,6 +3,7 @@ import { spaceGrotesk, inter, jetbrainsMono } from '@/lib/fonts'; import { Navbar } from '@/components/layout/Navbar'; import { Footer } from '@/components/layout/Footer'; import { ServiceWorkerRegister } from '@/components/ServiceWorkerRegister'; +import { ScrollProgressBar } from '@/components/ui/ScrollProgressBar'; import { Analytics } from '@vercel/analytics/next'; import { SpeedInsights } from '@vercel/speed-insights/next'; import './globals.css'; @@ -96,6 +97,7 @@ export default function RootLayout({ }), }} /> +
{children}