MetaMask / MetaMask/metamask-design-system
Create Migration Script: Icon Component Migration from Extension to Design System
- Dominant language
- TypeScript
- Stars
- 37
- Forks
- 14
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 60
Description
### **Description**
Create an automated migration script to convert the MetaMask extension'\''s Icon component usage to the `@metamask/design-system-react` Icon component. This script will handle both the component migration and the conversion of style utility props to Tailwind classes.
### **Technical Details**
The migration script should handle:
1. **Import Statements**
```typescript
// Find and replace imports
- import { Icon } from "../../ui/components/component-library/icon"
+ import { Icon } from "@metamask/design-system-react"
```
2. **Props Mapping**
```typescript
// Current Extension Icon Props -> Design System Icon Props
{
name -> name
size -> size
color -> color
// Style utility props will be converted to className
// Handle icon name mapping differences
}
```
3. **Icon Name Mappings**
```typescript
// Extension Icon Names -> Design System Icon Names
const iconNameMappings = {
// Map any differences in icon names between systems
// Example:
"add-square" -> "add-square-filled"
"arrow-2-right" -> "arrow-right"
// ... other mappings
}
```
4. **Size Mappings**
```typescript
// Extension Size -> Design System Size
const sizeMappings = {
IconSize.Xs -> "xs"
IconSize.Sm -> "sm"
IconSize.Md -> "md"
IconSize.Lg -> "lg"
IconSize.Xl -> "xl"
IconSize.Inherit -> "inherit"
}
```
5. **Color Mappings**
```typescript
// Extension Color -> Design System Color
const colorMappings = {
IconColor.PrimaryDefault -> "text-primary-default"
IconColor.PrimaryInverse -> "text-primary-inverse"
IconColor.InheritDefault -> "text-inherit"
// ... other color mappings
}
```
6. **Style Utility Props to Tailwind**
```typescript
// Example transformations
marginTop={4} -> className="mt-4"
display="block" -> className="block"
```
### **Implementation Details**
1. **Script Structure**
```typescript
import { Parser } from "some-ts-parser";
import { transform } from "some-code-transformer";
const migrateIconComponent = async (filePath: string) => {
// Read file
// Parse AST
// Transform nodes
// Write changes
};
const handleImports = (ast: AST) => {
// Update imports
};
const transformProps = (props: Props) => {
// Convert props including icon name mappings
};
const convertStyleProps = (props: StyleProps) => {
// Convert to Tailwind
};
```
2. **Icon Name Validation**
```typescript
const validateIconName = (name: string) => {
// Check if icon exists in design system
// Warn if icon not found
// Suggest alternatives
};
```
3. **Class Merging Logic**
```typescript
const mergeClasses = (existingClasses: string, newClasses: string) => {
// Merge and dedupe classes
return twMerge(existingClasses, newClasses);
};
```
### **Acceptance Criteria**
- [ ] Script successfully identifies all Icon component usage
- [ ] Correctly transforms imports
- [ ] Accurately maps icon names between systems
- [ ] Properly maps size values
- [ ] Correctly maps color values
- [ ] Converts style utility props to Tailwind classes
- [ ] Handles className merging correctly
- [ ] Validates icon names exist in design system
- [ ] Provides warnings for missing icons
- [ ] Maintains code formatting and comments
- [ ] Provides detailed migration report
- [ ] Includes dry-run option
- [ ] Has error handling and logging
- [ ] Includes tests for all transformations
- [ ] Provides rollback capability
### **Testing Strategy**
1. **Unit Tests**
```typescript
describe("Icon Component Migration", () => {
test("import transformation", () => {});
test("icon name mapping", () => {});
test("size mapping", () => {});
test("color mapping", () => {});
test("style utility conversion", () => {});
test("className merging", () => {});
});
```
2. **Integration Tests**
- Test with real component examples
- Verify output matches expected results
- Check edge cases and complex scenarios
3. **Visual Regression Tests**
- Compare icons before and after migration
- Ensure sizes and colors are preserved
- Verify positioning and alignment
### **Usage Example**
```bash
# Run migration
yarn migrate-icon-component --dry-run
yarn migrate-icon-component --path=./src
yarn migrate-icon-component --single-file=./src/component.tsx
```
### **Migration Report Example**
```
Migration Report:
- Files processed: 150
- Icons migrated: 300
- Missing icons: 2
- custom-icon-1 (used in: src/components/A.tsx)
- custom-icon-2 (used in: src/components/B.tsx)
- Warnings: 3
- Size "xxl" not supported (src/components/C.tsx)
- Unknown color value (src/components/D.tsx)
```
### **References**
- [Extension Icon Component](https://github.com/MetaMask/metamask-extension/tree/main/ui/components/component-library/icon)
- [Design System React Icon Component](https://github.com/MetaMask/metamask-design-system/tree/main/packages/design-system-react/src/components/icon)
- [jscodeshift](https://github.com/facebook/jscodeshift)
- [AST Explorer](https://astexplorer.net/)
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
Contributor guide
Assessment
This issue has not been assessed yet.