feat(codebase): add file-type specific subtle colored icons to the file tree
This commit is contained in:
61
vibn-frontend/components/project/file-icons.tsx
Normal file
61
vibn-frontend/components/project/file-icons.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
FileText,
|
||||
Braces,
|
||||
CodeXml,
|
||||
TerminalSquare,
|
||||
Info,
|
||||
GitBranch,
|
||||
Settings,
|
||||
Image as ImageIcon,
|
||||
Palette,
|
||||
FileCode2,
|
||||
FileJson,
|
||||
FileBox,
|
||||
Box,
|
||||
Hash,
|
||||
Database
|
||||
} from "lucide-react";
|
||||
|
||||
export function getFileIconAndColor(filename: string) {
|
||||
const name = filename.toLowerCase();
|
||||
|
||||
if (name.includes('package.json') || name.includes('package-lock.json') || name.endsWith('.json')) {
|
||||
return { icon: Braces, color: "#eab308" }; // yellow
|
||||
}
|
||||
if (name.startsWith('.env')) {
|
||||
return { icon: TerminalSquare, color: "#10b981" }; // green
|
||||
}
|
||||
if (name.endsWith('.html') || name.endsWith('.xml') || name.endsWith('.svg')) {
|
||||
return { icon: CodeXml, color: "#f97316" }; // orange
|
||||
}
|
||||
if (name.endsWith('.md') || name.endsWith('.mdx') || name.endsWith('.txt')) {
|
||||
return { icon: Info, color: "#3b82f6" }; // blue
|
||||
}
|
||||
if (name.endsWith('.ts') || name.endsWith('.tsx')) {
|
||||
return { icon: FileCode2, color: "#3b82f6" }; // blue
|
||||
}
|
||||
if (name.endsWith('.js') || name.endsWith('.jsx') || name.endsWith('.mjs') || name.endsWith('.cjs')) {
|
||||
return { icon: FileCode2, color: "#eab308" }; // yellow
|
||||
}
|
||||
if (name.endsWith('.css') || name.endsWith('.scss') || name.endsWith('.less') || name.includes('tailwind')) {
|
||||
return { icon: Palette, color: "#ec4899" }; // pink
|
||||
}
|
||||
if (name.endsWith('.sh') || name === 'procfile' || name === 'dockerfile') {
|
||||
return { icon: TerminalSquare, color: "#10b981" }; // green
|
||||
}
|
||||
if (name.endsWith('.yml') || name.endsWith('.yaml') || name.includes('config')) {
|
||||
return { icon: Settings, color: "#8b5cf6" }; // purple
|
||||
}
|
||||
if (name.includes('.git') || name.endsWith('ignore')) {
|
||||
return { icon: GitBranch, color: "#6b7280" }; // gray
|
||||
}
|
||||
if (name.match(/\.(jpg|jpeg|png|gif|webp|ico)$/)) {
|
||||
return { icon: ImageIcon, color: "#14b8a6" }; // teal
|
||||
}
|
||||
if (name.endsWith('.sql') || name.endsWith('.sqlite') || name.endsWith('.db')) {
|
||||
return { icon: Database, color: "#6366f1" }; // indigo
|
||||
}
|
||||
|
||||
// Default
|
||||
return { icon: FileText, color: "#9ca3af" }; // gray-400
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { useEffect, useState, useCallback } from "react";
|
||||
import { Loader2, AlertCircle } from "lucide-react";
|
||||
import { Tree, Folder, File } from "@/components/ui/file-tree";
|
||||
import { THEME } from "@/components/project/dashboard-ui";
|
||||
import { getFileIconAndColor } from "@/components/project/file-icons";
|
||||
|
||||
interface TreeItem {
|
||||
name: string;
|
||||
@@ -240,6 +241,9 @@ export function GiteaFileTree({
|
||||
</Folder>
|
||||
);
|
||||
}
|
||||
|
||||
const { icon: FileIconComponent, color } = getFileIconAndColor(item.name);
|
||||
|
||||
return (
|
||||
<File
|
||||
key={item.path}
|
||||
@@ -247,6 +251,9 @@ export function GiteaFileTree({
|
||||
handleSelect={() => onSelectFile?.(item.path)}
|
||||
isSelectable={!!onSelectFile}
|
||||
isSelect={selectedPath === item.path}
|
||||
fileIcon={
|
||||
<FileIconComponent size={15} style={{ color, marginRight: 2 }} />
|
||||
}
|
||||
>
|
||||
<span>{item.name}</span>
|
||||
</File>
|
||||
|
||||
Reference in New Issue
Block a user