Skip to content

Commit a96d5a1

Browse files
committed
feat(repo-tracker): apply UI & theme changes for Repo Tracker section
1 parent 13e94f8 commit a96d5a1

3 files changed

Lines changed: 236 additions & 55 deletions

File tree

src/components/RepositoryAnalyticsDashboard.tsx

Lines changed: 128 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ interface DashboardProps {
5757
theme: Theme;
5858
}
5959

60-
const COLORS = ['#2563eb', '#06b6d4', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6'];
60+
// Use CSS variables so the tracker section follows the website theme
61+
const COLORS = [
62+
'var(--color-primary)',
63+
'var(--color-accent)',
64+
'var(--color-success)',
65+
'var(--color-danger)',
66+
'var(--color-accent)',
67+
'var(--color-primary)'
68+
];
6169

6270
const formatMonthLabel = (date: Date) =>
6371
date.toLocaleDateString(undefined, { month: 'short', year: 'numeric' });
@@ -182,36 +190,30 @@ const RepositoryAnalyticsDashboard = ({
182190
label: 'Total repositories',
183191
value: analytics.repoCount,
184192
icon: Database,
185-
accentStart: '#2563eb',
186-
accentEnd: '#06b6d4',
193+
accentStart: 'var(--color-primary)',
194+
accentEnd: 'var(--color-accent)',
187195
},
188196
{
189197
label: 'Total stars',
190198
value: analytics.totalStars,
191199
icon: Star,
192-
accentStart: '#f59e0b',
193-
accentEnd: '#f97316',
194-
},
195-
{
196-
label: 'Total forks',
197-
value: analytics.totalForks,
198-
icon: GitFork,
199-
accentStart: '#10b981',
200-
accentEnd: '#14b8a6',
200+
accentStart: 'var(--color-danger)',
201+
accentEnd: 'var(--color-danger)',
201202
},
203+
// forks card intentionally removed to keep the summary concise and horizontal
202204
{
203205
label: 'Most used language',
204206
value: analytics.mostUsedLanguage,
205207
icon: Languages,
206-
accentStart: '#8b5cf6',
207-
accentEnd: '#d946ef',
208+
accentStart: 'var(--color-accent)',
209+
accentEnd: 'var(--color-accent)',
208210
},
209211
{
210212
label: 'Total contributions',
211213
value: totalContributions,
212214
icon: Activity,
213-
accentStart: '#0ea5e9',
214-
accentEnd: '#6366f1',
215+
accentStart: 'var(--color-primary)',
216+
accentEnd: 'var(--color-accent)',
215217
},
216218
];
217219

@@ -264,7 +266,7 @@ const RepositoryAnalyticsDashboard = ({
264266
p: { xs: 3, md: 4 },
265267
borderRadius: 6,
266268
color: 'white',
267-
background: 'linear-gradient(135deg, rgba(15,23,42,0.98), rgba(29,78,216,0.92) 45%, rgba(8,145,178,0.9))',
269+
background: 'linear-gradient(135deg, var(--color-primary), var(--color-accent))',
268270
boxShadow: '0 24px 80px rgba(15,23,42,0.24)',
269271
border: '1px solid rgba(255,255,255,0.12)',
270272
position: 'relative',
@@ -293,7 +295,15 @@ const RepositoryAnalyticsDashboard = ({
293295

294296
<Box sx={{ display: 'grid', gap: 2.5, gridTemplateColumns: { xs: '1fr', md: 'minmax(0, 1.4fr) minmax(0, 0.9fr)' }, alignItems: 'end' }}>
295297
<Box>
296-
<Typography variant="h4" sx={{ fontWeight: 900, lineHeight: 1.05, maxWidth: 720 }}>
298+
<Typography
299+
variant="h4"
300+
sx={{
301+
fontWeight: 900,
302+
lineHeight: 1.05,
303+
maxWidth: 720,
304+
fontSize: { xs: '1.4rem', md: '1.8rem' }, // slightly reduced on small and medium screens
305+
}}
306+
>
297307
Track stars, forks, languages, and contribution momentum in one place.
298308
</Typography>
299309
<Typography sx={{ mt: 1.5, maxWidth: 760, color: 'rgba(255,255,255,0.8)' }}>
@@ -350,13 +360,11 @@ const RepositoryAnalyticsDashboard = ({
350360

351361
<Box
352362
sx={{
353-
display: 'grid',
363+
display: 'flex',
354364
gap: 2,
355-
gridTemplateColumns: {
356-
xs: '1fr',
357-
sm: 'repeat(2, minmax(0, 1fr))',
358-
xl: 'repeat(5, minmax(0, 1fr))',
359-
},
365+
flexDirection: { xs: 'column', md: 'row' },
366+
alignItems: 'stretch',
367+
justifyContent: 'space-between',
360368
mb: 3,
361369
}}
362370
>
@@ -370,7 +378,8 @@ const RepositoryAnalyticsDashboard = ({
370378
sx={{
371379
p: 2.5,
372380
borderRadius: 4,
373-
height: '100%',
381+
minWidth: { md: '18%' },
382+
flex: { xs: '1 1 auto', md: '1 1 0' },
374383
position: 'relative',
375384
overflow: 'hidden',
376385
background: theme.palette.background.paper,
@@ -387,14 +396,36 @@ const RepositoryAnalyticsDashboard = ({
387396
},
388397
}}
389398
>
390-
<Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 2, pl: 1 }}>
399+
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, pl: 1 }}>
391400
<Box>
392-
<Typography variant="caption" sx={{ letterSpacing: '0.18em', textTransform: 'uppercase', color: 'text.secondary' }}>
401+
<Typography sx={{ letterSpacing: '0.18em', textTransform: 'uppercase', color: 'text.secondary', fontSize: { xs: '0.65rem', md: '0.75rem' } }}>
393402
{card.label}
394403
</Typography>
395-
<Typography variant="h4" sx={{ mt: 1, fontWeight: 900, lineHeight: 1 }}>
396-
{card.value}
397-
</Typography>
404+
{
405+
(() => {
406+
const isLanguage = card.label && card.label.toLowerCase().includes('language');
407+
const valueFont = isLanguage
408+
? { xs: '1rem', md: 'clamp(1.1rem, 2.2vw, 1.6rem)' }
409+
: { xs: '1.6rem', md: '2.25rem' };
410+
return (
411+
<Typography
412+
title={isLanguage ? String(card.value) : undefined}
413+
sx={{
414+
mt: 1,
415+
fontWeight: 900,
416+
lineHeight: 1,
417+
fontSize: valueFont,
418+
whiteSpace: 'nowrap',
419+
overflow: 'visible',
420+
textOverflow: 'clip',
421+
maxWidth: '100%',
422+
}}
423+
>
424+
{card.value}
425+
</Typography>
426+
);
427+
})()
428+
}
398429
</Box>
399430
<Box
400431
sx={{
@@ -427,19 +458,19 @@ const RepositoryAnalyticsDashboard = ({
427458
background:
428459
theme.palette.mode === 'dark'
429460
? 'linear-gradient(180deg, rgba(15,23,42,0.78), rgba(15,23,42,0.96))'
430-
: 'linear-gradient(180deg, #ffffff, #f8fbff)',
461+
: 'linear-gradient(180deg, var(--color-surface), rgba(248,250,252,1))',
431462
border: `1px solid ${theme.palette.divider}`,
432463
boxShadow: '0 18px 40px rgba(15,23,42,0.06)',
433464
position: 'relative',
434465
overflow: 'hidden',
435-
'&::after': {
466+
'&::after': {
436467
content: '""',
437468
position: 'absolute',
438469
left: 0,
439470
top: 0,
440471
right: 0,
441472
height: 5,
442-
background: 'linear-gradient(90deg, #2563eb, #06b6d4, #10b981)',
473+
background: 'linear-gradient(90deg, var(--color-primary), var(--color-accent), var(--color-success))',
443474
},
444475
}}
445476
>
@@ -465,9 +496,9 @@ const RepositoryAnalyticsDashboard = ({
465496
<YAxis stroke={theme.palette.text.secondary} width={30} />
466497
<Tooltip contentStyle={{ backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, borderRadius: 16, border: `1px solid ${theme.palette.divider}` }} />
467498
<Legend />
468-
<Area type="monotone" dataKey="repositories" stroke="#2563eb" fill="#2563eb" fillOpacity={0.18} />
469-
<Line type="monotone" dataKey="stars" stroke="#f59e0b" strokeWidth={3} dot={false} />
470-
<Line type="monotone" dataKey="forks" stroke="#10b981" strokeWidth={3} dot={false} />
499+
<Area type="monotone" dataKey="repositories" stroke="var(--color-primary)" fill="var(--color-primary)" fillOpacity={0.18} />
500+
<Line type="monotone" dataKey="stars" stroke="var(--color-danger)" strokeWidth={3} dot={false} />
501+
<Line type="monotone" dataKey="forks" stroke="var(--color-success)" strokeWidth={3} dot={false} />
471502
</ComposedChart>
472503
</ResponsiveContainer>
473504
) : (
@@ -500,28 +531,67 @@ const RepositoryAnalyticsDashboard = ({
500531
</Box>
501532

502533
{analytics.languageDistribution.length > 0 ? (
503-
<ResponsiveContainer width="100%" height="82%">
534+
<>
535+
<ResponsiveContainer width="100%" height={"70%"}>
504536
<PieChart>
537+
{/* compute language total for legend percentages */}
538+
{/* Pie: remove in-chart labels; use bottom legend instead */}
505539
<Pie
506540
data={analytics.languageDistribution}
507541
dataKey="value"
508542
nameKey="name"
509543
cx="50%"
510-
cy="50%"
511-
outerRadius={120}
512-
innerRadius={68}
513-
paddingAngle={5}
544+
cy="42%"
545+
outerRadius={110}
546+
innerRadius={64}
547+
paddingAngle={6}
514548
labelLine={false}
515-
label={({ name, percent }) => `${name} ${percent && percent > 0.1 ? `${Math.round(percent * 100)}%` : ''}`}
549+
label={false}
516550
>
517551
{analytics.languageDistribution.map((entry, index) => (
518552
<Cell key={`${entry.name}-${index}`} fill={COLORS[index % COLORS.length]} />
519553
))}
520554
</Pie>
521555
<Tooltip contentStyle={{ backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, borderRadius: 16, border: `1px solid ${theme.palette.divider}` }} />
522-
<Legend verticalAlign="bottom" />
556+
{/* Legend rendered below the chart (custom) */}
523557
</PieChart>
524-
</ResponsiveContainer>
558+
</ResponsiveContainer>
559+
560+
{/* Custom legend placed inside the card so it always stays within bounds */}
561+
<Box sx={{ display: 'flex', justifyContent: 'center', flexWrap: 'wrap', gap: 12, mt: 2 }}>
562+
{(() => {
563+
const languageTotal = analytics.languageDistribution.reduce((s, e) => s + (e.value ?? 0), 0);
564+
const topThree = analytics.languageDistribution.slice(0, 3);
565+
const othersCount = analytics.languageDistribution.length - topThree.length;
566+
567+
return (
568+
<>
569+
{topThree.map((entry, index) => {
570+
const pct = languageTotal > 0 ? Math.round(((entry.value ?? 0) / languageTotal) * 100) : 0;
571+
const color = COLORS[index % COLORS.length];
572+
return (
573+
<Box key={entry.name} sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
574+
<Box sx={{ width: 10, height: 10, borderRadius: '50%', background: color }} />
575+
<Typography variant="caption" sx={{ fontWeight: 700, color: theme.palette.text.primary }}>
576+
{entry.name} {pct}%
577+
</Typography>
578+
</Box>
579+
);
580+
})}
581+
582+
{othersCount > 0 && (
583+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
584+
<Box sx={{ width: 10, height: 10, borderRadius: '50%', background: 'rgba(0,0,0,0.08)' }} />
585+
<Typography variant="caption" sx={{ color: theme.palette.text.secondary }}>
586+
+{othersCount} others
587+
</Typography>
588+
</Box>
589+
)}
590+
</>
591+
);
592+
})()}
593+
</Box>
594+
</>
525595
) : (
526596
<Box sx={{ display: 'grid', placeItems: 'center', height: '82%', borderRadius: 3, border: `1px dashed ${theme.palette.divider}` }}>
527597
<Typography color="text.secondary">No language data available.</Typography>
@@ -540,7 +610,7 @@ const RepositoryAnalyticsDashboard = ({
540610
background:
541611
theme.palette.mode === 'dark'
542612
? 'linear-gradient(180deg, rgba(15,23,42,0.72), rgba(15,23,42,0.94))'
543-
: 'linear-gradient(180deg, #ffffff, #f9fbff)',
613+
: 'linear-gradient(180deg, var(--color-surface), rgba(249,251,255,1))',
544614
border: `1px solid ${theme.palette.divider}`,
545615
boxShadow: '0 18px 40px rgba(15,23,42,0.06)',
546616
}}
@@ -559,15 +629,15 @@ const RepositoryAnalyticsDashboard = ({
559629
<AreaChart data={weeklyCommitActivity.map((entry) => ({ label: formatWeekLabel(entry.week), commits: entry.commits }))}>
560630
<defs>
561631
<linearGradient id="commitFill" x1="0" y1="0" x2="0" y2="1">
562-
<stop offset="5%" stopColor="#06b6d4" stopOpacity={0.45} />
563-
<stop offset="95%" stopColor="#06b6d4" stopOpacity={0.03} />
632+
<stop offset="5%" stopColor="var(--color-accent)" stopOpacity={0.45} />
633+
<stop offset="95%" stopColor="var(--color-accent)" stopOpacity={0.03} />
564634
</linearGradient>
565635
</defs>
566636
<CartesianGrid strokeDasharray="3 3" stroke={theme.palette.divider} opacity={0.8} />
567637
<XAxis dataKey="label" stroke={theme.palette.text.secondary} tickMargin={10} />
568638
<YAxis stroke={theme.palette.text.secondary} width={30} />
569639
<Tooltip contentStyle={{ backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, borderRadius: 16, border: `1px solid ${theme.palette.divider}` }} />
570-
<Area type="monotone" dataKey="commits" stroke="#06b6d4" strokeWidth={3} fill="url(#commitFill)" dot={{ r: 3 }} activeDot={{ r: 6 }} />
640+
<Area type="monotone" dataKey="commits" stroke="var(--color-accent)" strokeWidth={3} fill="url(#commitFill)" dot={{ r: 3 }} activeDot={{ r: 6 }} />
571641
</AreaChart>
572642
</ResponsiveContainer>
573643
) : (
@@ -601,14 +671,19 @@ const RepositoryAnalyticsDashboard = ({
601671

602672
{analytics.topRepositories.length > 0 ? (
603673
<ResponsiveContainer width="100%" height="84%">
604-
<BarChart data={analytics.topRepositories}>
674+
<BarChart data={analytics.topRepositories} margin={{ bottom: 20 }}>
605675
<CartesianGrid strokeDasharray="3 3" stroke={theme.palette.divider} opacity={0.8} />
606-
<XAxis dataKey="name" stroke={theme.palette.text.secondary} interval={0} angle={-15} textAnchor="end" height={70} tickMargin={10} />
676+
{/* hide x-axis ticks to avoid overlap; show name on hover via Tooltip */}
677+
<XAxis dataKey="name" stroke={theme.palette.text.secondary} interval={0} tick={false} />
607678
<YAxis stroke={theme.palette.text.secondary} width={30} />
608-
<Tooltip contentStyle={{ backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, borderRadius: 16, border: `1px solid ${theme.palette.divider}` }} />
679+
<Tooltip
680+
contentStyle={{ backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, borderRadius: 16, border: `1px solid ${theme.palette.divider}` }}
681+
labelFormatter={(label) => `Repository: ${label}`}
682+
formatter={(value, name) => [value, name]}
683+
/>
609684
<Legend />
610-
<Bar dataKey="stars" fill="#f59e0b" radius={[10, 10, 0, 0]} />
611-
<Bar dataKey="forks" fill="#10b981" radius={[10, 10, 0, 0]} />
685+
<Bar dataKey="stars" fill="var(--color-danger)" radius={[10, 10, 0, 0]} />
686+
<Bar dataKey="forks" fill="var(--color-success)" radius={[10, 10, 0, 0]} />
612687
</BarChart>
613688
</ResponsiveContainer>
614689
) : (

0 commit comments

Comments
 (0)