Open Source Team Metrics based on PRs

tune down design

+40 -13
app/globals.css
··· 87 87 --sidebar-accent-foreground: oklch(0.37 0.03 259.73); 88 88 --sidebar-border: oklch(0.91 0.05 306.07); 89 89 --sidebar-ring: oklch(0.71 0.16 293.40); 90 + 91 + /* Custom neutral card colors to reduce purple overuse */ 92 + --card-neutral: oklch(0.98 0.01 0); 93 + --card-neutral-foreground: oklch(0.37 0.03 259.73); 94 + --card-subtle: oklch(0.96 0.02 0); 95 + --card-accent: oklch(0.94 0.02 0); 96 + 97 + /* Brand-tinted background veils (light) */ 98 + --bg-accent-1: oklch(0.71 0.16 293.40 / 0.06); 99 + --bg-accent-2: oklch(0.71 0.16 293.40 / 0.04); 90 100 91 101 --font-sans: Open Sans, sans-serif; 92 102 --font-serif: Source Serif 4, serif; ··· 106 116 } 107 117 108 118 .dark { 109 - --background: oklch(0.18 0.02 300.00); 110 - --foreground: oklch(0.93 0.03 273.66); 111 - --card: oklch(0.28 0.03 307.25); 112 - --card-foreground: oklch(0.93 0.03 273.66); 113 - --popover: oklch(0.28 0.03 307.25); 114 - --popover-foreground: oklch(0.93 0.03 273.66); 119 + /* Softer dark neutrals to avoid harsh black and blue undertones */ 120 + --background: oklch(0.21 0.01 260); 121 + --foreground: oklch(0.92 0.02 260); 122 + --card: oklch(0.24 0.01 260); 123 + --card-foreground: oklch(0.92 0.02 260); 124 + --popover: oklch(0.24 0.01 260); 125 + --popover-foreground: oklch(0.92 0.02 260); 115 126 --primary: oklch(0.79 0.12 295.97); 116 127 --primary-foreground: oklch(0.15 0.01 295.97); 117 128 --secondary: oklch(0.34 0.04 309.13); 118 129 --secondary-foreground: oklch(0.87 0.01 261.81); 119 - --muted: oklch(0.28 0.03 307.25); 120 - --muted-foreground: oklch(0.71 0.02 261.33); 121 - --accent: oklch(0.39 0.05 304.68); 122 - --accent-foreground: oklch(0.87 0.01 261.81); 130 + --muted: oklch(0.26 0.01 260); 131 + --muted-foreground: oklch(0.72 0.02 260); 132 + --accent: oklch(0.30 0.01 260); 133 + --accent-foreground: oklch(0.90 0.02 260); 123 134 --destructive: oklch(0.81 0.10 19.47); 124 - --border: oklch(0.34 0.04 309.13); 125 - --input: oklch(0.34 0.04 309.13); 135 + --border: oklch(0.32 0.01 260); 136 + --input: oklch(0.32 0.01 260); 126 137 --ring: oklch(0.79 0.12 295.97); 127 138 --chart-1: oklch(0.75 0.15 258.89); 128 139 --chart-2: oklch(0.69 0.17 26.11); 129 140 --chart-3: oklch(0.79 0.12 295.97); 130 141 --chart-4: oklch(0.72 0.16 162.48); 131 142 --chart-5: oklch(0.49 0.24 292.70); 132 - --sidebar: oklch(0.34 0.04 309.13); 143 + --sidebar: oklch(0.31 0.03 295.97); 133 144 --sidebar-foreground: oklch(0.93 0.03 273.66); 134 145 --sidebar-primary: oklch(0.79 0.12 295.97); 135 146 --sidebar-primary-foreground: oklch(0.22 0.01 52.96); ··· 137 148 --sidebar-accent-foreground: oklch(0.87 0.01 261.81); 138 149 --sidebar-border: oklch(0.34 0.04 309.13); 139 150 --sidebar-ring: oklch(0.79 0.12 295.97); 151 + 152 + /* Custom neutral card colors to reduce purple overuse */ 153 + --card-neutral: oklch(0.22 0.02 0); 154 + --card-neutral-foreground: oklch(0.93 0.03 273.66); 155 + --card-subtle: oklch(0.18 0.01 0); 156 + --card-accent: oklch(0.26 0.02 0); 157 + 158 + /* Brand-tinted background veils (dark) */ 159 + --bg-accent-1: oklch(0.79 0.12 295.97 / 0.09); 160 + --bg-accent-2: oklch(0.79 0.12 295.97 / 0.06); 140 161 141 162 --shadow-2xs: 0 1px 3px 0px oklch(0.00 0 0 / 0.05); 142 163 --shadow-xs: 0 1px 3px 0px oklch(0.00 0 0 / 0.05); ··· 163 184 } 164 185 165 186 @layer base { 187 + html { 188 + background-color: var(--sidebar); 189 + } 166 190 * { 167 191 @apply border-border outline-ring/50; 168 192 } 169 193 body { 170 194 @apply bg-background text-foreground; 195 + background-image: radial-gradient(80rem 40rem at 50% -10%, var(--bg-accent-1), transparent), 196 + radial-gradient(80rem 40rem at 50% 110%, var(--bg-accent-2), transparent); 197 + background-attachment: fixed; 171 198 } 172 199 } 173 200
+40 -14
components/actionable-recommendations.tsx
··· 89 89 const getImpactGradient = (priority: string) => { 90 90 switch (priority) { 91 91 case 'high': 92 - return 'from-purple-50 via-purple-100/30 to-purple-25/20 dark:from-purple-950/30 dark:via-purple-900/5 dark:to-purple-950/10'; 92 + return 'from-primary/25 via-primary/10 to-transparent dark:from-primary/25 dark:via-primary/10 dark:to-transparent'; 93 + case 'medium': 94 + return 'from-primary/15 to-transparent dark:from-primary/15 dark:to-transparent'; 95 + case 'low': 96 + return 'from-primary/10 to-transparent dark:from-primary/10 dark:to-transparent'; 97 + default: 98 + return 'from-primary/12 to-transparent dark:from-primary/12 dark:to-transparent'; 99 + } 100 + }; 101 + 102 + const getBorderColor = (priority: string) => { 103 + switch (priority) { 104 + case 'high': 105 + return 'border-primary/30 dark:border-primary/25'; 93 106 case 'medium': 94 - return 'from-purple-50 via-purple-100/30 to-purple-25/20 dark:from-purple-950/30 dark:via-purple-900/5 dark:to-purple-950/10'; 107 + return 'border-primary/20 dark:border-primary/15'; 95 108 case 'low': 96 - return 'from-emerald-50 via-emerald-100/30 to-emerald-25/20 dark:from-emerald-950/30 dark:via-emerald-900/5 dark:to-emerald-950/10'; 109 + return 'border-primary/10 dark:border-primary/10'; 97 110 default: 98 - return 'from-gray-100 to-gray-50/30 dark:from-gray-950/60 dark:to-gray-900/10'; 111 + return 'border-primary/15 dark:border-primary/10'; 112 + } 113 + }; 114 + 115 + const getIconColor = (priority: string) => { 116 + switch (priority) { 117 + case 'high': 118 + return 'text-primary'; 119 + case 'medium': 120 + return 'text-primary/90'; 121 + case 'low': 122 + return 'text-primary/80'; 123 + default: 124 + return 'text-primary/80'; 99 125 } 100 126 }; 101 127 ··· 156 182 </CardHeader> 157 183 <CardContent> 158 184 <div className="text-center py-8"> 159 - <div className="mb-4 mx-auto w-12 h-12 rounded-full bg-linear-to-br from-green-400 to-emerald-500 flex items-center justify-center"> 185 + <div className="mb-4 mx-auto w-12 h-12 rounded-full bg-gradient-to-br from-green-400 to-emerald-500 flex items-center justify-center"> 160 186 <IconCheck className="h-6 w-6 text-white" /> 161 187 </div> 162 188 <h3 className="text-lg font-semibold mb-2">All Systems Running Well</h3> ··· 225 251 {groupedRecs.high.map((rec) => ( 226 252 <Card 227 253 key={rec.id} 228 - className={`bg-linear-to-tl ${getImpactGradient(rec.priority)} border-purple-200/40 dark:border-purple-800/20`} 254 + className={`bg-gradient-to-tl ${getImpactGradient(rec.priority)} ${getBorderColor(rec.priority)}`} 229 255 > 230 256 <CardHeader className="pb-3"> 231 257 <div className="flex items-start space-x-3"> 232 - <div className="mt-0.5 text-purple-500 dark:text-purple-300"> 258 + <div className={`mt-0.5 ${getIconColor(rec.priority)}`}> 233 259 {getTypeIcon(rec.type)} 234 260 </div> 235 261 <div className="flex-1"> ··· 239 265 </div> 240 266 </CardHeader> 241 267 <CardContent className="pt-0 space-y-3"> 242 - <div className="bg-white/60 dark:bg-black/20 rounded-lg p-3"> 268 + <div className="bg-white/60 dark:bg-card/20 rounded-lg p-3"> 243 269 <p className="text-sm font-medium mb-1">Expected Impact</p> 244 270 <p className="text-sm text-muted-foreground">{rec.impact}</p> 245 271 <div className="mt-2 flex items-center justify-between text-xs"> ··· 274 300 {groupedRecs.medium.map((rec) => ( 275 301 <Card 276 302 key={rec.id} 277 - className={`bg-linear-to-tl ${getImpactGradient(rec.priority)} border-purple-200/40 dark:border-purple-800/20`} 303 + className={`bg-gradient-to-tl ${getImpactGradient(rec.priority)} ${getBorderColor(rec.priority)}`} 278 304 > 279 305 <CardHeader className="pb-3"> 280 306 <div className="flex items-start space-x-3"> 281 - <div className="mt-0.5 text-purple-500 dark:text-purple-300"> 307 + <div className={`mt-0.5 ${getIconColor(rec.priority)}`}> 282 308 {getTypeIcon(rec.type)} 283 309 </div> 284 310 <div className="flex-1"> ··· 288 314 </div> 289 315 </CardHeader> 290 316 <CardContent className="pt-0 space-y-3"> 291 - <div className="bg-white/60 dark:bg-black/20 rounded-lg p-3"> 317 + <div className="bg-white/60 dark:bg-card/20 rounded-lg p-3"> 292 318 <p className="text-sm font-medium mb-1">Expected Impact</p> 293 319 <p className="text-sm text-muted-foreground">{rec.impact}</p> 294 320 <div className="mt-2 flex items-center justify-between text-xs"> ··· 323 349 {groupedRecs.low.map((rec) => ( 324 350 <Card 325 351 key={rec.id} 326 - className={`bg-linear-to-tl ${getImpactGradient(rec.priority)} border-emerald-200/40 dark:border-emerald-800/20`} 352 + className={`bg-gradient-to-tl ${getImpactGradient(rec.priority)} ${getBorderColor(rec.priority)}`} 327 353 > 328 354 <CardHeader className="pb-3"> 329 355 <div className="flex items-start space-x-3"> 330 - <div className="mt-0.5 text-emerald-500 dark:text-emerald-300"> 356 + <div className={`mt-0.5 ${getIconColor(rec.priority)}`}> 331 357 {getTypeIcon(rec.type)} 332 358 </div> 333 359 <div className="flex-1"> ··· 337 363 </div> 338 364 </CardHeader> 339 365 <CardContent className="pt-0 space-y-3"> 340 - <div className="bg-white/60 dark:bg-black/20 rounded-lg p-3"> 366 + <div className="bg-white/60 dark:bg-card/20 rounded-lg p-3"> 341 367 <p className="text-sm font-medium mb-1">Expected Impact</p> 342 368 <p className="text-sm text-muted-foreground">{rec.impact}</p> 343 369 <div className="mt-2 flex items-center justify-between text-xs">
+1 -1
components/landing/open-source-section.tsx
··· 51 51 <div className="w-full border-t border-dashed border-border/50 mb-12"></div> 52 52 53 53 <div className="text-center mb-6"> 54 - <div className="inline-flex items-center px-4 py-2 rounded-full bg-white/60 dark:bg-black/20 border border-green-200 dark:border-green-800"> 54 + <div className="inline-flex items-center px-4 py-2 rounded-full bg-white/60 dark:bg-card/20 border border-green-200 dark:border-green-800"> 55 55 <span className="text-sm font-medium text-green-700 dark:text-green-300"> 56 56 With support from our friends at: 57 57 </span>
+2 -2
components/recommendations-insights.tsx
··· 92 92 case "quality": 93 93 return <Badge variant="outline" className="bg-indigo-500/10 text-indigo-700 dark:text-indigo-400">Quality</Badge>; 94 94 case "collaboration": 95 - return <Badge variant="outline" className="bg-purple-500/10 text-purple-700 dark:text-purple-400">Collaboration</Badge>; 95 + return <Badge variant="outline" className="bg-blue-500/10 text-blue-700 dark:text-blue-400">Collaboration</Badge>; 96 96 case "process": 97 97 return <Badge variant="outline" className="bg-amber-500/10 text-amber-700 dark:text-amber-400">Process</Badge>; 98 98 default: ··· 147 147 </CardHeader> 148 148 <CardContent> 149 149 <div className="text-center py-8"> 150 - <div className="mb-4 mx-auto w-12 h-12 rounded-full bg-linear-to-br from-green-400 to-emerald-500 flex items-center justify-center"> 150 + <div className="mb-4 mx-auto w-12 h-12 rounded-full bg-gradient-to-br from-green-400 to-emerald-500 flex items-center justify-center"> 151 151 <IconCheck className="h-6 w-6 text-white" /> 152 152 </div> 153 153 <h3 className="text-lg font-semibold mb-2">Great Work!</h3>
+1 -1
components/section-cards-engineering.tsx
··· 191 191 if (error && !data) return <ErrorCard error={error} refresh={refresh} />; 192 192 193 193 return ( 194 - <div className="grid grid-cols-1 gap-4 px-4 lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4"> 194 + <div className="grid grid-cols-1 gap-4 px-4 lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:from-gray-50/30 *:data-[slot=card]:to-white dark:*:data-[slot=card]:from-card/10 dark:*:data-[slot=card]:to-card *:data-[slot=card]:shadow-xs"> 195 195 {METRICS_CONFIG.map((config) => ( 196 196 <MetricCard 197 197 key={config.key}
+1 -1
components/section-cards.tsx
··· 12 12 13 13 export function SectionCards() { 14 14 return ( 15 - <div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-4 px-4 *:data-[slot=card]:bg-linear-to-t *:data-[slot=card]:shadow-xs lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4"> 15 + <div className="grid grid-cols-1 gap-4 px-4 lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:from-gray-50/30 *:data-[slot=card]:to-white dark:*:data-[slot=card]:from-card/10 dark:*:data-[slot=card]:to-card *:data-[slot=card]:shadow-xs"> 16 16 <Card className="@container/card"> 17 17 <CardHeader> 18 18 <CardDescription>Total Revenue</CardDescription>