diff --git a/.changeset/slow-numbers-invite.md b/.changeset/slow-numbers-invite.md
new file mode 100644
index 00000000..366499a4
--- /dev/null
+++ b/.changeset/slow-numbers-invite.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-primer-react": minor
+---
+
+Add a rule that warns against removing `unsafeDisableTooltip` prop
diff --git a/README.md b/README.md
index aa008488..b2a22db4 100644
--- a/README.md
+++ b/README.md
@@ -38,3 +38,4 @@ ESLint rules for Primer React
- [a11y-tooltip-interactive-trigger](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-tooltip-interactive-trigger.md)
- [a11y-explicit-heading](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-explicit-heading.md)
- [a11y-link-in-text-block](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-link-in-text-block.md)
+- [a11y-remove-disable-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-remove-disable-tooltip.md)
diff --git a/docs/rules/a11y-remove-disable-tooltip.md b/docs/rules/a11y-remove-disable-tooltip.md
new file mode 100644
index 00000000..8b41f449
--- /dev/null
+++ b/docs/rules/a11y-remove-disable-tooltip.md
@@ -0,0 +1,25 @@
+## Rule Details
+
+This rule enforces to remove the `unsafeDisableTooltip` from `IconButton` component so that they have a tooltip by default. `unsafeDisableTooltip` prop is created for an incremental migration and should be removed once all icon buttons have a tooltip.
+
+👎 Examples of **incorrect** code for this rule:
+
+```jsx
+import {IconButton} from '@primer/react'
+
+const App = () => (
+
+ // OR
+
+ // OR
+ // This is incorrect because it should be removed
+)
+```
+
+👍 Examples of **correct** code for this rule:
+
+```jsx
+import {IconButton} from '@primer/react'
+
+const App = () =>
+```
diff --git a/src/configs/recommended.js b/src/configs/recommended.js
index 25b878ca..7b4aa489 100644
--- a/src/configs/recommended.js
+++ b/src/configs/recommended.js
@@ -16,6 +16,7 @@ module.exports = {
'primer-react/new-color-css-vars': 'error',
'primer-react/a11y-explicit-heading': 'error',
'primer-react/no-deprecated-props': 'warn',
+ 'primer-react/a11y-remove-disable-tooltip': 'error',
},
settings: {
github: {
diff --git a/src/index.js b/src/index.js
index 3a21b191..5ec93def 100644
--- a/src/index.js
+++ b/src/index.js
@@ -8,6 +8,7 @@ module.exports = {
'a11y-explicit-heading': require('./rules/a11y-explicit-heading'),
'no-deprecated-props': require('./rules/no-deprecated-props'),
'a11y-link-in-text-block': require('./rules/a11y-link-in-text-block'),
+ 'a11y-remove-disable-tooltip': require('./rules/a11y-remove-disable-tooltip'),
},
configs: {
recommended: require('./configs/recommended'),
diff --git a/src/rules/__tests__/a11y-remove-disable-tooltip.test.js b/src/rules/__tests__/a11y-remove-disable-tooltip.test.js
new file mode 100644
index 00000000..ebf6fb9a
--- /dev/null
+++ b/src/rules/__tests__/a11y-remove-disable-tooltip.test.js
@@ -0,0 +1,50 @@
+'use strict'
+
+const {RuleTester} = require('eslint')
+const rule = require('../a11y-remove-disable-tooltip')
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+})
+
+ruleTester.run('a11y-remove-disable-tooltip', rule, {
+ valid: [
+ `import {IconButton} from '@primer/react';
+ `,
+ ],
+ invalid: [
+ {
+ code: ``,
+ output: ``,
+ errors: [
+ {
+ messageId: 'removeDisableTooltipProp',
+ },
+ ],
+ },
+ {
+ code: ``,
+ output: ``,
+ errors: [
+ {
+ messageId: 'removeDisableTooltipProp',
+ },
+ ],
+ },
+ {
+ code: ``,
+ output: ``,
+ errors: [
+ {
+ messageId: 'removeDisableTooltipProp',
+ },
+ ],
+ },
+ ],
+})
diff --git a/src/rules/a11y-remove-disable-tooltip.js b/src/rules/a11y-remove-disable-tooltip.js
new file mode 100644
index 00000000..b2896aaa
--- /dev/null
+++ b/src/rules/a11y-remove-disable-tooltip.js
@@ -0,0 +1,47 @@
+'use strict'
+const {getJSXOpeningElementAttribute} = require('../utils/get-jsx-opening-element-attribute')
+const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
+
+/**
+ * @type {import('eslint').Rule.RuleModule}
+ */
+module.exports = {
+ meta: {
+ type: 'error',
+ docs: {
+ description:
+ 'Icon buttons should have tooltip by default. Please remove `unsafeDisableTooltip` prop from `IconButton` component to enable the tooltip and help making icon button more accessible.',
+ recommended: true,
+ },
+ fixable: 'code',
+ schema: [],
+ messages: {
+ removeDisableTooltipProp:
+ 'Please remove `unsafeDisableTooltip` prop from `IconButton` component to enable the tooltip and help make icon button more accessible.',
+ },
+ },
+ create(context) {
+ return {
+ JSXOpeningElement(node) {
+ const openingElName = getJSXOpeningElementName(node)
+ if (openingElName !== 'IconButton') {
+ return
+ }
+ const unsafeDisableTooltip = getJSXOpeningElementAttribute(node, 'unsafeDisableTooltip')
+ if (unsafeDisableTooltip !== undefined) {
+ context.report({
+ node,
+ messageId: 'removeDisableTooltipProp',
+ fix(fixer) {
+ const start = unsafeDisableTooltip.range[0]
+ const end = unsafeDisableTooltip.range[1]
+ return [
+ fixer.removeRange([start - 1, end]), // remove the space before unsafeDisableTooltip as well
+ ]
+ },
+ })
+ }
+ },
+ }
+ },
+}