feat: upgrade all dependencies and overhaul UI with new branding

This commit is contained in:
2026-02-22 19:29:23 +01:00
parent d126f77d39
commit 3ec80a5fcb

View File

@@ -136,28 +136,30 @@ function App() {
<div className="flex flex-col h-screen bg-base text-text"> <div className="flex flex-col h-screen bg-base text-text">
<div data-tauri-drag-region className="titlebar shrink-0"> <div data-tauri-drag-region className="titlebar shrink-0">
<div className="titlebar-drag gap-2 px-4" data-tauri-drag-region> <div className="titlebar-drag gap-2 px-4" data-tauri-drag-region>
<Activity size={16} className="text-mauve" /> <div className="w-7 h-7 rounded-xl bg-gradient-to-br from-mauve via-blue to-teal flex items-center justify-center shadow-xl shadow-mauve/20 border border-white/10">
<span className="font-bold tracking-tight">SysPulse</span> <Activity size={16} className="text-base" strokeWidth={3} />
</div>
<span className="font-black tracking-tighter uppercase italic text-xl">SysPulse</span>
</div> </div>
<div className="flex items-center gap-4 px-4"> <div className="flex items-center gap-4 px-4">
<button <button
className="flex items-center gap-2 text-subtext0 hover:text-text transition-colors text-xs" className="flex items-center gap-2 text-subtext0 hover:text-text transition-colors text-xs font-bold"
onClick={() => setExcludeSelf(!excludeSelf)} onClick={() => setExcludeSelf(!excludeSelf)}
> >
{excludeSelf ? <CheckSquare size={14} className="text-blue" /> : <SquareIcon size={14} />} {excludeSelf ? <CheckSquare size={14} className="text-blue" /> : <SquareIcon size={14} />}
<span>Hide SysPulse</span> <span>HIDE OVERHEAD</span>
</button> </button>
<button <button
className={cn( className={cn(
"flex items-center gap-2 px-4 py-1.5 rounded-full text-xs font-bold transition-all shadow-lg", "flex items-center gap-2 px-6 py-2 rounded-xl text-xs font-black transition-all shadow-xl",
stats.is_recording stats.is_recording
? "bg-red text-base animate-pulse" ? "bg-red text-base animate-pulse ring-4 ring-red/20"
: "bg-green text-base hover:scale-105 active:scale-95" : "bg-green text-base hover:scale-105 active:scale-95 hover:shadow-green/20"
)} )}
onClick={toggleRecording} onClick={toggleRecording}
> >
{stats.is_recording ? <Square size={12} fill="currentColor" /> : <Play size={12} fill="currentColor" />} {stats.is_recording ? <Square size={12} fill="currentColor" /> : <Play size={12} fill="currentColor" />}
{stats.is_recording ? `STOP (${formatDuration(stats.recording_duration)})` : "RECORD PROFILE"} {stats.is_recording ? `STOP (${formatDuration(stats.recording_duration)})` : "START PROFILING"}
</button> </button>
</div> </div>
</div> </div>
@@ -167,34 +169,38 @@ function App() {
<div className="flex-1 flex flex-col items-center justify-center gap-8 animate-in fade-in zoom-in duration-500"> <div className="flex-1 flex flex-col items-center justify-center gap-8 animate-in fade-in zoom-in duration-500">
<div className="relative"> <div className="relative">
<div className="absolute inset-0 bg-red/20 blur-3xl rounded-full scale-150 animate-pulse" /> <div className="absolute inset-0 bg-red/20 blur-3xl rounded-full scale-150 animate-pulse" />
<div className="relative bg-surface0 p-12 rounded-full border-4 border-red/30 shadow-2xl"> <div className="relative bg-surface0 p-12 rounded-[2.5rem] border-4 border-red/30 shadow-2xl overflow-hidden group">
<Activity size={64} className="text-red animate-pulse" /> <div className="absolute inset-0 bg-gradient-to-t from-red/10 to-transparent" />
<Activity size={64} className="text-red animate-pulse relative z-10" />
</div> </div>
</div> </div>
<div className="text-center space-y-2"> <div className="text-center space-y-2">
<h2 className="text-3xl font-black text-text tracking-tighter uppercase italic">Profiling Active</h2> <h2 className="text-4xl font-black text-text tracking-tighter uppercase italic drop-shadow-lg">Profiling Active</h2>
<p className="text-subtext1 font-mono text-xl">{formatDuration(stats.recording_duration)}</p> <p className="text-red font-mono text-2xl font-black tabular-nums">{formatDuration(stats.recording_duration)}</p>
</div> </div>
<div className="grid grid-cols-2 gap-4 w-full max-w-md"> <div className="grid grid-cols-2 gap-4 w-full max-w-md">
<div className="bg-surface0 p-4 rounded-2xl border border-surface1"> <div className="bg-surface0 p-6 rounded-[1.5rem] border border-surface1 shadow-xl">
<div className="text-xs font-bold text-subtext0 mb-1 uppercase tracking-widest">CPU</div> <div className="text-[10px] font-black text-overlay2 mb-2 uppercase tracking-widest">Global CPU</div>
<div className="text-2xl font-black text-blue">{avgCpu.toFixed(1)}%</div> <div className="text-3xl font-black text-blue tabular-nums">{avgCpu.toFixed(1)}%</div>
</div> </div>
<div className="bg-surface0 p-4 rounded-2xl border border-surface1"> <div className="bg-surface0 p-6 rounded-[1.5rem] border border-surface1 shadow-xl">
<div className="text-xs font-bold text-subtext0 mb-1 uppercase tracking-widest">RAM</div> <div className="text-[10px] font-black text-overlay2 mb-2 uppercase tracking-widest">Global RAM</div>
<div className="text-2xl font-black text-mauve">{memoryPercent.toFixed(1)}%</div> <div className="text-3xl font-black text-mauve tabular-nums">{memoryPercent.toFixed(1)}%</div>
</div> </div>
</div> </div>
<p className="text-overlay1 text-sm italic">Minimal footprint mode enabled to ensure accurate results.</p> <div className="flex items-center gap-2 text-overlay1 text-sm font-bold bg-surface0/50 px-4 py-2 rounded-full border border-surface1">
<Shield size={14} className="text-green" />
<span>Minimal footprint mode enabled</span>
</div>
</div> </div>
) : ( ) : (
<> <>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 shrink-0"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 shrink-0">
<div className="card group"> <div className="card group bg-gradient-to-b from-surface0 to-base/50">
<div className="card-title"><Cpu size={16} className="text-blue" /> CPU Load</div> <div className="card-title"><Cpu size={16} className="text-blue" strokeWidth={3} /> CPU Load</div>
<div className="flex items-end gap-2"> <div className="flex items-end gap-2">
<span className="stat-value text-blue">{avgCpu.toFixed(1)}</span> <span className="stat-value text-blue tabular-nums">{avgCpu.toFixed(1)}</span>
<span className="text-subtext0 font-bold mb-2">%</span> <span className="text-subtext0 font-black mb-2">%</span>
</div> </div>
<div className="h-16 mt-4"> <div className="h-16 mt-4">
<ResponsiveContainer width="100%" height="100%"> <ResponsiveContainer width="100%" height="100%">
@@ -205,71 +211,78 @@ function App() {
<stop offset="95%" stopColor="var(--blue)" stopOpacity={0}/> <stop offset="95%" stopColor="var(--blue)" stopOpacity={0}/>
</linearGradient> </linearGradient>
</defs> </defs>
<Area type="monotone" dataKey="cpu" stroke="var(--blue)" fill="url(#cpuDash)" strokeWidth={2} isAnimationActive={false} /> <Area type="monotone" dataKey="cpu" stroke="var(--blue)" fill="url(#cpuDash)" strokeWidth={3} isAnimationActive={false} />
</AreaChart> </AreaChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
</div> </div>
<div className="card"> <div className="card bg-gradient-to-b from-surface0 to-base/50">
<div className="card-title"><Database size={16} className="text-mauve" /> Memory</div> <div className="card-title"><Database size={16} className="text-mauve" strokeWidth={3} /> Memory</div>
<div className="flex items-end gap-2"> <div className="flex items-end gap-2">
<span className="stat-value text-mauve">{(stats.used_memory / 1024 / 1024 / 1024).toFixed(1)}</span> <span className="stat-value text-mauve tabular-nums">{(stats.used_memory / 1024 / 1024 / 1024).toFixed(1)}</span>
<span className="text-subtext0 font-bold mb-2">GB used</span> <span className="text-subtext0 font-black mb-2">GB used</span>
</div> </div>
<div className="mt-6"> <div className="mt-6">
<div className="flex justify-between text-[10px] font-bold text-overlay2 uppercase mb-1"> <div className="flex justify-between text-[10px] font-black text-overlay2 uppercase mb-2">
<span>{memoryPercent.toFixed(1)}%</span> <span>{memoryPercent.toFixed(1)}% Utilized</span>
<span>{(stats.total_memory / 1024 / 1024 / 1024).toFixed(0)} GB</span> <span>{(stats.total_memory / 1024 / 1024 / 1024).toFixed(0)} GB Total</span>
</div> </div>
<div className="h-2 bg-surface1 rounded-full overflow-hidden"> <div className="h-3 bg-surface1/50 rounded-full overflow-hidden border border-surface2">
<div className="h-full bg-mauve transition-all duration-700" style={{ width: `${memoryPercent}%` }} /> <div className="h-full bg-gradient-to-r from-mauve to-pink transition-all duration-700 shadow-lg shadow-mauve/20" style={{ width: `${memoryPercent}%` }} />
</div> </div>
</div> </div>
</div> </div>
<div className="card"> <div className="card bg-gradient-to-b from-surface0 to-base/50">
<div className="card-title"><Server size={16} className="text-green" /> Tasks</div> <div className="card-title"><Server size={16} className="text-green" strokeWidth={3} /> Tasks</div>
<div className="flex items-end gap-2"> <div className="flex items-end gap-2">
<span className="stat-value text-green">{stats.processes.length}</span> <span className="stat-value text-green tabular-nums">{stats.processes.length}</span>
<span className="text-subtext0 font-bold mb-2">active</span> <span className="text-subtext0 font-black mb-2">Processes</span>
</div> </div>
<div className="mt-4 text-xs text-overlay2 font-medium leading-relaxed"> <div className="mt-4 text-xs text-subtext1 font-medium leading-relaxed bg-base/30 p-3 rounded-xl border border-surface1">
Profiling will merge child processes into their parents for consolidated analysis. Automatic aggregation is active. Child processes are merged for cleaner profiling.
</div> </div>
</div> </div>
</div> </div>
<div className="card flex-1 flex flex-col min-h-0 overflow-hidden shadow-2xl border border-surface1/50"> <div className="card flex-1 flex flex-col min-h-0 overflow-hidden shadow-[0_35px_60px_-15px_rgba(0,0,0,0.5)] border border-surface1/50">
<div className="flex justify-between items-center mb-6"> <div className="flex justify-between items-center mb-6 px-2">
<h3 className="text-lg font-black tracking-tighter uppercase italic flex items-center gap-2"> <h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
<Activity size={20} className="text-red" /> <Activity size={24} className="text-red" strokeWidth={3} />
Live Process Feed Live Feed
</h3> </h3>
<div className="text-[10px] bg-surface1 px-2 py-1 rounded font-bold text-overlay2 uppercase">Top 50 Consumers</div> <div className="text-[10px] bg-red/10 text-red border border-red/20 px-3 py-1.5 rounded-full font-black uppercase tracking-widest flex items-center gap-1.5">
<div className="w-1.5 h-1.5 rounded-full bg-red animate-pulse" />
Real-time
</div>
</div> </div>
<div className="table-header grid grid-cols-[4fr_1fr_1.5fr_1.5fr_0.5fr] gap-4 px-4 py-3 bg-surface1/30 rounded-t-xl"> <div className="grid grid-cols-[1fr_100px_100px_120px_80px] gap-4 px-6 py-4 bg-surface1/50 rounded-2xl font-black uppercase tracking-widest text-[10px] text-overlay1 mb-2">
<div>Name</div> <div>Process</div>
<div>PID</div> <div className="text-right">PID</div>
<div>CPU</div> <div className="text-right">CPU %</div>
<div>Memory</div> <div className="text-right">Memory</div>
<div className="text-center">Action</div> <div className="text-center">Action</div>
</div> </div>
<div className="overflow-y-auto flex-1 custom-scrollbar"> <div className="overflow-y-auto flex-1 custom-scrollbar px-2">
{stats.processes.map((proc) => ( {stats.processes.map((proc) => (
<div key={proc.pid} className="table-row grid grid-cols-[4fr_1fr_1.5fr_1.5fr_0.5fr] gap-4 px-4 py-3 border-b border-surface1/30 group hover:bg-surface1/20 transition-all"> <div key={proc.pid} className="grid grid-cols-[1fr_100px_100px_120px_80px] gap-4 px-4 py-4 border-b border-surface1/20 group hover:bg-surface1/20 transition-all rounded-xl">
<div className="font-bold text-text truncate text-sm" title={proc.name}>{proc.name}</div> <div className="font-black text-text truncate text-sm flex items-center gap-3" title={proc.name}>
<div className="font-mono text-overlay1 text-xs mt-1">{proc.pid}</div> <div className="w-2 h-2 rounded-full bg-surface2 group-hover:bg-blue transition-colors" />
<div className="text-blue font-black text-sm">{proc.cpu_usage.toFixed(1)}%</div> {proc.name}
<div className="text-mauve font-black text-sm">{(proc.memory / 1024 / 1024).toFixed(0)} MB</div> </div>
<div className="flex justify-center"> <div className="font-mono text-overlay2 text-xs text-right self-center">{proc.pid}</div>
<div className="text-blue font-black text-sm text-right self-center tabular-nums">{proc.cpu_usage.toFixed(1)}%</div>
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">{(proc.memory / 1024 / 1024).toFixed(0)} MB</div>
<div className="flex justify-center items-center">
<button <button
onClick={() => killProcess(proc.pid)} onClick={() => killProcess(proc.pid)}
className="opacity-0 group-hover:opacity-100 p-1.5 hover:bg-red/20 text-red rounded-lg transition-all" className="opacity-0 group-hover:opacity-100 p-2 hover:bg-red/20 text-red rounded-xl transition-all hover:scale-110 active:scale-90"
title="Terminate Process"
> >
<Shield size={14} /> <Shield size={16} strokeWidth={2.5} />
</button> </button>
</div> </div>
</div> </div>
@@ -328,51 +341,53 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
<div className="flex flex-col h-screen bg-base text-text"> <div className="flex flex-col h-screen bg-base text-text">
<div className="titlebar shrink-0"> <div className="titlebar shrink-0">
<div className="titlebar-drag gap-2 px-4"> <div className="titlebar-drag gap-2 px-4">
<Activity size={16} className="text-mauve" /> <div className="w-7 h-7 rounded-xl bg-gradient-to-br from-mauve via-blue to-teal flex items-center justify-center shadow-xl shadow-mauve/20 border border-white/10">
<span className="font-bold uppercase italic tracking-tighter">Profiling Report</span> <Activity size={16} className="text-base" strokeWidth={3} />
</div>
<span className="font-black tracking-tighter uppercase italic text-xl">Profiling Report</span>
</div> </div>
<div className="flex gap-4 px-4"> <div className="flex gap-4 px-4">
<button <button
onClick={saveReport} onClick={saveReport}
className="flex items-center gap-2 px-3 py-1 bg-surface1 hover:bg-surface2 rounded text-xs font-bold transition-all text-text" className="flex items-center gap-2 px-4 py-1.5 bg-surface1/50 hover:bg-surface1 border border-surface2 rounded-xl text-xs font-black transition-all text-text uppercase tracking-widest"
> >
<Save size={14} className="text-blue" /> SAVE JSON <Save size={14} className="text-blue" /> SAVE JSON
</button> </button>
<button <button
onClick={onBack} onClick={onBack}
className="flex items-center gap-2 px-3 py-1 bg-surface1 hover:bg-surface2 rounded text-xs font-bold transition-all text-text" className="flex items-center gap-2 px-4 py-1.5 bg-mauve/10 hover:bg-mauve/20 border border-mauve/30 rounded-xl text-xs font-black transition-all text-mauve uppercase tracking-widest"
> >
<ArrowLeft size={14} className="text-mauve" /> DASHBOARD <ArrowLeft size={14} /> DASHBOARD
</button> </button>
</div> </div>
</div> </div>
<main className="flex-1 overflow-y-auto p-6 flex flex-col gap-6 custom-scrollbar relative"> <main className="flex-1 overflow-y-auto p-6 flex flex-col gap-6 custom-scrollbar relative">
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 shrink-0"> <div className="grid grid-cols-1 md:grid-cols-4 gap-4 shrink-0">
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center"> <div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-mauve/30 transition-colors">
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Session Time</div> <div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Session Duration</div>
<div className="text-2xl font-black text-text font-mono">{formatDuration(report.duration_seconds)}</div> <div className="text-2xl font-black text-text font-mono tabular-nums">{formatDuration(report.duration_seconds)}</div>
</div> </div>
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center"> <div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-blue/30 transition-colors">
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">End of Session</div> <div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Session End</div>
<div className="text-xl font-bold text-text">{new Date(report.end_time).toLocaleTimeString()}</div> <div className="text-xl font-bold text-text tabular-nums">{new Date(report.end_time).toLocaleTimeString()}</div>
</div> </div>
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center"> <div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-green/30 transition-colors">
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Uniques</div> <div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Unique Processes</div>
<div className="text-2xl font-black text-blue">{report.aggregated_processes.length}</div> <div className="text-2xl font-black text-blue tabular-nums">{report.aggregated_processes.length}</div>
</div> </div>
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center"> <div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-red/30 transition-colors">
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Issue Alerts</div> <div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Issue Alerts</div>
<div className="text-2xl font-black text-red"> <div className="text-2xl font-black text-red tabular-nums">
{report.aggregated_processes.filter(p => p.warnings.length > 0).length} {report.aggregated_processes.filter(p => p.warnings.length > 0).length}
</div> </div>
</div> </div>
</div> </div>
<div className="card h-72 border border-surface1/50 shadow-2xl"> <div className="card h-72 border border-surface1/50 shadow-2xl bg-gradient-to-b from-surface0 to-base/50">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h3 className="text-sm font-black uppercase italic tracking-widest flex items-center gap-2"> <h3 className="text-sm font-black uppercase italic tracking-widest flex items-center gap-2">
<Activity size={16} className="text-blue" /> Session Load Profile <Activity size={16} className="text-blue" strokeWidth={3} /> Session Load Profile
</h3> </h3>
</div> </div>
<div className="flex-1 min-h-0"> <div className="flex-1 min-h-0">
@@ -388,7 +403,7 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
<XAxis dataKey="time" stroke="var(--subtext0)" tick={{fontSize: 9}} minTickGap={50} /> <XAxis dataKey="time" stroke="var(--subtext0)" tick={{fontSize: 9}} minTickGap={50} />
<YAxis stroke="var(--subtext0)" tick={{fontSize: 9}} /> <YAxis stroke="var(--subtext0)" tick={{fontSize: 9}} />
<Tooltip <Tooltip
contentStyle={{ background: 'var(--mantle)', border: '1px solid var(--surface1)', borderRadius: '12px', fontSize: '11px' }} contentStyle={{ background: 'var(--mantle)', border: '1px solid var(--surface1)', borderRadius: '12px', fontSize: '11px', fontWeight: 'bold' }}
itemStyle={{ color: 'var(--text)' }} itemStyle={{ color: 'var(--text)' }}
/> />
<Area type="monotone" dataKey="avg_cpu" name="CPU %" stroke="var(--blue)" fill="url(#cpuReportGradient)" strokeWidth={3} isAnimationActive={true} /> <Area type="monotone" dataKey="avg_cpu" name="CPU %" stroke="var(--blue)" fill="url(#cpuReportGradient)" strokeWidth={3} isAnimationActive={true} />
@@ -398,45 +413,50 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
</div> </div>
</div> </div>
<div className="card flex-1 flex flex-col min-h-0 border border-surface1/50 shadow-2xl overflow-hidden"> <div className="card flex-1 flex flex-col min-h-0 border border-surface1/50 shadow-[0_35px_60px_-15px_rgba(0,0,0,0.5)] overflow-hidden">
<div className="flex justify-between items-center mb-6 px-2"> <div className="flex justify-between items-center mb-6 px-2">
<h3 className="text-lg font-black tracking-tighter uppercase italic flex items-center gap-2"> <h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
<Server size={20} className="text-green" /> Analysis Matrix <Server size={24} className="text-green" strokeWidth={3} /> Analysis Matrix
</h3> </h3>
<span className="text-[10px] text-overlay1 font-bold">CLICK PROCESS TO INSPECT</span> <span className="text-[10px] bg-surface1 px-3 py-1.5 rounded-full font-black text-overlay1 uppercase tracking-widest">Select Process to Inspect</span>
</div> </div>
<div className="table-header grid grid-cols-[2fr_0.8fr_1fr_1fr_1fr_1fr_2fr] gap-2 px-4 py-3 bg-surface1/30 rounded-t-xl font-bold uppercase tracking-widest text-[9px] text-overlay1"> <div className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-6 py-4 bg-surface1/50 rounded-2xl font-black uppercase tracking-widest text-[10px] text-overlay1 mb-2">
<div className="cursor-pointer hover:text-text transition-colors flex items-center gap-1" onClick={() => handleSort('name')}> <div className="cursor-pointer hover:text-text transition-colors flex items-center gap-1" onClick={() => handleSort('name')}>
Process {sortField === 'name' && (sortOrder === 'asc' ? '↑' : '↓')} Process {sortField === 'name' && (sortOrder === 'asc' ? '↑' : '↓')}
</div> </div>
<div className="cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('instance_count')}>Units</div> <div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('instance_count')}>Units</div>
<div className="cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_cpu')}>Avg CPU</div> <div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_cpu')}>Avg CPU</div>
<div className="cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_cpu')}>Peak CPU</div> <div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_cpu')}>Peak CPU</div>
<div className="cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_memory_mb')}>Avg Mem</div> <div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_memory_mb')}>Avg Mem</div>
<div className="cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_memory_mb')}>Peak Mem</div> <div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_memory_mb')}>Peak Mem</div>
<div>Insights</div> <div className="pl-4">Insights</div>
</div> </div>
<div className="overflow-y-auto flex-1 custom-scrollbar"> <div className="overflow-y-auto flex-1 custom-scrollbar px-2">
{sortedProcesses.map((proc, i) => ( {sortedProcesses.map((proc, i) => (
<div <div
key={i} key={i}
onClick={() => setSelectedProcess(proc)} onClick={() => setSelectedProcess(proc)}
className="table-row grid grid-cols-[2fr_0.8fr_1fr_1fr_1fr_1fr_2fr] gap-2 px-4 py-3 border-b border-surface1/20 hover:bg-surface1/30 cursor-pointer transition-colors group" className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-4 py-4 border-b border-surface1/20 hover:bg-surface1/20 cursor-pointer transition-all rounded-xl group"
> >
<div className="font-bold text-text truncate text-xs group-hover:text-blue" title={proc.name}>{proc.name}</div> <div className="font-black text-text truncate text-sm flex items-center gap-3 group-hover:text-blue transition-colors" title={proc.name}>
<div className="text-overlay1 font-mono text-xs">{proc.instance_count}</div> <div className="w-2 h-2 rounded-full bg-surface2 group-hover:bg-blue transition-colors shrink-0" />
<div className="text-blue font-black text-xs">{proc.avg_cpu.toFixed(1)}%</div> {proc.name}
<div className="text-subtext0 text-[10px] font-bold">{proc.peak_cpu.toFixed(1)}%</div> </div>
<div className="text-mauve font-black text-xs">{proc.avg_memory_mb.toFixed(0)}MB</div> <div className="text-overlay2 font-mono text-xs text-right self-center tabular-nums">{proc.instance_count}</div>
<div className="text-subtext0 text-[10px] font-bold">{proc.peak_memory_mb.toFixed(0)}MB</div> <div className="text-blue font-black text-sm text-right self-center tabular-nums">{proc.avg_cpu.toFixed(1)}%</div>
<div className="flex flex-wrap gap-1"> <div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_cpu.toFixed(1)}%</div>
{proc.warnings.map((w, idx) => ( <div className="text-mauve font-black text-sm text-right self-center tabular-nums">{proc.avg_memory_mb.toFixed(0)}MB</div>
<span key={idx} className="bg-red/10 text-red text-[9px] font-black px-1.5 py-0.5 rounded-full border border-red/20 flex items-center gap-1 uppercase tracking-tighter"> <div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_memory_mb.toFixed(0)}MB</div>
<AlertTriangle size={8} /> {w} <div className="flex flex-wrap gap-1.5 pl-4 items-center">
{proc.warnings.length > 0 ? proc.warnings.map((w, idx) => (
<span key={idx} className="bg-red/10 text-red text-[9px] font-black px-2 py-1 rounded-lg border border-red/20 flex items-center gap-1 uppercase tracking-tighter">
<AlertTriangle size={8} strokeWidth={3} /> {w}
</span> </span>
))} )) : (
<span className="text-[10px] text-green/40 font-black uppercase italic tracking-tighter">Healthy</span>
)}
</div> </div>
</div> </div>
))} ))}