Create icons - NekoDesigner/garanteasy GitHub Wiki

Icon Creation

Overview

This guide provides comprehensive documentation for creating SVG icon components using the Garanteasy CLI. The CLI generates consistent, reusable icon components that follow React Native SVG patterns and project conventions.

Quick Start

Generate a New Icon

# Using the specific icon command
npm run cli generate-icon <iconName>
npm run cli gic <iconName>

# Using the general generate command
npm run cli generate icon <iconName>
npm run cli g icon <iconName>

Examples

# Create a home icon
npm run cli gic home
# Output: components/ui/Icons/HomeIcon.tsx

# Create a user profile icon
npm run cli gic userProfile
# Output: components/ui/Icons/UserProfileIcon.tsx

# Create a shopping cart icon
npm run cli gic shoppingCart
# Output: components/ui/Icons/ShoppingCartIcon.tsx

Generated File Structure

When you run the icon generation command, it creates a single file in the components/ui/Icons/ directory:

components/ui/Icons/
โ”œโ”€โ”€ @types.ts                 # Shared icon types (already exists)
โ”œโ”€โ”€ YourNewIcon.tsx          # Your generated icon component
โ”œโ”€โ”€ utils.ts                 # Shared utilities (already exists)
โ””โ”€โ”€ ... other existing icons

Icon Component Template

The CLI generates icons using this template structure:

/**
* YourIconIcon - Generated by Garanteasier CLI
*/

import * as React from "react";
import Svg from "react-native-svg";
import { COLORS } from "../../../constants";
import { IconProps } from "./@types";

const DEFAULT_PROPS = {
  size: 24,
  color: COLORS.light,
};

// TODO: create tests for this YourIconIcon component
function YourIconIcon ({
  size = DEFAULT_PROPS.size,
  color = DEFAULT_PROPS.color,
  ...props
}: IconProps) {
  return (
    <Svg
      width={size}
      height={size}
      viewBox={`0 0 ${DEFAULT_PROPS.size} ${DEFAULT_PROPS.size}`}
      fill="none"
      {...props}
    >
      {/* TODO: Add your SVG paths here */}
    </Svg>
  );
}

export default YourIconIcon;

Adding SVG Content

After generating the icon component, you need to add the actual SVG paths. Here are the common SVG elements you can use:

1. Path Elements

import Svg, { Path } from "react-native-svg";

<Path
  d="M11 19a8 8 0 100-16 8 8 0 000 16zM21 21l-4.3-4.3"
  stroke={color}
  strokeWidth="2"
  strokeLinecap="round"
  strokeLinejoin="round"
/>

2. Circle Elements

import Svg, { Circle } from "react-native-svg";

<Circle
  cx="12"
  cy="12"
  r="10"
  stroke={color}
  strokeWidth="2"
  fill="none"
/>

3. Rectangle Elements

import Svg, { Rect } from "react-native-svg";

<Rect
  x="3"
  y="3"
  width="18"
  height="18"
  rx="2"
  ry="2"
  stroke={color}
  strokeWidth="2"
  fill="none"
/>

4. Line Elements

import Svg, { Line } from "react-native-svg";

<Line
  x1="12"
  y1="2"
  x2="12"
  y2="22"
  stroke={color}
  strokeWidth="2"
/>

Complete Icon Example

Here's a complete example of a Search icon:

/**
* SearchIcon - Generated by Garanteasier CLI
*/

import * as React from "react";
import Svg, { Path } from "react-native-svg";
import { COLORS } from "../../../constants";
import { IconProps } from "./@types";

const DEFAULT_PROPS = {
  size: 24,
  color: COLORS.light,
};

function SearchIcon ({
  size = DEFAULT_PROPS.size,
  color = DEFAULT_PROPS.color,
  ...props
}: IconProps) {
  return (
    <Svg
      width={size}
      height={size}
      viewBox={`0 0 ${DEFAULT_PROPS.size} ${DEFAULT_PROPS.size}`}
      fill="none"
      {...props}
    >
      <Path
        d="M11 19a8 8 0 100-16 8 8 0 000 16zM21 21l-4.3-4.3"
        stroke={color}
        strokeWidth="2"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </Svg>
  );
}

export default SearchIcon;

Icon Properties (IconProps)

All generated icons accept these props:

Prop Type Default Description
size number 24 Width and height of the icon in pixels
color string COLORS.light Primary color for strokes and fills
color2 string undefined Secondary color for multi-color icons
style StyleProp<ViewStyle> undefined Additional React Native styles
className string undefined CSS class name (for web)
testID string undefined Test identifier for testing

Usage Examples

Basic Usage

import SearchIcon from '@/components/ui/Icons/SearchIcon';

<SearchIcon />

With Custom Size and Color

