Skip to content

Commit b989c58

Browse files
committed
feat(dashboard): Phase 1 - Theme foundation with light/dark mode support
- DashboardLayout: Added theme-aware Toaster, sidebar state persistence - Sidebar: Migrated to theme tokens, lucide-react icons - TopNav: Theme toggle button, shadcn Button, proper theme tokens - DashboardStats: Theme tokens for stat cards with indigo accent - DashboardHome: Full theme migration, lucide-react icons - RepoList: Theme tokens, lucide-react icons for repo cards - AddRepoForm: Migrated to shadcn Input, Label, Button components All hardcoded colors (bg-[#09090b], text-gray-400, border-white/5) replaced with theme tokens (bg-background, text-muted-foreground, border-border)
1 parent 09bb12d commit b989c58

7 files changed

Lines changed: 253 additions & 252 deletions

File tree

frontend/src/components/AddRepoForm.tsx

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { useState } from 'react'
22
import { motion, AnimatePresence } from 'framer-motion'
3-
import { Package, Plus, X } from 'lucide-react'
3+
import { Package, Plus, X, Loader2 } from 'lucide-react'
4+
import { Button } from '@/components/ui/button'
5+
import { Input } from '@/components/ui/input'
6+
import { Label } from '@/components/ui/label'
47

58
interface AddRepoFormProps {
69
onAdd: (gitUrl: string, branch: string) => Promise<void>
@@ -23,47 +26,45 @@ export function AddRepoForm({ onAdd, loading }: AddRepoFormProps) {
2326

2427
return (
2528
<>
26-
<motion.button
27-
whileHover={{ scale: 1.02 }}
28-
whileTap={{ scale: 0.98 }}
29+
<Button
2930
onClick={() => setShowForm(true)}
30-
className="px-5 py-2.5 bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white text-sm font-medium rounded-xl transition-all shadow-lg shadow-blue-500/20 flex items-center gap-2"
3131
disabled={loading}
32+
className="bg-primary hover:bg-primary/90 text-primary-foreground gap-2"
3233
>
33-
<span className="text-lg">+</span>
34-
<span>Add Repository</span>
35-
</motion.button>
34+
<Plus className="w-4 h-4" />
35+
Add Repository
36+
</Button>
3637

3738
<AnimatePresence>
3839
{showForm && (
3940
<motion.div
4041
initial={{ opacity: 0 }}
4142
animate={{ opacity: 1 }}
4243
exit={{ opacity: 0 }}
43-
className="fixed inset-0 bg-black/70 backdrop-blur-md flex items-center justify-center z-50"
44+
className="fixed inset-0 bg-background/80 backdrop-blur-md flex items-center justify-center z-50"
4445
onClick={() => !loading && setShowForm(false)}
4546
>
4647
<motion.div
4748
initial={{ opacity: 0, scale: 0.95, y: 20 }}
4849
animate={{ opacity: 1, scale: 1, y: 0 }}
4950
exit={{ opacity: 0, scale: 0.95, y: 20 }}
5051
onClick={e => e.stopPropagation()}
51-
className="bg-gradient-to-br from-[#111113] to-[#0a0a0c] border border-white/10 rounded-2xl shadow-2xl w-full max-w-md mx-4"
52+
className="bg-card border border-border rounded-xl shadow-2xl w-full max-w-md mx-4"
5253
>
5354
{/* Header */}
54-
<div className="flex items-center justify-between p-6 border-b border-white/5">
55+
<div className="flex items-center justify-between p-6 border-b border-border">
5556
<div className="flex items-center gap-3">
56-
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500/20 to-purple-500/20 flex items-center justify-center">
57-
<Package className="w-5 h-5 text-blue-400" />
57+
<div className="w-10 h-10 rounded-xl bg-primary/10 border border-primary/20 flex items-center justify-center">
58+
<Package className="w-5 h-5 text-primary" />
5859
</div>
5960
<div>
60-
<h3 className="text-lg font-semibold text-white">Add Repository</h3>
61-
<p className="text-sm text-gray-500">Clone and index with AI</p>
61+
<h3 className="text-lg font-semibold text-foreground">Add Repository</h3>
62+
<p className="text-sm text-muted-foreground">Clone and index with AI</p>
6263
</div>
6364
</div>
6465
<button
6566
onClick={() => setShowForm(false)}
66-
className="w-8 h-8 flex items-center justify-center rounded-lg text-gray-400 hover:text-white hover:bg-white/10 transition-colors"
67+
className="w-8 h-8 flex items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
6768
disabled={loading}
6869
>
6970
<X className="w-4 h-4" />
@@ -72,63 +73,62 @@ export function AddRepoForm({ onAdd, loading }: AddRepoFormProps) {
7273

7374
{/* Form */}
7475
<form onSubmit={handleSubmit} className="p-6 space-y-5">
75-
<div>
76-
<label className="block text-sm font-medium mb-2 text-gray-300">Git URL</label>
77-
<input
76+
<div className="space-y-2">
77+
<Label htmlFor="gitUrl">Git URL</Label>
78+
<Input
79+
id="gitUrl"
7880
type="url"
7981
value={gitUrl}
8082
onChange={(e) => setGitUrl(e.target.value)}
8183
placeholder="https://github.com/username/repo"
82-
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder:text-gray-500 focus:outline-none focus:border-blue-500/50 focus:ring-2 focus:ring-blue-500/20 transition-all"
8384
required
8485
disabled={loading}
8586
autoFocus
8687
/>
8788
</div>
8889

89-
<div>
90-
<label className="block text-sm font-medium mb-2 text-gray-300">Branch</label>
91-
<input
90+
<div className="space-y-2">
91+
<Label htmlFor="branch">Branch</Label>
92+
<Input
93+
id="branch"
9294
type="text"
9395
value={branch}
9496
onChange={(e) => setBranch(e.target.value)}
9597
placeholder="main"
96-
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder:text-gray-500 focus:outline-none focus:border-blue-500/50 focus:ring-2 focus:ring-blue-500/20 transition-all"
9798
required
9899
disabled={loading}
99100
/>
100-
<p className="mt-2 text-xs text-gray-500">Repository will be cloned and automatically indexed</p>
101+
<p className="text-xs text-muted-foreground">Repository will be cloned and automatically indexed</p>
101102
</div>
102103

103104
{/* Actions */}
104105
<div className="flex gap-3 pt-2">
105-
<button
106+
<Button
106107
type="button"
108+
variant="outline"
107109
onClick={() => { setShowForm(false); setGitUrl(''); setBranch('main') }}
108-
className="flex-1 px-4 py-3 bg-white/5 border border-white/10 text-gray-300 font-medium rounded-xl hover:bg-white/10 transition-colors disabled:opacity-50"
109110
disabled={loading}
111+
className="flex-1"
110112
>
111113
Cancel
112-
</button>
113-
<motion.button
114-
whileHover={{ scale: 1.02 }}
115-
whileTap={{ scale: 0.98 }}
114+
</Button>
115+
<Button
116116
type="submit"
117-
className="flex-1 px-4 py-3 bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white font-medium rounded-xl transition-all disabled:opacity-50 flex items-center justify-center gap-2 shadow-lg shadow-blue-500/20"
118117
disabled={loading}
118+
className="flex-1 bg-primary hover:bg-primary/90 text-primary-foreground"
119119
>
120120
{loading ? (
121121
<>
122-
<div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
123-
<span>Adding...</span>
122+
<Loader2 className="w-4 h-4 animate-spin" />
123+
Adding...
124124
</>
125125
) : (
126126
<>
127127
<Plus className="w-4 h-4" />
128-
<span>Add & Index</span>
128+
Add & Index
129129
</>
130130
)}
131-
</motion.button>
131+
</Button>
132132
</div>
133133
</form>
134134
</motion.div>

frontend/src/components/RepoList.tsx

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState, useRef, useMemo } from 'react'
22
import { motion } from 'framer-motion'
3+
import { FolderGit2, Plus } from 'lucide-react'
34
import type { Repository } from '../types'
45
import { RepoGridSkeleton } from './ui/Skeleton'
56

@@ -16,11 +17,11 @@ const StatusBadge = ({ status }: { status: string }) => {
1617
return (
1718
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-full border
1819
${isIndexed
19-
? 'bg-blue-500/10 text-blue-400 border-blue-500/20'
20-
: 'bg-zinc-800 text-zinc-400 border-zinc-700'
20+
? 'bg-primary/10 text-primary border-primary/20'
21+
: 'bg-muted text-muted-foreground border-border'
2122
}`}
2223
>
23-
<span className={`w-1.5 h-1.5 rounded-full ${isIndexed ? 'bg-blue-400' : 'bg-zinc-500 animate-pulse'}`} />
24+
<span className={`w-1.5 h-1.5 rounded-full ${isIndexed ? 'bg-primary' : 'bg-muted-foreground animate-pulse'}`} />
2425
{isIndexed ? 'Indexed' : 'Pending'}
2526
</span>
2627
)
@@ -50,42 +51,40 @@ const RepoCard = ({ repo, index, onSelect }: {
5051
}}
5152
onMouseEnter={() => setHovering(true)}
5253
onMouseLeave={() => setHovering(false)}
53-
className="group relative text-left rounded-2xl overflow-hidden w-full
54-
bg-[#111113] border border-white/[0.06] hover:border-blue-500/40
55-
focus:outline-none focus:ring-2 focus:ring-blue-500/50 p-5 transition-colors"
54+
className="group relative text-left rounded-xl overflow-hidden w-full
55+
bg-card border border-border hover:border-primary/40
56+
focus:outline-none focus:ring-2 focus:ring-primary/50 p-5 transition-colors"
5657
>
57-
{/* Mouse glow */}
58+
{/* Mouse glow effect */}
5859
{hovering && (
5960
<div
6061
className="pointer-events-none absolute inset-0"
6162
style={{
62-
background: `radial-gradient(300px circle at ${mousePos.x}px ${mousePos.y}px, rgba(37, 99, 235, 0.08), transparent 50%)`,
63+
background: `radial-gradient(300px circle at ${mousePos.x}px ${mousePos.y}px, hsl(var(--primary) / 0.08), transparent 50%)`,
6364
}}
6465
/>
6566
)}
6667

6768
<div className="relative">
6869
{/* Header */}
6970
<div className="flex items-start justify-between mb-4">
70-
<div className="w-11 h-11 rounded-xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center group-hover:bg-blue-500/15 transition-colors">
71-
<svg className="w-5 h-5 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
72-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
73-
</svg>
71+
<div className="w-11 h-11 rounded-xl bg-primary/10 border border-primary/20 flex items-center justify-center group-hover:bg-primary/15 transition-colors">
72+
<FolderGit2 className="w-5 h-5 text-primary" />
7473
</div>
7574
<StatusBadge status={repo.status} />
7675
</div>
7776

7877
{/* Title */}
79-
<h3 className="text-lg font-semibold text-white mb-0.5 group-hover:text-blue-400 transition-colors">
78+
<h3 className="text-lg font-semibold text-foreground mb-0.5 group-hover:text-primary transition-colors">
8079
{repo.name}
8180
</h3>
82-
<p className="text-xs text-zinc-500 font-mono mb-5">{repo.branch}</p>
81+
<p className="text-xs text-muted-foreground font-mono mb-5">{repo.branch}</p>
8382

8483
{/* Stats */}
85-
<div className="pt-4 border-t border-white/[0.06]">
84+
<div className="pt-4 border-t border-border">
8685
<div className="flex items-center justify-between">
87-
<span className="text-sm text-zinc-500">Functions</span>
88-
<span className="text-2xl font-bold text-blue-500">
86+
<span className="text-sm text-muted-foreground">Functions</span>
87+
<span className="text-2xl font-bold text-primary">
8988
{(repo.file_count || 0).toLocaleString()}
9089
</span>
9190
</div>
@@ -103,22 +102,19 @@ export function RepoList({ repos, selectedRepo, onSelect, loading }: RepoListPro
103102
<motion.div
104103
initial={{ opacity: 0 }}
105104
animate={{ opacity: 1 }}
106-
className="bg-[#111113] border border-white/[0.06] rounded-2xl p-16 text-center"
105+
className="bg-card border border-border rounded-xl p-16 text-center"
107106
>
108-
<div className="w-14 h-14 mx-auto mb-4 rounded-xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center">
109-
<svg className="w-6 h-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
110-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 4v16m8-8H4" />
111-
</svg>
107+
<div className="w-14 h-14 mx-auto mb-4 rounded-xl bg-primary/10 border border-primary/20 flex items-center justify-center">
108+
<Plus className="w-6 h-6 text-primary" />
112109
</div>
113-
<h3 className="text-lg font-semibold mb-2 text-white">No repositories yet</h3>
114-
<p className="text-sm text-zinc-500 max-w-xs mx-auto">
110+
<h3 className="text-lg font-semibold mb-2 text-foreground">No repositories yet</h3>
111+
<p className="text-sm text-muted-foreground max-w-xs mx-auto">
115112
Add your first repository to start searching code with AI
116113
</p>
117114
</motion.div>
118115
)
119116
}
120117

121-
// Sort: indexed first, then by function count desc
122118
const sortedRepos = useMemo(() => {
123119
return [...repos].sort((a, b) => {
124120
if (a.status === 'indexed' && b.status !== 'indexed') return -1

frontend/src/components/dashboard/DashboardHome.tsx

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import { useState, useEffect } from 'react'
22
import { motion, AnimatePresence } from 'framer-motion'
33
import { toast } from 'sonner'
4-
import { LayoutDashboard, Search, GitFork, Code2, Zap } from 'lucide-react'
4+
import {
5+
LayoutDashboard,
6+
Search,
7+
GitFork,
8+
Code2,
9+
Zap,
10+
ArrowLeft,
11+
FolderGit2,
12+
ExternalLink
13+
} from 'lucide-react'
514
import { useAuth } from '../../contexts/AuthContext'
615
import { RepoList } from '../RepoList'
716
import { AddRepoForm } from '../AddRepoForm'
@@ -122,8 +131,8 @@ export function DashboardHome() {
122131
{/* Header */}
123132
<div className="flex items-start justify-between">
124133
<div>
125-
<h1 className="text-3xl font-bold text-white mb-1">Repositories</h1>
126-
<p className="text-gray-400">
134+
<h1 className="text-3xl font-bold text-foreground mb-1">Repositories</h1>
135+
<p className="text-muted-foreground">
127136
Semantic code search powered by AI
128137
</p>
129138
</div>
@@ -158,44 +167,43 @@ export function DashboardHome() {
158167
<div className="mb-6">
159168
<button
160169
onClick={() => { setSelectedRepo(null); setActiveTab('overview') }}
161-
className="group flex items-center gap-2 text-sm text-gray-400 hover:text-white transition-colors mb-4"
170+
className="group flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors mb-4"
162171
>
163-
<span className="group-hover:-translate-x-1 transition-transform"></span>
172+
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
164173
<span>Back to Repositories</span>
165174
</button>
166175

167176
<div className="flex items-start justify-between">
168177
<div className="flex items-center gap-4">
169-
<div className="w-14 h-14 rounded-xl bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-white/10 flex items-center justify-center">
170-
<svg className="w-7 h-7 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
171-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
172-
</svg>
178+
<div className="w-14 h-14 rounded-xl bg-primary/10 border border-primary/20 flex items-center justify-center">
179+
<FolderGit2 className="w-7 h-7 text-primary" />
173180
</div>
174181
<div>
175-
<h1 className="text-2xl font-bold text-white">{selectedRepoData.name}</h1>
182+
<h1 className="text-2xl font-bold text-foreground">{selectedRepoData.name}</h1>
176183
<a
177184
href={selectedRepoData.git_url?.replace('.git', '')}
178185
target="_blank"
179186
rel="noopener noreferrer"
180-
className="text-sm text-gray-400 hover:text-blue-400 transition-colors font-mono"
187+
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-primary transition-colors font-mono"
181188
>
182189
{selectedRepoData.git_url}
190+
<ExternalLink className="w-3 h-3" />
183191
</a>
184192
</div>
185193
</div>
186194
</div>
187195
</div>
188196

189197
{/* Tabs */}
190-
<div className="flex gap-1 mb-6 p-1.5 bg-white/5 rounded-xl w-fit border border-white/5">
198+
<div className="flex gap-1 mb-6 p-1.5 bg-muted rounded-xl w-fit border border-border">
191199
{tabs.map(tab => (
192200
<button
193201
key={tab.id}
194202
onClick={() => setActiveTab(tab.id)}
195203
className={`px-4 py-2 text-sm font-medium rounded-lg transition-all flex items-center gap-2 ${
196204
activeTab === tab.id
197-
? 'bg-blue-500/20 text-blue-400 shadow-lg shadow-blue-500/10'
198-
: 'text-gray-400 hover:text-white hover:bg-white/5'
205+
? 'bg-primary/20 text-primary shadow-lg'
206+
: 'text-muted-foreground hover:text-foreground hover:bg-background'
199207
}`}
200208
>
201209
<tab.icon className="w-4 h-4" />
@@ -205,7 +213,7 @@ export function DashboardHome() {
205213
</div>
206214

207215
{/* Tab Content */}
208-
<div className="bg-gradient-to-br from-[#111113] to-[#0a0a0c] border border-white/5 rounded-2xl overflow-hidden">
216+
<div className="bg-card border border-border rounded-xl overflow-hidden">
209217
{activeTab === 'overview' && (
210218
<RepoOverview
211219
repo={selectedRepoData}

0 commit comments

Comments
 (0)