Create icons - NekoDesigner/garanteasy GitHub Wiki
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.
# 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>
# 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
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
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;
After generating the icon component, you need to add the actual SVG paths. Here are the common SVG elements you can use:
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"
/>
import Svg, { Circle } from "react-native-svg";
<Circle
cx="12"
cy="12"
r="10"
stroke={color}
strokeWidth="2"
fill="none"
/>
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"
/>
import Svg, { Line } from "react-native-svg";
<Line
x1="12"
y1="2"
x2="12"
y2="22"
stroke={color}
strokeWidth="2"
/>
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;
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 |
import SearchIcon from '@/components/ui/Icons/SearchIcon';
<SearchIcon />
import SearchIcon from '@/components/ui/Icons/SearchIcon';
import { COLORS } from '@/constants';
<SearchIcon
size={32}
color={COLORS.primary}
/>
import SearchIcon from '@/components/ui/Icons/SearchIcon';
<SearchIcon
size={20}
color="#ff0000"
style={{ marginRight: 8 }}
testID="search-icon"
/>
import CustomIcon from '@/components/ui/Icons/CustomIcon';
<CustomIcon
size={24}
color="#000000"
color2="#ff0000"
/>
- Use PascalCase for icon names
- Add "Icon" suffix automatically by the CLI
- Use descriptive names:
UserProfile
,ShoppingCart
,ArrowLeft
- Use
viewBox="0 0 24 24"
for 24px icons (default) - Prefer
stroke
overfill
for outlined icons - Use
strokeWidth="2"
for consistent line thickness - Add
strokeLinecap="round"
andstrokeLinejoin="round"
for smoother lines
- 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
- Add meaningful
testID
props for testing - Consider icon size for touch targets (minimum 44px for touchable icons)
- Ensure sufficient color contrast
- Keep SVG paths simple and optimized
- Avoid complex gradients or effects
- Use minimal number of path elements
When you have an SVG from external sources (like icon libraries), follow these steps:
<!-- 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>
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>
- Replace
fill="currentColor"
withstroke={color}
- Replace hardcoded dimensions with size props
- Add consistent styling properties
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
// __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);
});
});
Solution: Check the viewBox
dimensions and ensure they match your SVG content scale.
Solution: Ensure you're using stroke={color}
or fill={color}
instead of hardcoded colors.
Solution: Use vector paths instead of embedded raster images in your SVG.
Solution: Check import statements and ensure all required SVG elements are imported from react-native-svg
.
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
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 |
-
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
After generating an icon:
- โ Generate the icon component with CLI
- ๐ Add SVG paths and elements
- ๐จ Test with different sizes and colors
- ๐งช Write unit tests
- ๐ Add to Storybook (if applicable)
- ๐ Use in your components
Need Help? Check the existing icons in components/ui/Icons/
for reference examples or consult the main CLI Documentation.