Skip to content

Add file tree icon style toggle: Simple (Lucide) vs Rich (Material) #483

@pedramamini

Description

@pedramamini

Summary

Add a File Tree Icon Style toggle to Settings > Display that lets users switch between two icon rendering modes in the file explorer panel:

Mode Description
Simple (default) Current behavior — monochrome Lucide icons colored with theme.colors.accent. Git-changed files use success/warning/error colors.
Rich Colorful, language-specific icons using a Material-style file icon library (e.g., material-icon-theme or react-file-icon). Each file type gets its own distinct color and shape.

Visual Reference

Simple (current):

  • All file icons are the same accent color from the active theme
  • Icons differentiate by shape only (FileCode, BookOpen, Settings, etc.)
  • Folders use accent-colored Folder/FolderOpen icons

Rich (target):

  • Each file type has a unique, colorful icon (e.g., TypeScript = blue TS shield, Python = green/yellow snake, JSON = yellow braces, Markdown = blue M)
  • Folders can also have type-specific icons (node_modules, src, public, .git, etc.)
  • Colors are inherent to the icon, NOT derived from the theme

Implementation Guide

1. Setting — settingsStore.ts

Add fileTreeIconStyle to the Zustand store following the existing pattern:

// State
fileTreeIconStyle: 'simple' as 'simple' | 'rich',

// Setter
setFileTreeIconStyle: (value: 'simple' | 'rich') => {
    set({ fileTreeIconStyle: value });
    window.maestro.settings.set('fileTreeIconStyle', value);
},

// In loadAllSettings()
if (allSettings['fileTreeIconStyle'] !== undefined)
    patch.fileTreeIconStyle = allSettings['fileTreeIconStyle'] as 'simple' | 'rich';

2. UI Toggle — SettingsModal.tsx (Display tab)

Add a ToggleButtonGroup in the Display tab. Place it after User Message Alignment and before Window Chrome — it's a visual preference so it groups well there.

Follow the existing userMessageAlignment pattern:

<ToggleButtonGroup
    label="File Tree Icon Style"
    options={[
        { value: 'simple', label: 'Simple' },
        { value: 'rich', label: 'Rich' },
    ]}
    value={fileTreeIconStyle ?? 'simple'}
    onChange={setFileTreeIconStyle}
    theme={theme}
/>

3. Icon Resolution — theme.tsx

Current icon functions to modify:

  • getExplorerFileIcon() (lines 174-263) — maps file extensions/names → Lucide icons
  • getExplorerFolderIcon() (lines 265-304) — maps folder names → Lucide icons

Approach: Add the fileTreeIconStyle parameter to both functions. When 'simple', return current Lucide icons unchanged. When 'rich', return the Material-style icon instead.

Consider creating a new utility file (e.g., src/renderer/utils/fileIcons.tsx) to keep the rich icon mappings separate from the existing theme logic, then import/delegate from the existing functions based on the style parameter.

4. Icon Library Choice

Evaluate and pick ONE:

  • react-file-icon — lightweight, customizable SVG file icons
  • vscode-icons — comprehensive, familiar to devs
  • material-icon-theme assets — the gold standard for file icons, would need SVG extraction
  • Custom SVG sprite sheet — maximum control, more upfront work

Key requirements for the chosen library:

  • Must support the same w-3.5 h-3.5 (14px) size as current icons
  • Must look good on both light and dark theme backgrounds
  • Must cover common file types: .ts, .tsx, .js, .jsx, .py, .rs, .go, .java, .sh, .json, .yaml, .md, .css, .html, .svg, .png, .env, .gitignore, lock files
  • Must have folder icons (generic + special: node_modules, src, .git, public, dist, test)
  • Fallback: if a file type has no rich icon, fall back to the current Lucide icon

5. Consuming the Setting — FileExplorerPanel.tsx

The render call at line ~1000 already passes theme:

{isFolder
    ? getExplorerFolderIcon(node.name, isExpanded, theme)
    : getExplorerFileIcon(node.name, theme, change?.type)}

Update to also pass the icon style setting. The setting is available from useSettings() which is already used in the component.

6. Git Change Colors

In Rich mode, git-change coloring behavior needs a decision:

  • Option A: Rich icons keep their natural colors; git status is shown via OTHER indicators (dot, badge, background tint)
  • Option B: Rich icons get a colored overlay/tint for git changes (may look muddy)
  • Option C (recommended): Rich icons keep natural colors for unmodified files, but git-changed files fall back to Simple-style Lucide icons with git colors — this is clear and unambiguous

Files to Touch

File Change
src/renderer/stores/settingsStore.ts Add fileTreeIconStyle state + setter + loader
src/renderer/components/SettingsModal.tsx Add toggle in Display tab
src/renderer/utils/theme.tsx Update getExplorerFileIcon and getExplorerFolderIcon
src/renderer/utils/fileIcons.tsx (new) Rich icon mappings
src/renderer/components/FileExplorerPanel.tsx Pass icon style to icon functions
package.json Add chosen icon library dependency
Tests for affected components Update to cover both icon styles

Acceptance Criteria

  • Default icon style is Simple — no behavior change for existing users
  • Toggle is accessible in Settings > Display as a ToggleButtonGroup
  • Simple mode renders identically to current implementation
  • Rich mode renders colorful, file-type-specific icons
  • Rich mode covers at minimum: TS, TSX, JS, JSX, Python, Rust, Go, Java, Shell, JSON, YAML, Markdown, CSS, HTML, SVG, PNG/image, .env, .gitignore, lock files, folders
  • File types without a rich icon fall back gracefully to Lucide
  • Setting persists across app restarts
  • Icons render at the correct 14px size in both modes
  • Both modes look good on light and dark themes
  • Git-change indicators remain clear in Rich mode

Simple Look:

Image

Rich Look

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions