feat(ui): language distribution bar on project cards
Extract LanguageBar into a shared component used by both DashPage (compact, bar only) and ProjectPage (full, with percentage labels). Remove redundant forge source text from project cards since the forge icon already indicates it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
35
ui/src/components/LanguageBar.tsx
Normal file
35
ui/src/components/LanguageBar.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
export function LanguageBar({ languages, colorMap, compact }: {
|
||||
languages: Record<string, number>;
|
||||
colorMap: Record<string, string>;
|
||||
compact?: boolean;
|
||||
}) {
|
||||
const total = Object.values(languages).reduce((a, b) => a + b, 0);
|
||||
if (total === 0) return null;
|
||||
|
||||
const sorted = Object.entries(languages).sort(([, a], [, b]) => b - a);
|
||||
|
||||
return (
|
||||
<div className={compact ? 'mb-1' : 'mt-2'}>
|
||||
<div className="language-bar">
|
||||
{sorted.map(([lang, bytes]) => (
|
||||
<div
|
||||
key={lang}
|
||||
className="language-bar-segment"
|
||||
style={{ width: `${(bytes / total) * 100}%`, backgroundColor: colorMap[lang] ?? '#8b8b8b' }}
|
||||
title={`${lang} ${((bytes / total) * 100).toFixed(1)}%`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{!compact && (
|
||||
<div className="d-flex flex-wrap gap-2 mt-1" style={{ fontSize: '0.75rem' }}>
|
||||
{sorted.slice(0, 8).map(([lang, bytes]) => (
|
||||
<span key={lang}>
|
||||
<span className="language-dot" style={{ backgroundColor: colorMap[lang] ?? '#8b8b8b' }} />
|
||||
{lang} {((bytes / total) * 100).toFixed(1)}%
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user