diff --git a/frontend/src/pages/LandingPage.tsx b/frontend/src/pages/LandingPage.tsx index 9bd0c90..4aa44d6 100644 --- a/frontend/src/pages/LandingPage.tsx +++ b/frontend/src/pages/LandingPage.tsx @@ -9,9 +9,9 @@ import { API_URL } from '../config/api' import { HeroPlayground } from '@/components/playground' import { playgroundAPI } from '@/services/playground-api' import type { SearchResult } from '../types' +import { cn } from '@/lib/utils' -// Icons (only GitHubIcon and SparklesIcon are used in this file) - +// Icons const GitHubIcon = () => ( @@ -24,6 +24,18 @@ const SparklesIcon = () => ( ) +const SearchIcon = () => ( + + + +) + +const ArrowLeftIcon = () => ( + + + +) + // Scroll animation hook function useScrollAnimation() { const ref = useRef(null) @@ -65,9 +77,111 @@ function AnimatedSection({ children, className = '' }: { children: React.ReactNo ) } +// ============ COMPACT SEARCH BAR (for results view) ============ +function CompactSearchBar({ + query, + onQueryChange, + onSearch, + onNewSearch, + loading, + remaining +}: { + query: string + onQueryChange: (q: string) => void + onSearch: () => void + onNewSearch: () => void + loading: boolean + remaining: number +}) { + return ( +
+
+
+ {/* Back button */} + + + {/* Search input */} +
{ e.preventDefault(); onSearch(); }} className="flex-1 flex items-center gap-3"> +
+
+ +
+ onQueryChange(e.target.value)} + placeholder="Search again..." + className="w-full bg-zinc-900/80 border border-zinc-800 rounded-xl pl-12 pr-4 py-3 text-white placeholder:text-zinc-500 focus:outline-none focus:border-zinc-700 transition-colors" + /> +
+ +
+
+
+
+ ) +} + +// ============ RESULT CARD with staggered animation ============ +function ResultCard({ result, index }: { result: SearchResult; index: number }) { + return ( + +
+
+
+

{result.name}

+ + {result.type.replace('_', ' ')} + +
+

+ {result.file_path.split('/').slice(-2).join('/')} +

+
+
+
{(result.score * 100).toFixed(0)}%
+
match
+
+
+ + {result.code} + +
+ ) +} + export function LandingPage() { const navigate = useNavigate() - const resultsRef = useRef(null) const [results, setResults] = useState([]) const [loading, setLoading] = useState(false) const [searchTime, setSearchTime] = useState(null) @@ -77,15 +191,10 @@ export function LandingPage() { const [availableRepos, setAvailableRepos] = useState([]) const [rateLimitError, setRateLimitError] = useState(null) const [lastQuery, setLastQuery] = useState('') + const [currentRepoId, setCurrentRepoId] = useState('') + const [isCustomRepo, setIsCustomRepo] = useState(false) - // Scroll to results when they appear - const scrollToResults = () => { - setTimeout(() => { - resultsRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }) - }, 100) - } - - // Reset to search state + // Reset to hero state const handleNewSearch = () => { setHasSearched(false) setResults([]) @@ -122,6 +231,8 @@ export function LandingPage() { setLoading(true) setHasSearched(true) setLastQuery(query) + setCurrentRepoId(repoId) + setIsCustomRepo(isCustom) setRateLimitError(null) const startTime = Date.now() @@ -143,8 +254,6 @@ export function LandingPage() { if (typeof data.remaining_searches === 'number') { setRemaining(data.remaining_searches) } - // Scroll to results after they load - scrollToResults() } else if (data.status === 429) { setRateLimitError('Daily limit reached. Sign up for unlimited searches!') setRemaining(0) @@ -156,6 +265,13 @@ export function LandingPage() { } } + // Re-search with updated query (from compact search bar) + const handleReSearch = () => { + if (lastQuery.trim() && currentRepoId) { + handleSearch(lastQuery, currentRepoId, isCustomRepo) + } + } + return (
{/* Navigation */} @@ -185,131 +301,130 @@ export function LandingPage() {
- {/* ============ HERO SECTION ============ */} -
-
-
- - AI-powered code search -
- -

- grep returned - 847 results. -
- - Find the one that matters. - -

- -

- Search any codebase by meaning, not keywords. Index your own repo in seconds. -

- - {/* HeroPlayground - handles demo repos + custom repo indexing */} - + {/* Compact Search Bar - sticky below nav */} + -
-
- - {/* ============ RESULTS SECTION (if searched) ============ */} - {hasSearched && ( -
-
- {/* Results Header */} -
-
- - | - - {results.length} results for "{lastQuery}" - - {searchTime && ( - - {searchTime > 1000 ? `${(searchTime/1000).toFixed(1)}s` : `${searchTime}ms`} + + {/* Results Content - immediately visible */} +
+
+ {/* Results Header - contextual based on loading state */} +
+ {loading ? ( + + Searching for "{lastQuery}"... + ) : ( +
+ + {results.length} results for "{lastQuery}" + + {searchTime && ( + + {searchTime > 1000 ? `${(searchTime/1000).toFixed(1)}s` : `${searchTime}ms`} + + )} +
+ )} + {!loading && remaining > 0 && remaining < limit && ( +
{remaining} remaining
)}
- {remaining > 0 && remaining < limit && ( -
{remaining} remaining
- )} -
- {/* Loading State */} - {loading && ( -
-
-
+ {/* Loading State */} + {loading && ( +
+
+
+
+

Searching codebase...

+

This may take a few seconds for first search

-

Searching codebase...

-

This may take a few seconds for first search

-
- )} - - {/* Results Content (only when not loading) */} - {!loading && ( - <> - {(remaining <= 0 || rateLimitError) && ( - -

You've reached today's limit

-

- {rateLimitError || 'Sign up to get unlimited searches and index your own repos.'} -

- -
- )} + )} -
- {results.map((result, idx) => ( - -
-
-
-

{result.name}

- {result.type.replace('_', ' ')} -
-

{result.file_path.split('/').slice(-2).join('/')}

-
-
-
{(result.score * 100).toFixed(0)}%
-
match
-
-
- - {result.code} - + {/* Results List */} + {!loading && ( + <> + {(remaining <= 0 || rateLimitError) && ( + +

You've reached today's limit

+

+ {rateLimitError || 'Sign up to get unlimited searches and index your own repos.'} +

+
- ))} -
+ )} - {results.length === 0 && ( -
-
🔍
-

No results found

-

Try a different query

+
+ {results.map((result, idx) => ( + + ))}
- )} - - )} -
-
- )} - {/* ============ STORY SECTIONS (only before search) ============ */} - {!hasSearched && ( + {results.length === 0 && ( +
+
🔍
+

No results found

+

Try a different query

+ +
+ )} + + )} +
+
+ + ) : ( + /* ============ HERO VIEW (full landing page experience) ============ */ <> + {/* Hero Section */} +
+
+
+ + AI-powered code search +
+ +

+ grep returned + 847 results. +
+ + Find the one that matters. + +

+ +

+ Search any codebase by meaning, not keywords. Index your own repo in seconds. +

+ + {/* HeroPlayground - handles demo repos + custom repo indexing */} + +
+
+ {/* THE PROBLEM */}