Skip to content

Add ESLint rule to replace deprecated Octicon component with specific icons and remove unused imports #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 6, 2025

This PR adds a new ESLint rule no-deprecated-octicon that automatically transforms deprecated Octicon component usage to use specific icon components directly from @primer/octicons-react. The rule also removes unused Octicon imports when all usages have been replaced.

What it does

The rule transforms various usage patterns and cleans up imports:

Basic transformation with import removal

// Before
import {Octicon} from '@primer/react/deprecated'
import {XIcon} from '@primer/octicons-react'

<Octicon icon={XIcon} size={16} className="test" />

// After  
import {XIcon} from '@primer/octicons-react'

<XIcon size={16} className="test" />

Partial import cleanup

// Before
import {Octicon, Button} from '@primer/react/deprecated'
import {XIcon} from '@primer/octicons-react'

<Octicon icon={XIcon} />

// After
import {Button} from '@primer/react/deprecated'
import {XIcon} from '@primer/octicons-react'

<XIcon />

Advanced transformations

The rule also supports:

Conditional expressions:

// Before
<Octicon icon={condition ? XIcon : CheckIcon} size={16} />

// After
condition ? <XIcon size={16} /> : <CheckIcon size={16} />

Dynamic icon access:

// Before
<Octicon icon={icons.close} size={24} className="icon" />

// After
React.createElement(icons.close, {size: 24, className: "icon"})

Key features

  • Automatic transformation: Replaces <Octicon icon={IconName} /> with <IconName />
  • Smart import cleanup: Removes Octicon from imports when no longer needed
  • Advanced conditional support: Transforms conditional icon usage into conditional JSX expressions
  • Dynamic icon handling: Uses React.createElement for dynamic icon access patterns
  • Preserves all props: Maintains size, className, aria-label, spread props, etc. across all transformation types
  • Handles complex JSX: Works with both self-closing tags and elements with children
  • Safe edge case handling: Provides autofixes for complex usage patterns

Implementation details

The rule uses AST analysis to identify JSX elements using the Octicon component, extract and analyze the icon prop to determine the appropriate transformation strategy, and generate fixes that include both JSX transformation and import cleanup when appropriate.

The import removal logic carefully handles comma placement and whitespace to ensure clean output in all scenarios.

Fixes #375.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copy link
Contributor Author

Copilot AI commented Aug 6, 2025

@joshblack 👋 This repository doesn't have Copilot instructions. With Copilot instructions, I can understand the repository better, work faster and produce higher quality PRs.

I can generate a .github/copilot-instructions.md file for you automatically. Click here to open a pre-filled issue and assign it to me. I'll write the instructions, and then tag you for review.

Copy link

changeset-bot bot commented Aug 6, 2025

⚠️ No Changeset found

Latest commit: ab189c5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@Copilot Copilot AI changed the title [WIP] Add an eslint rule for updating Octicon to a named icon from @primer/octicons-react Add ESLint rule to replace deprecated Octicon component with specific icons Aug 6, 2025
@Copilot Copilot AI requested a review from joshblack August 6, 2025 20:38
Copilot finished work on behalf of joshblack August 6, 2025 20:38
Comment on lines 158 to 171
// Complex conditional case - should report but not autofix
{
code: `import {Octicon} from '@primer/react/deprecated'
import {XIcon, CheckIcon} from '@primer/octicons-react'
export default function App() {
return <Octicon icon={condition ? XIcon : CheckIcon} />
}`,
output: null,
errors: [
{
messageId: 'replaceDeprecatedOcticon',
},
],
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update this rule to autofix like:

Suggested change
// Complex conditional case - should report but not autofix
{
code: `import {Octicon} from '@primer/react/deprecated'
import {XIcon, CheckIcon} from '@primer/octicons-react'
export default function App() {
return <Octicon icon={condition ? XIcon : CheckIcon} />
}`,
output: null,
errors: [
{
messageId: 'replaceDeprecatedOcticon',
},
],
},
// Complex conditional case - should report but not autofix
{
code: `import {Octicon} from '@primer/react/deprecated'
import {XIcon, CheckIcon} from '@primer/octicons-react'
export default function App() {
return condition ? <XIcon /> : <CheckIcon />
}`,
output: null,
errors: [
{
messageId: 'replaceDeprecatedOcticon',
},
],
},

It should also apply the same props from Octicon to each component in the condition

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot make this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I've updated the rule to autofix conditional expressions by transforming <Octicon icon={condition ? XIcon : CheckIcon} /> to condition ? <XIcon /> : <CheckIcon /> and properly apply all props from Octicon to each component in the condition. Added test cases covering both scenarios with and without additional props. Commit: d35c34c

],
},

// Dynamic icon access - should report but not autofix
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the autofix for this scenario, it should create a React element from this icon like React.createElement(icons.x)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added! The rule now autofixes dynamic icon access scenarios by transforming <Octicon icon={icons.x} /> to React.createElement(icons.x, {}) and properly handles all props. Added test cases for both with and without props scenarios. Commit: d35c34c

@Copilot Copilot AI changed the title Add ESLint rule to replace deprecated Octicon component with specific icons Add ESLint rule to replace deprecated Octicon component with specific icons including conditional and dynamic usage Aug 6, 2025
@Copilot Copilot AI requested a review from joshblack August 6, 2025 21:18
Copilot finished work on behalf of joshblack August 6, 2025 21:18
Copy link
Member

@joshblack joshblack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot update this rule to also include removing the import to Octicon if all Octicons have been replaced

Copy link
Contributor Author

Copilot AI commented Aug 7, 2025

@copilot update this rule to also include removing the import to Octicon if all Octicons have been replaced

Added import removal functionality! The rule now automatically removes the Octicon import when all Octicon usages have been replaced, handling both full import removal and partial removal when other components are imported from the same module. Currently debugging an edge case with multiple Octicons. Commit: ba61171

@Copilot Copilot AI changed the title Add ESLint rule to replace deprecated Octicon component with specific icons including conditional and dynamic usage Add ESLint rule to replace deprecated Octicon component with specific icons and remove unused imports Aug 7, 2025
@Copilot Copilot AI requested a review from joshblack August 7, 2025 21:52
Copilot finished work on behalf of joshblack August 7, 2025 21:52
},
}
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add an eslint rule for updating Octicon to a named icon from @primer/octicons-react
3 participants