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 { Loader2, AlertCircle } from "lucide-react";
|
||||||
import { Tree, Folder, File } from "@/components/ui/file-tree";
|
import { Tree, Folder, File } from "@/components/ui/file-tree";
|
||||||
import { THEME } from "@/components/project/dashboard-ui";
|
import { THEME } from "@/components/project/dashboard-ui";
|
||||||
|
import { getFileIconAndColor } from "@/components/project/file-icons";
|
||||||
|
|
||||||
interface TreeItem {
|
interface TreeItem {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -240,6 +241,9 @@ export function GiteaFileTree({
|
|||||||
</Folder>
|
</Folder>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { icon: FileIconComponent, color } = getFileIconAndColor(item.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<File
|
<File
|
||||||
key={item.path}
|
key={item.path}
|
||||||
@@ -247,6 +251,9 @@ export function GiteaFileTree({
|
|||||||
handleSelect={() => onSelectFile?.(item.path)}
|
handleSelect={() => onSelectFile?.(item.path)}
|
||||||
isSelectable={!!onSelectFile}
|
isSelectable={!!onSelectFile}
|
||||||
isSelect={selectedPath === item.path}
|
isSelect={selectedPath === item.path}
|
||||||
|
fileIcon={
|
||||||
|
<FileIconComponent size={15} style={{ color, marginRight: 2 }} />
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</File>
|
</File>
|
||||||
|
|||||||
Reference in New Issue
Block a user