Skip to content

Icon System Architecture

This document details the technical architecture of Hibiscus's centralized icon system, which replaced inline SVG icons with a unified "griddy icons" approach.

System Overview

The icon system provides a centralized, type-safe way to manage and use icons throughout the Hibiscus application. It replaces inline SVG definitions with a unified icon handler that ensures consistency, maintainability, and performance.

Architecture Components

1. Icon Definition Structure

Icons are defined in a centralized structure with type safety:

// Icon definitions with categorization
interface IconDefinitions {
  // File operations
  file: string
  folder: string
  openFile: string

  // UI controls
  close: string
  expand: string
  collapse: string

  // Navigation
  back: string
  forward: string
  up: string
  down: string

  // Application specific
  hibiscus: string
  knowledge: string
  graph: string
}

2. Icon Handler Component

The Icon component provides a unified interface for rendering icons:

interface IconProps {
  name: keyof IconDefinitions
  size?: number | string
  className?: string
  onClick?: () => void
}

export function Icon({ name, size = 16, className, onClick }: IconProps) {
  const iconPath = icons[name]
  return (
    <svg 
      width={size} 
      height={size} 
      viewBox="0 0 24 24"
      className={className}
      onClick={onClick}
    >
      <path d={iconPath} fill="currentColor" />
    </svg>
  )
}

3. SVG Path Optimization

All SVG icons are optimized for:

  • Minimal Path Data: Simplified path commands for smaller bundle size
  • Consistent ViewBox: Standard 24x24 viewBox for uniform scaling
  • Fill-CurrentColor: Icons inherit text color for theme integration
  • No Stroke Data: Simplified rendering with fill-only paths

Implementation Details

Icon Library Structure

The icon system is organized into logical categories:

File System Icons

  • file - Generic file icon
  • folder - Folder/directory icon
  • folderOpen - Open folder state
  • fileText - Text file icon
  • fileCode - Code file icon
  • arrowLeft - Left navigation
  • arrowRight - Right navigation
  • arrowUp - Up navigation
  • arrowDown - Down navigation
  • chevronLeft - Collapsed state
  • chevronRight - Expanded state

Action Icons

  • close - Close/dismiss action
  • add - Add/create action
  • remove - Remove/delete action
  • edit - Edit/modify action
  • save - Save action

Application Icons

  • hibiscus - Application logo/icon
  • graph - Knowledge graph icon
  • search - Search functionality
  • settings - Settings/configuration

Theme Integration

Icons seamlessly integrate with the theme system:

.icon {
  color: var(--text);
  transition: color 0.2s ease;
}

.icon:hover {
  color: var(--accent);
}

.icon.active {
  color: var(--accent-secondary);
}

Performance Optimizations

Bundle Size Reduction

  • Deduplication: Eliminated duplicate inline SVG definitions
  • Path Compression: Optimized SVG path data
  • Tree Shaking: Unused icons are eliminated during build

Runtime Performance

  • No DOM Parsing: Icons rendered as SVG elements directly
  • CSS Inheritance: Icons inherit text color properties
  • Minimal Re-renders: Icon components are pure functions

Migration from Inline SVGs

Before (Inline SVGs)

// Old approach with inline SVGs
function FileIcon() {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24">
      <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2Z" />
    </svg>
  )
}

After (Griddy Icons)

// New approach with centralized icons
function FileIcon() {
  return <Icon name="file" size={16} />
}

Benefits of Migration

  1. Maintainability: Single source of truth for icon definitions
  2. Consistency: All icons use the same rendering approach
  3. Performance: Reduced bundle size and better runtime performance
  4. Developer Experience: Type-safe icon usage with IntelliSense support
  5. Theme Integration: Automatic theme color inheritance

Component Integration

Updated Components

All UI components were updated to use the new icon system:

Tree View Component

// Before
<TreeNode>
  <svg>...</svg> {/* inline */}
  <span>{name}</span>
</TreeNode>

// After
<TreeNode>
  <Icon name={isFolder ? 'folder' : 'file'} />
  <span>{name}</span>
</TreeNode>

Tab Bar Component

// Before
<Tab>
  <svg>...</svg> {/* inline close icon */}
  <span>{title}</span>
</Tab>

// After
<Tab>
  <Icon name="close" onClick={onClose} />
  <span>{title}</span>
</Tab>

Search Panel Component

// Before
<SearchResult>
  <svg>...</svg> {/* inline search icon */}
  <span>{result}</span>
</SearchResult>

// After
<SearchResult>
  <Icon name="search" />
  <span>{result}</span>
</SearchResult>

Icon Usage Guidelines

When to Use Icons

  • Navigation: Use arrow icons for directional navigation
  • Actions: Use action icons for user interactions
  • States: Use icons to represent component states
  • Hierarchy: Use folder/file icons for tree structures

Icon Sizing

Standard icon sizes for different contexts:

  • Header/Title Bar: 16px
  • Button Icons: 14px
  • Tree View: 16px
  • Tab Bar: 12px
  • Status Bar: 12px
  • Small Controls: 10px

Color Usage

Icons inherit text color by default but can be customized:

/* Default behavior */
.icon {
  color: var(--text);
}

/* Hover state */
.icon:hover {
  color: var(--accent);
}

/* Active state */
.icon.active {
  color: var(--accent-secondary);
}

/* Disabled state */
.icon.disabled {
  color: var(--text-muted);
}

Adding New Icons

1. Define Icon Path

Add the SVG path to the icon definitions:

// icons.ts
export const icons = {
  // existing icons...
  newIcon: "M12,2L14.09,8.26L21,9.27L16.5,13.14L17.82,20L12,16.77L6.18,20L7.5,13.14L3,9.27L9.91,8.26L12,2Z"
}

2. Update Type Definitions

Add the new icon to the type definitions:

interface IconDefinitions {
  // existing icons...
  newIcon: string
}

3. Use in Components

Use the new icon throughout the application:

<Icon name="newIcon" size={16} />

Future Enhancements

Planned Improvements

  1. Icon Sprites: Consider SVG sprite optimization for very large icon sets
  2. Dynamic Loading: Lazy load icon definitions for reduced initial bundle
  3. Icon Animation: Add support for animated icons
  4. Custom Icons: Allow user-defined icon extensions
  5. Icon Themes: Support for different icon styles (outlined, filled, etc.)

Extensibility

The icon system is designed to be extensible:

  • Plugin Architecture: Easy to add new icon packs
  • Theme Variants: Support for different icon styles per theme
  • Custom Definitions: Allow runtime icon definition additions
  • Icon Packs: Support for loading external icon libraries

Testing Considerations

Unit Tests

  • Icon Rendering: Verify icons render correctly with different props
  • Theme Integration: Test icon color changes with theme switches
  • Size Variations: Ensure icons scale properly at different sizes
  • Accessibility: Verify icons have proper ARIA labels when needed

Visual Regression Tests

  • Icon Consistency: Ensure icons maintain appearance across updates
  • Theme Testing: Verify icon appearance in all theme variants
  • Browser Compatibility: Test rendering across different browsers
  • Performance: Monitor icon rendering performance

This icon system provides a robust, maintainable foundation for visual elements throughout Hibiscus, ensuring consistency and performance while enabling future extensibility.