import SearchIcon from '@/components/ui/Icons/SearchIcon';
import { COLORS } from '@/constants';

<SearchIcon 
  size={32} 
  color={COLORS.primary} 
/>

With Custom Styles

import SearchIcon from '@/components/ui/Icons/SearchIcon';

<SearchIcon 
  size={20}
  color="#ff0000"
  style={{ marginRight: 8 }}
  testID="search-icon"
/>

Multi-Color Icons

import CustomIcon from '@/components/ui/Icons/CustomIcon';

<CustomIcon 
  size={24}
  color="#000000"
  color2="#ff0000"
/>

Best Practices

1. Naming Conventions

  • Use PascalCase for icon names
  • Add "Icon" suffix automatically by the CLI
  • Use descriptive names: UserProfile, ShoppingCart, ArrowLeft

2. SVG Optimization

  • Use viewBox="0 0 24 24" for 24px icons (default)
  • Prefer stroke over fill for outlined icons
  • Use strokeWidth="2" for consistent line thickness
  • Add strokeLinecap="round" and strokeLinejoin="round" for smoother lines

3. Color Management

  • Use the color prop for primary colors
  • Use color2 prop for secondary colors in multi-color icons
  • Default to COLORS.light from constants
  • Avoid hardcoded colors in SVG paths

4. Accessibility

  • Add meaningful testID props for testing
  • Consider icon size for touch targets (minimum 44px for touchable icons)
  • Ensure sufficient color contrast

5. Performance

  • Keep SVG paths simple and optimized
  • Avoid complex gradients or effects
  • Use minimal number of path elements

Converting External SVGs

When you have an SVG from external sources (like icon libraries), follow these steps:

1. Copy the SVG Content

<!-- Example external SVG -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
  <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>

2. Convert to React Native SVG

import Svg, { Path } from "react-native-svg";

<Svg
  width={size}
  height={size}
  viewBox="0 0 24 24"
  fill="none"
  {...props}
>
  <Path
    d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
    stroke={color}
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  />
</Svg>

3. Update Properties

  • Replace fill="currentColor" with stroke={color}
  • Replace hardcoded dimensions with size props
  • Add consistent styling properties

Testing Icons

After creating an icon, you should add tests. The CLI generates a TODO comment reminding you to create tests:

// TODO: create tests for this YourIconIcon component

Example Test Structure

// __tests__/YourIcon.spec.tsx
import React from 'react';
import { render } from '@testing-library/react-native';
import YourIcon from '../YourIcon';

describe('YourIcon', () => {
  it('renders correctly with default props', () => {
    const { getByTestId } = render(
      <YourIcon testID="your-icon" />
    );
    expect(getByTestId('your-icon')).toBeTruthy();
  });

  it('applies custom size and color', () => {
    const { getByTestId } = render(
      <YourIcon 
        testID="your-icon"
        size={32}
        color="#ff0000"
      />
    );
    const icon = getByTestId('your-icon');
    expect(icon.props.width).toBe(32);
    expect(icon.props.height).toBe(32);
  });
});

Common Issues and Solutions

Issue: Icon appears too large/small

Solution: Check the viewBox dimensions and ensure they match your SVG content scale.

Issue: Icon color not changing

Solution: Ensure you're using stroke={color} or fill={color} instead of hardcoded colors.

Issue: Icon looks pixelated

Solution: Use vector paths instead of embedded raster images in your SVG.

Issue: Icon not displaying

Solution: Check import statements and ensure all required SVG elements are imported from react-native-svg.

Integration with Design Systems

Icons generated with this CLI integrate seamlessly with the Garanteasy design system:

  • Colors: Use COLORS constants from @/constants
  • Sizing: Follow the 8px grid system (16, 24, 32, 40px)
  • Spacing: Consider icon placement within touch targets
  • Consistency: All icons follow the same structural patterns

CLI Command Reference

Command Alias Description
npm run cli generate-icon <name> npm run cli gic <name> Generate a new icon component
npm run cli generate icon <name> npm run cli g icon <name> Alternative generate command

File Locations

  • Generated Icons: components/ui/Icons/[IconName]Icon.tsx
  • Icon Types: components/ui/Icons/@types.ts
  • Icon Utils: components/ui/Icons/utils.ts
  • Constants: constants/Colors.ts

Next Steps

After generating an icon:

  1. โœ… Generate the icon component with CLI
  2. ๐Ÿ“ Add SVG paths and elements
  3. ๐ŸŽจ Test with different sizes and colors
  4. ๐Ÿงช Write unit tests
  5. ๐Ÿ“š Add to Storybook (if applicable)
  6. ๐Ÿš€ Use in your components

Need Help? Check the existing icons in components/ui/Icons/ for reference examples or consult the main CLI Documentation.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