diff --git a/.yarn/offline-mirror/eslint-plugin-react-hooks-2.3.0.tgz b/.yarn/offline-mirror/eslint-plugin-react-hooks-2.3.0.tgz deleted file mode 100644 index be1c1517de58..000000000000 Binary files a/.yarn/offline-mirror/eslint-plugin-react-hooks-2.3.0.tgz and /dev/null differ diff --git a/.yarn/offline-mirror/eslint-plugin-react-hooks-4.0.4.tgz b/.yarn/offline-mirror/eslint-plugin-react-hooks-4.0.4.tgz new file mode 100644 index 000000000000..ec6dfa2b2872 Binary files /dev/null and b/.yarn/offline-mirror/eslint-plugin-react-hooks-4.0.4.tgz differ diff --git a/package.json b/package.json index f401bb7fe07c..908d347b8b67 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "enzyme-adapter-react-16": "^1.14.0", "enzyme-to-json": "^3.3.5", "eslint": "^6.8.0", - "eslint-config-carbon": "10.7.0", + "eslint-config-carbon": "2.0.0", "fs-extra": "^8.1.0", "glob": "^7.1.4", "husky": "^4.0.10", diff --git a/packages/components/demo/js/components/ComponentExample/ComponentExample.js b/packages/components/demo/js/components/ComponentExample/ComponentExample.js index 10d016a5aef7..7ee06db6ae2b 100644 --- a/packages/components/demo/js/components/ComponentExample/ComponentExample.js +++ b/packages/components/demo/js/components/ComponentExample/ComponentExample.js @@ -66,6 +66,7 @@ class ComponentExample extends Component { this._instantiateComponents(); } + // eslint-disable-next-line react/no-deprecated componentWillUpdate({ component, htmlFile }) { const { component: prevComponent, htmlFile: prevHtmlFile } = this.props; if (prevComponent !== component || prevHtmlFile !== htmlFile) { diff --git a/packages/components/demo/js/components/RootPage.js b/packages/components/demo/js/components/RootPage.js index 56d1270d2fa3..38210c689ae5 100644 --- a/packages/components/demo/js/components/RootPage.js +++ b/packages/components/demo/js/components/RootPage.js @@ -195,6 +195,7 @@ class RootPage extends Component { currentTheme: themeSwitcherItems[0].id, }; + // eslint-disable-next-line react/prop-types static getDerivedStateFromProps({ componentItems, isComponentsX }, state) { const { prevComponentItems, @@ -517,6 +518,7 @@ class RootPage extends Component { value={currentTheme} onChange={this._handleChangeThemeSwitcherDropdown}> {themeSwitcherItems.map(({ id, text }) => ( + // eslint-disable-next-line react/jsx-key ))} diff --git a/packages/eslint-config-carbon/base.js b/packages/eslint-config-carbon/base.js new file mode 100644 index 000000000000..a8ea9199579b --- /dev/null +++ b/packages/eslint-config-carbon/base.js @@ -0,0 +1,35 @@ +/** + * Copyright IBM Corp. 2018, 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. + */ + +'use strict'; + +module.exports = { + parser: 'babel-eslint', + extends: ['eslint:recommended', require.resolve('./plugins/jsdoc')], + rules: { + // Handle cases where we are destructuring but may not be using the initial + // variables + 'no-unused-vars': [ + 'error', + { + args: 'after-used', + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + }, + env: { + node: true, + browser: true, + es6: true, + jest: true, + jasmine: true, + }, + globals: { + __DEV__: true, + }, +}; diff --git a/packages/eslint-config-carbon/index.js b/packages/eslint-config-carbon/index.js index f4b3d808275e..7693ab4c0e0f 100644 --- a/packages/eslint-config-carbon/index.js +++ b/packages/eslint-config-carbon/index.js @@ -8,68 +8,5 @@ 'use strict'; module.exports = { - parser: 'babel-eslint', - extends: ['eslint:recommended', 'plugin:jsx-a11y/recommended'], - plugins: ['react', 'jsdoc', 'jsx-a11y', 'react-hooks'], - rules: { - // Handle cases where we are destructuring but may not be using the initial - // variables - 'no-unused-vars': [ - 'error', - { - args: 'after-used', - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - }, - ], - 'react/jsx-uses-vars': 1, - 'react/jsx-uses-react': 1, - 'react/no-find-dom-node': 1, - 'react/no-typos': 2, - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'error', - 'jsdoc/check-param-names': 2, - 'jsdoc/check-tag-names': [ - 'error', - { - definedTags: ['jest-environment'], - }, - ], - 'jsdoc/check-types': 2, - 'jsx-a11y/no-static-element-interactions': 1, - 'jsx-a11y/no-noninteractive-element-interactions': 1, - 'jsx-a11y/click-events-have-key-events': 1, - 'jsx-a11y/anchor-is-valid': 1, - 'jsx-a11y/interactive-supports-focus': 1, - 'jsx-a11y/label-has-for': [ - 1, - { - components: ['Label'], - required: { - some: ['nesting', 'id'], - }, - allowChildren: true, - }, - ], - }, - env: { - node: true, - browser: true, - es6: true, - jest: true, - jasmine: true, - }, - globals: { - __DEV__: true, - }, - settings: { - jsdoc: { - tagNamePreference: { - augments: 'extends', - }, - }, - react: { - version: 'detect', - }, - }, + extends: [require.resolve('./base'), require.resolve('./plugins/react')], }; diff --git a/packages/eslint-config-carbon/package.json b/packages/eslint-config-carbon/package.json index 77b688bd323c..85ac16c36060 100644 --- a/packages/eslint-config-carbon/package.json +++ b/packages/eslint-config-carbon/package.json @@ -1,11 +1,17 @@ { "name": "eslint-config-carbon", "private": true, - "version": "10.7.0", + "version": "2.0.0", "license": "Apache-2.0", "main": "index.js", "repository": "https://github.com/carbon-design-system/carbon/tree/master/packages/eslint-config-carbon", "bugs": "https://github.com/carbon-design-system/carbon/issues", + "files": [ + "plugins", + "index.js", + "react.js", + "vanilla.js" + ], "keywords": [ "ibm", "carbon", @@ -29,7 +35,7 @@ "eslint-plugin-jsx-a11y": "^6.2.1", "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-react": "^7.18.0", - "eslint-plugin-react-hooks": "^2.3.0", + "eslint-plugin-react-hooks": "^4.0.4", "eslint-restricted-globals": "^0.2.0" } } diff --git a/packages/eslint-config-carbon/plugins/jsdoc.js b/packages/eslint-config-carbon/plugins/jsdoc.js new file mode 100644 index 000000000000..08a70be27054 --- /dev/null +++ b/packages/eslint-config-carbon/plugins/jsdoc.js @@ -0,0 +1,29 @@ +/** + * Copyright IBM Corp. 2018, 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. + */ + +'use strict'; + +module.exports = { + plugins: ['jsdoc'], + settings: { + jsdoc: { + tagNamePreference: { + augments: 'extends', + }, + }, + }, + rules: { + 'jsdoc/check-param-names': 2, + 'jsdoc/check-tag-names': [ + 'error', + { + definedTags: ['jest-environment'], + }, + ], + 'jsdoc/check-types': 2, + }, +}; diff --git a/packages/eslint-config-carbon/plugins/react.js b/packages/eslint-config-carbon/plugins/react.js new file mode 100644 index 000000000000..7b4bbc9b2615 --- /dev/null +++ b/packages/eslint-config-carbon/plugins/react.js @@ -0,0 +1,81 @@ +/** + * Copyright IBM Corp. 2018, 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. + */ + +'use strict'; + +module.exports = { + extends: [ + 'plugin:react/recommended', + 'plugin:react-hooks/recommended', + 'plugin:jsx-a11y/recommended', + ], + plugins: ['react', 'react-hooks'], + settings: { + react: { + version: 'detect', + }, + }, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + rules: { + // react + 'react/jsx-uses-vars': 1, + 'react/jsx-uses-react': 1, + 'react/no-find-dom-node': 1, + 'react/jsx-no-useless-fragment': 2, + 'react/no-typos': 2, + + // react-hooks + 'react-hooks/rules-of-hooks': 2, + 'react-hooks/exhaustive-deps': 2, + }, + overrides: [ + // Sometimes we'll want to define a quick component in a story to use as a + // wrapper for a component we're documenting. For example: + // + // function DemoComponent({ children }) { + // return

