From 1f246aa5673f2610715776df14408ad3eb573d6e Mon Sep 17 00:00:00 2001
From: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com>
Date: Tue, 27 Feb 2024 13:38:23 -0500
Subject: [PATCH] feat(Tabs): updated props and markup (#578)
* feat(Tabs): updated props and markup
* Added rule for isSecondary renamed to isSubtab
* Added rule to warn about scroll button markup change
---
.../src/ruleCustomization.ts | 1 +
.../tabs-renamed-isSecondary-prop.md | 17 +++++++
.../tabs-renamed-isSecondary-prop.test.ts | 25 ++++++++++
.../tabs-renamed-isSecondary-prop.ts | 15 ++++++
.../tabsRenamedIsSecondaryPropInput.tsx | 3 ++
.../tabsRenamedIsSecondaryPropOutput.tsx | 3 ++
.../tabs-replace-variant-light300.md | 17 +++++++
.../tabs-replace-variant-light300.test.ts | 25 ++++++++++
.../tabs-replace-variant-light300.ts | 49 +++++++++++++++++++
.../tabsReplaceVariantLight300Input.tsx | 5 ++
.../tabsReplaceVariantLight300Output.tsx | 5 ++
.../v6/tabsUpdateMarkup/tabs-update-markup.md | 7 +++
.../tabs-update-markup.test.ts | 22 +++++++++
.../v6/tabsUpdateMarkup/tabs-update-markup.ts | 44 +++++++++++++++++
.../tabsUpdateMarkupInput.tsx | 3 ++
.../tabsUpdateMarkupOutput.tsx | 3 ++
16 files changed, 244 insertions(+)
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.md
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.test.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropInput.tsx
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropOutput.tsx
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.md
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.test.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Input.tsx
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Output.tsx
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.md
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.test.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.ts
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupInput.tsx
create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupOutput.tsx
diff --git a/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts b/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts
index 43be75691..d72b510ff 100644
--- a/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts
+++ b/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts
@@ -29,6 +29,7 @@ export const warningRules = [
"simpleFileUpload-warn-changes",
"table-warn-actionsColumn",
"table-warn-thExpandType",
+ "tabs-update-markup",
"tabs-warn-children-type-changed",
"tooltip-warn-triggerRef-may-be-required",
"wizard-warn-button-order",
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.md
new file mode 100644
index 000000000..c15f35bb0
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.md
@@ -0,0 +1,17 @@
+### tabs-renamed-isSecondary-prop [(#10044)](https://github.com/patternfly/patternfly-react/pull/10044)
+
+The `isSecondary` prop for Tabs has been renamed to \`isSubtab\`.
+
+#### Examples
+
+In:
+
+```jsx
+%inputExample%
+```
+
+Out:
+
+```jsx
+%outputExample%
+```
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.test.ts
new file mode 100644
index 000000000..2c89e6b5c
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.test.ts
@@ -0,0 +1,25 @@
+const ruleTester = require("../../ruletester");
+import * as rule from "./tabs-renamed-isSecondary-prop";
+
+ruleTester.run("tabs-renamed-isSecondary-prop", rule, {
+ valid: [
+ {
+ code: ``,
+ },
+ {
+ code: `import { Tabs } from '@patternfly/react-core'; `,
+ },
+ ],
+ invalid: [
+ {
+ code: `import { Tabs } from '@patternfly/react-core'; `,
+ output: `import { Tabs } from '@patternfly/react-core'; `,
+ errors: [
+ {
+ message: `The \`isSecondary\` prop for Tabs has been renamed to \`isSubtab\`.`,
+ type: "JSXOpeningElement",
+ },
+ ],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.ts
new file mode 100644
index 000000000..93e0f90eb
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabs-renamed-isSecondary-prop.ts
@@ -0,0 +1,15 @@
+import { renameProps } from "../../helpers";
+
+// https://github.com/patternfly/patternfly-react/pull/10044
+module.exports = {
+ meta: { fixable: "code" },
+ create: renameProps({
+ Tabs: {
+ isSecondary: {
+ newName: "isSubtab",
+ message:
+ "The `isSecondary` prop for Tabs has been renamed to `isSubtab`.",
+ },
+ },
+ }),
+};
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropInput.tsx
new file mode 100644
index 000000000..0b7b8902e
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropInput.tsx
@@ -0,0 +1,3 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsRenamedIsSecondaryPropInput = () => ;
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropOutput.tsx
new file mode 100644
index 000000000..c3ba24df8
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsRenamedIsSecondaryProp/tabsRenamedIsSecondaryPropOutput.tsx
@@ -0,0 +1,3 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsRenamedIsSecondaryPropInput = () => ;
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.md
new file mode 100644
index 000000000..b025c4f09
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.md
@@ -0,0 +1,17 @@
+### tabs-replace-variant-light300 [(#9930)](https://github.com/patternfly/patternfly-react/pull/9930) [(#10044)](https://github.com/patternfly/patternfly-react/pull/10044)
+
+The "light300" value for the `variant` prop on Tabs has been replaced with the "secondary" value.
+
+#### Examples
+
+In:
+
+```jsx
+%inputExample%
+```
+
+Out:
+
+```jsx
+%outputExample%
+```
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.test.ts
new file mode 100644
index 000000000..aa170fba9
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.test.ts
@@ -0,0 +1,25 @@
+const ruleTester = require("../../ruletester");
+import * as rule from "./tabs-replace-variant-light300";
+
+ruleTester.run("tabs-replace-variant-light300", rule, {
+ valid: [
+ {
+ code: ``,
+ },
+ {
+ code: `import { Tabs } from '@patternfly/react-core'; `,
+ },
+ ],
+ invalid: [
+ {
+ code: `import { Tabs } from '@patternfly/react-core'; `,
+ output: `import { Tabs } from '@patternfly/react-core'; `,
+ errors: [
+ {
+ message: `The "light300" value for the \`variant\` prop on Tabs has been replaced with the "secondary" value.`,
+ type: "JSXOpeningElement",
+ },
+ ],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.ts
new file mode 100644
index 000000000..6b522cddb
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabs-replace-variant-light300.ts
@@ -0,0 +1,49 @@
+import { getFromPackage } from "../../helpers";
+
+// https://github.com/patternfly/patternfly-react/pull/9930
+// https://github.com/patternfly/patternfly-react/pull/10044
+module.exports = {
+ meta: { fixable: "code" },
+ create: function (context: {
+ report: (arg0: {
+ node: any;
+ message: string;
+ fix(fixer: any): any;
+ }) => void;
+ }) {
+ const { imports, exports } = getFromPackage(
+ context,
+ "@patternfly/react-core"
+ );
+
+ const tabsImport = imports.find(
+ (specifier: { imported: { name: string }; local: { name: string } }) =>
+ specifier.imported.name === "Tabs"
+ );
+
+ return !tabsImport
+ ? {}
+ : {
+ JSXOpeningElement(node: { name: { name: any }; attributes: any[] }) {
+ if (node.name.name === tabsImport.local.name) {
+ const attribute = node.attributes.find(
+ (attr: { name: { name: string }; value: { value: string } }) =>
+ attr.name?.name === "variant"
+ );
+ if (attribute && attribute.value.value === "light300") {
+ context.report({
+ node,
+ message:
+ 'The "light300" value for the `variant` prop on Tabs has been replaced with the "secondary" value.',
+ fix(fixer: {
+ replaceText: (arg0: any, arg1: string) => any;
+ }) {
+ return fixer.replaceText(attribute.value, '"secondary"');
+ },
+ });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Input.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Input.tsx
new file mode 100644
index 000000000..9ad7b53b7
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Input.tsx
@@ -0,0 +1,5 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsReplaceVariantLight300Input = () => (
+
+);
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Output.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Output.tsx
new file mode 100644
index 000000000..49047c604
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsReplaceVariantLight300/tabsReplaceVariantLight300Output.tsx
@@ -0,0 +1,5 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsReplaceVariantLight300Input = () => (
+
+);
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.md
new file mode 100644
index 000000000..ba01c2faf
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.md
@@ -0,0 +1,7 @@
+### tabs-update-markup [(#10044)](https://github.com/patternfly/patternfly-react/pull/10044)
+
+The markup for the Tabs scroll buttons have been updated in the following ways:
+
+- Replaced the native `button` HTML element internally with our Button components
+- Added a wrapper `div` around them
+- Removed styling when the `isSubtab` (previously `isSecondary`) prop is true
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.test.ts
new file mode 100644
index 000000000..ef50f5fe3
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.test.ts
@@ -0,0 +1,22 @@
+const ruleTester = require("../../ruletester");
+import * as rule from "./tabs-update-markup";
+
+ruleTester.run("tabs-update-markup", rule, {
+ valid: [
+ {
+ code: `import { Tabs } from 'someOtherPackage';`,
+ },
+ ],
+ invalid: [
+ {
+ code: `import { Tabs } from '@patternfly/react-core';`,
+ output: `import { Tabs } from '@patternfly/react-core';`,
+ errors: [
+ {
+ message: `The markup for the Tabs scroll buttons has been updated. They are now rendered with a div wrapper, use our Button component, and no longer have adjusted styling when the \`isSubtab\` prop is true.`,
+ type: "ImportDeclaration",
+ },
+ ],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.ts
new file mode 100644
index 000000000..42b168982
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabs-update-markup.ts
@@ -0,0 +1,44 @@
+import { getFromPackage } from "../../helpers";
+
+// https://github.com/patternfly/patternfly-react/pull/10044
+module.exports = {
+ meta: { fixable: "code" },
+ create: function (context: {
+ report: (arg0: {
+ node: any;
+ message: string;
+ fix?(fixer: any): any;
+ }) => void;
+ }) {
+ const { imports, exports } = getFromPackage(
+ context,
+ "@patternfly/react-core"
+ );
+
+ const tabsImport = imports.find(
+ (specifier: { imported: { name: string } }) =>
+ specifier.imported.name === "Tabs"
+ );
+
+ return !tabsImport
+ ? {}
+ : {
+ ImportDeclaration(node: {
+ specifiers: { imported: { name: string } }[];
+ }) {
+ if (
+ node.specifiers.find(
+ (specifier: { imported: { name: string } }) =>
+ specifier.imported.name === tabsImport.imported.name
+ )
+ ) {
+ context.report({
+ node,
+ message:
+ "The markup for the Tabs scroll buttons has been updated. They are now rendered with a div wrapper, use our Button component, and no longer have adjusted styling when the `isSubtab` prop is true.",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupInput.tsx
new file mode 100644
index 000000000..bced10252
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupInput.tsx
@@ -0,0 +1,3 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsUpdateMarkupInput = () => ;
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupOutput.tsx
new file mode 100644
index 000000000..bced10252
--- /dev/null
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/tabsUpdateMarkup/tabsUpdateMarkupOutput.tsx
@@ -0,0 +1,3 @@
+import { Tabs } from "@patternfly/react-core";
+
+export const TabsUpdateMarkupInput = () => ;