MetaMask / MetaMask/metamask-design-system

Create Migration Script: Button Component Migration from Extension to Design System

Open
#269 0 comments 0 reactions 1 assignee Claimed by @georgewrmarshall View on GitHub
team-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 Button component usage to the `@metamask/design-system-react` Button component. This script will handle component migration, style utility props conversion to Tailwind classes, and ensure all button variants and states are properly mapped.

### **Technical Details**

The migration script should handle:

1. **Import Statements**
```typescript
// Find and replace imports
- import { Button } from "../../ui/components/component-library/button"
+ import { Button } from "@metamask/design-system-react"
```

2. **Props Mapping**
```typescript
// Current Extension Button Props -> Design System Button Props
{
variant -> variant
size -> size
danger -> danger
disabled -> disabled
loading -> loading
icon -> startIcon/endIcon
iconPositioning -> (remove, handled by separate props)
block -> className="w-full"
// Style utility props will be converted to className
}
```

3. **Variant Mappings**
```typescript
// Extension ButtonVariant -> Design System ButtonVariant
const variantMappings = {
ButtonVariant.Primary -> "primary"
ButtonVariant.Secondary -> "secondary"
ButtonVariant.Link -> "link"
// Handle any variant differences between systems
}
```

4. **Size Mappings**
```typescript
// Extension Size -> Design System Size
const sizeMappings = {
ButtonSize.Sm -> "sm"
ButtonSize.Md -> "md"
ButtonSize.Lg -> "lg"
ButtonSize.Auto -> "auto"
}
```

5. **Icon Handling**
```typescript
// Convert icon prop to startIcon/endIcon based on iconPositioning
const transformIconProps = (props) => {
const { icon, iconPositioning, ...rest } = props;
if (!icon) return rest;

return {
...rest,
[iconPositioning === "left" ? "startIcon" : "endIcon"]: icon
};
};
```

6. **Style Utility Props to Tailwind**
```typescript
// Example transformations
marginTop={4} -> className="mt-4"
display="block" -> className="block"
width="full" -> className="w-full"
```

### **Implementation Details**

1. **Script Structure**
```typescript
import { Parser } from "some-ts-parser";
import { transform } from "some-code-transformer";

const migrateButtonComponent = async (filePath: string) => {
// Read file
// Parse AST
// Transform nodes
// Write changes
};

const handleImports = (ast: AST) => {
// Update imports
};

const transformProps = (props: Props) => {
// Convert props including variant and size mappings
// Handle icon positioning
};

const convertStyleProps = (props: StyleProps) => {
// Convert to Tailwind
};
```

2. **Event Handler Validation**
```typescript
const validateEventHandlers = (props: Props) => {
// Verify onClick handlers
// Check for proper event types
// Warn about any deprecated patterns
};
```

3. **Accessibility Checks**
```typescript
const validateA11y = (props: Props) => {
// Check for aria-labels when needed
// Verify proper roles
// Ensure keyboard navigation works
};
```

### **Edge Cases to Handle**

1. **Custom Styling**
```typescript
// Handle cases where custom styles need to be preserved
const customStyleMappings = {
// Map custom extension styles to Tailwind equivalents
};
```

2. **Complex Icon Scenarios**
```typescript
// Handle cases with multiple icons or custom icon components
const handleComplexIcons = (props) => {
// Transform complex icon scenarios
};
```

3. **State Management**
```typescript
// Handle any state management differences
const transformStateHandling = (component) => {
// Update state management patterns if needed
};
```

### **Acceptance Criteria**

- [ ] Script successfully identifies all Button component usage
- [ ] Correctly transforms imports
- [ ] Accurately maps variants between systems
- [ ] Properly maps size values
- [ ] Correctly handles icon positioning
- [ ] Converts style utility props to Tailwind classes
- [ ] Handles className merging correctly
- [ ] Preserves all event handlers
- [ ] Maintains accessibility features
- [ ] Handles loading states correctly
- [ ] Preserves disabled states
- [ ] Maintains danger variants
- [ ] Handles block/full-width styling
- [ ] 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("Button Component Migration", () => {
test("import transformation", () => {});
test("variant mapping", () => {});
test("size mapping", () => {});
test("icon positioning", () => {});
test("style utility conversion", () => {});
test("event handler preservation", () => {});

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.