{children}

; + // } + // + // In these cases, we don't need to handle prop type validation like we + // would for code we ship to users. + { + files: ['*-story.js'], + rules: { + 'react/prop-types': 0, + }, + }, + + // When writing fixtures, we tend to focus on the specific component and + // don't require React in scope as we never end up executing the code. The + // fixtures are often used for asserting transformations on the file + { + files: ['**/fixtures/**/*.js'], + rules: { + 'react/react-in-jsx-scope': 0, + }, + }, + + { + files: ['*-test.js'], + rules: { + // We often write inline functions for certain types of props, typically + // `render*` props. For example, `renderIcon={() =>
test
}` + 'react/display-name': 0, + + // While writing tests, we often write helper components that are meant + // to emulate a specific situation or behavior. These do not require prop + // types as they are not shipped to end-users and are not valuable for + // test authors. + 'react/prop-types': 0, + }, + }, + ], +}; diff --git a/packages/icon-build-helpers/src/builders/react/components/__tests__/Icon-test.js b/packages/icon-build-helpers/src/builders/react/components/__tests__/Icon-test.js index d9283a8e0b60..fc00dd472fac 100644 --- a/packages/icon-build-helpers/src/builders/react/components/__tests__/Icon-test.js +++ b/packages/icon-build-helpers/src/builders/react/components/__tests__/Icon-test.js @@ -92,7 +92,6 @@ describe('Icon', () => { width={16} height={16} viewBox="0 0 16 16" - tabIndex="0" aria-label="Mock icon" tabIndex="0"> diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index c3b48c579528..1207c8b83880 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -68,6 +68,19 @@ Map { }, "BreadcrumbItem" => Object { "propTypes": Object { + "aria-current": Object { + "args": Array [ + Array [ + Object { + "type": "string", + }, + Object { + "type": "bool", + }, + ], + ], + "type": "oneOfType", + }, "children": Object { "type": "node", }, @@ -449,6 +462,9 @@ Map { ], "type": "shape", }, + "helperText": Object { + "type": "string", + }, "id": Object { "isRequired": true, "type": "string", @@ -521,6 +537,9 @@ Map { ], "type": "oneOf", }, + "titleText": Object { + "type": "string", + }, "translateWithId": Object { "type": "func", }, @@ -541,12 +560,18 @@ Map { "selectorPrimaryFocus": "[data-modal-primary-focus]", }, "propTypes": Object { + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, "containerClassName": Object { "type": "string", }, + "danger": Object { + "type": "bool", + }, "onClose": Object { "type": "func", }, @@ -559,6 +584,9 @@ Map { "selectorPrimaryFocus": Object { "type": "string", }, + "selectorsFloatingMenus": Object { + "type": "string", + }, "size": Object { "args": Array [ Array [ @@ -615,6 +643,9 @@ Map { "ModalBody" => Object { "propTypes": Object { "aria-label": [Function], + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, @@ -644,6 +675,26 @@ Map { "danger": Object { "type": "bool", }, + "inputref": Object { + "args": Array [ + Array [ + Object { + "type": "func", + }, + Object { + "args": Array [ + Object { + "current": Object { + "type": "any", + }, + }, + ], + "type": "shape", + }, + ], + ], + "type": "oneOfType", + }, "onRequestClose": Object { "type": "func", }, @@ -716,6 +767,9 @@ Map { "feedbackTimeout": Object { "type": "number", }, + "onAnimationEnd": Object { + "type": "func", + }, "onClick": Object { "type": "func", }, @@ -754,6 +808,9 @@ Map { "overflowMenuOnHover": true, }, "propTypes": Object { + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, @@ -897,6 +954,9 @@ Map { "description": Object { "type": "node", }, + "stickyHeader": Object { + "type": "bool", + }, "title": Object { "type": "node", }, @@ -911,6 +971,9 @@ Map { "className": Object { "type": "string", }, + "enableExpando": Object { + "type": "bool", + }, "expandIconDescription": Object { "type": "string", }, @@ -943,6 +1006,9 @@ Map { "isRequired": true, "type": "bool", }, + "isSelected": Object { + "type": "bool", + }, "onExpand": Object { "isRequired": true, "type": "func", @@ -1026,6 +1092,9 @@ Map { "className": Object { "type": "string", }, + "isSelected": Object { + "type": "bool", + }, }, }, "TableSelectAll": Object { @@ -1044,6 +1113,9 @@ Map { "className": Object { "type": "string", }, + "disabled": Object { + "type": "bool", + }, "id": Object { "isRequired": true, "type": "string", @@ -1188,9 +1260,15 @@ Map { "className": Object { "type": "string", }, + "defaultExpanded": Object { + "type": "bool", + }, "defaultValue": Object { "type": "string", }, + "expanded": Object { + "type": "bool", + }, "id": Object { "type": "string", }, @@ -1200,6 +1278,9 @@ Map { "onChange": Object { "type": "func", }, + "onExpand": Object { + "type": "func", + }, "persistant": [Function], "persistent": Object { "type": "bool", @@ -1207,7 +1288,7 @@ Map { "placeHolderText": Object { "type": "string", }, - "searchContainerClasses": Object { + "searchContainerClass": Object { "type": "string", }, "tabIndex": Object { @@ -1300,6 +1381,9 @@ Map { "isRequired": true, "type": "arrayOf", }, + "shouldShowBorder": Object { + "type": "bool", + }, "size": Object { "args": Array [ Array [ @@ -1320,6 +1404,12 @@ Map { "translateWithId": Object { "type": "func", }, + "useStaticWidth": Object { + "type": "bool", + }, + "useZebraStyles": Object { + "type": "bool", + }, }, "translationKeys": Array [ "carbon.table.row.expand", @@ -1338,6 +1428,9 @@ Map { "overflowMenuOnHover": true, }, "propTypes": Object { + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, @@ -1481,6 +1574,9 @@ Map { "description": Object { "type": "node", }, + "stickyHeader": Object { + "type": "bool", + }, "title": Object { "type": "node", }, @@ -1495,6 +1591,9 @@ Map { "className": Object { "type": "string", }, + "enableExpando": Object { + "type": "bool", + }, "expandIconDescription": Object { "type": "string", }, @@ -1527,6 +1626,9 @@ Map { "isRequired": true, "type": "bool", }, + "isSelected": Object { + "type": "bool", + }, "onExpand": Object { "isRequired": true, "type": "func", @@ -1610,6 +1712,9 @@ Map { "className": Object { "type": "string", }, + "isSelected": Object { + "type": "bool", + }, }, }, "TableSelectAll" => Object { @@ -1628,6 +1733,9 @@ Map { "className": Object { "type": "string", }, + "disabled": Object { + "type": "bool", + }, "id": Object { "isRequired": true, "type": "string", @@ -1737,9 +1845,15 @@ Map { "className": Object { "type": "string", }, + "defaultExpanded": Object { + "type": "bool", + }, "defaultValue": Object { "type": "string", }, + "expanded": Object { + "type": "bool", + }, "id": Object { "type": "string", }, @@ -1749,6 +1863,9 @@ Map { "onChange": Object { "type": "func", }, + "onExpand": Object { + "type": "func", + }, "persistant": [Function], "persistent": Object { "type": "bool", @@ -1756,7 +1873,7 @@ Map { "placeHolderText": Object { "type": "string", }, - "searchContainerClasses": Object { + "searchContainerClass": Object { "type": "string", }, "tabIndex": Object { @@ -1968,9 +2085,22 @@ Map { "type": "text", }, "propTypes": Object { + "datePickerType": Object { + "args": Array [ + Array [ + "simple", + "single", + "range", + ], + ], + "type": "oneOf", + }, "disabled": Object { "type": "bool", }, + "hideLabel": Object { + "type": "bool", + }, "iconDescription": Object { "type": "string", }, @@ -1981,6 +2111,9 @@ Map { "invalid": Object { "type": "bool", }, + "invalidText": Object { + "type": "string", + }, "labelText": Object { "isRequired": true, "type": "node", @@ -1991,7 +2124,13 @@ Map { "onClick": Object { "type": "func", }, + "openCalendar": Object { + "type": "func", + }, "pattern": [Function], + "placeholder": Object { + "type": "string", + }, "size": Object { "args": Array [ Array [ @@ -2021,6 +2160,9 @@ Map { "ariaLabel": Object { "type": "string", }, + "className": Object { + "type": "string", + }, "direction": Object { "args": Array [ Array [ @@ -2276,6 +2418,9 @@ Map { "iconDescription": Object { "type": "string", }, + "invalid": Object { + "type": "bool", + }, "status": Object { "args": Array [ Array [ @@ -2433,6 +2578,16 @@ Map { "onDelete": Object { "type": "func", }, + "size": Object { + "args": Array [ + Array [ + "default", + "field", + "small", + ], + ], + "type": "oneOf", + }, "status": Object { "args": Array [ Array [ @@ -2776,6 +2931,9 @@ Map { "iconTitle": Object { "type": "string", }, + "name": Object { + "type": "string", + }, "role": Object { "type": "string", }, @@ -3027,6 +3185,9 @@ Map { "modalText": Object { "type": "string", }, + "onKeyDown": Object { + "type": "func", + }, "passiveModal": Object { "type": "bool", }, @@ -3049,6 +3210,9 @@ Map { "secondaryButtonText": Object { "type": "string", }, + "selectorPrimaryFocus": Object { + "type": "string", + }, "shouldCloseAfterSubmit": Object { "type": "bool", }, @@ -3793,12 +3957,18 @@ Map { "disabled": Object { "type": "bool", }, + "handleOverflowMenuItemFocus": Object { + "type": "func", + }, "hasDivider": Object { "type": "bool", }, "href": Object { "type": "string", }, + "index": Object { + "type": "number", + }, "isDelete": Object { "type": "bool", }, @@ -4118,6 +4288,9 @@ Map { "light": Object { "type": "bool", }, + "onChange": Object { + "type": "func", + }, "placeHolderText": Object { "type": "string", }, @@ -4394,6 +4567,9 @@ Map { "inputType": Object { "type": "string", }, + "invalid": Object { + "type": "bool", + }, "labelText": Object { "type": "node", }, @@ -4423,6 +4599,9 @@ Map { "onRelease": Object { "type": "func", }, + "required": Object { + "type": "bool", + }, "step": Object { "type": "number", }, @@ -4740,6 +4919,9 @@ Map { "filter": Object { "type": "bool", }, + "id": Object { + "type": "string", + }, "onClose": Object { "type": "func", }, @@ -5192,6 +5374,12 @@ Map { "className": Object { "type": "string", }, + "handleClick": Object { + "type": "func", + }, + "handleKeyDown": Object { + "type": "func", + }, "href": Object { "type": "string", }, @@ -5221,6 +5409,12 @@ Map { "className": Object { "type": "string", }, + "handleClick": Object { + "type": "func", + }, + "handleKeyDown": Object { + "type": "func", + }, "iconDescription": [Function], "id": Object { "type": "string", @@ -5281,6 +5475,9 @@ Map { "expanded": Object { "type": "bool", }, + "handleClick": Object { + "type": "func", + }, "id": Object { "type": "string", }, @@ -5325,6 +5522,9 @@ Map { "checked": Object { "type": "bool", }, + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, @@ -5556,6 +5756,9 @@ Map { "labelText": Object { "type": "string", }, + "onChange": Object { + "type": "func", + }, "onToggle": Object { "type": "func", }, @@ -5597,6 +5800,9 @@ Map { "labelText": Object { "type": "string", }, + "onChange": Object { + "type": "func", + }, "onToggle": Object { "type": "func", }, @@ -5672,12 +5878,18 @@ Map { "id": Object { "type": "string", }, + "labelId": Object { + "type": "string", + }, "labelText": Object { "type": "node", }, "placeHolderText": Object { "type": "string", }, + "role": Object { + "type": "string", + }, "small": Object { "type": "bool", }, @@ -5710,6 +5922,9 @@ Map { "isRequired": true, "type": "string", }, + "className": Object { + "type": "string", + }, "direction": Object { "args": Array [ Array [ @@ -5722,6 +5937,15 @@ Map { "id": Object { "type": "string", }, + "onFocus": Object { + "type": "func", + }, + "onMouseEnter": Object { + "type": "func", + }, + "onMouseLeave": Object { + "type": "func", + }, "tooltipText": Object { "isRequired": true, "type": "node", @@ -5751,6 +5975,9 @@ Map { "isRequired": true, "type": "node", }, + "className": Object { + "type": "string", + }, "direction": Object { "args": Array [ Array [ @@ -5765,6 +5992,12 @@ Map { "id": Object { "type": "string", }, + "onFocus": Object { + "type": "func", + }, + "onMouseEnter": Object { + "type": "func", + }, "tooltipText": Object { "isRequired": true, "type": "string", @@ -6137,6 +6370,9 @@ Map { "className": Object { "type": "string", }, + "id": Object { + "type": "string", + }, "range": Object { "type": "bool", }, @@ -6441,6 +6677,9 @@ Map { "hasDivider": false, }, "propTypes": Object { + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, @@ -6497,6 +6736,9 @@ Map { "isRequired": true, "type": "string", }, + "className": Object { + "type": "string", + }, "href": Object { "isRequired": true, "type": "string", @@ -6579,6 +6821,9 @@ Map { "isRequired": true, "type": "string", }, + "className": Object { + "type": "string", + }, "expanded": Object { "isRequired": true, "type": "bool", @@ -6594,6 +6839,9 @@ Map { }, "SideNavHeader" => Object { "propTypes": Object { + "children": Object { + "type": "node", + }, "className": Object { "type": "string", }, diff --git a/packages/react/src/components/Breadcrumb/BreadcrumbItem.js b/packages/react/src/components/Breadcrumb/BreadcrumbItem.js index 6310cabad87b..3c01f1a22813 100644 --- a/packages/react/src/components/Breadcrumb/BreadcrumbItem.js +++ b/packages/react/src/components/Breadcrumb/BreadcrumbItem.js @@ -51,6 +51,8 @@ const BreadcrumbItem = ({ }; BreadcrumbItem.propTypes = { + 'aria-current': PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), + /** * Pass in content that will be inside of the BreadcrumbItem */ diff --git a/packages/react/src/components/Checkbox/Checkbox-story.js b/packages/react/src/components/Checkbox/Checkbox-story.js index 87e8b1850777..60319cc474f5 100644 --- a/packages/react/src/components/Checkbox/Checkbox-story.js +++ b/packages/react/src/components/Checkbox/Checkbox-story.js @@ -79,7 +79,7 @@ storiesOf('Checkbox', module) aria-label="loading checkbox" aria-live="assertive" role="status" - tabindex="0" // eslint-disable-line jsx-a11y/no-noninteractive-tabindex + tabIndex="0" // eslint-disable-line jsx-a11y/no-noninteractive-tabindex > diff --git a/packages/react/src/components/ComboBox/ComboBox.js b/packages/react/src/components/ComboBox/ComboBox.js index 11c6b28d02af..e71be91f083b 100644 --- a/packages/react/src/components/ComboBox/ComboBox.js +++ b/packages/react/src/components/ComboBox/ComboBox.js @@ -180,6 +180,9 @@ export default class ComboBox extends React.Component { * Specify the direction of the combobox dropdown. Can be either top or bottom. */ direction: PropTypes.oneOf(['top', 'bottom']), + + titleText: PropTypes.string, + helperText: PropTypes.string, }; static defaultProps = { diff --git a/packages/react/src/components/ComposedModal/ComposedModal-story.js b/packages/react/src/components/ComposedModal/ComposedModal-story.js index b9619bc20e6f..65aeb6576a92 100644 --- a/packages/react/src/components/ComposedModal/ComposedModal-story.js +++ b/packages/react/src/components/ComposedModal/ComposedModal-story.js @@ -141,7 +141,7 @@ storiesOf('ComposedModal', module) const { size, ...rest } = props.composedModal(); const { hasScrollingContent, ...bodyProps } = props.modalBody(); return ( - + + ref={inputref}> {primaryButtonText} )} diff --git a/packages/react/src/components/Copy/Copy.js b/packages/react/src/components/Copy/Copy.js index 9c1ef3534b42..812e056c5f19 100644 --- a/packages/react/src/components/Copy/Copy.js +++ b/packages/react/src/components/Copy/Copy.js @@ -28,12 +28,14 @@ export default function Copy({ [`${prefix}--copy-btn--animating`]: animation, [`${prefix}--copy-btn--${animation}`]: animation, }); + // eslint-disable-next-line react-hooks/exhaustive-deps const handleFadeOut = useCallback( debounce(() => { setAnimation('fade-out'); }, feedbackTimeout), [feedbackTimeout] ); + const handleClick = useCallback(() => { setAnimation('fade-in'); handleFadeOut(); @@ -99,6 +101,12 @@ Copy.propTypes = { *