From d8b35fbf475f67f842203156e94c589a72bd0661 Mon Sep 17 00:00:00 2001 From: TJ Egan Date: Mon, 3 May 2021 16:29:48 -0700 Subject: [PATCH 1/3] feat(codemod): add in codemod for size prop updates --- codemods/transforms/size-prop-update.js | 155 +++++++++ .../data-table/_data-table-action.scss | 23 +- .../src/components/DataTable/TableToolbar.js | 3 +- .../src/components/Test/code-mod-story.js | 298 ++++++++++++++++++ 4 files changed, 475 insertions(+), 4 deletions(-) create mode 100644 codemods/transforms/size-prop-update.js create mode 100644 packages/react/src/components/Test/code-mod-story.js diff --git a/codemods/transforms/size-prop-update.js b/codemods/transforms/size-prop-update.js new file mode 100644 index 000000000000..e92a0a9a684c --- /dev/null +++ b/codemods/transforms/size-prop-update.js @@ -0,0 +1,155 @@ +/** + * Copyright IBM Corp. 2016, 2020 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +import fs from 'fs'; + +const defaultOptions = { + quote: 'auto', + trailingComma: true, +}; + +function transform(fileInfo, api, options) { + const printOptions = options.printOptions || defaultOptions; + const j = api.jscodeshift; + const root = j(fileInfo.source); + + function replacePropForComponent(name) { + // Multiselect.Filterable has a different AST structure, so we need to + // adjust the query to find it properly. If it is not 'Filterable', we use + // the default query + let isFilterable = name === 'Filterable'; + let openingElementQuery = { + name: { + name, + }, + }; + if (isFilterable) { + openingElementQuery = { + name: { + object: { + name: 'MultiSelect', + }, + property: { + name: name, + }, + }, + }; + } + root + .find(j.JSXOpeningElement, openingElementQuery) + .forEach((openingElement) => { + // Multiselect.Filterable has a different AST structure, so the name is located differently + const { name } = isFilterable + ? openingElement.node.name.property + : openingElement.node.name; + + // Some components were originally set to `xl`, but are being reduced to `lg` + const downsizedComponents = [ + 'Accordion', + 'ComboBox', + 'ContentSwitcher', + 'DatePickerInput', + 'Dropdown', + 'MultiSelect', + 'Filterable', + 'NumberInput', + 'OverflowMenu', + 'Search', + 'Select', + 'TextInput', + 'TimePicker', + ]; + + const isDownsized = downsizedComponents.includes(name); + + j(openingElement) + .find(j.JSXAttribute, { + name: { + name: 'size', + }, + }) + .forEach((path) => { + j(path).replaceWith((nodePath) => { + const { node } = nodePath; + const { value } = node.value; + + switch (value) { + case 'compact': + node.value.value = 'xs'; + return node; + case 'short': + case 'small': + node.value.value = 'sm'; + return node; + case 'field': + node.value.value = 'md'; + return node; + case 'default': + case 'normal': + node.value.value = 'lg'; + return node; + case 'tall': + case 'lg': + node.value.value = isDownsized ? 'md' : 'xl'; + return node; + case 'xl': + node.value.value = isDownsized ? 'lg' : '2xl'; + return node; + } + return node; + }); + }); + }); + } + + const components = [ + 'Accordion', + 'Button', + 'ComboBox', + 'ContentSwitcher', + 'DataTable', + 'DatePickerInput', + 'Dropdown', + 'FileUploader', + 'FileUploaderButton', + 'FileUploaderDropContainer', + 'FileUploaderItem', + 'MultiSelect', + 'Filterable', + 'NumberInput', + 'OverflowMenu', + 'Search', + 'Select', + 'Table', + 'TableToolbar', + 'TextInput', + 'TimePicker', + ]; + for (const component of components) { + replacePropForComponent(component); + } + + // Remove before merging + // Prints test file to `Test` folder in React package + fs.writeFile( + '../packages/react/src/components/Test/output.js', + root.toSource(), + (err) => { + if (err) { + console.log(err); + } else { + console.log('File written'); + } + } + ); + + return root.toSource(printOptions); +} + +module.exports = transform; diff --git a/packages/components/src/components/data-table/_data-table-action.scss b/packages/components/src/components/data-table/_data-table-action.scss index 90232c9a0d9f..016cde32aeba 100644 --- a/packages/components/src/components/data-table/_data-table-action.scss +++ b/packages/components/src/components/data-table/_data-table-action.scss @@ -445,7 +445,9 @@ //------------------------------------------------- //SMALL TOOLBAR //------------------------------------------------- - .#{$prefix}--table-toolbar--small { + // V11: remove --small + .#{$prefix}--table-toolbar--small, + .#{$prefix}--table-toolbar--sm { height: rem(32px); .#{$prefix}--toolbar-search-container-expandable, @@ -531,31 +533,46 @@ //------------------------------------------------- // SMALL BATCH ACTIONS //------------------------------------------------- + // V11: remove --small selector block .#{$prefix}--table-toolbar--small + .#{$prefix}--batch-actions + .#{$prefix}--action-list, + .#{$prefix}--table-toolbar--sm .#{$prefix}--batch-actions .#{$prefix}--action-list { height: rem(32px); } - .#{$prefix}--table-toolbar--small .#{$prefix}--toolbar-action { + // V11: remove --small selector block + .#{$prefix}--table-toolbar--small .#{$prefix}--toolbar-action, + .#{$prefix}--table-toolbar--sm .#{$prefix}--toolbar-action { width: rem(32px); height: rem(32px); padding: $spacing-03 0; } - .#{$prefix}--table-toolbar--small .#{$prefix}--btn--primary { + // V11: remove --small selector block + .#{$prefix}--table-toolbar--small .#{$prefix}--btn--primary, + .#{$prefix}--table-toolbar--sm .#{$prefix}--btn--primary { height: rem(32px); min-height: auto; padding-top: calc(0.375rem - 3px); padding-bottom: calc(0.375rem - 3px); } + // V11: remove --small selector block .#{$prefix}--table-toolbar--small + .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel::before, + .#{$prefix}--table-toolbar--sm .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel::before { top: rem(8px); } + // V11: remove --small selector block .#{$prefix}--table-toolbar--small + .#{$prefix}--toolbar-action + ~ .#{$prefix}--btn, + .#{$prefix}--table-toolbar--sm .#{$prefix}--toolbar-action ~ .#{$prefix}--btn { overflow: hidden; diff --git a/packages/react/src/components/DataTable/TableToolbar.js b/packages/react/src/components/DataTable/TableToolbar.js index 33bfd328c71f..5b9f1c3748f2 100644 --- a/packages/react/src/components/DataTable/TableToolbar.js +++ b/packages/react/src/components/DataTable/TableToolbar.js @@ -38,8 +38,9 @@ TableToolbar.propTypes = { /** * `normal` Change the row height of table + * V11: remove small, normal */ - size: PropTypes.oneOf(['small', 'normal']), + size: PropTypes.oneOf(['small', 'sm', 'normal', 'lg']), }; TableToolbar.defaultProps = { diff --git a/packages/react/src/components/Test/code-mod-story.js b/packages/react/src/components/Test/code-mod-story.js new file mode 100644 index 000000000000..571f99735c5c --- /dev/null +++ b/packages/react/src/components/Test/code-mod-story.js @@ -0,0 +1,298 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* eslint-disable */ +import React from 'react'; +import { + Accordion, + AccordionItem, + Button, + CodeSnippet, + ComboBox, + ContentSwitcher, + Table, + TableHead, + TableRow, + TableHeader, + TableBody, + TableCell, + DatePicker, + DatePickerInput, + Dropdown, + MultiSelect, + NumberInput, + OverflowMenu, + Search, + Select, + Switch, + TextInput, + TimePicker, +} from '../../index'; +import { FeatureFlags } from '../FeatureFlags'; + +const items = [ + { + id: 'option-0', + text: 'Lorem, ipsum dolor sit amet consectetur adipisicing elit.', + }, + { + id: 'option-1', + text: 'Option 1', + }, + { + id: 'option-2', + text: 'Option 2', + }, + { + id: 'option-3', + text: 'Option 3', + }, + { + id: 'option-4', + text: 'Option 4', + }, + { + id: 'option-5', + text: 'Option 5', + }, +]; + +const rows = [ + { + id: 'load-balancer-1', + name: 'Load Balancer 1', + rule: 'Round robin', + Status: 'Starting', + }, + { + id: 'load-balancer-2', + name: 'Load Balancer 2', + rule: 'DNS delegation', + status: 'Active', + }, + { + id: 'load-balancer-3', + name: 'Load Balancer 3', + rule: 'Round robin', + status: 'Disabled', + }, +]; +const headers = ['Name', 'Rule', 'Status']; + +export default { + title: 'CodeMode/Test', + + parameters: { + component: CodeModTest, + }, +}; + +export const CodeModTest = () => { + return ( +
+

Accordion - size XL -> LG

+
+ + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. +

+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. +

+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. +

+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. +

+
+
+
+
+ +

Button variants

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +

ComboBox - size XL -> LG

+
+ {}} + id="carbon-combobox" + items={items} + itemToString={(item) => (item ? item.text : '')} + placeholder="Filter..." + titleText="ComboBox title" + helperText="Combobox helper text" + /> +
+
+
+ +

Content Switcher - size XL -> LG

+ + + + + +
+
+ +

Dropdown - size XL -> LG

+
+ (item ? item.text : '')} + /> +
+
+
+ +

DataTable - size Tall -> XL

+ + + + {headers.map((header) => ( + {header} + ))} + + + + {rows.map((row) => ( + + {Object.keys(row) + .filter((key) => key !== 'id') + .map((key) => { + return {row[key]}; + })} + + ))} + +
+
+
+ +

Datepicker - size XL -> LG

+ + + +
+
+ +

Multiselect ( and Filterable) - size XL -> LG

+
+ (item ? item.text : '')} + /> +
+
+
+ (item ? item.text : '')} + /> +
+
+
+ +

