refactor: dashboard design critique — eliminate redundancy, differentiate sections
- Remove GreetingStatStrip (duplicated PerformanceCards data) - Strip left-border accent from stat cards (AI slop pattern) - Redesign KnowledgeBaseCards: icon grid → compact row list with icon badges - Redesign TeamSummary: distinct inline-row layout, no longer identical twin - Differentiate hover: stat cards use subtle border-hover, sessions keep springy lift - Add loading skeletons to PerformanceCards, KnowledgeBaseCards, TeamSummary - Add error state to PerformanceCards - Extract timeAgo() to shared lib/timeAgo.ts (replaced 4 duplicates) - Fix Skeleton bg-brand-border (undefined CSS var) → border-default - Fix double text-xs text-[0.5625rem] class conflicts across dashboard Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +1,19 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Network, Code2, ListChecks, ArrowRight } from 'lucide-react'
|
||||
import { Network, Code2, ListChecks, ArrowRight, ChevronRight } from 'lucide-react'
|
||||
import { sidebarApi } from '@/api'
|
||||
import { Skeleton } from '@/components/ui/Skeleton'
|
||||
|
||||
export function KnowledgeBaseCards() {
|
||||
const navigate = useNavigate()
|
||||
const [flowCount, setFlowCount] = useState(0)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
sidebarApi.getStats()
|
||||
.then((stats) => setFlowCount(stats.tree_counts.total))
|
||||
.catch(() => {})
|
||||
.finally(() => setLoading(false))
|
||||
}, [])
|
||||
|
||||
const items = [
|
||||
@@ -33,23 +36,35 @@ export function KnowledgeBaseCards() {
|
||||
Browse <ArrowRight size={10} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 divide-x" style={{ borderColor: 'var(--color-border-default)' }}>
|
||||
{items.map((item) => (
|
||||
<div className="py-1">
|
||||
{loading ? Array.from({ length: 3 }).map((_, i) => (
|
||||
<div key={i} className="flex items-center gap-3 px-5 py-3" style={{ borderBottom: i < 2 ? '1px solid var(--color-border-default)' : undefined }}>
|
||||
<Skeleton className="h-8 w-8 rounded-md shrink-0" />
|
||||
<Skeleton className="h-4 flex-1 max-w-24" />
|
||||
<Skeleton className="h-5 w-8" />
|
||||
</div>
|
||||
)) : items.map((item, i) => (
|
||||
<button
|
||||
key={item.label}
|
||||
onClick={() => navigate(item.href)}
|
||||
className="flex flex-col items-center gap-2 py-5 rounded-lg hover:bg-card-hover transition-all duration-350"
|
||||
style={{ transition: 'transform 350ms cubic-bezier(0.34, 1.56, 0.64, 1), background 200ms ease' }}
|
||||
onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-4px)' }}
|
||||
onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)' }}
|
||||
className="flex w-full items-center gap-3 px-5 py-3 text-left hover:bg-[var(--color-bg-card-hover)] transition-colors group"
|
||||
style={{
|
||||
borderBottom: i < items.length - 1 ? '1px solid var(--color-border-default)' : undefined,
|
||||
}}
|
||||
>
|
||||
<item.icon size={20} style={{ color: item.color }} />
|
||||
<p className="font-heading text-xl font-extrabold text-foreground">{item.value}</p>
|
||||
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
{item.label}
|
||||
</p>
|
||||
<span
|
||||
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-md"
|
||||
style={{ backgroundColor: `${item.color}15` }}
|
||||
>
|
||||
<item.icon size={15} style={{ color: item.color }} />
|
||||
</span>
|
||||
<span className="flex-1 text-sm font-medium text-foreground">{item.label}</span>
|
||||
<span className="font-heading text-base font-bold text-foreground tabular-nums mr-1">
|
||||
{item.value}
|
||||
</span>
|
||||
<ChevronRight size={14} className="text-muted-foreground opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all" />
|
||||
</button>
|
||||
))}
|
||||
)))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user