diff --git a/.nvmrc b/.nvmrc index 2ef343043146..932b2b01d712 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.14 +18.15 diff --git a/.yarn/cache/@types-cheerio-npm-0.22.29-35d27ce75a-4f872a0469.zip b/.yarn/cache/@types-cheerio-npm-0.22.29-35d27ce75a-4f872a0469.zip deleted file mode 100644 index 3ea0f056fbdf..000000000000 Binary files a/.yarn/cache/@types-cheerio-npm-0.22.29-35d27ce75a-4f872a0469.zip and /dev/null differ diff --git a/.yarn/cache/@wojtekmaj-enzyme-adapter-react-17-npm-0.8.0-898ccbe6bd-aa9674f06f.zip b/.yarn/cache/@wojtekmaj-enzyme-adapter-react-17-npm-0.8.0-898ccbe6bd-aa9674f06f.zip deleted file mode 100644 index 60da09ac63b2..000000000000 Binary files a/.yarn/cache/@wojtekmaj-enzyme-adapter-react-17-npm-0.8.0-898ccbe6bd-aa9674f06f.zip and /dev/null differ diff --git a/.yarn/cache/@wojtekmaj-enzyme-adapter-utils-npm-0.2.0-733e83a927-837741f138.zip b/.yarn/cache/@wojtekmaj-enzyme-adapter-utils-npm-0.2.0-733e83a927-837741f138.zip deleted file mode 100644 index d5237261de22..000000000000 Binary files a/.yarn/cache/@wojtekmaj-enzyme-adapter-utils-npm-0.2.0-733e83a927-837741f138.zip and /dev/null differ diff --git a/.yarn/cache/array-filter-npm-1.0.0-2d57caf5c8-467054291f.zip b/.yarn/cache/array-filter-npm-1.0.0-2d57caf5c8-467054291f.zip deleted file mode 100644 index 95065f5fb0ef..000000000000 Binary files a/.yarn/cache/array-filter-npm-1.0.0-2d57caf5c8-467054291f.zip and /dev/null differ diff --git a/.yarn/cache/cheerio-npm-1.0.0-rc.3-27acf9bb0c-90163e8f36.zip b/.yarn/cache/cheerio-npm-1.0.0-rc.3-27acf9bb0c-90163e8f36.zip deleted file mode 100644 index 1784e3a43481..000000000000 Binary files a/.yarn/cache/cheerio-npm-1.0.0-rc.3-27acf9bb0c-90163e8f36.zip and /dev/null differ diff --git a/.yarn/cache/css-select-npm-1.2.0-a7a03607e0-607cca60d2.zip b/.yarn/cache/css-select-npm-1.2.0-a7a03607e0-607cca60d2.zip deleted file mode 100644 index 5402a1d2f8fb..000000000000 Binary files a/.yarn/cache/css-select-npm-1.2.0-a7a03607e0-607cca60d2.zip and /dev/null differ diff --git a/.yarn/cache/css-what-npm-2.1.3-a9583898e8-a52d56c591.zip b/.yarn/cache/css-what-npm-2.1.3-a9583898e8-a52d56c591.zip deleted file mode 100644 index 212013c37137..000000000000 Binary files a/.yarn/cache/css-what-npm-2.1.3-a9583898e8-a52d56c591.zip and /dev/null differ diff --git a/.yarn/cache/discontinuous-range-npm-1.0.0-572abfd975-8ee88d7082.zip b/.yarn/cache/discontinuous-range-npm-1.0.0-572abfd975-8ee88d7082.zip deleted file mode 100644 index 74176736b041..000000000000 Binary files a/.yarn/cache/discontinuous-range-npm-1.0.0-572abfd975-8ee88d7082.zip and /dev/null differ diff --git a/.yarn/cache/dom-serializer-npm-0.1.1-4c6e4ec242-4f6a3eff80.zip b/.yarn/cache/dom-serializer-npm-0.1.1-4c6e4ec242-4f6a3eff80.zip deleted file mode 100644 index 325a14f349cd..000000000000 Binary files a/.yarn/cache/dom-serializer-npm-0.1.1-4c6e4ec242-4f6a3eff80.zip and /dev/null differ diff --git a/.yarn/cache/domhandler-npm-2.4.2-497ea9cea1-49bd70c9c7.zip b/.yarn/cache/domhandler-npm-2.4.2-497ea9cea1-49bd70c9c7.zip deleted file mode 100644 index ccabf332fdbe..000000000000 Binary files a/.yarn/cache/domhandler-npm-2.4.2-497ea9cea1-49bd70c9c7.zip and /dev/null differ diff --git a/.yarn/cache/domutils-npm-1.5.1-6f8de414e8-800d1f9d1c.zip b/.yarn/cache/domutils-npm-1.5.1-6f8de414e8-800d1f9d1c.zip deleted file mode 100644 index 531ccc7179c2..000000000000 Binary files a/.yarn/cache/domutils-npm-1.5.1-6f8de414e8-800d1f9d1c.zip and /dev/null differ diff --git a/.yarn/cache/enhanced-resolve-npm-5.9.3-a003123a80-64c2dbbdd6.zip b/.yarn/cache/enhanced-resolve-npm-5.12.0-c291ce4ee3-bf3f787fac.zip similarity index 57% rename from .yarn/cache/enhanced-resolve-npm-5.9.3-a003123a80-64c2dbbdd6.zip rename to .yarn/cache/enhanced-resolve-npm-5.12.0-c291ce4ee3-bf3f787fac.zip index 0290e65e0506..2c4f4e4e5aee 100644 Binary files a/.yarn/cache/enhanced-resolve-npm-5.9.3-a003123a80-64c2dbbdd6.zip and b/.yarn/cache/enhanced-resolve-npm-5.12.0-c291ce4ee3-bf3f787fac.zip differ diff --git a/.yarn/cache/enzyme-npm-3.11.0-74bfb15742-69ae80049c.zip b/.yarn/cache/enzyme-npm-3.11.0-74bfb15742-69ae80049c.zip deleted file mode 100644 index 9e190512f003..000000000000 Binary files a/.yarn/cache/enzyme-npm-3.11.0-74bfb15742-69ae80049c.zip and /dev/null differ diff --git a/.yarn/cache/enzyme-shallow-equal-npm-1.0.4-208ea272dd-54bbad0955.zip b/.yarn/cache/enzyme-shallow-equal-npm-1.0.4-208ea272dd-54bbad0955.zip deleted file mode 100644 index 0161fda9dece..000000000000 Binary files a/.yarn/cache/enzyme-shallow-equal-npm-1.0.4-208ea272dd-54bbad0955.zip and /dev/null differ diff --git a/.yarn/cache/enzyme-to-json-npm-3.6.2-ea15cbb1e0-e81f3dc05b.zip b/.yarn/cache/enzyme-to-json-npm-3.6.2-ea15cbb1e0-e81f3dc05b.zip deleted file mode 100644 index 8136bf58ec10..000000000000 Binary files a/.yarn/cache/enzyme-to-json-npm-3.6.2-ea15cbb1e0-e81f3dc05b.zip and /dev/null differ diff --git a/.yarn/cache/html-element-map-npm-1.2.0-d84ca33cc2-b5e7cad2da.zip b/.yarn/cache/html-element-map-npm-1.2.0-d84ca33cc2-b5e7cad2da.zip deleted file mode 100644 index 576021037573..000000000000 Binary files a/.yarn/cache/html-element-map-npm-1.2.0-d84ca33cc2-b5e7cad2da.zip and /dev/null differ diff --git a/.yarn/cache/htmlparser2-npm-3.10.1-1bc462e640-6875f7dd87.zip b/.yarn/cache/htmlparser2-npm-3.10.1-1bc462e640-6875f7dd87.zip deleted file mode 100644 index 4a862bde24f3..000000000000 Binary files a/.yarn/cache/htmlparser2-npm-3.10.1-1bc462e640-6875f7dd87.zip and /dev/null differ diff --git a/.yarn/cache/is-subset-npm-0.1.1-15dc569569-97b8d7852a.zip b/.yarn/cache/is-subset-npm-0.1.1-15dc569569-97b8d7852a.zip deleted file mode 100644 index 80a9a8ac0258..000000000000 Binary files a/.yarn/cache/is-subset-npm-0.1.1-15dc569569-97b8d7852a.zip and /dev/null differ diff --git a/.yarn/cache/lodash.escape-npm-4.0.1-5ea709377f-fcb54f4574.zip b/.yarn/cache/lodash.escape-npm-4.0.1-5ea709377f-fcb54f4574.zip deleted file mode 100644 index 28e03c3b77f0..000000000000 Binary files a/.yarn/cache/lodash.escape-npm-4.0.1-5ea709377f-fcb54f4574.zip and /dev/null differ diff --git a/.yarn/cache/lodash.flattendeep-npm-4.4.0-26b2b4cbd7-8521c919ac.zip b/.yarn/cache/lodash.flattendeep-npm-4.4.0-26b2b4cbd7-8521c919ac.zip deleted file mode 100644 index 7e35ec6c7b5e..000000000000 Binary files a/.yarn/cache/lodash.flattendeep-npm-4.4.0-26b2b4cbd7-8521c919ac.zip and /dev/null differ diff --git a/.yarn/cache/moo-npm-0.5.1-6281c30315-2d8c013f1f.zip b/.yarn/cache/moo-npm-0.5.1-6281c30315-2d8c013f1f.zip deleted file mode 100644 index 5f1049e494c5..000000000000 Binary files a/.yarn/cache/moo-npm-0.5.1-6281c30315-2d8c013f1f.zip and /dev/null differ diff --git a/.yarn/cache/nearley-npm-2.19.1-ea5339fa47-790f11929c.zip b/.yarn/cache/nearley-npm-2.19.1-ea5339fa47-790f11929c.zip deleted file mode 100644 index 7510268ec30e..000000000000 Binary files a/.yarn/cache/nearley-npm-2.19.1-ea5339fa47-790f11929c.zip and /dev/null differ diff --git a/.yarn/cache/parse5-npm-3.0.3-fb7c9e4969-6a82d59d60.zip b/.yarn/cache/parse5-npm-3.0.3-fb7c9e4969-6a82d59d60.zip deleted file mode 100644 index 5e728261bdbc..000000000000 Binary files a/.yarn/cache/parse5-npm-3.0.3-fb7c9e4969-6a82d59d60.zip and /dev/null differ diff --git a/.yarn/cache/railroad-diagrams-npm-1.0.0-ab8798413c-9e312af352.zip b/.yarn/cache/railroad-diagrams-npm-1.0.0-ab8798413c-9e312af352.zip deleted file mode 100644 index 262e5c4c9074..000000000000 Binary files a/.yarn/cache/railroad-diagrams-npm-1.0.0-ab8798413c-9e312af352.zip and /dev/null differ diff --git a/.yarn/cache/randexp-npm-0.4.6-60140c8119-3c0d440a3f.zip b/.yarn/cache/randexp-npm-0.4.6-60140c8119-3c0d440a3f.zip deleted file mode 100644 index 1647bb8679c0..000000000000 Binary files a/.yarn/cache/randexp-npm-0.4.6-60140c8119-3c0d440a3f.zip and /dev/null differ diff --git a/.yarn/cache/react-shallow-renderer-npm-16.14.1-b8a4f845ff-f344c663c4.zip b/.yarn/cache/react-shallow-renderer-npm-16.14.1-b8a4f845ff-f344c663c4.zip deleted file mode 100644 index a10480a8b0d6..000000000000 Binary files a/.yarn/cache/react-shallow-renderer-npm-16.14.1-b8a4f845ff-f344c663c4.zip and /dev/null differ diff --git a/.yarn/cache/react-test-renderer-npm-17.0.2-1086717127-e6b5c6ed2a.zip b/.yarn/cache/react-test-renderer-npm-17.0.2-1086717127-e6b5c6ed2a.zip deleted file mode 100644 index d3323bfc72ee..000000000000 Binary files a/.yarn/cache/react-test-renderer-npm-17.0.2-1086717127-e6b5c6ed2a.zip and /dev/null differ diff --git a/.yarn/cache/rst-selector-parser-npm-2.2.3-94eed38823-fbfb2f6a7d.zip b/.yarn/cache/rst-selector-parser-npm-2.2.3-94eed38823-fbfb2f6a7d.zip deleted file mode 100644 index 9f8f8488fe83..000000000000 Binary files a/.yarn/cache/rst-selector-parser-npm-2.2.3-94eed38823-fbfb2f6a7d.zip and /dev/null differ diff --git a/.yarn/cache/string.prototype.trim-npm-1.2.1-d9e9f2fdd7-ff77c2b022.zip b/.yarn/cache/string.prototype.trim-npm-1.2.1-d9e9f2fdd7-ff77c2b022.zip deleted file mode 100644 index c38ddda9a503..000000000000 Binary files a/.yarn/cache/string.prototype.trim-npm-1.2.1-d9e9f2fdd7-ff77c2b022.zip and /dev/null differ diff --git a/.yarn/cache/watchpack-npm-2.3.1-89e7852543-70a34f9284.zip b/.yarn/cache/watchpack-npm-2.4.0-7ec4b9cc65-23d4bc5863.zip similarity index 63% rename from .yarn/cache/watchpack-npm-2.3.1-89e7852543-70a34f9284.zip rename to .yarn/cache/watchpack-npm-2.4.0-7ec4b9cc65-23d4bc5863.zip index c49c6a16551a..ed21e484ead3 100644 Binary files a/.yarn/cache/watchpack-npm-2.3.1-89e7852543-70a34f9284.zip and b/.yarn/cache/watchpack-npm-2.4.0-7ec4b9cc65-23d4bc5863.zip differ diff --git a/.yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip b/.yarn/cache/webpack-npm-5.76.1-9aeb64c072-b01fe0bc2d.zip similarity index 74% rename from .yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip rename to .yarn/cache/webpack-npm-5.76.1-9aeb64c072-b01fe0bc2d.zip index 9f77205ce468..fcb3132fe3c0 100644 Binary files a/.yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip and b/.yarn/cache/webpack-npm-5.76.1-9aeb64c072-b01fe0bc2d.zip differ diff --git a/config/jest-config-carbon/index.js b/config/jest-config-carbon/index.js index cb86b4228a3d..311f704a4cca 100644 --- a/config/jest-config-carbon/index.js +++ b/config/jest-config-carbon/index.js @@ -20,7 +20,6 @@ module.exports = { reporters: ['default'], setupFiles: [require.resolve('./setup/setup.js')], setupFilesAfterEnv: [require.resolve('./setup/setupAfterEnv.js')], - snapshotSerializers: ['enzyme-to-json/serializer'], testMatch: [ '/**/__tests__/**/*.js?(x)', '/**/*.(spec|test).js?(x)', diff --git a/config/jest-config-carbon/package.json b/config/jest-config-carbon/package.json index ff82d4b82fab..6ba027164ae5 100644 --- a/config/jest-config-carbon/package.json +++ b/config/jest-config-carbon/package.json @@ -2,7 +2,7 @@ "name": "jest-config-carbon", "private": true, "description": "Jest configuration and preset for Carbon", - "version": "1.7.0", + "version": "1.8.0", "license": "Apache-2.0", "main": "index.js", "repository": { @@ -27,13 +27,10 @@ "@babel/preset-env": "^7.18.2", "@babel/preset-react": "^7.17.12", "@babel/runtime": "^7.18.3", - "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "accessibility-checker": "^3.1.32", "axe-core": "^4.3.5", "babel-jest": "^28.1.0", "chalk": "^4.1.1", - "enzyme": "^3.11.0", - "enzyme-to-json": "^3.6.2", "jest-circus": "^28.1.0", "jest-environment-jsdom": "^28.1.0", "jest-watch-typeahead": "^1.1.0", diff --git a/config/jest-config-carbon/setup/setup.js b/config/jest-config-carbon/setup/setup.js index 6a8cc9eeb59f..f3b0ff11f2bf 100644 --- a/config/jest-config-carbon/setup/setup.js +++ b/config/jest-config-carbon/setup/setup.js @@ -17,11 +17,6 @@ global.requestAnimationFrame = function requestAnimationFrame(callback) { callback(); }; -const enzyme = jest.requireActual('enzyme'); -const Adapter = jest.requireActual('@wojtekmaj/enzyme-adapter-react-17'); - -enzyme.configure({ adapter: new Adapter() }); - if (global.HTMLElement) { // This is a quirk that we need to bring in due to how our `tabbable` dependency // determines what nodes are focusable. Without this override, it's unable to diff --git a/docs/release.md b/docs/release.md index 3b95f7cb1d99..2f3cdcaabed1 100644 --- a/docs/release.md +++ b/docs/release.md @@ -133,7 +133,7 @@ following: to automatically generate the prerelease versions for packages - [ ] Specify `minor` as the release type - [ ] Provide the tag for the release. For example, if the previous release - was `v11.1.0-rc.0` this tag would be `v11.2.0`. To find the previous + was `v11.1.0-rc.0` this tag would be `v11.1.0`. To find the previous release, view the [tag list](https://github.com/carbon-design-system/carbon/tags). - [ ] Review and approve the Pull Request generated from this action diff --git a/e2e/components/ComboButton/ComboButton-test.e2e.js b/e2e/components/ComboButton/ComboButton-test.e2e.js new file mode 100644 index 000000000000..56dc75346093 --- /dev/null +++ b/e2e/components/ComboButton/ComboButton-test.e2e.js @@ -0,0 +1,37 @@ +/** + * Copyright IBM Corp. 2023 + * + * 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 { expect, test } = require('@playwright/test'); +const { themes } = require('../../test-utils/env'); +const { snapshotStory, visitStory } = require('../../test-utils/storybook'); + +test.describe('ComboButton', () => { + themes.forEach((theme) => { + test.describe(theme, () => { + test('combo-button @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'ComboButton', + id: 'experimental-unstable-combobutton--default', + theme, + }); + }); + }); + }); + + test('accessibility-checker @avt', async ({ page }) => { + await visitStory(page, { + component: 'ComboButton', + id: 'experimental-unstable-combobutton--default', + globals: { + theme: 'white', + }, + }); + await expect(page).toHaveNoACViolations('ComboButton'); + }); +}); diff --git a/e2e/components/MenuButton/MenuButton-test.e2e.js b/e2e/components/MenuButton/MenuButton-test.e2e.js new file mode 100644 index 000000000000..b11456cb0ff6 --- /dev/null +++ b/e2e/components/MenuButton/MenuButton-test.e2e.js @@ -0,0 +1,37 @@ +/** + * Copyright IBM Corp. 2023 + * + * 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 { expect, test } = require('@playwright/test'); +const { themes } = require('../../test-utils/env'); +const { snapshotStory, visitStory } = require('../../test-utils/storybook'); + +test.describe('MenuButton', () => { + themes.forEach((theme) => { + test.describe(theme, () => { + test('menu-button @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'MenuButton', + id: 'experimental-unstable-menubutton--default', + theme, + }); + }); + }); + }); + + test('accessibility-checker @avt', async ({ page }) => { + await visitStory(page, { + component: 'MenuButton', + id: 'experimental-unstable-menubutton--default', + globals: { + theme: 'white', + }, + }); + await expect(page).toHaveNoACViolations('MenuButton'); + }); +}); diff --git a/examples/class-prefix/package.json b/examples/class-prefix/package.json index 228febf9bc3a..7b75f58378c0 100644 --- a/examples/class-prefix/package.json +++ b/examples/class-prefix/package.json @@ -1,14 +1,14 @@ { "name": "class-prefix", "private": true, - "version": "0.21.0", + "version": "0.22.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/codesandbox-styles/package.json b/examples/codesandbox-styles/package.json index b24239921216..dde8f90d8304 100644 --- a/examples/codesandbox-styles/package.json +++ b/examples/codesandbox-styles/package.json @@ -1,7 +1,7 @@ { "name": "codesandbox-styles", "private": true, - "version": "0.27.0", + "version": "0.28.0", "scripts": { "develop": "vite" }, @@ -9,7 +9,7 @@ "vite": "^2.8.0" }, "dependencies": { - "@carbon/styles": "^1.24.0", + "@carbon/styles": "^1.25.0", "sass": "^1.51.0" } } diff --git a/examples/codesandbox-with-sass-compilation/package.json b/examples/codesandbox-with-sass-compilation/package.json index 4027d59cdd8e..c5b290e42260 100644 --- a/examples/codesandbox-with-sass-compilation/package.json +++ b/examples/codesandbox-with-sass-compilation/package.json @@ -1,9 +1,9 @@ { "name": "codesandbox-with-sass-compilation", - "version": "0.25.0", + "version": "0.26.0", "private": true, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/codesandbox/package.json b/examples/codesandbox/package.json index a7806e572400..f7ee455f275a 100644 --- a/examples/codesandbox/package.json +++ b/examples/codesandbox/package.json @@ -1,9 +1,9 @@ { "name": "codesandbox", - "version": "0.25.0", + "version": "0.26.0", "private": true, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/custom-theme/package.json b/examples/custom-theme/package.json index fd5a71b6703a..7be8d5b8ab03 100644 --- a/examples/custom-theme/package.json +++ b/examples/custom-theme/package.json @@ -1,14 +1,14 @@ { "name": "custom-theme", "private": true, - "version": "0.22.0", + "version": "0.23.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/id-prefix/package.json b/examples/id-prefix/package.json index 761112b93c5d..5872468ddbf6 100644 --- a/examples/id-prefix/package.json +++ b/examples/id-prefix/package.json @@ -1,14 +1,14 @@ { "name": "id-prefix", "private": true, - "version": "0.21.0", + "version": "0.22.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/incremental-migration/package.json b/examples/incremental-migration/package.json index dde6bbfe2168..55787a88309c 100644 --- a/examples/incremental-migration/package.json +++ b/examples/incremental-migration/package.json @@ -1,7 +1,7 @@ { "name": "incremental-migration", "private": true, - "version": "0.24.0", + "version": "0.25.0", "scripts": { "build": "next build", "dev": "next dev", @@ -13,7 +13,7 @@ }, "dependencies": { "@carbon/icons-react": "^10.49.0", - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "carbon-components": "^10.57.0", "carbon-components-react": "^7.57.0", "carbon-icons": "^7.0.7", diff --git a/examples/light-dark-mode/package.json b/examples/light-dark-mode/package.json index 434e19f6cebf..e78731ff8b4b 100644 --- a/examples/light-dark-mode/package.json +++ b/examples/light-dark-mode/package.json @@ -1,7 +1,7 @@ { "name": "examples-light-dark", "private": true, - "version": "0.22.0", + "version": "0.23.0", "scripts": { "build": "next build", "dev": "next dev", @@ -9,7 +9,7 @@ "start": "next start" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "next": "12.1.4", "react": "18.0.0", "react-dom": "18.0.0" diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 970c84b642ad..f52e7e2e81fa 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -1,7 +1,7 @@ { "name": "examples-nextjs", "private": true, - "version": "0.24.0", + "version": "0.25.0", "scripts": { "build": "next build", "dev": "next dev", @@ -9,7 +9,7 @@ "start": "next start" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "next": "12.1.4", "react": "18.0.0", "react-dom": "18.0.0" diff --git a/examples/vite/package.json b/examples/vite/package.json index 21fbb7785972..14bec57ccd3a 100644 --- a/examples/vite/package.json +++ b/examples/vite/package.json @@ -1,14 +1,14 @@ { "name": "vite", "private": true, - "version": "0.22.0", + "version": "0.23.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.24.0", + "@carbon/react": "^1.25.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/vite/src/index.scss b/examples/vite/src/index.scss index 721dd089fc51..286413dd009b 100644 --- a/examples/vite/src/index.scss +++ b/examples/vite/src/index.scss @@ -1,11 +1,3 @@ -@use '@carbon/react/scss/compat/themes' as compat; -@use '@carbon/react/scss/themes'; -@use '@carbon/react/scss/theme' with ( - $fallback: compat.$g100, - $theme: themes.$g100 +@use '@carbon/react' with ( + $font-path: '@ibm/plex' ); -@use '@carbon/react'; - -:root { - @include theme.theme(); -} diff --git a/packages/carbon-components-react/package.json b/packages/carbon-components-react/package.json index 00c8a88c027a..316d5199c626 100644 --- a/packages/carbon-components-react/package.json +++ b/packages/carbon-components-react/package.json @@ -1,7 +1,7 @@ { "name": "carbon-components-react", "description": "The Carbon Design System is IBM’s open-source design system for products and experiences.", - "version": "8.24.0", + "version": "8.25.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -39,8 +39,8 @@ "sass": "^1.33.0" }, "dependencies": { - "@carbon/react": "^1.24.0", - "@carbon/styles": "^1.24.0", + "@carbon/react": "^1.25.0", + "@carbon/styles": "^1.25.0", "@carbon/telemetry": "0.1.0" }, "devDependencies": { diff --git a/packages/carbon-components/package.json b/packages/carbon-components/package.json index e5dcce555870..83206fed55b1 100644 --- a/packages/carbon-components/package.json +++ b/packages/carbon-components/package.json @@ -1,7 +1,7 @@ { "name": "carbon-components", "description": "The Carbon Design System is IBM’s open-source design system for products and experiences.", - "version": "11.24.0", + "version": "11.25.0", "license": "Apache-2.0", "repository": { "type": "git", @@ -40,7 +40,7 @@ "sass": "^1.33.0" }, "dependencies": { - "@carbon/styles": "^1.24.0", + "@carbon/styles": "^1.25.0", "@carbon/telemetry": "0.1.0" }, "devDependencies": { diff --git a/packages/react/.storybook/preview.js b/packages/react/.storybook/preview.js index cce9912be450..f60d4b5787ab 100644 --- a/packages/react/.storybook/preview.js +++ b/packages/react/.storybook/preview.js @@ -8,7 +8,6 @@ import './styles.scss'; import '../src/feature-flags'; -import { configureActions } from '@storybook/addon-actions'; import { white, g10, g90, g100 } from '@carbon/themes'; import React from 'react'; import { breakpoints } from '@carbon/layout'; @@ -203,11 +202,6 @@ export const parameters = { }, }; -configureActions({ - depth: 3, - limit: 10, -}); - export const decorators = [ (Story, context) => { const { locale, theme } = context.globals; diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index 62bad90809e1..410bede864ed 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -111,9 +111,10 @@ Map { "isRequired": true, "type": "string", }, - "ariaLabel": Object { + "aria-label": Object { "type": "string", }, + "ariaLabel": [Function], "children": Object { "type": "node", }, @@ -529,16 +530,17 @@ Map { }, "CodeSnippet" => Object { "defaultProps": Object { - "ariaLabel": "Copy to clipboard", + "aria-label": "Copy to clipboard", "showLessText": "Show less", "showMoreText": "Show more", "type": "single", "wrapText": false, }, "propTypes": Object { - "ariaLabel": Object { + "aria-label": Object { "type": "string", }, + "ariaLabel": [Function], "children": Object { "type": "node", }, @@ -2690,9 +2692,10 @@ Map { "type": "default", }, "propTypes": Object { - "ariaLabel": Object { + "aria-label": Object { "type": "string", }, + "ariaLabel": [Function], "className": Object { "type": "string", }, @@ -3165,7 +3168,6 @@ Map { "multiple": false, "onAddFiles": [Function], "pattern": ".[0-9a-z]+$", - "tabIndex": 0, }, "propTypes": Object { "accept": Object { @@ -3198,15 +3200,14 @@ Map { "onAddFiles": Object { "type": "func", }, - "pattern": Object { - "type": "string", + "onClick": Object { + "type": "func", }, - "role": Object { + "pattern": Object { "type": "string", }, - "tabIndex": Object { - "type": "number", - }, + "role": [Function], + "tabIndex": [Function], }, }, "FileUploaderItem" => Object { @@ -3278,6 +3279,9 @@ Map { "invalid": Object { "type": "bool", }, + "name": Object { + "type": "string", + }, "status": Object { "args": Array [ Array [ @@ -4025,6 +4029,9 @@ Map { "role": "status", }, "propTypes": Object { + "aria-label": Object { + "type": "string", + }, "children": Object { "type": "node", }, @@ -5063,7 +5070,7 @@ Map { }, "NotificationButton" => Object { "defaultProps": Object { - "ariaLabel": "close notification", + "aria-label": "close notification", "notificationType": "toast", "renderIcon": Object { "$$typeof": Symbol(react.forward_ref), @@ -5087,9 +5094,10 @@ Map { "type": "button", }, "propTypes": Object { - "ariaLabel": Object { + "aria-label": Object { "type": "string", }, + "ariaLabel": [Function], "className": Object { "type": "string", }, @@ -7097,9 +7105,7 @@ Map { "leftOverflowButtonProps": Object { "type": "object", }, - "light": Object { - "type": "bool", - }, + "light": [Function], "rightOverflowButtonProps": Object { "type": "object", }, @@ -7833,6 +7839,8 @@ Map { "onClick": [Function], "placeholder": "", "rows": 4, + "warn": false, + "warnText": "", }, "propTypes": Object { "className": Object { @@ -7911,6 +7919,12 @@ Map { ], "type": "oneOfType", }, + "warn": Object { + "type": "bool", + }, + "warnText": Object { + "type": "node", + }, }, "render": [Function], }, @@ -8449,9 +8463,10 @@ Map { "timeout": 0, }, "propTypes": Object { - "ariaLabel": Object { + "aria-label": Object { "type": "string", }, + "ariaLabel": [Function], "caption": Object { "type": "string", }, @@ -9024,6 +9039,57 @@ Map { "8": "cool-gray", "9": "warm-gray", }, + "unstable_ComboButton" => Object { + "$$typeof": Symbol(react.forward_ref), + "propTypes": Object { + "children": Object { + "isRequired": true, + "type": "node", + }, + "className": Object { + "type": "string", + }, + "disabled": Object { + "type": "bool", + }, + "label": Object { + "isRequired": true, + "type": "string", + }, + "onClick": Object { + "type": "func", + }, + "size": Object { + "args": Array [ + Array [ + "sm", + "md", + "lg", + ], + ], + "type": "oneOf", + }, + "tooltipAlign": Object { + "args": Array [ + Array [ + "top", + "top-left", + "top-right", + "bottom", + "bottom-left", + "bottom-right", + "left", + "right", + ], + ], + "type": "oneOf", + }, + "translateWithId": Object { + "type": "func", + }, + }, + "render": [Function], + }, "unstable_FeatureFlags" => Object { "propTypes": Object { "children": Object { @@ -9087,6 +9153,9 @@ Map { "onClose": Object { "type": "func", }, + "onOpen": Object { + "type": "func", + }, "open": Object { "type": "bool", }, @@ -9143,6 +9212,46 @@ Map { }, "render": [Function], }, + "unstable_MenuButton" => Object { + "$$typeof": Symbol(react.forward_ref), + "propTypes": Object { + "children": Object { + "isRequired": true, + "type": "node", + }, + "className": Object { + "type": "string", + }, + "disabled": Object { + "type": "bool", + }, + "kind": Object { + "args": Array [ + Array [ + "primary", + "tertiary", + "ghost", + ], + ], + "type": "oneOf", + }, + "label": Object { + "isRequired": true, + "type": "string", + }, + "size": Object { + "args": Array [ + Array [ + "sm", + "md", + "lg", + ], + ], + "type": "oneOf", + }, + }, + "render": [Function], + }, "unstable_MenuItem" => Object { "$$typeof": Symbol(react.forward_ref), "propTypes": Object { @@ -9971,6 +10080,12 @@ Map { ], "type": "oneOfType", }, + "warn": Object { + "type": "bool", + }, + "warnText": Object { + "type": "node", + }, }, }, "unstable__FluidTextAreaSkeleton" => Object { diff --git a/packages/react/package.json b/packages/react/package.json index 2133f31ca309..382eda8afe59 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/react", "description": "React components for the Carbon Design System", - "version": "1.24.0", + "version": "1.25.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -46,7 +46,7 @@ "@carbon/feature-flags": "^0.13.0", "@carbon/icons-react": "^11.17.0", "@carbon/layout": "^11.12.0", - "@carbon/styles": "^1.24.0", + "@carbon/styles": "^1.25.0", "@carbon/telemetry": "0.1.0", "classnames": "2.3.2", "copy-to-clipboard": "^3.3.1", diff --git a/packages/react/src/__tests__/index-test.js b/packages/react/src/__tests__/index-test.js index 8cf6b6628a68..475bd9305453 100644 --- a/packages/react/src/__tests__/index-test.js +++ b/packages/react/src/__tests__/index-test.js @@ -221,9 +221,11 @@ describe('Carbon Components React', () => { "UnorderedList", "VStack", "types", + "unstable_ComboButton", "unstable_FeatureFlags", "unstable_LayoutDirection", "unstable_Menu", + "unstable_MenuButton", "unstable_MenuItem", "unstable_MenuItemDivider", "unstable_MenuItemGroup", diff --git a/packages/react/src/components/Accordion/__tests__/Accordion.Skeleton-test.js b/packages/react/src/components/Accordion/__tests__/Accordion.Skeleton-test.js deleted file mode 100644 index 72a880aa58b2..000000000000 --- a/packages/react/src/components/Accordion/__tests__/Accordion.Skeleton-test.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2023 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import { mount } from 'enzyme'; -import React from 'react'; -import AccordionSkeleton from '../Accordion.Skeleton'; -import SkeletonText from '../../SkeletonText'; -import { render, screen } from '@testing-library/react'; - -const prefix = 'cds'; - -describe('AccordionSkeleton', () => { - it('should render', () => { - const wrapper = mount(); - expect(wrapper).toMatchSnapshot(); - }); - - it('should support rendering without any open items', () => { - const wrapper = mount(); - expect(wrapper.contains()).toEqual(false); - }); - - it('should support rendering a custom number of items', () => { - const count = 8; - const wrapper = mount(); - expect(wrapper.find(`.${prefix}--accordion__item`)).toHaveLength(count); - }); - - it('should align to the left if prop isFlush is passed', () => { - render(); - - expect(screen.getByTestId('skeleton-1')).toHaveClass( - `${prefix}--accordion--flush` - ); - }); - - it('should not align to left if align="start"', () => { - render( - - ); - expect(screen.getByTestId('skeleton-2')).not.toHaveClass( - `${prefix}--accordion--flush` - ); - }); -}); diff --git a/packages/react/src/components/Accordion/__tests__/AccordionItem-test.js b/packages/react/src/components/Accordion/__tests__/AccordionItem-test.js index 6d70f676779c..82a08d9ac50d 100644 --- a/packages/react/src/components/Accordion/__tests__/AccordionItem-test.js +++ b/packages/react/src/components/Accordion/__tests__/AccordionItem-test.js @@ -1,111 +1,118 @@ /** - * Copyright IBM Corp. 2016, 2023 + * Copyright IBM Corp. 2022 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ -import { getByText } from '@carbon/test-utils/dom'; -import { render, cleanup } from '@carbon/test-utils/react'; import React from 'react'; -import { Simulate } from 'react-dom/test-utils'; import AccordionItem from '../AccordionItem'; -import { mount } from 'enzyme'; - -const prefix = 'cds'; +import userEvent from '@testing-library/user-event'; +import { render, screen } from '@testing-library/react'; describe('AccordionItem', () => { - afterEach(cleanup); - - it('should render', () => { - const wrapper = mount( - - Lorem ipsum. - - ); - expect(wrapper).toMatchSnapshot(); - }); + describe('renders as expected - Component API', () => { + it('should spread extra props onto outermost element', () => { + const { container } = render(); - it('should update the item open state when the `open` prop changes', () => { - const wrapper = mount( - - Lorem ipsum. - - ); - - expect( - wrapper - .find(`.${prefix}--accordion__item`) - .hasClass(`${prefix}--accordion__item--active`) - ).toBe(true); - - wrapper.setProps({ open: false }); - wrapper.update(); - - expect( - wrapper - .find(`.${prefix}--accordion__item`) - .hasClass(`${prefix}--accordion__item--active`) - ).toBe(false); - }); + expect(container.firstChild).toHaveAttribute('data-testid', 'test-id'); + }); - it('should call `onClick` when the accordion list item is clicked', () => { - const title = 'test title'; - const onClick = jest.fn(); - const { container } = render( - - Lorem ipsum. - - ); - - Simulate.click(getByText(container, title)); - expect(onClick).toHaveBeenCalledTimes(1); - }); + it('should render and match snapshot', () => { + const { container } = render( + + Lorem ipsum. + + ); - it('should call `onHeadingClick` when the accordion header is clicked', () => { - const onHeadingClick = jest.fn(); - const wrapper = mount( - - Lorem ipsum. - - ); - wrapper.find('button').simulate('click'); - expect(onHeadingClick).toHaveBeenCalledTimes(1); - }); + expect(container).toMatchSnapshot(); + }); + + it('should support a custom `className` prop on the outermost element', () => { + const { container } = render(); - it('should close an open AccordionItem panel when the Esc key is pressed', () => { - const wrapper = mount( - - Lorem ipsum. - - ); - wrapper.find('button').simulate('keydown', { - key: 'Escape', - keyCode: 27, - which: 27, + expect(container.firstChild).toHaveClass('custom-class'); + }); + + it('should respect disabled prop', () => { + render(); + + expect(screen.getByRole('button')).toBeDisabled(); + }); + + it('should call onClick when expected', () => { + const onClick = jest.fn(); + render(); + + userEvent.click(screen.getByText('Test title')); + + expect(onClick).toHaveBeenCalled(); + }); + + it('should call onHeadingClick prop when expected', () => { + const onHeadingClick = jest.fn(); + render( + + ); + + userEvent.click(screen.getByText('Test title')); + + expect(onHeadingClick).toHaveBeenCalled(); + }); + + it('should respect open prop', () => { + render(); + + expect(screen.getByRole('button')).toHaveAttribute( + 'aria-expanded', + 'true' + ); + }); + + it('should respect renderToggle prop', () => { + const renderToggle = jest.fn((props) => ( + + + + )); + render(); + + expect(renderToggle).toHaveBeenCalled(); + }); + + it('should respect title prop', () => { + render(); + + expect(screen.getByText('Test title')).toBeInTheDocument(); }); - expect( - wrapper - .find(`.${prefix}--accordion__item`) - .hasClass(`${prefix}--accordion__item--active`) - ).toBe(false); }); - it('should not close an open AccordionItem panel if the Esc key is pressed in the panel', () => { - const wrapper = mount( - - - - ); - wrapper.find('[data-test-id="input"]').simulate('keydown', { - key: 'Escape', - keyCode: 27, - which: 27, + describe('behaves as expected', () => { + it('should close an open AccordionItem panel when the Esc key is pressed', () => { + render( + + Lorem ipsum. + + ); + userEvent.type(screen.getByRole('button'), '{esc}'); + + expect(screen.getByRole('button')).toHaveAttribute( + 'aria-expanded', + 'false' + ); + }); + + it('should not close an open AccordionItem panel if the Esc key is pressed in the panel', () => { + render( + + + + ); + userEvent.type(screen.getByRole('textbox'), '{esc}'); + expect(screen.getByRole('button')).toHaveAttribute( + 'aria-expanded', + 'true' + ); }); - expect( - wrapper - .find(`.${prefix}--accordion__item`) - .hasClass(`${prefix}--accordion__item--active`) - ).toBe(true); }); }); diff --git a/packages/react/src/components/Accordion/__tests__/AccordionSkeleton-test.js b/packages/react/src/components/Accordion/__tests__/AccordionSkeleton-test.js new file mode 100644 index 000000000000..6738ee2549a4 --- /dev/null +++ b/packages/react/src/components/Accordion/__tests__/AccordionSkeleton-test.js @@ -0,0 +1,67 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import AccordionSkeleton from '../Accordion.Skeleton'; +import { render, screen } from '@testing-library/react'; + +describe('AccordionSkeleton', () => { + describe('renders as expected - Component API', () => { + it('should spread extra props onto outermost element', () => { + const { container } = render(); + + expect(container.firstChild).toHaveAttribute('data-testid', 'test-id'); + }); + + it('should render and match snapshot', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('should respect align prop', () => { + const { container, rerender } = render( + + ); + expect(container.firstChild).toHaveClass('cds--accordion--start'); + + rerender(); + expect(container.firstChild).toHaveClass('cds--accordion--end'); + }); + + it('should support a custom `className` prop on the outermost element', () => { + const { container } = render( + + ); + + expect(container.firstChild).toHaveClass('custom-class'); + }); + + it('should respect count prop', () => { + render(); + + expect(screen.getAllByRole('listitem').length).toBe(8); + }); + + it('should respect isFlush prop', () => { + const { container } = render(); + + expect(container.firstChild).toHaveClass('cds--accordion--flush'); + }); + + it('should respect open prop', () => { + render(); + expect(screen.getAllByRole('listitem')[0]).toHaveClass( + 'cds--accordion__item--active' + ); + }); + }); + + describe('behaves as expected', () => { + // Add tests for relevant component behavior. For more information, visit https://github.com/carbon-design-system/carbon/issues/10184#issuecomment-992978122 + }); +}); diff --git a/packages/react/src/components/Accordion/__tests__/__snapshots__/Accordion.Skeleton-test.js.snap b/packages/react/src/components/Accordion/__tests__/__snapshots__/Accordion.Skeleton-test.js.snap deleted file mode 100644 index f0a04602cd70..000000000000 --- a/packages/react/src/components/Accordion/__tests__/__snapshots__/Accordion.Skeleton-test.js.snap +++ /dev/null @@ -1,259 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccordionSkeleton should render 1`] = ` - -
    -
  • - - - - - - - - - -

    - - -

    - -

    - - -

    - - -

    - -

    -
  • - -
  • - - - - - - - - - -

    - - -

  • -
    - -
  • - - - - - - - - - -

    - - -

  • -
    - -
  • - - - - - - - - - -

    - - -

  • -
    -
-
-`; diff --git a/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionItem-test.js.snap b/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionItem-test.js.snap index 800c369f7772..c6f7f1bcc432 100644 --- a/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionItem-test.js.snap +++ b/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionItem-test.js.snap @@ -1,78 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AccordionItem should render 1`] = ` - +exports[`AccordionItem renders as expected - Component API should render and match snapshot 1`] = ` +
  • - - - + + +
    + Test title +
    +
    Lorem ipsum.
  • - +
    `; diff --git a/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionSkeleton-test.js.snap b/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionSkeleton-test.js.snap new file mode 100644 index 000000000000..98016f0b213b --- /dev/null +++ b/packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionSkeleton-test.js.snap @@ -0,0 +1,134 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AccordionSkeleton renders as expected - Component API should render and match snapshot 1`] = ` +
    +
      +
    • + + +

      + +

      +

      +

      +

      +

      +
    • +
    • + + +

      + +

    • +
    • + + +

      + +

    • +
    • + + +

      + +

    • +
    +
    +`; diff --git a/packages/react/src/components/Breadcrumb/Breadcrumb.stories.js b/packages/react/src/components/Breadcrumb/Breadcrumb.stories.js index 2bfc8b62efd3..c84ddb04ebbe 100644 --- a/packages/react/src/components/Breadcrumb/Breadcrumb.stories.js +++ b/packages/react/src/components/Breadcrumb/Breadcrumb.stories.js @@ -45,7 +45,7 @@ export const BreadcrumbWithOverflowMenu = () => ( Breadcrumb 2 - + diff --git a/packages/react/src/components/CodeSnippet/CodeSnippet.js b/packages/react/src/components/CodeSnippet/CodeSnippet.js index 615f501ce471..5da71c42ee78 100644 --- a/packages/react/src/components/CodeSnippet/CodeSnippet.js +++ b/packages/react/src/components/CodeSnippet/CodeSnippet.js @@ -32,7 +32,8 @@ function CodeSnippet({ feedback, feedbackTimeout, onClick, - ariaLabel, + ['aria-label']: ariaLabel, + ariaLabel: deprecatedAriaLabel, copyText, copyButtonDescription, light, @@ -185,7 +186,7 @@ function CodeSnippet({
        * node
        */
    -  ariaLabel: PropTypes.string,
    +  ['aria-label']: PropTypes.string,
    +
    +  /**
    +   * Deprecated, please use `aria-label` instead.
    +   * Specify a label to be read by screen readers on the containing 
    +   * node
    +   */
    +  ariaLabel: deprecate(
    +    PropTypes.string,
    +    'This prop syntax has been deprecated. Please use the new `aria-label`.'
    +  ),
     
       /**
        * Provide the content of your CodeSnippet as a node or string
    @@ -387,7 +402,7 @@ CodeSnippet.propTypes = {
     };
     
     CodeSnippet.defaultProps = {
    -  ariaLabel: 'Copy to clipboard',
    +  ['aria-label']: 'Copy to clipboard',
       type: 'single',
       showMoreText: 'Show more',
       showLessText: 'Show less',
    diff --git a/packages/react/src/components/CodeSnippet/CodeSnippet.stories.js b/packages/react/src/components/CodeSnippet/CodeSnippet.stories.js
    index b6e605d65456..a960f5e404c8 100644
    --- a/packages/react/src/components/CodeSnippet/CodeSnippet.stories.js
    +++ b/packages/react/src/components/CodeSnippet/CodeSnippet.stories.js
    @@ -235,6 +235,11 @@ export const Playground = (args) => (
     );
     
     Playground.argTypes = {
    +  ['aria-label']: {
    +    table: {
    +      disable: true,
    +    },
    +  },
       ariaLabel: {
         table: {
           disable: true,
    diff --git a/packages/react/src/components/ComboBox/ComboBox.stories.js b/packages/react/src/components/ComboBox/ComboBox.stories.js
    index 923035a48cdc..2aad23664b04 100644
    --- a/packages/react/src/components/ComboBox/ComboBox.stories.js
    +++ b/packages/react/src/components/ComboBox/ComboBox.stories.js
    @@ -117,7 +117,6 @@ export const WithLayer = () => (
     export const Playground = (args) => (
       
    {}} id="carbon-combobox" items={items} downshiftProps={{ @@ -184,7 +183,7 @@ Playground.argTypes = { }, }, onChange: { - action: 'clicked', + action: 'changed', }, onClick: { action: 'clicked', diff --git a/packages/react/src/components/ComboButton/ComboButton-test.js b/packages/react/src/components/ComboButton/ComboButton-test.js new file mode 100644 index 000000000000..8ff643d1c320 --- /dev/null +++ b/packages/react/src/components/ComboButton/ComboButton-test.js @@ -0,0 +1,162 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { MenuItem } from '../Menu'; + +import { ComboButton } from './'; + +const prefix = 'cds'; + +describe('ComboButton', () => { + describe('renders as expected - Component API', () => { + it('supports a ref on the outermost element', () => { + const ref = jest.fn(); + const { container } = render( + + + + ); + expect(ref).toHaveBeenCalledWith(container.firstChild); + }); + + it('supports a custom class name on the outermost element', () => { + const { container } = render( + + + + ); + expect(container.firstChild).toHaveClass('test'); + }); + + it('forwards additional props on the outermost element', () => { + const { container } = render( + + + + ); + expect(container.firstChild).toHaveAttribute('data-testid', 'test'); + }); + + it('renders props.label on the trigger button', () => { + render( + + + + ); + expect(screen.getAllByRole('button')[0]).toHaveTextContent(/^Test$/); + }); + + it('supports props.disabled', () => { + render( + + + + ); + + // primary action button + expect(screen.getAllByRole('button')[0]).toBeDisabled(); + + // trigger button + expect(screen.getAllByRole('button')[1]).toBeDisabled(); + }); + + describe('supports props.size', () => { + const sizes = ['sm', 'md', 'lg']; + + sizes.forEach((size) => { + it(`size="${size}"`, () => { + const { container } = render( + + + + ); + + expect(container.firstChild).toHaveClass( + `${prefix}--combo-button__container--${size}` + ); + }); + }); + }); + + describe('supports props.tooltipAlign', () => { + const alignments = [ + 'top', + 'top-left', + 'top-right', + 'bottom', + 'bottom-left', + 'bottom-right', + 'left', + 'right', + ]; + + alignments.forEach((alignment) => { + it(`tooltipAlign="${alignment}"`, () => { + const { container } = render( + + + + ); + + expect(container.firstChild.lastChild).toHaveClass( + `${prefix}--popover--${alignment}` + ); + }); + }); + }); + + it('supports props.translateWithId', () => { + const t = () => 'test'; + + render( + + + + ); + + const triggerButton = screen.getAllByRole('button')[1]; + const tooltipId = triggerButton.getAttribute('aria-labelledby'); + const tooltip = document.getElementById(tooltipId); + + expect(tooltip).toHaveTextContent(t()); + }); + }); + + describe('behaves as expected', () => { + it('emits props.onClick on primary action click', async () => { + const onClick = jest.fn(); + render( + + + + ); + + expect(onClick).toHaveBeenCalledTimes(0); + await userEvent.click(screen.getAllByRole('button')[0]); + expect(onClick).toHaveBeenCalledTimes(1); + }); + + it('opens a menu on click on the trigger button', async () => { + render( + + + + ); + + await userEvent.click(screen.getAllByRole('button')[1]); + + expect(screen.getByRole('menu')).toBeTruthy(); + expect(screen.getByRole('menuitem')).toHaveTextContent( + /^Additional action$/ + ); + }); + }); +}); diff --git a/packages/react/src/components/ComboButton/ComboButton.mdx b/packages/react/src/components/ComboButton/ComboButton.mdx new file mode 100644 index 000000000000..13c7627d82af --- /dev/null +++ b/packages/react/src/components/ComboButton/ComboButton.mdx @@ -0,0 +1,36 @@ +import { ArgsTable, Canvas, Story } from '@storybook/addon-docs'; + +# ComboButton + +[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/ComboButton) + + + + +- [Overview](#overview) +- [Component API](#component-api) +- [Feedback](#feedback) + + + +## Overview + +A `ComboButton` can be used to offer additional, secondary actions in a disclosed list next to the primary action. These additional actions must be `MenuItem`s passed as `children`. The primary action's label is passed as `props.label`. + +```jsx + + + + + +``` + +## Component API + + + +## Feedback + +Help us improve this component by providing feedback, asking questions on Slack, +or updating this file on +[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/ComboButton/ComboButton.mdx). diff --git a/packages/react/src/components/ComboButton/ComboButton.stories.js b/packages/react/src/components/ComboButton/ComboButton.stories.js new file mode 100644 index 000000000000..ca696bfa0319 --- /dev/null +++ b/packages/react/src/components/ComboButton/ComboButton.stories.js @@ -0,0 +1,85 @@ +/** + * Copyright IBM Corp. 2023 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { action } from '@storybook/addon-actions'; + +import { MenuItem, MenuItemDivider } from '../Menu'; + +import { ComboButton } from './'; +import mdx from './ComboButton.mdx'; + +export default { + title: 'Experimental/unstable__ComboButton', + component: ComboButton, + subcomponents: { + MenuItem, + MenuItemDivider, + }, + parameters: { + docs: { + page: mdx, + }, + }, +}; + +export const Default = () => ( + + + + + +); + +export const WithDanger = () => ( + + + + + + + +); + +export const Playground = (args) => { + const onClick = action('onClick (MenuItem)'); + + return ( + + + + + + + + ); +}; + +Playground.argTypes = { + children: { + table: { + disable: true, + }, + }, + className: { + table: { + disable: true, + }, + }, + translateWithId: { + table: { + disable: true, + }, + }, + label: { + defaultValue: 'Primary action', + }, +}; + +Playground.args = { + onClick: action('onClick'), +}; diff --git a/packages/react/src/components/ComboButton/docs/overview.mdx b/packages/react/src/components/ComboButton/docs/overview.mdx new file mode 100644 index 000000000000..fa1ff29e53f9 --- /dev/null +++ b/packages/react/src/components/ComboButton/docs/overview.mdx @@ -0,0 +1,13 @@ +## Live demo + + diff --git a/packages/react/src/components/ComboButton/index.js b/packages/react/src/components/ComboButton/index.js new file mode 100644 index 000000000000..85ed51b55c6c --- /dev/null +++ b/packages/react/src/components/ComboButton/index.js @@ -0,0 +1,184 @@ +/** + * Copyright IBM Corp. 2023 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, { useRef, useState } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { ChevronDown } from '@carbon/icons-react'; +import { Button } from '../Button'; +import { IconButton } from '../IconButton'; +import { Menu } from '../Menu'; + +import { useAttachedMenu } from '../../internal/useAttachedMenu'; +import { useId } from '../../internal/useId'; +import { useMergedRefs } from '../../internal/useMergedRefs'; +import { usePrefix } from '../../internal/usePrefix'; + +const spacing = 4; // top and bottom spacing between the button and the menu. in px +const defaultTranslations = { + 'carbon.combo-button.additional-actions': 'Additional actions', +}; + +function defaultTranslateWithId(messageId) { + return defaultTranslations[messageId]; +} + +const ComboButton = React.forwardRef(function ComboButton( + { + children, + className, + disabled, + label, + onClick, + size = 'lg', + tooltipAlign, + translateWithId: t = defaultTranslateWithId, + ...rest + }, + forwardRef +) { + const id = useId('combobutton'); + const prefix = usePrefix(); + + const containerRef = useRef(null); + const menuRef = useRef(null); + const ref = useMergedRefs([forwardRef, containerRef]); + const [width, setWidth] = useState(0); + const { + open, + x, + y, + handleClick: hookOnClick, + handleMousedown: handleTriggerMousedown, + handleClose, + } = useAttachedMenu(containerRef); + + function handleTriggerClick() { + if (containerRef.current) { + const { width: w } = containerRef.current.getBoundingClientRect(); + setWidth(w); + hookOnClick(); + } + } + + function handlePrimaryActionClick(e) { + if (onClick) { + onClick(e); + } + } + + function handleOpen() { + menuRef.current.style.width = `${width}px`; + } + + const containerClasses = classNames( + `${prefix}--combo-button__container`, + `${prefix}--combo-button__container--${size}`, + { + [`${prefix}--combo-button__container--open`]: open, + }, + className + ); + + const primaryActionClasses = classNames( + `${prefix}--combo-button__primary-action` + ); + const triggerClasses = classNames(`${prefix}--combo-button__trigger`); + + return ( +
    +
    + +
    + + + + + {children} + +
    + ); +}); + +ComboButton.propTypes = { + /** + * A collection of MenuItems to be rendered as additional actions for this ComboButton. + */ + children: PropTypes.node.isRequired, + + /** + * Additional CSS class names. + */ + className: PropTypes.string, + + /** + * Specify whether the ComboButton should be disabled, or not. + */ + disabled: PropTypes.bool, + + /** + * Provide the label to be renderd on the primary action button. + */ + label: PropTypes.string.isRequired, + + /** + * Provide an optional function to be called when the primary action element is clicked. + */ + onClick: PropTypes.func, + + /** + * Specify the size of the buttons and menu. + */ + size: PropTypes.oneOf(['sm', 'md', 'lg']), + + /** + * Specify how the trigger tooltip should be aligned. + */ + tooltipAlign: PropTypes.oneOf([ + 'top', + 'top-left', + 'top-right', + 'bottom', + 'bottom-left', + 'bottom-right', + 'left', + 'right', + ]), + + /** + * Optional method that takes in a message id and returns an + * internationalized string. + */ + translateWithId: PropTypes.func, +}; + +export { ComboButton }; diff --git a/packages/react/src/components/ComposedModal/ComposedModal.js b/packages/react/src/components/ComposedModal/ComposedModal.js index dad58a6d4700..34d7138a4bfb 100644 --- a/packages/react/src/components/ComposedModal/ComposedModal.js +++ b/packages/react/src/components/ComposedModal/ComposedModal.js @@ -241,8 +241,7 @@ const ComposedModal = React.forwardRef(function ComposedModal( onBlur={handleBlur} onMouseDown={handleMousedown} onKeyDown={handleKeyDown} - className={modalClass} - tabIndex="-1"> + className={modalClass}>
    diff --git a/packages/react/src/components/DataTable/TableToolbarMenu.tsx b/packages/react/src/components/DataTable/TableToolbarMenu.tsx index 2fd3baca6612..ddeb66d47157 100644 --- a/packages/react/src/components/DataTable/TableToolbarMenu.tsx +++ b/packages/react/src/components/DataTable/TableToolbarMenu.tsx @@ -46,7 +46,7 @@ const TableToolbarMenu: React.FC = ({ ); return ( ( Delete + Delete + + @@ -203,7 +215,10 @@ export const Playground = (args) => ( aria-hidden={batchActionProps.shouldShowBatchActions}> { + action('TableToolbarSearch - onChange')(evt); + onInputChange(evt); + }} /> @@ -240,7 +255,10 @@ export const Playground = (args) => ( {rows.map((row, i) => ( - + {row.cells.map((cell) => ( {cell.value} ))} diff --git a/packages/react/src/components/DataTable/stories/DataTable-filtering.stories.js b/packages/react/src/components/DataTable/stories/DataTable-filtering.stories.js index 60c06235b18b..86b47e201403 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-filtering.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-filtering.stories.js @@ -130,7 +130,12 @@ export const Playground = (args) => ( {/* pass in `onInputChange` change here to make filtering work */} - + { + action('TableToolbarSearch - onChange')(evt); + onInputChange(evt); + }} + /> Action 1 diff --git a/packages/react/src/components/DataTable/stories/DataTable-selection.stories.js b/packages/react/src/components/DataTable/stories/DataTable-selection.stories.js index b0ca3f2d68d2..d3fab40e3a29 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-selection.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-selection.stories.js @@ -70,19 +70,8 @@ export const Default = () => ( {rows.map((row, i) => ( - { - action('TableRow onClick')(evt); - }}> - { - action('TableSelectRow onSelect')(evt); - getSelectionProps({ row }).onSelect(evt); - }} - /> + + {row.cells.map((cell) => ( {cell.value} ))} @@ -214,10 +203,7 @@ export const Playground = (args) => ( }}> { - action('TableSelectRow onSelect')(evt); - getSelectionProps({ row }).onSelect(evt); - }} + onChange={action('TableSelectRow - onChange')} /> {row.cells.map((cell) => ( {cell.value} diff --git a/packages/react/src/components/DataTable/stories/DataTable-sorting.stories.js b/packages/react/src/components/DataTable/stories/DataTable-sorting.stories.js index 2fa8c80ca529..f3670adf7129 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-sorting.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-sorting.stories.js @@ -67,7 +67,7 @@ export const Default = () => ( ); export const Playground = (args) => ( - + {({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => ( diff --git a/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js b/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js index 31333f670b2d..6a0a6a270996 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js @@ -300,7 +300,12 @@ export const Playground = (args) => ( - + { + action('TableToolbarSearch - onChange')(evt); + onInputChange(evt); + }} + /> Action 1 diff --git a/packages/react/src/components/DataTable/stories/dynamic-content/DataTable-dynamic-content.stories.js b/packages/react/src/components/DataTable/stories/dynamic-content/DataTable-dynamic-content.stories.js index c937b5b00423..684442c11849 100644 --- a/packages/react/src/components/DataTable/stories/dynamic-content/DataTable-dynamic-content.stories.js +++ b/packages/react/src/components/DataTable/stories/dynamic-content/DataTable-dynamic-content.stories.js @@ -9,6 +9,7 @@ import './story.scss'; import React from 'react'; import { TrashCan, Save, Download } from '@carbon/icons-react'; +import { action } from '@storybook/addon-actions'; import DataTable, { Table, TableBatchAction, @@ -299,12 +300,25 @@ export const Playground = (args) => { - + { + action('TableToolbarSearch - onChange')(evt); + onInputChange(evt); + }} + /> - + { + action('handleOnRowAdd')(evt); + this.handleOnRowAdd(); + }}> Add row - + { + action('handleOnHeaderAdd')(evt); + this.handleOnHeaderAdd(); + }}> Add header @@ -325,8 +339,13 @@ export const Playground = (args) => { {rows.map((row) => ( - - + + {row.cells.map((cell) => ( {cell.value} ))} diff --git a/packages/react/src/components/DataTable/stories/expansion/DataTable-expansion.stories.js b/packages/react/src/components/DataTable/stories/expansion/DataTable-expansion.stories.js index f4955d470d42..f8e70ecff332 100644 --- a/packages/react/src/components/DataTable/stories/expansion/DataTable-expansion.stories.js +++ b/packages/react/src/components/DataTable/stories/expansion/DataTable-expansion.stories.js @@ -22,6 +22,7 @@ import DataTable, { import { Pagination } from '../../../../'; import { rows, headers } from '../shared'; import mdx from '../../DataTable.mdx'; +import { action } from '@storybook/addon-actions'; export default { title: 'Components/DataTable/Expansion', @@ -288,7 +289,9 @@ export const Playground = (args) => ( {rows.map((row) => ( - + {row.cells.map((cell) => ( {cell.value} ))} diff --git a/packages/react/src/components/DataTable/stories/shared.js b/packages/react/src/components/DataTable/stories/shared.js index 085405ea0f58..6273d3b453da 100644 --- a/packages/react/src/components/DataTable/stories/shared.js +++ b/packages/react/src/components/DataTable/stories/shared.js @@ -93,4 +93,4 @@ export const headers = [ ]; export const batchActionClick = (selectedRows) => () => - action('batch action click')(selectedRows); + action('Batch action click')(selectedRows); diff --git a/packages/react/src/components/DatePicker/DatePicker.stories.js b/packages/react/src/components/DatePicker/DatePicker.stories.js index 08eaab0d08b0..e2cda293ca02 100644 --- a/packages/react/src/components/DatePicker/DatePicker.stories.js +++ b/packages/react/src/components/DatePicker/DatePicker.stories.js @@ -257,13 +257,13 @@ Playground.argTypes = { }, }, onChange: { - action: 'clicked', + action: 'onChange', }, onClose: { - action: 'clicked', + action: 'onClose', }, onOpen: { - action: 'clicked', + action: 'onOpen', }, readOnly: { control: { diff --git a/packages/react/src/components/Dropdown/Dropdown.tsx b/packages/react/src/components/Dropdown/Dropdown.tsx index 4fd374615493..4edf6138d627 100644 --- a/packages/react/src/components/Dropdown/Dropdown.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.tsx @@ -61,8 +61,15 @@ export interface OnChangeData { export interface DropdownProps extends Omit, ExcludedAttributes> { /** + * Specify a label to be read by screen readers on the container node * 'aria-label' of the ListBox component. */ + ['aria-label']?: string; + + /** + * @deprecated please use `aria-label` instead. + * Specify a label to be read by screen readers on the container note. + */ ariaLabel?: string; /** @@ -206,7 +213,8 @@ const Dropdown = React.forwardRef( direction, items, label, - ariaLabel, + ['aria-label']: ariaLabel, + ariaLabel: deprecatedAriaLabel, itemToString = defaultItemToString, itemToElement, renderSelectedItem, @@ -358,7 +366,7 @@ const Dropdown = React.forwardRef( { if (matches(evt, [keys.Enter, keys.Space])) { diff --git a/packages/react/src/components/FileUploader/FileUploaderDropContainer.js b/packages/react/src/components/FileUploader/FileUploaderDropContainer.js index 3c0a38689df8..7233f74195e8 100644 --- a/packages/react/src/components/FileUploader/FileUploaderDropContainer.js +++ b/packages/react/src/components/FileUploader/FileUploaderDropContainer.js @@ -11,6 +11,8 @@ import classNames from 'classnames'; import { keys, matches } from '../../internal/keyboard'; import uniqueId from '../../tools/uniqueId'; import { usePrefix } from '../../internal/usePrefix'; +import { composeEventHandlers } from '../../tools/events'; +import deprecate from '../../prop-types/deprecate'; function FileUploaderDropContainer({ accept, @@ -21,9 +23,8 @@ function FileUploaderDropContainer({ multiple, name, onAddFiles, + onClick, pattern, - role, - tabIndex, // eslint-disable-next-line react/prop-types innerRef, ...rest @@ -32,13 +33,15 @@ function FileUploaderDropContainer({ const inputRef = useRef(null); const { current: uid } = useRef(id || uniqueId()); const [isActive, setActive] = useState(false); - const labelClasses = classNames(`${prefix}--file-browse-btn`, { - [`${prefix}--file-browse-btn--disabled`]: disabled, - }); - const dropareaClasses = classNames(`${prefix}--file__drop-container`, { - [`${prefix}--file__drop-container--drag-over`]: isActive, - [className]: className, - }); + const dropareaClasses = classNames( + `${prefix}--file__drop-container`, + `${prefix}--file-browse-btn`, + { + [`${prefix}--file__drop-container--drag-over`]: isActive, + [`${prefix}--file-browse-btn--disabled`]: disabled, + [className]: className, + } + ); /** * Filters the array of added files based on file type restrictions @@ -79,6 +82,12 @@ function FileUploaderDropContainer({ return onAddFiles(event, { addedFiles }); } + const handleClick = () => { + if (!disabled) { + inputRef.current.click(); + } + }; + return (
    - {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */} -