Numberinput - size XL -> LG

+ +
+
+

OverflowMenu - size XL -> LG

+ +
+
+

Search

+ +
+
+ +
+
+

Select

+ +
+
+ +
+
+

TextInput

+ +
+
+ +
+
+

TimePicker - size xl -> lg

+ +
+ ); +}; + +export const CodeModeTestResults = () => { + // Paste the contents of the code mode inside the component to verify the two stories are the same + return ( + +

+ To test the results, navigate to the codemods folder and + run + + yarn jscodeshift -d -t ./transforms/size-prop-update.js + '../packages/react/src/components/Test/code-mod-story.js' + {' '} + and then paste the results into the CodeModeTestResults + story +

+
+ ); +}; +/* eslint-enable */ From 8cd0c3a3cb1718789df328b0410a9865ad7314b9 Mon Sep 17 00:00:00 2001 From: TJ Egan Date: Tue, 4 May 2021 12:16:24 -0700 Subject: [PATCH 2/3] test(codemod): add tests for size prop codemod --- .../size-prop-update.input.js | 143 ++++++++++++++++++ .../size-prop-update.output.js | 143 ++++++++++++++++++ .../__tests__/size-prop-update-test.js | 12 ++ .../__snapshots__/PublicAPI-test.js.snap | 4 + 4 files changed, 302 insertions(+) create mode 100644 codemods/transforms/__testfixtures__/size-prop-update.input.js create mode 100644 codemods/transforms/__testfixtures__/size-prop-update.output.js create mode 100644 codemods/transforms/__tests__/size-prop-update-test.js diff --git a/codemods/transforms/__testfixtures__/size-prop-update.input.js b/codemods/transforms/__testfixtures__/size-prop-update.input.js new file mode 100644 index 000000000000..8594479a9de9 --- /dev/null +++ b/codemods/transforms/__testfixtures__/size-prop-update.input.js @@ -0,0 +1,143 @@ +function Accordion() { + return ( +
+ + + Test + +
+ ); +} + +function Button() { + return ( +
+ + + + +
+ ); +} + +function ComboBox() { + return ; +} + +function ContentSwitcher() { + return ( + + + + + + ); +} + +function Dropdown() { + return ; +} + +function DataTable() { + return ( +
+
+
+
+ + + +
+ ); +} + +function DatePicker() { + return ( + + + + ); +} + +function FileUploader() { + return ( +
+ + + + + + + + + + + + +
+ ); +} + +function Link() { + return ; +} + +function MultiSelect() { + return ( +
+ (item ? item.text : '')} + /> + (item ? item.text : '')} + /> +
+ ); +} + +function NumberInput() { + return ; +} + +function OverflowMenu() { + return ; +} + +function Search() { + return ( +
+ + +
+ ); +} + +function Select() { + return ( +
+ +
+ ); +} + +function TextInput() { + return ( +
+ + +
+ ); +} + +function TimePicker() { + return ; +} diff --git a/codemods/transforms/__testfixtures__/size-prop-update.output.js b/codemods/transforms/__testfixtures__/size-prop-update.output.js new file mode 100644 index 000000000000..aceb7395d49d --- /dev/null +++ b/codemods/transforms/__testfixtures__/size-prop-update.output.js @@ -0,0 +1,143 @@ +function Accordion() { + return ( +
+ + + Test + +
+ ); +} + +function Button() { + return ( +
+ + + + +
+ ); +} + +function ComboBox() { + return ; +} + +function ContentSwitcher() { + return ( + + + + + + ); +} + +function Dropdown() { + return ; +} + +function DataTable() { + return ( +
+
+
+
+ + + +
+ ); +} + +function DatePicker() { + return ( + + + + ); +} + +function FileUploader() { + return ( +
+ + + + + + + + + + + + +
+ ); +} + +function Link() { + return ; +} + +function MultiSelect() { + return ( +
+ (item ? item.text : '')} + /> + (item ? item.text : '')} + /> +
+ ); +} + +function NumberInput() { + return ; +} + +function OverflowMenu() { + return ; +} + +function Search() { + return ( +
+ + +
+ ); +} + +function Select() { + return ( +
+ +
+ ); +} + +function TextInput() { + return ( +
+ + +
+ ); +} + +function TimePicker() { + return ; +} diff --git a/codemods/transforms/__tests__/size-prop-update-test.js b/codemods/transforms/__tests__/size-prop-update-test.js new file mode 100644 index 000000000000..a21c19fef41d --- /dev/null +++ b/codemods/transforms/__tests__/size-prop-update-test.js @@ -0,0 +1,12 @@ +/** + * Copyright IBM Corp. 2016, 2020 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const { defineTest } = require('jscodeshift/dist/testUtils'); + +defineTest(__dirname, 'size-prop-update'); diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index a950eceeeec8..0634babfbbb8 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -1347,7 +1347,9 @@ Map { "args": Array [ Array [ "small", + "sm", "normal", + "lg", ], ], "type": "oneOf", @@ -1984,7 +1986,9 @@ Map { "args": Array [ Array [ "small", + "sm", "normal", + "lg", ], ], "type": "oneOf", From 55a938c9f4305b606d4e761be9410831afb958b5 Mon Sep 17 00:00:00 2001 From: TJ Egan Date: Wed, 5 May 2021 11:23:49 -0700 Subject: [PATCH 3/3] docs(codemod): remove testing story --- codemods/transforms/size-prop-update.js | 17 +- .../src/components/Test/code-mod-story.js | 298 ------------------ 2 files changed, 1 insertion(+), 314 deletions(-) delete mode 100644 packages/react/src/components/Test/code-mod-story.js diff --git a/codemods/transforms/size-prop-update.js b/codemods/transforms/size-prop-update.js index e92a0a9a684c..c9dfeca47381 100644 --- a/codemods/transforms/size-prop-update.js +++ b/codemods/transforms/size-prop-update.js @@ -7,8 +7,6 @@ 'use strict'; -import fs from 'fs'; - const defaultOptions = { quote: 'auto', trailingComma: true, @@ -131,24 +129,11 @@ function transform(fileInfo, api, options) { 'TextInput', 'TimePicker', ]; + for (const component of components) { replacePropForComponent(component); } - // Remove before merging - // Prints test file to `Test` folder in React package - fs.writeFile( - '../packages/react/src/components/Test/output.js', - root.toSource(), - (err) => { - if (err) { - console.log(err); - } else { - console.log('File written'); - } - } - ); - return root.toSource(printOptions); } diff --git a/packages/react/src/components/Test/code-mod-story.js b/packages/react/src/components/Test/code-mod-story.js deleted file mode 100644 index 571f99735c5c..000000000000 --- a/packages/react/src/components/Test/code-mod-story.js +++ /dev/null @@ -1,298 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* eslint-disable */ -import React from 'react'; -import { - Accordion, - AccordionItem, - Button, - CodeSnippet, - ComboBox, - ContentSwitcher, - Table, - TableHead, - TableRow, - TableHeader, - TableBody, - TableCell, - DatePicker, - DatePickerInput, - Dropdown, - MultiSelect, - NumberInput, - OverflowMenu, - Search, - Select, - Switch, - TextInput, - TimePicker, -} from '../../index'; -import { FeatureFlags } from '../FeatureFlags'; - -const items = [ - { - id: 'option-0', - text: 'Lorem, ipsum dolor sit amet consectetur adipisicing elit.', - }, - { - id: 'option-1', - text: 'Option 1', - }, - { - id: 'option-2', - text: 'Option 2', - }, - { - id: 'option-3', - text: 'Option 3', - }, - { - id: 'option-4', - text: 'Option 4', - }, - { - id: 'option-5', - text: 'Option 5', - }, -]; - -const rows = [ - { - id: 'load-balancer-1', - name: 'Load Balancer 1', - rule: 'Round robin', - Status: 'Starting', - }, - { - id: 'load-balancer-2', - name: 'Load Balancer 2', - rule: 'DNS delegation', - status: 'Active', - }, - { - id: 'load-balancer-3', - name: 'Load Balancer 3', - rule: 'Round robin', - status: 'Disabled', - }, -]; -const headers = ['Name', 'Rule', 'Status']; - -export default { - title: 'CodeMode/Test', - - parameters: { - component: CodeModTest, - }, -}; - -export const CodeModTest = () => { - return ( -
-

Accordion - size XL -> LG

-
- - -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. -

-
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. -

-
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. -

-
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. -

-
-
-
-
- -

Button variants

- -
-
- -
-
- -
-
- -
-
- -
-
- -

ComboBox - size XL -> LG

-
- {}} - id="carbon-combobox" - items={items} - itemToString={(item) => (item ? item.text : '')} - placeholder="Filter..." - titleText="ComboBox title" - helperText="Combobox helper text" - /> -
-
-
- -

Content Switcher - size XL -> LG

- - - - - -
-
- -

Dropdown - size XL -> LG

-
- (item ? item.text : '')} - /> -
-
-
- -

DataTable - size Tall -> XL

- - - - {headers.map((header) => ( - {header} - ))} - - - - {rows.map((row) => ( - - {Object.keys(row) - .filter((key) => key !== 'id') - .map((key) => { - return {row[key]}; - })} - - ))} - -
-
-
- -

Datepicker - size XL -> LG

- - - -
-
- -

Multiselect ( and Filterable) - size XL -> LG

-
- (item ? item.text : '')} - /> -
-
-
- (item ? item.text : '')} - /> -
-
-
- -

Numberinput - size XL -> LG

- -
-
-

OverflowMenu - size XL -> LG

- -
-
-

Search

- -
-
- -
-
-

Select

- -
-
- -
-
-

TextInput

- -
-
- -
-
-

TimePicker - size xl -> lg

- -
- ); -}; - -export const CodeModeTestResults = () => { - // Paste the contents of the code mode inside the component to verify the two stories are the same - return ( - -

- To test the results, navigate to the codemods folder and - run - - yarn jscodeshift -d -t ./transforms/size-prop-update.js - '../packages/react/src/components/Test/code-mod-story.js' - {' '} - and then paste the results into the CodeModeTestResults - story -

-
- ); -}; -/* eslint-enable */