diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24b0e36786..1dbc08c77a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,26 @@ jobs: - name: CI build checks run: yarn ci-check:build + format: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '20.x' + cache: yarn + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: lint-modules-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - name: Install + run: yarn + - name: Check formatting of project files + run: yarn format:diff + lint: runs-on: ubuntu-latest steps: diff --git a/SECURITY.md b/SECURITY.md index 3cde270c3b..09eaf24555 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,28 +2,31 @@ ## Version support -| Version | Status | Ongoing support | -| ------- | ------- | --------------- | -| 2.x | Active | ✅ | -| 1.x | Active | ✅ | +| Version | Status | Ongoing support | +| ------- | ------ | --------------- | +| 2.x | Active | ✅ | +| 1.x | Active | ✅ | Version 2.x corresponds with Carbon v11 while 1.x corresponds with Carbon v10. -Support for these versions includes the discrete version numbers of -individual packages as listed in the +Support for these versions includes the discrete version numbers of individual +packages as listed in the [release changelogs](https://github.com/carbon-design-system/ibm-products/releases). -Please note that the **1.x version is anticipated to reach maintenance phase near the end of 2023**. +Please note that the **1.x version is anticipated to reach maintenance phase +near the end of 2023**. ## Reporting a vulnerability **Please do not report security vulnerabilities through public GitHub issues.** -Instead, report a vulnerability through GitHub’s [security advisory feature](https://github.com/carbon-design-system/ibm-products/security/advisories/new) via new issues. +Instead, report a vulnerability through GitHub’s +[security advisory feature](https://github.com/carbon-design-system/ibm-products/security/advisories/new) +via new issues. Please include a description of the issue, the steps you took to create the -issue, affected versions, and, if known, mitigation steps for the issue. Our team -aims to respond to all new vulnerability reports within 7 business days. +issue, affected versions, and, if known, mitigation steps for the issue. Our +team aims to respond to all new vulnerability reports within 7 business days. Additional information on reporting vulnerabilities to IBM is available at diff --git a/cspell.json b/cspell.json index 97e60cb238..042e6ab0eb 100644 --- a/cspell.json +++ b/cspell.json @@ -133,6 +133,7 @@ "Menlo", "mordech", "namor", + "nocheck", "Neue", "nodataemptystate", "noninteractive", diff --git a/jest.e2e.config.js b/jest.e2e.config.js index 39234e0e29..0e13b57f76 100644 --- a/jest.e2e.config.js +++ b/jest.e2e.config.js @@ -17,12 +17,9 @@ module.exports = { ], testMatch: [ '/e2e/**/*-test.avt.e2e.js', - '/e2e/**/*-test.vrt.e2e.js' - ], - testPathIgnorePatterns: [ - 'examples', - '/packages/ibm-products/', + '/e2e/**/*-test.vrt.e2e.js', ], + testPathIgnorePatterns: ['examples', '/packages/ibm-products/'], transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], reporters: ['default', 'jest-junit'], }; diff --git a/package.json b/package.json index 5c6da0e2b3..0f3e7b66d2 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,10 @@ "coverage": "echo 'you can pass a name argument to specify which tests are ran such as `yarn coverage decorator` and then view the results with `yarn coverage:report`'; yarn test:c4p --coverage", "coverage:report": "open ./packages/ibm-products/coverage/index.html", "format": "run-p -s 'format:*'", - "format:packages": "prettier ./packages/**/*.{js,jsx,tsx,md,scss} --write --ignore-unknown", + "format:config": "prettier ./*.{js,jsx,tsx,ts,md,scss} --write --ignore-unknown", + "format:packages": "prettier ./packages/**/*.{js,jsx,tsx,ts,md,scss} --write --ignore-unknown", "format:e2e": "prettier ./e2e/**/*.js --write --ignore-unknown", + "format:diff": "prettier --list-different '**/*.{js,jsx,md,scss,ts,tsx}' '*.{js,jsx,md,scss,ts,tsx}' '!**/{build,es,lib,storybook,ts,umd}/**' '!examples/**/*' '!scripts/**/*'", "generate": "lerna run generate --loglevel success --scope \"@carbon/ibm-products\" --", "lint": "run-p -s 'lint:*'", "lint:license": "scripts/check-license.cjs -a", @@ -78,6 +80,7 @@ "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.4.3", + "@types/carbon__layout": "^0.0.3", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "accessibility-checker": "^3.1.65", diff --git a/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap b/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap index f544a0ba03..1e390bb4e6 100644 --- a/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap +++ b/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap @@ -2580,7 +2580,7 @@ p.c4p--about-modal__copyright-text:first-child { left: 0; border-right: 1px solid var(--cds-border-subtle-02, #e0e0e0); } -.c4p--side-panel.c4p--side-panel.c4p--side-panel--has-slug { +.c4p--side-panel.c4p--side-panel.c4p--side-panel--has-slug, .c4p--side-panel.c4p--side-panel.c4p--side-panel--has-ai-label { border-color: transparent; box-shadow: inset 0 -80px 70px -65px var(--cds-ai-inner-shadow, rgba(69, 137, 255, 0.1)), 0 4px 10px 2px var(--cds-ai-drop-shadow, rgba(15, 98, 254, 0.1)); } @@ -2645,10 +2645,10 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--side-panel .c4p--side-panel__header:not(.c4p--side-panel__header--has-title)::before { background-color: transparent; } -.c4p--side-panel.c4p--side-panel:has(.c4p--side-panel__action-toolbar), .c4p--side-panel.c4p--side-panel--has-action-toolbar, .c4p--side-panel.c4p--side-panel--has-slug { +.c4p--side-panel.c4p--side-panel:has(.c4p--side-panel__action-toolbar), .c4p--side-panel.c4p--side-panel--has-action-toolbar, .c4p--side-panel.c4p--side-panel--has-slug, .c4p--side-panel.c4p--side-panel--has-ai-label { --c4p--side-panel--title-padding-right: 4rem; } -.c4p--side-panel.c4p--side-panel:has(.c4p--side-panel__action-toolbar).c4p--side-panel--has-slug, .c4p--side-panel.c4p--side-panel--has-action-toolbar.c4p--side-panel--has-slug { +.c4p--side-panel.c4p--side-panel:has(.c4p--side-panel__action-toolbar).c4p--side-panel--has-slug, .c4p--side-panel.c4p--side-panel:has(.c4p--side-panel__action-toolbar).c4p--side-panel--has-ai-label, .c4p--side-panel.c4p--side-panel--has-action-toolbar.c4p--side-panel--has-slug, .c4p--side-panel.c4p--side-panel--has-action-toolbar.c4p--side-panel--has-ai-label { --c4p--side-panel--title-padding-right: 5rem; } .c4p--side-panel .c4p--side-panel__animated-scroll-wrapper { @@ -2745,7 +2745,7 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--side-panel .c4p--side-panel__header--has-action-toolbar + .c4p--side-panel__inner-content { padding-top: 0.5rem; } -.c4p--side-panel.c4p--side-panel--has-slug .c4p--side-panel--scrolls { +.c4p--side-panel.c4p--side-panel--has-slug .c4p--side-panel--scrolls, .c4p--side-panel.c4p--side-panel--has-ai-label .c4p--side-panel--scrolls { background: linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)) 0%, var(--cds-ai-aura-start, rgba(69, 137, 255, 0.1)) 0%, 15%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%) padding-box, linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)), var(--cds-layer, var(--cds-ai-popover-background, #ffffff))) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, rgba(166, 200, 255, 0.64)), var(--cds-ai-border-end, #78a9ff)) border-box, linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)), var(--cds-layer, var(--cds-ai-popover-background, #ffffff))) border-box; box-shadow: inset 0 -80px 70px -65px var(--cds-ai-inner-shadow, rgba(69, 137, 255, 0.1)), 0 4px 10px 2px var(--cds-ai-drop-shadow, rgba(15, 98, 254, 0.1)); } @@ -2793,7 +2793,8 @@ p.c4p--about-modal__copyright-text:first-child { width: 2.5rem; height: 2.5rem; } -.c4p--side-panel .c4p--side-panel__slug-and-close { +.c4p--side-panel .c4p--side-panel__slug-and-close, +.c4p--side-panel .c4p--side-panel__ai-label-and-close { position: absolute; z-index: 10; /* must be higher than title container border bottom */ top: 0; @@ -2802,7 +2803,8 @@ p.c4p--about-modal__copyright-text:first-child { /* stylelint-disable-next-line max-nesting-depth */ } @media (prefers-reduced-motion) { - .c4p--side-panel .c4p--side-panel__slug-and-close { + .c4p--side-panel .c4p--side-panel__slug-and-close, + .c4p--side-panel .c4p--side-panel__ai-label-and-close { position: absolute; } } @@ -2886,7 +2888,8 @@ p.c4p--about-modal__copyright-text:first-child { inset: 0; } -.c4p--side-panel--has-slug + .c4p--side-panel__overlay { +.c4p--side-panel--has-slug + .c4p--side-panel__overlay, +.c4p--side-panel--has-ai-label + .c4p--side-panel__overlay { /* stylelint-disable-next-line carbon/theme-token-use */ background-color: var(--cds-ai-overlay, rgba(0, 17, 65, 0.5)); } @@ -2989,7 +2992,7 @@ p.c4p--about-modal__copyright-text:first-child { max-height: calc(100% - 3rem); transform: translate3d(0, min(95vh, 500px), 0); } -.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__container { +.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__container, .c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet--has-ai-label .c4p--tearsheet__container { border: 1px solid transparent; border-bottom: 0; /* override carbon ai removing background gradient */ @@ -3093,10 +3096,10 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-nav { padding: 1.5rem 2rem 0; } -.c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon, .c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header { +.c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon, .c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header, .c4p--tearsheet.c4p--tearsheet--has-ai-label .c4p--tearsheet__header.c4p--tearsheet__header { padding-inline-end: 5rem; } -.c4p--tearsheet.c4p--tearsheet--wide.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon { +.c4p--tearsheet.c4p--tearsheet--wide.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon, .c4p--tearsheet.c4p--tearsheet--wide.c4p--tearsheet--has-ai-label .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon { /* spacing 11 plus additional space for slug/close */ /* stylelint-disable-next-line carbon/layout-token-use */ padding-inline-end: calc(8rem); @@ -3160,7 +3163,7 @@ p.c4p--about-modal__copyright-text:first-child { overflow: auto; flex-grow: 1; } -.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__content { +.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__content, .c4p--tearsheet.c4p--tearsheet--has-ai-label .c4p--tearsheet__content { background: linear-gradient(to top, var(--cds-ai-popover-background, var(--cds-ai-popover-background, #ffffff)) 0%, var(--cds-ai-aura-start, rgba(69, 137, 255, 0.1)) 0%, 15%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%) padding-box, linear-gradient(to top, var(--cds-ai-popover-background, var(--cds-ai-popover-background, #ffffff)), var(--cds-ai-popover-background, var(--cds-ai-popover-background, #ffffff))) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, rgba(166, 200, 255, 0.64)), var(--cds-ai-border-end, #78a9ff)) border-box, linear-gradient(to top, var(--cds-ai-popover-background, var(--cds-ai-popover-background, #ffffff)), var(--cds-ai-popover-background, var(--cds-ai-popover-background, #ffffff))) border-box; box-shadow: inset 0 -80px 70px -65px var(--cds-ai-inner-shadow, rgba(69, 137, 255, 0.1)); } @@ -3202,11 +3205,11 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__buttons { background: var(--cds-background, #ffffff); } -.c4p--tearsheet.c4p--tearsheet--has-slug { +.c4p--tearsheet.c4p--tearsheet--has-slug, .c4p--tearsheet.c4p--tearsheet--has-ai-label { /* stylelint-disable-next-line carbon/theme-token-use */ --overlay-color: var(--cds-ai-overlay, rgba(0, 17, 65, 0.5)); } -.c4p--tearsheet.c4p--tearsheet--has-slug:not(.c4p--tearsheet--has-close) .cds--slug { +.c4p--tearsheet.c4p--tearsheet--has-slug:not(.c4p--tearsheet--has-close) .cds--slug, .c4p--tearsheet.c4p--tearsheet--has-ai-label:not(.c4p--tearsheet--has-close) .cds--slug { inset-inline-end: 0; margin-block: 6px; margin-inline-end: 1rem; @@ -3472,6 +3475,7 @@ p.c4p--about-modal__copyright-text:first-child { background-color: var(--cds-background, #ffffff); } +/* This section to be removed after support for slug dropped - start */ .c4p--datagrid th.c4p--datagrid__with-slug { /* stylelint-disable-next-line carbon/theme-token-use */ box-shadow: inset 0 1px var(--cds-ai-border-strong, #4589ff); @@ -3512,6 +3516,47 @@ p.c4p--about-modal__copyright-text:first-child { margin-left: 0.5rem; } +/* This section to be removed after support for slug dropped - end */ +.c4p--datagrid th.c4p--datagrid__with-ai-label { + /* stylelint-disable-next-line carbon/theme-token-use */ + box-shadow: inset 0 1px var(--cds-ai-border-strong, #4589ff); +} + +.c4p--datagrid th.c4p--datagrid__with-ai-label, +.c4p--datagrid td.c4p--datagrid__ai-label--cell { + background: linear-gradient(to right, var(--cds-ai-aura-start-sm, rgba(69, 137, 255, 0.16)) 0%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%, transparent 50%); +} + +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row, +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row + .c4p--datagrid__expanded-row { + background: linear-gradient(to right, var(--cds-ai-aura-start-sm, rgba(69, 137, 255, 0.16)) 0%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%, transparent 50%); + background-attachment: fixed; +} + +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row { + /* stylelint-disable-next-line carbon/theme-token-use */ + box-shadow: inset 1px 0 var(--cds-ai-border-strong, #4589ff); +} + +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row:hover, +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row.cds--data-table--selected:hover, +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row.c4p--datagrid__carbon-row-expanded:hover + .c4p--datagrid__expanded-row, +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__expandable-row--hover.c4p--datagrid__ai-label--row { + background: linear-gradient(to right, var(--cds-ai-aura-hover-start, rgba(69, 137, 255, 0.32)) 0%, 15%, var(--cds-ai-aura-hover-end, rgba(255, 255, 255, 0)) 50%), var(--cds-ai-aura-hover-background, #edf5ff); +} + +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__expandable-row--hover.c4p--datagrid__ai-label--row td { + background-color: transparent; +} + +.c4p--datagrid .cds--data-table tbody tr.c4p--datagrid__ai-label--row.cds--data-table--selected { + background: linear-gradient(to right, var(--cds-ai-aura-start-sm, rgba(69, 137, 255, 0.16)) 0%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%, transparent 50%), var(--cds-layer-selected); +} + +.c4p--datagrid th.c4p--datagrid__with-ai-label .cds--slug { + margin-left: 0.5rem; +} + .c4p--datagrid__grid-container { display: block; width: 100%; @@ -3583,7 +3628,8 @@ p.c4p--about-modal__copyright-text:first-child { -webkit-line-clamp: 2; white-space: initial; } -.c4p--datagrid__grid-container .c4p--datagrid__defaultStringRenderer.c4p--datagrid__defaultStringRenderer--slug { +.c4p--datagrid__grid-container .c4p--datagrid__defaultStringRenderer.c4p--datagrid__defaultStringRenderer--slug, +.c4p--datagrid__grid-container .c4p--datagrid__defaultStringRenderer.c4p--datagrid__defaultStringRenderer--ai-label { width: fit-content; } .c4p--datagrid__grid-container .c4p--datagrid__expanded-row { @@ -3693,6 +3739,9 @@ p.c4p--about-modal__copyright-text:first-child { background-color: var(--cds-background-selected-hover, rgba(141, 141, 141, 0.32)); } +.c4p--datagrid__resizableColumn:hover { + background-color: var(--cds-background-selected-hover, rgba(141, 141, 141, 0.32)); +} .c4p--datagrid__resizableColumn:hover .c4p--datagrid__resizer { border-right: 0.125rem solid var(--cds-border-strong-01, #8d8d8d); background-color: var(--cds-background-selected-hover, rgba(141, 141, 141, 0.32)); @@ -4072,7 +4121,7 @@ p.c4p--about-modal__copyright-text:first-child { display: flex; align-items: center; } -.c4p--datagrid .c4p--datagrid__table-row-ai-enabled.c4p--datagrid__slug--expanded { +.c4p--datagrid .c4p--datagrid__table-row-ai-enabled.c4p--datagrid__slug--expanded, .c4p--datagrid .c4p--datagrid__table-row-ai-enabled.c4p--datagrid__ai-label--expanded { border: none; } @@ -5770,16 +5819,19 @@ th.c4p--datagrid__select-all-toggle-on.button { right: 1rem; } -.c4p--card__header-container--has-slug { +.c4p--card__header-container--has-slug, +.c4p--card__header-container--has-ai-label { width: 100%; padding-right: 2rem; } -.c4p--card__header-container--has-slug.c4p--card__header-container--has-actions { +.c4p--card__header-container--has-slug.c4p--card__header-container--has-actions, +.c4p--card__header-container--has-ai-label.c4p--card__header-container--has-actions { padding-right: 2.5rem; } -.c4p--card__header-container--has-slug.c4p--card__header-container--large-tile-or-label { +.c4p--card__header-container--has-slug.c4p--card__header-container--large-tile-or-label, +.c4p--card__header-container--has-ai-label.c4p--card__header-container--large-tile-or-label { padding-right: 3rem; } @@ -5792,13 +5844,15 @@ th.c4p--datagrid__select-all-toggle-on.button { pointer-events: none; } -.c4p--card--has-slug { +.c4p--card--has-slug, +.c4p--card--has-ai-label { background: linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)) 0%, var(--cds-ai-aura-start, rgba(69, 137, 255, 0.1)) 0%, 15%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%) padding-box, linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)), var(--cds-layer, var(--cds-ai-popover-background, #ffffff))) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, rgba(166, 200, 255, 0.64)), var(--cds-ai-border-end, #78a9ff)) border-box, linear-gradient(to top, var(--cds-layer, var(--cds-ai-popover-background, #ffffff)), var(--cds-layer, var(--cds-ai-popover-background, #ffffff))) border-box; border: 1px solid transparent; box-shadow: inset 0 -80px 70px -65px var(--cds-ai-inner-shadow, rgba(69, 137, 255, 0.1)), 0 4px 10px 2px var(--cds-ai-drop-shadow, rgba(15, 98, 254, 0.1)); } -.c4p--card__clickable.c4p--card--has-slug::before { +.c4p--card__clickable.c4p--card--has-slug::before, +.c4p--card__clickable.c4p--card--has-ai-label::before { background: linear-gradient(to top, var(--cds-ai-aura-hover-start, rgba(69, 137, 255, 0.32)) 0%, 15%, var(--cds-ai-aura-hover-end, rgba(255, 255, 255, 0)) 50%) padding-box, linear-gradient(to top, var(--cds-ai-aura-hover-background, #edf5ff), var(--cds-ai-aura-hover-background, #edf5ff)) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, rgba(166, 200, 255, 0.64)), var(--cds-ai-border-end, #78a9ff)) border-box, linear-gradient(to top, var(--cds-ai-aura-hover-background, #edf5ff), var(--cds-ai-aura-hover-background, #edf5ff)) border-box; position: absolute; display: block; @@ -5812,7 +5866,8 @@ th.c4p--datagrid__select-all-toggle-on.button { transition: opacity 110ms cubic-bezier(0.2, 0, 0.38, 0.9); } -.c4p--card__clickable.c4p--card--has-slug:hover::before { +.c4p--card__clickable.c4p--card--has-slug:hover::before, +.c4p--card__clickable.c4p--card--has-ai-label:hover::before { opacity: 1; } @@ -9252,15 +9307,27 @@ button.c4p--add-select__global-filter-toggle--open { flex: 1 0 60%; } } +.c4p--page-header .c4p--page-header__tooltip { + min-width: 0; + flex-basis: auto; +} +.c4p--page-header .c4p--page-header__tooltip button { + border-block-end: none; + cursor: default; +} +.c4p--page-header .c4p--page-header__titleText { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} .c4p--page-header .c4p--page-header__title { font-size: var(--cds-heading-04-font-size, 1.75rem); font-weight: var(--cds-heading-04-font-weight, 400); line-height: var(--cds-heading-04-line-height, 1.28572); letter-spacing: var(--cds-heading-04-letter-spacing, 0); + display: flex; min-height: 2.5rem; - overflow-x: hidden; - text-overflow: ellipsis; - white-space: nowrap; } .c4p--page-header .c4p--page-header__title--editable { display: flex; diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyDownloader.js b/packages/ibm-products/src/components/APIKeyModal/APIKeyDownloader.js index 822827bcf3..03e05d4686 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyDownloader.js +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyDownloader.js @@ -16,6 +16,7 @@ export const APIKeyDownloader = ({ fileName, fileType, linkText, + downloadLinkLabel, }) => { const [linkProps, setLinkProps] = useState({}); @@ -44,6 +45,8 @@ export const APIKeyDownloader = ({ {linkText} @@ -62,6 +65,10 @@ APIKeyDownloader.propTypes = { * body content for the downloader */ body: PropTypes.string.isRequired, + /** + * aria-label for the download link + */ + downloadLinkLabel: PropTypes.string, /** * designates the name of downloadable json file with the key. if not specified will default to 'apikey' */ diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.stories.jsx b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.stories.jsx index 3c7af85008..0343951e57 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.stories.jsx +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.stories.jsx @@ -68,6 +68,7 @@ const defaultProps = { downloadBodyText: 'This is your unique API key and is non-recoverable. If you lose this API key, you will have to reset it.', downloadLinkText: 'Download as JSON', + downloadLinkLabel: 'Download API Key in Java Script File format', hasDownloadLink: true, downloadFileName: 'apikey', downloadFileType: 'json', @@ -76,7 +77,7 @@ const defaultProps = { generateSuccessTitle: 'API key successfully created', editSuccessTitle: 'API key successfully saved', loadingText: 'Generating...', - modalLabel: 'Generate API key', + modalLabel: 'An example of Generate API key', }; const blockClass = `${pkg.prefix}--apikey-modal`; diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.test.js b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.test.js index 198d10af7d..a151a3bc7e 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.test.js +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.test.js @@ -39,6 +39,7 @@ const defaultProps = { downloadFileName: 'filename', downloadFileType: 'json', downloadLinkText: 'download link text', + downloadLinkLabel: 'Download API Key in Java Script File format', editButtonText: 'edit button', editSuccess: false, editSuccessTitle: 'edited successfully', diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx index 18f2f9a261..f8997b8c06 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx @@ -55,6 +55,7 @@ export let APIKeyModal: React.FC = forwardRef( downloadFileName, downloadFileType, downloadLinkText, + downloadLinkLabel = downloadLinkText, editButtonText, editSuccess, editSuccessTitle, @@ -289,6 +290,7 @@ export let APIKeyModal: React.FC = forwardRef( fileName={downloadFileName} linkText={downloadLinkText} fileType={downloadFileType} + downloadLinkLabel={downloadLinkLabel} /> ) : (
@@ -403,6 +405,10 @@ APIKeyModal.propTypes = { * designates the file type for the downloadable key */ downloadFileType: downloadRequiredProps(PropTypes.oneOf(['txt', 'json'])), + /** + * aria-label for the download link + */ + downloadLinkLabel: downloadRequiredProps(PropTypes.string), /** * anchor text for the download link */ diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.types.ts b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.types.ts index 61b9a60d4b..8432158c05 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.types.ts +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.types.ts @@ -212,6 +212,10 @@ type HasDownloadLinkProps = { * anchor text for the download link */ downloadLinkText: string; + /** + * Aria-label for the download link + */ + downloadLinkLabel?: string; }; export type APIKeyModalProps = APIKeyModalCommonProps & diff --git a/packages/ibm-products/src/components/ActionSet/ActionSet.tsx b/packages/ibm-products/src/components/ActionSet/ActionSet.tsx index e5265d8797..e1a1bc63f2 100644 --- a/packages/ibm-products/src/components/ActionSet/ActionSet.tsx +++ b/packages/ibm-products/src/components/ActionSet/ActionSet.tsx @@ -67,6 +67,7 @@ const ActionSetButton = React.forwardRef( ActionSetButton.displayName = 'ActionSetButton'; ActionSetButton.propTypes = { + /**@ts-ignore*/ ...Button.PropTypes, kind: PropTypes.oneOf([ 'ghost', @@ -96,7 +97,7 @@ export interface ActionSetProps { * * See https://react.carbondesignsystem.com/?path=/docs/components-button--default#component-api */ - actions: ButtonProps[]; + actions: ButtonProps[]; /** * The size of buttons to use for the actions. The allowed values are @@ -304,6 +305,7 @@ ActionSet.propTypes = { ActionSet.validateActions(), PropTypes.arrayOf( PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf([ 'ghost', @@ -315,6 +317,7 @@ ActionSet.propTypes = { label: PropTypes.string, loading: PropTypes.bool, // we duplicate this Button prop to improve the DocGen here + /**@ts-ignore*/ onClick: Button.propTypes.onClick, }) ), @@ -326,6 +329,7 @@ ActionSet.propTypes = { * the buttons will be set to this size, overriding any 'size' values (if any) * supplied in the actions array (if any). */ + /**@ts-ignore*/ buttonSize: Button.propTypes.size, /** diff --git a/packages/ibm-products/src/components/AddSelect/AddSelectBody.tsx b/packages/ibm-products/src/components/AddSelect/AddSelectBody.tsx index 6774f2a95a..125f65fa55 100644 --- a/packages/ibm-products/src/components/AddSelect/AddSelectBody.tsx +++ b/packages/ibm-products/src/components/AddSelect/AddSelectBody.tsx @@ -9,7 +9,12 @@ import React, { ForwardedRef, ReactNode, forwardRef, useState } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { Tag } from '@carbon/react'; -import { Tearsheet, TearsheetNarrow } from '../../components/Tearsheet'; +import { + Tearsheet, + TearsheetNarrow, + TearsheetNarrowProps, + TearsheetProps, +} from '../../components/Tearsheet'; import { NotFoundEmptyState } from '../EmptyStates'; import { AddSelectSidebar } from './AddSelectSidebar'; import { AddSelectBreadcrumbs } from './AddSelectBreadcrumbs'; @@ -69,6 +74,9 @@ export interface AddSelectBodyProps { useNormalizedItems?: boolean; } +type CommonTearsheetProps = TearsheetNarrowProps & + TearsheetProps & { ref: ForwardedRef }; + export const AddSelectBody = forwardRef( ( { @@ -231,7 +239,7 @@ export const AddSelectBody = forwardRef( parentId: path[0].id, }; - const commonTearsheetProps = { + const commonTearsheetProps: CommonTearsheetProps = { ...rest, className: tearsheetClassnames, open, diff --git a/packages/ibm-products/src/components/AddSelect/types/index.ts b/packages/ibm-products/src/components/AddSelect/types/index.ts index 9ce2fbcdcd..dc2c88e3d3 100644 --- a/packages/ibm-products/src/components/AddSelect/types/index.ts +++ b/packages/ibm-products/src/components/AddSelect/types/index.ts @@ -55,5 +55,5 @@ export interface SortOption { id?: string; direction?: string; attribute?: string; - itemText?: object; + itemText?: ReactNode; } diff --git a/packages/ibm-products/src/components/Checklist/Checklist.tsx b/packages/ibm-products/src/components/Checklist/Checklist.tsx index 948269c484..de1fdec0a8 100644 --- a/packages/ibm-products/src/components/Checklist/Checklist.tsx +++ b/packages/ibm-products/src/components/Checklist/Checklist.tsx @@ -145,7 +145,6 @@ const defaults = { taskLists: [], theme: Themes.light, toggleLabel: 'Toggle', - toggleLabelAlign: 'top', }; /** @@ -170,7 +169,7 @@ export let Checklist = React.forwardRef( theme = defaults.theme, title, toggleLabel = defaults.toggleLabel, - toggleLabelAlign = defaults.toggleLabelAlign, + toggleLabelAlign = 'top', viewAllLabel, ...rest }: ChecklistProps, diff --git a/packages/ibm-products/src/components/CoachmarkStack/CoachmarkStackHome.tsx b/packages/ibm-products/src/components/CoachmarkStack/CoachmarkStackHome.tsx index c6e895978e..67cda9ddf7 100644 --- a/packages/ibm-products/src/components/CoachmarkStack/CoachmarkStackHome.tsx +++ b/packages/ibm-products/src/components/CoachmarkStack/CoachmarkStackHome.tsx @@ -124,7 +124,7 @@ export let CoachmarkStackHome = forwardRef< }, ref ) => { - const buttonFocusRef = useRef | null>(null); + const buttonFocusRef = useRef | null>(null); const [linkFocusIndex, setLinkFocusIndex] = useState(0); useEffect(() => { setTimeout(() => { @@ -152,7 +152,7 @@ export let CoachmarkStackHome = forwardRef< function renderNavLink( index, label, - ref: React.RefObject> | null = null + ref: React.RefObject> | null = null ) { return (
  • diff --git a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.stories.jsx b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.stories.jsx index f7104d7e3c..f1031bef63 100644 --- a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.stories.jsx +++ b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.stories.jsx @@ -85,6 +85,7 @@ const defaultFullPageProps = { "If you cancel, the information you have entered won't be saved.", modalDangerButtonText: 'Cancel partition', modalSecondaryButtonText: 'Return to form', + onClickInfluencerStep: (step) => console.log('Step: ', step), onRequestSubmit: action('Submit handler called'), onClose: action('Close handler called'), }; @@ -194,17 +195,20 @@ const Template = ({ ...args }) => { title="Dynamic step" description="Example dynamic step" includeStep={shouldIncludeAdditionalStep} + onPrevious={() => console.log('custom onPrevious handler')} /> console.log('custom onPrevious handler')} /> console.log('custom onPrevious handler')} > @@ -259,6 +263,7 @@ const Template = ({ ...args }) => { title="Message retention" subtitle="This is how many copies of a topic will be made for high availability" description="The partitions of each topic can be replicated across a configurable number of brokers" + onPrevious={() => console.log('custom onPrevious handler')} > diff --git a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.test.js b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.test.js index db9df6f44c..eb259f9ea6 100644 --- a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.test.js +++ b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.test.js @@ -42,6 +42,7 @@ const onRequestSubmitRejectFn = jest.fn(() => Promise.reject(rejectionErrorMessage) ); const onNextStepFn = jest.fn(() => Promise.resolve()); +const onPreviousStepFn = jest.fn(); const onNextStepNonPromiseFn = jest.fn(); const onNextStepRejectionFn = jest.fn(() => Promise.reject(rejectionErrorMessage) @@ -96,6 +97,7 @@ const renderCreateFullPage = ({ rejectOnNext = false, submitFn = onRequestSubmitFn, onNext = onNextStepFn, + onPrevious = onPreviousStepFn, finalOnNextFn = finalStepOnNext, rejectOnSubmitNext = false, ...rest @@ -121,6 +123,7 @@ const renderCreateFullPage = ({ description="2" fieldsetLegendText="2" invalid={false} + onPrevious={onPrevious} > {stepFormField} @@ -212,6 +215,17 @@ describe(componentName, () => { expect(container.querySelector(`.${blockClass}`)).toBeTruthy(); }); + it('should call onClickInfluencerStep when expected', async () => { + const onChange = jest.fn(); + renderCreateFullPage({ + ...defaultFullPageProps, + onClickInfluencerStep: onChange, + }); + + await userEvent.click(screen.getByTitle('Title 2')); + expect(onChange).toHaveBeenCalled(); + }); + it('should render the CreateFullPage on the specified initialStep prop provided', () => { const { container } = renderCreateFullPage({ ...defaultFullPageProps, @@ -303,6 +317,28 @@ describe(componentName, () => { }); }); + it('calls the onPrevious function prop as expected', async () => { + const { click } = userEvent; + const { container } = renderCreateFullPage(defaultFullPageProps); + const nextButtonElement = screen.getByText(nextButtonText); + const backButtonElement = screen.getByText(backButtonText); + await act(() => click(nextButtonElement)); + const createFullPageSteps = container.querySelector( + `.${blockClass}__content` + ).children; + expect( + createFullPageSteps[0].classList.contains( + `.${blockClass}__step__step--visible-step` + ) + ); + + await waitFor(() => { + expect(onNextStepFn).toHaveBeenCalled(); + }); + click(backButtonElement); + await waitFor(() => expect(onPreviousStepFn).toHaveBeenCalledTimes(1)); + }); + it('renders a modal when cancel button has been clicked and recognizes primary and secondary button clicks in modal', async () => { const { click } = userEvent; const { container, rerender } = renderCreateFullPage(defaultFullPageProps); diff --git a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.tsx b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.tsx index e1234c70bd..140e228f45 100644 --- a/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.tsx +++ b/packages/ibm-products/src/components/CreateFullPage/CreateFullPage.tsx @@ -161,6 +161,12 @@ type CreateFullPageBaseProps = { */ noTrailingSlash?: boolean; + /** + * onChange event for Progress Indicator in the Influencer + * @param data step index + */ + onClickInfluencerStep?: (data: number) => void; + /** * An optional handler that is called when the user closes the full page (by * clicking the secondary button, located in the modal, which triggers after @@ -233,6 +239,7 @@ export let CreateFullPage = React.forwardRef( modalSecondaryButtonText, modalTitle, nextButtonText, + onClickInfluencerStep, onClose, onRequestSubmit, firstFocusElement, @@ -253,6 +260,7 @@ export let CreateFullPage = React.forwardRef( // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc const previousState = usePreviousValue({ currentStep, open }); const [isDisabled, setIsDisabled] = useState(false); + const [onPrevious, setOnPrevious] = useState(); const [onNext, setOnNext] = useState(); const [onMount, setOnMount] = useState(); const [stepData, setStepData] = useState([]); @@ -309,6 +317,7 @@ export let CreateFullPage = React.forwardRef( firstIncludedStep, lastIncludedStep, stepData, + onPrevious, onNext, isSubmitDisabled: isDisabled, setCurrentStep, @@ -355,6 +364,7 @@ export let CreateFullPage = React.forwardRef( stepData={stepData} currentStep={currentStep} title={secondaryTitle} + onClickStep={onClickInfluencerStep} />
  • @@ -366,6 +376,7 @@ export let CreateFullPage = React.forwardRef( { currentStep, setIsDisabled, + setOnPrevious: (fn) => setOnPrevious(() => fn), setOnNext: (fn) => setOnNext(() => fn), setOnMount: (fn) => setOnMount(() => fn), setStepData, @@ -527,6 +538,11 @@ CreateFullPage.propTypes = { */ noTrailingSlash: PropTypes.bool, + /** + * onChange event for Progress Indicator in the Influencer + */ + onClickInfluencerStep: PropTypes.func, + /** * An optional handler that is called when the user closes the full page (by * clicking the secondary button, located in the modal, which triggers after diff --git a/packages/ibm-products/src/components/CreateFullPage/CreateFullPageStep.tsx b/packages/ibm-products/src/components/CreateFullPage/CreateFullPageStep.tsx index 9d300f7516..f86f95748d 100644 --- a/packages/ibm-products/src/components/CreateFullPage/CreateFullPageStep.tsx +++ b/packages/ibm-products/src/components/CreateFullPage/CreateFullPageStep.tsx @@ -81,6 +81,11 @@ interface CreateFullPageStepBaseProps extends PropsWithChildren { */ onNext?: () => void | Promise; + /** + * Optional function to be called when you move to the previous step. + */ + onPrevious?: () => void; + /** * Sets the optional secondary label on the progress step component */ @@ -138,6 +143,7 @@ export let CreateFullPageStep = forwardRef( hasFieldset, fieldsetLegendText, onNext, + onPrevious, onMount, secondaryLabel, @@ -184,8 +190,9 @@ export let CreateFullPageStep = forwardRef( if (stepNumber === stepsContext?.currentStep) { stepsContext.setIsDisabled(disableSubmit as boolean); stepsContext?.setOnNext(onNext); // needs to be updated here otherwise there could be stale state values from only initially setting onNext + stepsContext?.setOnPrevious(onPrevious); } - }, [stepsContext, stepNumber, disableSubmit, onNext]); + }, [stepsContext, stepNumber, disableSubmit, onNext, onPrevious]); const span = { span: 50 }; // Half. @@ -326,6 +333,11 @@ CreateFullPageStep.propTypes = { */ onNext: PropTypes.func, + /** + * Optional function to be called when you move to the previous step. + */ + onPrevious: PropTypes.func, + /** * Sets the optional secondary label on the progress step component */ diff --git a/packages/ibm-products/src/components/CreateInfluencer/CreateInfluencer.tsx b/packages/ibm-products/src/components/CreateInfluencer/CreateInfluencer.tsx index 0a4ee037b4..39a2ad955a 100644 --- a/packages/ibm-products/src/components/CreateInfluencer/CreateInfluencer.tsx +++ b/packages/ibm-products/src/components/CreateInfluencer/CreateInfluencer.tsx @@ -33,6 +33,10 @@ interface CreateInfluencerProps { * Provide the current step number. */ currentStep: number; + /** + * onChange event for Progress Indicator + */ + onClickStep?: (step: number) => void; /** * Provide the Set Data. */ @@ -46,6 +50,7 @@ interface CreateInfluencerProps { export const CreateInfluencer = ({ className, currentStep, + onClickStep, stepData, title, }: PropsWithChildren) => { @@ -86,11 +91,12 @@ export const CreateInfluencer = ({ spaceEqually vertical className={cx(`${blockClass}__progress-indicator`)} + onChange={onClickStep} > - {progressSteps.map((step, stepIndex) => { + {progressSteps.map((step: Step, stepIndex: number) => { return ( , - ref + ref: LegacyRef ) => { const renderPortalUse = usePortalTarget(portalTargetIn); @@ -222,7 +222,7 @@ CreateModal.propTypes = { /** * Specifies which DOM element in the form should be focused. */ - selectorPrimaryFocus: PropTypes.node.isRequired, + selectorPrimaryFocus: PropTypes.string.isRequired, /** * The subtitle of the CreateModal is optional and serves to provide more information about the modal. */ diff --git a/packages/ibm-products/src/components/CreateSidePanel/CreateSidePanel.tsx b/packages/ibm-products/src/components/CreateSidePanel/CreateSidePanel.tsx index bbfeccddbc..83b35b0d53 100644 --- a/packages/ibm-products/src/components/CreateSidePanel/CreateSidePanel.tsx +++ b/packages/ibm-products/src/components/CreateSidePanel/CreateSidePanel.tsx @@ -16,7 +16,7 @@ import { pkg } from '../../settings'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; // Carbon and package components we use. -import { Form } from '@carbon/react'; +import { ButtonProps, Form } from '@carbon/react'; import { SidePanel } from '../SidePanel'; import uuidv4 from '../../global/js/utils/uuidv4'; @@ -128,7 +128,7 @@ export let CreateSidePanel = React.forwardRef( }: PropsWithChildren, ref: React.Ref ) => { - const actions = [ + const actions: ButtonProps[] = [ { label: primaryButtonText, onClick: (event) => { diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridSelectAll.tsx b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridSelectAll.tsx index 8b4b9a4a07..068c90d101 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridSelectAll.tsx +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridSelectAll.tsx @@ -78,6 +78,7 @@ const SelectAll = (datagridState: DataGridState) => { return ( { const radioGroupRef = useRef(undefined); @@ -63,6 +64,7 @@ const RowSizeDropdown = ({ className={`${blockClass}-options-container`} onKeyDown={onKeyHandler} onBlur={onBlurHandler} + autoAlign={autoAlign} > ['align']; shouldHideMenuItem?: (...args) => void; - shouldDisableMenuItem?: (...args) => void; + shouldDisableMenuItem?: (...args) => boolean; disabled?: boolean; onClick?: (...args) => void; } @@ -281,7 +281,7 @@ export interface DataGridState emptyStateAction?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; emptyStateLink?: { @@ -305,7 +305,7 @@ export interface DataGridState allPageRowsLabel?: string | object; allRowsLabel?: string | object; onSelectAllRows?: (val?: boolean) => void; - toolbarBatchActions?: ButtonProps[]; + toolbarBatchActions?: ButtonProps[]; setGlobalFilter?: (filterValue: FilterValue) => void; batchActionMenuButtonLabel?: string; translateWithIdBatchActions?: TableBatchActionsProps['translateWithId']; diff --git a/packages/ibm-products/src/components/EditSidePanel/EditSidePanel.tsx b/packages/ibm-products/src/components/EditSidePanel/EditSidePanel.tsx index ecb5b006ae..538cb3c197 100644 --- a/packages/ibm-products/src/components/EditSidePanel/EditSidePanel.tsx +++ b/packages/ibm-products/src/components/EditSidePanel/EditSidePanel.tsx @@ -11,7 +11,7 @@ import '../../global/js/utils/props-helper'; import React, { ForwardedRef, ReactNode } from 'react'; // Carbon and package components we use. -import { Form } from '@carbon/react'; +import { ButtonProps, Form } from '@carbon/react'; // Other standard imports. import PropTypes from 'prop-types'; import { SidePanel } from '../SidePanel'; @@ -159,7 +159,7 @@ export let EditSidePanel = React.forwardRef( }: EditSidePanelProps, ref: ForwardedRef ) => { - const actions = [ + const actions: ButtonProps[] = [ { label: primaryButtonText, onClick: (event) => { diff --git a/packages/ibm-products/src/components/EditTearsheet/EditTearsheet.tsx b/packages/ibm-products/src/components/EditTearsheet/EditTearsheet.tsx index 89722a68ad..565bbd826a 100644 --- a/packages/ibm-products/src/components/EditTearsheet/EditTearsheet.tsx +++ b/packages/ibm-products/src/components/EditTearsheet/EditTearsheet.tsx @@ -17,7 +17,13 @@ import React, { import PropTypes from 'prop-types'; import cx from 'classnames'; // @ts-ignore -import { Form, SideNav, SideNavItems, SideNavMenuItem } from '@carbon/react'; +import { + ButtonProps, + Form, + SideNav, + SideNavItems, + SideNavMenuItem, +} from '@carbon/react'; import { pkg } from '../../settings'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; import { TearsheetShell } from '../Tearsheet/TearsheetShell'; @@ -170,7 +176,7 @@ export let EditTearsheet = forwardRef( } setIsSubmitting(false); }; - const actions = [ + const actions: ButtonProps[] = [ { key: 'edit-action-button-submit', label: submitButtonText, diff --git a/packages/ibm-products/src/components/EmptyStates/EmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/EmptyState.tsx index ece4bfc013..fbde2f7712 100644 --- a/packages/ibm-products/src/components/EmptyStates/EmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/EmptyState.tsx @@ -44,7 +44,7 @@ export interface EmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -162,9 +162,11 @@ EmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -196,6 +198,7 @@ EmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/ErrorEmptyState/ErrorEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/ErrorEmptyState/ErrorEmptyState.tsx index fe1b2f35e0..0b70b344ec 100644 --- a/packages/ibm-products/src/components/EmptyStates/ErrorEmptyState/ErrorEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/ErrorEmptyState/ErrorEmptyState.tsx @@ -33,7 +33,7 @@ export interface ErrorEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -157,9 +157,11 @@ ErrorEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -190,6 +192,7 @@ ErrorEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/NoDataEmptyState/NoDataEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/NoDataEmptyState/NoDataEmptyState.tsx index 02087ac4e2..a8e61a941e 100644 --- a/packages/ibm-products/src/components/EmptyStates/NoDataEmptyState/NoDataEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/NoDataEmptyState/NoDataEmptyState.tsx @@ -32,7 +32,7 @@ export interface NoDataEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -156,9 +156,11 @@ NoDataEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore */ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore */ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -189,6 +191,7 @@ NoDataEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore */ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/NoTagsEmptyState/NoTagsEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/NoTagsEmptyState/NoTagsEmptyState.tsx index 6462f3f78c..9acf8297b9 100644 --- a/packages/ibm-products/src/components/EmptyStates/NoTagsEmptyState/NoTagsEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/NoTagsEmptyState/NoTagsEmptyState.tsx @@ -33,7 +33,7 @@ export interface NoTagsEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -157,9 +157,11 @@ NoTagsEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -190,6 +192,7 @@ NoTagsEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/NotFoundEmptyState/NotFoundEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/NotFoundEmptyState/NotFoundEmptyState.tsx index 56828d7c2d..bc4b82417c 100644 --- a/packages/ibm-products/src/components/EmptyStates/NotFoundEmptyState/NotFoundEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/NotFoundEmptyState/NotFoundEmptyState.tsx @@ -33,7 +33,7 @@ export interface NotFoundEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -159,9 +159,11 @@ NotFoundEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -192,6 +194,7 @@ NotFoundEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/NotificationsEmptyState/NotificationsEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/NotificationsEmptyState/NotificationsEmptyState.tsx index 57bd5333b5..51a3afc4a1 100644 --- a/packages/ibm-products/src/components/EmptyStates/NotificationsEmptyState/NotificationsEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/NotificationsEmptyState/NotificationsEmptyState.tsx @@ -34,7 +34,7 @@ export interface NotificationsEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -161,9 +161,11 @@ NotificationsEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -194,6 +196,7 @@ NotificationsEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/EmptyStates/UnauthorizedEmptyState/UnauthorizedEmptyState.tsx b/packages/ibm-products/src/components/EmptyStates/UnauthorizedEmptyState/UnauthorizedEmptyState.tsx index 411037a951..138de84a24 100644 --- a/packages/ibm-products/src/components/EmptyStates/UnauthorizedEmptyState/UnauthorizedEmptyState.tsx +++ b/packages/ibm-products/src/components/EmptyStates/UnauthorizedEmptyState/UnauthorizedEmptyState.tsx @@ -32,7 +32,7 @@ export interface UnauthorizedEmptyStateProps { action?: { kind?: 'primary' | 'secondary' | 'tertiary'; renderIcon?: CarbonIconType; - onClick?: ButtonProps['onClick']; + onClick?: ButtonProps['onClick']; text?: string; }; @@ -159,9 +159,11 @@ UnauthorizedEmptyState.propTypes = { * Empty state action button */ action: PropTypes.shape({ + /**@ts-ignore*/ ...Button.propTypes, kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary']), renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /**@ts-ignore*/ onClick: Button.propTypes.onClick, text: PropTypes.string, }), @@ -192,6 +194,7 @@ UnauthorizedEmptyState.propTypes = { /** * Empty state link object */ + /**@ts-ignore*/ link: PropTypes.shape({ ...Link.propTypes, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/packages/ibm-products/src/components/FeatureFlags/FeatureFlags.test.js b/packages/ibm-products/src/components/FeatureFlags/FeatureFlags.test.js index 2a5f1ac0ce..919b966016 100644 --- a/packages/ibm-products/src/components/FeatureFlags/FeatureFlags.test.js +++ b/packages/ibm-products/src/components/FeatureFlags/FeatureFlags.test.js @@ -44,87 +44,29 @@ describe('FeatureFlags', () => { function TestComponent() { const featureFlags = useFeatureFlags(); const a = useFeatureFlag('a'); - const b = useFeatureFlag('b'); checkFlags({ a: featureFlags.enabled('a'), - b: featureFlags.enabled('b'), }); checkFlag({ a, - b, }); return null; } render( - + ); expect(checkFlags).toHaveBeenLastCalledWith({ a: true, - b: false, }); expect(checkFlag).toHaveBeenLastCalledWith({ a: true, - b: false, - }); - }); - - it('should re-render when flags change', () => { - const checkFlags = jest.fn(); - const checkFlag = jest.fn(); - - function TestComponent() { - const featureFlags = useFeatureFlags(); - const a = useFeatureFlag('a'); - const b = useFeatureFlag('b'); - - checkFlags({ - a: featureFlags.enabled('a'), - b: featureFlags.enabled('b'), - }); - - checkFlag({ - a, - b, - }); - - return null; - } - - const { rerender } = render( - - - - ); - - expect(checkFlags).toHaveBeenLastCalledWith({ - a: true, - b: false, - }); - expect(checkFlag).toHaveBeenLastCalledWith({ - a: true, - b: false, - }); - - rerender( - - - - ); - - expect(checkFlags).toHaveBeenLastCalledWith({ - a: false, - b: true, - }); - expect(checkFlag).toHaveBeenLastCalledWith({ - a: false, - b: true, }); }); diff --git a/packages/ibm-products/src/components/Guidebanner/Guidebanner.test.js b/packages/ibm-products/src/components/Guidebanner/Guidebanner.test.js index 9976a0b52b..9a03cca179 100644 --- a/packages/ibm-products/src/components/Guidebanner/Guidebanner.test.js +++ b/packages/ibm-products/src/components/Guidebanner/Guidebanner.test.js @@ -6,12 +6,17 @@ */ import React from 'react'; -import { render, screen } from '@testing-library/react'; // https://testing-library.com/docs/react-testing-library/intro +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; // https://testing-library.com/docs/react-testing-library/intro -import { pkg } from '../../settings'; +import { pkg, carbon } from '../../settings'; import uuidv4 from '../../global/js/utils/uuidv4'; -import { Guidebanner, GuidebannerElement } from '.'; +import { + Guidebanner, + GuidebannerElement, + GuidebannerElementButton, + GuidebannerElementLink, +} from '.'; const blockClass = `${pkg.prefix}--guidebanner`; const componentName = Guidebanner.displayName; @@ -32,7 +37,14 @@ const renderComponent = (customProps = {}) => { // The Guidebanner must have at least one GuidebannerElement as a child. return render( - + + Show Me + + } + > ); }; @@ -79,10 +91,12 @@ describe(componentName, () => { screen.getByTestId(dataTestId); }); - it('forwards a ref to an appropriate node', () => { + it('forwards a ref to an appropriate node', async () => { const ref = React.createRef(); renderComponent({ ref }); - + await waitFor(() => expect(ref.current).toHaveClass(blockClass), { + timeout: 10, + }); expect(ref.current).toHaveClass(blockClass); }); @@ -92,4 +106,90 @@ describe(componentName, () => { componentName ); }); + + it('renders the icon in the CTA button', () => { + renderComponent(); + + const button = screen.getByRole('button', { name: /show me/i }); + + expect(button).toBeInTheDocument(); + + const svgIcon = button.querySelector('svg'); + expect(svgIcon).toBeInTheDocument(); + + expect(svgIcon).toHaveAttribute('width', '16'); + expect(svgIcon).toHaveAttribute('height', '16'); + }); + + it('renders default ghost button variant if type is not passed for GuidebannerElementButton', () => { + render( + + Show Me} + /> + + ); + const button = screen.getByRole('button', { name: /show me/i }); + expect(button).toBeInTheDocument(); + expect(button).toHaveClass(`${blockClass}__element-button`); + expect(button).toHaveClass(`${carbon.prefix}--btn--ghost`); + }); + + it('returns link for GuidebannerElementLink', () => { + render( + + Learn more} + /> + + ); + const link = screen.getByRole('link', { name: /learn more/i }); + expect(link).toBeInTheDocument(); + }); + + it('expands/collapses the guidebanner', () => { + renderComponent({ collapsible: true }); + + const toggleButton = screen.getByRole('button', { name: /read more/i }); + expect(toggleButton).toHaveClass(`${blockClass}__toggle-button`); + + // starts collapsed + expect(toggleButton).toHaveAttribute('aria-expanded', 'false'); + + // Expands on click + fireEvent.click(toggleButton); + expect(toggleButton).toHaveTextContent('Read less'); + expect(toggleButton).toHaveAttribute('aria-expanded', 'true'); + + // Collapses back on second click + fireEvent.click(toggleButton); + expect(toggleButton).toHaveTextContent('Read more'); + expect(toggleButton).toHaveAttribute('aria-expanded', 'false'); + }); + + it('renders the close button and triggers the onClose callback when provided', () => { + const onCloseMock = jest.fn(); + renderComponent({ onClose: onCloseMock }); + + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + + fireEvent.click(closeButton); + expect(onCloseMock).toHaveBeenCalledTimes(1); + }); + + it('throws error for an invalid child', () => { + const errorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); + + render( + +

    invalid child

    +
    + ); + expect(errorMock).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx b/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx index b89021e867..7ca647b52d 100644 --- a/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx +++ b/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx @@ -221,7 +221,7 @@ export let Guidebanner = React.forwardRef( {onClose && ( = forwardRef( { // The component props, in alphabetical order (for consistency). - accept = defaults.accept, + accept = [], className, defaultErrorBody, defaultErrorHeader, @@ -199,7 +194,7 @@ export let ImportModal: React.FC = forwardRef( // Collect any other property values passed in. ...rest }, - ref + ref: ForwardedRef ) => { const carbonPrefix = usePrefix(); const [files, setFiles] = useState>([]); @@ -258,7 +253,7 @@ export let ImportModal: React.FC = forwardRef( const fileName = importUrl .substring(importUrl.lastIndexOf('/') + 1) .split('?')[0]; - const pendingFile = { + const pendingFile: FileType = { name: fileName, status: 'uploading', uuid: uuidv4(), @@ -350,7 +345,7 @@ export let ImportModal: React.FC = forwardRef(
    = forwardRef( size="sm" disabled={importButtonDisabled} renderIcon={ - inputButtonIcon ? (props) => : null + inputButtonIcon + ? (props) => + : undefined } > {inputButtonText} @@ -387,7 +384,9 @@ export let ImportModal: React.FC = forwardRef( invalid={file.invalid} errorBody={file.errorBody} errorSubject={file.errorSubject} - filesize={file.fileSize /* cspell:disable-line */} + {...{ + filesize: file.fileSize /* cspell:disable-line */, + }} /> ))}
    diff --git a/packages/ibm-products/src/components/InlineTip/InlineTipButton.tsx b/packages/ibm-products/src/components/InlineTip/InlineTipButton.tsx index 55ba186f24..366af03fdb 100644 --- a/packages/ibm-products/src/components/InlineTip/InlineTipButton.tsx +++ b/packages/ibm-products/src/components/InlineTip/InlineTipButton.tsx @@ -8,7 +8,7 @@ // Import portions of React that are needed. import React, { ForwardedRef, PropsWithChildren, ReactNode } from 'react'; -import { Button } from '@carbon/react'; +import { Button, ButtonProps } from '@carbon/react'; // Other standard imports. import PropTypes from 'prop-types'; import cx from 'classnames'; @@ -37,7 +37,7 @@ export interface InlineTipButtonProps { export let InlineTipButton = React.forwardRef( ( { children, className, ...rest }: PropsWithChildren, - ref: ForwardedRef + ref: ForwardedRef> ) => { return ( - ); -}; +export let TooltipTrigger = React.forwardRef< + HTMLDivElement, + TooltipTriggerProps +>( + ({ + children, + className, + // Collect any other property values passed in. + ...rest + }) => { + return ( + + ); + } +); // Return a placeholder if not released and not enabled by feature flag. TooltipTrigger = pkg.checkComponentEnabled(TooltipTrigger, componentName); diff --git a/packages/ibm-products/src/components/TruncatedList/TruncatedList.tsx b/packages/ibm-products/src/components/TruncatedList/TruncatedList.tsx index 9258649125..07aec989e6 100644 --- a/packages/ibm-products/src/components/TruncatedList/TruncatedList.tsx +++ b/packages/ibm-products/src/components/TruncatedList/TruncatedList.tsx @@ -72,7 +72,7 @@ export interface TruncatedListProps extends PropsWithChildren { /** * Callback function for building the label when the list is collapsed. */ - viewMoreLabel?: (value: any) => void; + viewMoreLabel?: (value: any) => ReactNode; } /** * The `TruncatedList` allows consumers to control how many items are diff --git a/packages/ibm-products/src/components/UserProfileImage/UserProfileImage.tsx b/packages/ibm-products/src/components/UserProfileImage/UserProfileImage.tsx index 1df3b98199..cbc1b884f1 100644 --- a/packages/ibm-products/src/components/UserProfileImage/UserProfileImage.tsx +++ b/packages/ibm-products/src/components/UserProfileImage/UserProfileImage.tsx @@ -9,10 +9,9 @@ import '../../global/js/utils/props-helper'; // Carbon and package components we use. import { Group, User } from '@carbon/react/icons'; -import { Tooltip, usePrefix } from '@carbon/react'; +import { PopoverAlignment, Tooltip, usePrefix } from '@carbon/react'; import { CarbonIconType } from '@carbon/icons-react/lib/CarbonIcon'; -import { IconButton } from '@carbon/react'; // Other standard imports. import PropTypes from 'prop-types'; // Import portions of React that are needed. @@ -28,11 +27,6 @@ const componentName = 'UserProfileImage'; // NOTE: the component SCSS is not imported here: it is rolled up separately. -// Default values for props -const defaults = { - tooltipAlignment: 'bottom', -}; - type Size = 'xl' | 'lg' | 'md'; type Theme = 'light' | 'dark'; @@ -92,7 +86,7 @@ type UserProfileImageBaseProps = { /** * Specify how the trigger should align with the tooltip */ - tooltipAlignment?: React.ComponentProps['align']; + tooltipAlignment?: PopoverAlignment; /** * Pass in the display name to have it shown on hover @@ -121,7 +115,7 @@ export let UserProfileImage = React.forwardRef< size, theme, tooltipText, - tooltipAlignment = defaults.tooltipAlignment, + tooltipAlignment = 'bottom', // Collect any other property values passed in. ...rest }, @@ -224,7 +218,6 @@ export let UserProfileImage = React.forwardRef< label={tooltipText} className={`${blockClass}__tooltip ${carbonPrefix}--icon-tooltip`} > - {/**@ts-ignore */} {renderUserProfileImage()} ) : ( diff --git a/packages/ibm-products/src/components/WebTerminal/WebTerminal.tsx b/packages/ibm-products/src/components/WebTerminal/WebTerminal.tsx index 45c5ca5d58..a0ff859eae 100644 --- a/packages/ibm-products/src/components/WebTerminal/WebTerminal.tsx +++ b/packages/ibm-products/src/components/WebTerminal/WebTerminal.tsx @@ -41,7 +41,7 @@ const defaults = { }; interface Action { - renderIcon: () => void; + renderIcon?: React.ElementType; onClick: () => void; iconDescription: string; } @@ -269,6 +269,7 @@ WebTerminal.propTypes = { /** * Array of objects for each documentation link. Each documentation link uses the prop types of OverflowMenuItems. See more: https://react.carbondesignsystem.com/?path=/docs/components-overflowmenu--default */ + /**@ts-ignore */ documentationLinks: PropTypes.arrayOf( PropTypes.shape({ ...OverflowMenuItem.propTypes, diff --git a/packages/ibm-products/src/custom-typings/index.d.ts b/packages/ibm-products/src/custom-typings/index.d.ts index 4072d7dfa3..0517f20f1b 100644 --- a/packages/ibm-products/src/custom-typings/index.d.ts +++ b/packages/ibm-products/src/custom-typings/index.d.ts @@ -139,6 +139,7 @@ declare module '@carbon/react' { SideNav, SideNavItems, SideNavLink, + SideNavMenuItem, SkeletonIcon, SkeletonIconProps, SkeletonPlaceholder, diff --git a/playwright.config.js b/playwright.config.js index e1e79573de..aaf719bfe5 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -7,7 +7,7 @@ const { devices, expect } = require('@playwright/test'); const path = require('path'); -const { pkg } = require('./packages/ibm-products/src/settings'); +const { pkg } = require('./packages/ibm-products/src/settings'); const config = { // https://playwright.dev/docs/api/class-testconfig#test-config-test-dir @@ -88,7 +88,7 @@ expect.extend({ 'aria_content_in_landmark', 'aria_child_tabbable', 'skip_main_described', - 'target_spacing_sufficient' + 'target_spacing_sufficient', ]); const ruleset = await aChecker.getRuleset('IBM_Accessibility'); @@ -101,7 +101,8 @@ expect.extend({ return !denylist.has(rule.id); }); return checkpoint; - }); + } + ); aChecker.addRuleset(customRuleset); } @@ -154,7 +155,7 @@ expect.extend({ globals: ${JSON.stringify(options.globals)} args: ${JSON.stringify(options.args)}, } - ` + `, }; } }, diff --git a/yarn.lock b/yarn.lock index 9ac7ef13bf..f7ac81cd03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7800,6 +7800,13 @@ __metadata: languageName: node linkType: hard +"@types/carbon__layout@npm:^0.0.3": + version: 0.0.3 + resolution: "@types/carbon__layout@npm:0.0.3" + checksum: a5bc0d216f8d710ae8f286ea7673963f0553d6d9e8bd5ca9d26ddcf26eb5091f4a443c34341b5fb0615b83549ad34d656c7afd0be4d78e1e35a072712b1a2169 + languageName: node + linkType: hard + "@types/connect@npm:*": version: 3.4.38 resolution: "@types/connect@npm:3.4.38" @@ -16065,6 +16072,7 @@ __metadata: "@testing-library/react": "npm:^14.0.0" "@testing-library/react-hooks": "npm:^8.0.1" "@testing-library/user-event": "npm:^14.4.3" + "@types/carbon__layout": "npm:^0.0.3" "@typescript-eslint/eslint-plugin": "npm:^6.21.0" "@typescript-eslint/parser": "npm:^6.21.0" accessibility-checker: "npm:^3.1.65"