Reduce lag
diff --git a/code/core/src/manager/components/sidebar/Refs.stories.tsx b/code/core/src/manager/components/sidebar/Refs.stories.tsx
index d183e41896b8..21cbe3736588 100644
--- a/code/core/src/manager/components/sidebar/Refs.stories.tsx
+++ b/code/core/src/manager/components/sidebar/Refs.stories.tsx
@@ -1,7 +1,9 @@
import React from 'react';
+import type { StoryAnnotations } from 'storybook/internal/csf';
+
import { ManagerContext } from 'storybook/manager-api';
-import { fn } from 'storybook/test';
+import { fn, within } from 'storybook/test';
import { standardData as standardHeaderData } from './Heading.stories';
import { IconSymbols } from './IconSymbols';
@@ -249,6 +251,51 @@ export const Errored = () => (
setHighlighted={() => {}}
/>
);
+export const ErroredMobile = () => (
+ [ {}}
+ />
+);
+ErroredMobile.globals = { sb_theme: 'stacked', viewport: { value: 'mobile1' } };
+export const ErroredWithErrorOpen: StoryAnnotations = {
+ render: () => Errored(),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('View error');
+ button.click();
+ },
+};
+export const ErroredMobileWithErrorOpen: StoryAnnotations = {
+ render: () => ErroredMobile(),
+ globals: { sb_theme: 'stacked', viewport: { value: 'mobile1' } },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('View error');
+ button.click();
+ },
+};
+export const ErroredWithIndicatorOpen: StoryAnnotations = {
+ render: () => Errored(),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const button = canvas.getByRole('button', { name: 'Extra actions' });
+ button.click();
+ },
+};
+export const ErroredMobileWithIndicatorOpen: StoryAnnotations = {
+ render: () => ErroredMobile(),
+ globals: { sb_theme: 'stacked', viewport: { value: 'mobile1' } },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const button = canvas.getByRole('button', { name: 'Extra actions' });
+ button.click();
+ },
+};
export const Auth = () => (
][ (
+ (storyFn, { globals, title }) => (
-
+
{storyFn()}
@@ -108,6 +114,21 @@ export default meta;
type Story = StoryObj;
+const mobileLayoutDecorator: DecoratorFunction = (storyFn, { globals, title }) => (
+
+
+
+ {storyFn()}
+
+
+);
+
const refs: Record = {
optimized: {
id: 'optimized',
@@ -148,6 +169,11 @@ export const SimpleInProduction: Story = {
},
};
+export const Mobile: Story = {
+ decorators: [mobileLayoutDecorator],
+ globals: { sb_theme: 'light', viewport: { value: 'mobile1' } },
+};
+
export const Loading: Story = {
args: {
previewInitialized: false,
@@ -155,12 +181,24 @@ export const Loading: Story = {
},
};
+export const LoadingMobile: Story = {
+ args: Loading.args,
+ decorators: [mobileLayoutDecorator],
+ globals: { sb_theme: 'light', viewport: { value: 'mobile1' } },
+};
+
export const Empty: Story = {
args: {
index: {},
},
};
+export const EmptyMobile: Story = {
+ args: Empty.args,
+ decorators: [mobileLayoutDecorator],
+ globals: { sb_theme: 'light', viewport: { value: 'mobile1' } },
+};
+
export const IndexError: Story = {
args: {
indexError,
@@ -209,6 +247,12 @@ export const WithRefsNarrow: Story = {
},
};
+export const WithRefsMobile: Story = {
+ args: WithRefs.args,
+ decorators: [mobileLayoutDecorator],
+ globals: { sb_theme: 'light', viewport: { value: 'mobile1' } },
+};
+
export const LoadingWithRefs: Story = {
args: {
...Loading.args,
@@ -223,6 +267,12 @@ export const LoadingWithRefError: Story = {
},
};
+export const LoadingWithRefErrorMobile: Story = {
+ args: LoadingWithRefError.args,
+ decorators: [mobileLayoutDecorator],
+ globals: { sb_theme: 'light', viewport: { value: 'mobile1' } },
+};
+
export const WithRefEmpty: Story = {
args: {
...Empty.args,
diff --git a/code/core/src/manager/components/sidebar/StatusButton.tsx b/code/core/src/manager/components/sidebar/StatusButton.tsx
index a0c9573bcaa6..e2b1079cc632 100644
--- a/code/core/src/manager/components/sidebar/StatusButton.tsx
+++ b/code/core/src/manager/components/sidebar/StatusButton.tsx
@@ -1,5 +1,5 @@
-import type { ComponentProps, FC } from 'react';
-import React from 'react';
+import type { ComponentProps } from 'react';
+import React, { forwardRef } from 'react';
import { Button } from 'storybook/internal/components';
import type { StatusValue } from 'storybook/internal/types';
@@ -88,6 +88,7 @@ const StyledButton = styled(Button)<{
}
);
-export const StatusButton: FC = (props) => {
- return ;
-};
+export const StatusButton = forwardRef((props, ref) => {
+ return ;
+});
+StatusButton.displayName = 'StatusButton';
diff --git a/code/core/src/manager/components/sidebar/TagsFilter.tsx b/code/core/src/manager/components/sidebar/TagsFilter.tsx
index 9f31381dabdd..352ec588846f 100644
--- a/code/core/src/manager/components/sidebar/TagsFilter.tsx
+++ b/code/core/src/manager/components/sidebar/TagsFilter.tsx
@@ -1,6 +1,6 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
-import { Badge, Button, WithTooltip } from 'storybook/internal/components';
+import { Badge, Button, WithPopover } from 'storybook/internal/components';
import type { StoryIndex, Tag } from 'storybook/internal/types';
import { FilterIcon } from '@storybook/icons';
@@ -14,10 +14,6 @@ const TAGS_FILTER = 'tags-filter';
const BUILT_IN_TAGS_HIDE = new Set(['dev', 'autodocs', 'test', 'attached-mdx', 'unattached-mdx']);
-const Wrapper = styled.div({
- position: 'relative',
-});
-
// Temporary to prevent regressions until TagFilterPanel can be refactored.
const StyledIconButton = styled(Button)<{ active: boolean }>(({ active, theme }) => ({
...(active && {
@@ -117,42 +113,36 @@ export const TagsFilter = ({
}
return (
- <>
- (
-
- )}
- closeOnOutsideClick
+ (
+
+ )}
+ >
+
-
-
-
-
- {selectedTags.length > 0 && }
-
-
- >
+
+ {selectedTags.length > 0 && }
+
+
);
};
diff --git a/code/core/src/manager/components/sidebar/Tree.stories.tsx b/code/core/src/manager/components/sidebar/Tree.stories.tsx
index beaffabf02bb..02c9f6f5b099 100644
--- a/code/core/src/manager/components/sidebar/Tree.stories.tsx
+++ b/code/core/src/manager/components/sidebar/Tree.stories.tsx
@@ -10,7 +10,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
import { action } from 'storybook/actions';
import { type ComponentEntry, type IndexHash, ManagerContext } from 'storybook/manager-api';
-import { expect, fn, userEvent, within } from 'storybook/test';
+import { expect, fn, screen, userEvent, within } from 'storybook/test';
import { DEFAULT_REF_ID } from './Sidebar';
import { Tree } from './Tree';
@@ -299,19 +299,16 @@ export const WithContextContent: Story = {
viewport: { value: 'desktop' },
},
play: async ({ canvasElement }) => {
- const screen = await within(canvasElement);
+ const canvas = within(canvasElement);
- const link = await screen.findByText('TooltipBuildList');
+ const link = await canvas.findByText('TooltipBuildList');
await userEvent.hover(link);
- const contextButton = await screen.findAllByTestId('context-menu');
+ const contextButton = await canvas.findAllByTestId('context-menu');
await userEvent.click(contextButton[0]);
- const body = await within(document.body);
-
- const tooltip = await body.findByTestId('tooltip');
-
- await expect(tooltip).toBeVisible();
- expect(tooltip).toHaveTextContent('TEST_PROVIDER_CONTEXT_CONTENT');
+ const popover = screen.getByRole('dialog');
+ await expect(popover).toBeVisible();
+ expect(popover).toHaveTextContent('TEST_PROVIDER_CONTEXT_CONTENT');
},
};
diff --git a/code/core/src/manager/globals/exports.ts b/code/core/src/manager/globals/exports.ts
index 702702080175..90cde0dcf35c 100644
--- a/code/core/src/manager/globals/exports.ts
+++ b/code/core/src/manager/globals/exports.ts
@@ -510,9 +510,11 @@ export default {
'ListItem',
'Loader',
'Modal',
+ 'ModalDecorator',
'OL',
'P',
'Placeholder',
+ 'Popover',
'Pre',
'ProgressSpinner',
'ResetWrapper',
@@ -536,11 +538,13 @@ export default {
'TooltipMessage',
'TooltipNote',
'UL',
+ 'WithPopover',
'WithTooltip',
'WithTooltipPure',
'Zoom',
'codeCommon',
'components',
+ 'convertToReactAriaPlacement',
'createCopyToClipboardFunction',
'getStoryHref',
'interleaveSeparators',
diff --git a/code/e2e-tests/addon-controls.spec.ts b/code/e2e-tests/addon-controls.spec.ts
index c2e3a4e97928..6ce2b16625fe 100644
--- a/code/e2e-tests/addon-controls.spec.ts
+++ b/code/e2e-tests/addon-controls.spec.ts
@@ -82,6 +82,8 @@ test.describe('addon-controls', () => {
const sbPage = new SbPage(page, expect);
await sbPage.waitUntilLoaded();
+ await sbPage.closeAnyPendingModal();
+
await sbPage.viewAddonPanel('Controls');
await sbPage.panelContent().locator('#control-select').selectOption('double space');
@@ -94,6 +96,7 @@ test.describe('addon-controls', () => {
const sbPage = new SbPage(page, expect);
await sbPage.waitUntilLoaded();
+ await sbPage.closeAnyPendingModal();
await sbPage.viewAddonPanel('Controls');
await sbPage.panelContent().locator('#control-multiSelect').selectOption('double space');
diff --git a/code/e2e-tests/addon-onboarding.spec.ts b/code/e2e-tests/addon-onboarding.spec.ts
index 06840cfc3858..aac9498b7f48 100644
--- a/code/e2e-tests/addon-onboarding.spec.ts
+++ b/code/e2e-tests/addon-onboarding.spec.ts
@@ -35,14 +35,14 @@ test.describe('addon-onboarding', () => {
// so we just create a random id to make it easier to run tests
const id = Math.random().toString(36).substring(7);
await page.getByPlaceholder('Story export name').fill('Test-' + id);
- await page.getByRole('button', { name: 'Create' }).click();
+ await page.getByRole('button', { exact: true, name: 'Create' }).click();
await expect(page.getByText('You just added your first')).toBeVisible();
await page.getByLabel('Last').click();
await page.getByRole('checkbox', { name: 'Application UI' }).check();
await page.getByRole('checkbox', { name: 'Functional testing' }).check();
- await page.getByRole('combobox').selectOption('Web Search');
+ await page.locator('#referrer').selectOption('Web Search');
await page.getByRole('button', { name: 'Submit' }).click();
await expect(
diff --git a/code/e2e-tests/manager.spec.ts b/code/e2e-tests/manager.spec.ts
index f14559df7b98..f450ede70fe4 100644
--- a/code/e2e-tests/manager.spec.ts
+++ b/code/e2e-tests/manager.spec.ts
@@ -21,17 +21,17 @@ test.describe('Manager UI', () => {
await page.locator('[aria-label="Settings"]').click();
// should only hide if pressing Escape, and not other keyboard inputs
- await expect(page.getByTestId('tooltip')).toBeVisible();
+ await expect(page.getByRole('dialog')).toBeVisible();
await page.keyboard.press('A');
- await expect(page.getByTestId('tooltip')).toBeVisible();
+ await expect(page.getByRole('dialog')).toBeVisible();
await page.keyboard.press('Escape');
- await expect(page.getByTestId('tooltip')).toBeHidden();
+ await expect(page.getByRole('dialog')).toBeHidden();
// should also hide if clicking anywhere outside the tooltip
await page.locator('[aria-label="Settings"]').click();
- await expect(page.getByTestId('tooltip')).toBeVisible();
+ await expect(page.getByRole('dialog')).toBeVisible();
await page.click('body');
- await expect(page.getByTestId('tooltip')).toBeHidden();
+ await expect(page.getByRole('dialog')).toBeHidden();
});
test('Sidebar toggling', async ({ page }) => {
@@ -63,9 +63,10 @@ test.describe('Manager UI', () => {
// Context menu should contain open in editor for component node
await page.locator('[data-item-id="example-button"]').hover();
await page
- .locator('[data-item-id="example-button"] div[data-testid="context-menu"] button')
+ .locator('[data-item-id="example-button"]')
+ .getByRole('button', { name: 'Open context menu' })
.click();
- const sidebarContextMenu = page.getByTestId('tooltip');
+ const sidebarContextMenu = page.getByRole('dialog');
await expect(
sidebarContextMenu.getByRole('button', { name: /open in editor/i })
).toBeVisible();
@@ -74,23 +75,25 @@ test.describe('Manager UI', () => {
// Context menu should contain open in editor for docs node
await page.locator('[data-item-id="example-button--docs"]').hover();
await page
- .locator('[data-item-id="example-button--docs"] div[data-testid="context-menu"] button')
+ .locator('[data-item-id="example-button--docs"]')
+ .getByRole('button', { name: 'Open context menu' })
.click();
await expect(
- page.getByTestId('tooltip').getByRole('button', { name: /open in editor/i })
+ page.getByRole('dialog').getByRole('button', { name: /open in editor/i })
).toBeVisible();
await page.click('body');
// Context menu should contain open in editor and copy story name for story node
await page.locator('[data-item-id="example-button--primary"]').hover();
await page
- .locator('[data-item-id="example-button--primary"] div[data-testid="context-menu"] button')
+ .locator('[data-item-id="example-button--primary"]')
+ .getByRole('button', { name: 'Open context menu' })
.click();
await expect(
- page.getByTestId('tooltip').getByRole('button', { name: /open in editor/i })
+ page.getByRole('dialog').getByRole('button', { name: /open in editor/i })
).toBeVisible();
await page
- .getByTestId('tooltip')
+ .getByRole('dialog')
.getByRole('button', { name: /copy story name/i })
.click();
diff --git a/code/e2e-tests/tags.spec.ts b/code/e2e-tests/tags.spec.ts
index 57761f59a63c..c3e624730c8f 100644
--- a/code/e2e-tests/tags.spec.ts
+++ b/code/e2e-tests/tags.spec.ts
@@ -51,7 +51,7 @@ test.describe('tags', () => {
test('filters stories via Tag filters tooltip (desktop)', async ({ page }) => {
// Open Tag filters tooltip
await page.locator('[aria-label="Tag filters"]').click();
- const tooltip = page.locator('[data-testid="tooltip"]');
+ const tooltip = page.locator('[role="dialog"]');
await expect(tooltip).toBeVisible();
// No checkbox selected by default and "Select all tags" is shown
@@ -84,26 +84,26 @@ test.describe('tags', () => {
// Open Tag filters tooltip
await page.locator('[aria-label="Tag filters"]').click();
- const tooltip = page.locator('[data-testid="tooltip"]');
- await expect(tooltip).toBeVisible();
+ const tagFilterPopover = page.getByRole('dialog', { name: 'Tag filters' });
+ await expect(tagFilterPopover).toBeVisible();
// No checkbox selected by default and "Select all tags" is shown
- await expect(tooltip.locator('#select-all')).toBeVisible();
- await expect(tooltip.locator('input[type="checkbox"]:checked')).toHaveCount(0);
+ await expect(tagFilterPopover.locator('#select-all')).toBeVisible();
+ await expect(tagFilterPopover.locator('input[type="checkbox"]:checked')).toHaveCount(0);
// Select the dev-only tag
- await tooltip.locator('#list-item-tag-dev-only').click();
+ await tagFilterPopover.locator('#list-item-tag-dev-only').click();
// Assert that only one story is visible in the (mobile) sidebar
const stories = page.locator('#storybook-explorer-menu .sidebar-item');
await expect(stories).toHaveCount(1);
// Clear selection
- await expect(tooltip.locator('#unselect-all')).toBeVisible();
- await tooltip.locator('#unselect-all').click();
+ await expect(tagFilterPopover.locator('#unselect-all')).toBeVisible();
+ await tagFilterPopover.locator('#unselect-all').click();
// Checkboxes are not selected anymore
- await expect(tooltip.locator('input[type="checkbox"]:checked')).toHaveCount(0);
+ await expect(tagFilterPopover.locator('input[type="checkbox"]:checked')).toHaveCount(0);
});
});
});
diff --git a/code/e2e-tests/util.ts b/code/e2e-tests/util.ts
index e761e46166aa..d7274e9a4b44 100644
--- a/code/e2e-tests/util.ts
+++ b/code/e2e-tests/util.ts
@@ -147,6 +147,16 @@ export class SbPage {
await this.waitForStoryLoaded();
}
+ /**
+ * We have stories with modals set to auto-open (e.g. startOpen color control). This helper closes
+ * them to free scroll and keyboard focus traps.
+ */
+ async closeAnyPendingModal() {
+ const popover = this.page.locator('[role="dialog"]');
+ await this.page.keyboard.press('Escape');
+ await popover.waitFor({ state: 'hidden' });
+ }
+
previewIframe() {
return this.page.frameLocator('#storybook-preview-iframe');
}
diff --git a/code/yarn.lock b/code/yarn.lock
index 9dcb3f485243..325a3a37738d 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -5130,13 +5130,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/primitive@npm:1.1.3":
- version: 1.1.3
- resolution: "@radix-ui/primitive@npm:1.1.3"
- checksum: 10c0/88860165ee7066fa2c179f32ffcd3ee6d527d9dcdc0e8be85e9cb0e2c84834be8e3c1a976c74ba44b193f709544e12f54455d892b28e32f0708d89deda6b9f1d
- languageName: node
- linkType: hard
-
"@radix-ui/react-collection@npm:1.0.3":
version: 1.0.3
resolution: "@radix-ui/react-collection@npm:1.0.3"
@@ -5229,51 +5222,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-context@npm:1.1.2":
- version: 1.1.2
- resolution: "@radix-ui/react-context@npm:1.1.2"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/cece731f8cc25d494c6589cc681e5c01a93867d895c75889973afa1a255f163c286e390baa7bc028858eaabe9f6b57270d0ca6377356f652c5557c1c7a41ccce
- languageName: node
- linkType: hard
-
-"@radix-ui/react-dialog@npm:^1.1.2":
- version: 1.1.15
- resolution: "@radix-ui/react-dialog@npm:1.1.15"
- dependencies:
- "@radix-ui/primitive": "npm:1.1.3"
- "@radix-ui/react-compose-refs": "npm:1.1.2"
- "@radix-ui/react-context": "npm:1.1.2"
- "@radix-ui/react-dismissable-layer": "npm:1.1.11"
- "@radix-ui/react-focus-guards": "npm:1.1.3"
- "@radix-ui/react-focus-scope": "npm:1.1.7"
- "@radix-ui/react-id": "npm:1.1.1"
- "@radix-ui/react-portal": "npm:1.1.9"
- "@radix-ui/react-presence": "npm:1.1.5"
- "@radix-ui/react-primitive": "npm:2.1.3"
- "@radix-ui/react-slot": "npm:1.2.3"
- "@radix-ui/react-use-controllable-state": "npm:1.2.2"
- aria-hidden: "npm:^1.2.4"
- react-remove-scroll: "npm:^2.6.3"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/2f2c88e3c281acaea2fd9b96fa82132d59177d3aa5da2e7c045596fd4028e84e44ac52ac28f4f236910605dd7d9338c2858ba44a9ced2af2e3e523abbfd33014
- languageName: node
- linkType: hard
-
"@radix-ui/react-direction@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-direction@npm:1.0.1"
@@ -5302,63 +5250,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-dismissable-layer@npm:1.1.11":
- version: 1.1.11
- resolution: "@radix-ui/react-dismissable-layer@npm:1.1.11"
- dependencies:
- "@radix-ui/primitive": "npm:1.1.3"
- "@radix-ui/react-compose-refs": "npm:1.1.2"
- "@radix-ui/react-primitive": "npm:2.1.3"
- "@radix-ui/react-use-callback-ref": "npm:1.1.1"
- "@radix-ui/react-use-escape-keydown": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/c825572a64073c4d3853702029979f6658770ffd6a98eabc4984e1dee1b226b4078a2a4dc7003f96475b438985e9b21a58e75f51db74dd06848dcae1f2d395dc
- languageName: node
- linkType: hard
-
-"@radix-ui/react-focus-guards@npm:1.1.3":
- version: 1.1.3
- resolution: "@radix-ui/react-focus-guards@npm:1.1.3"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/0bab65eb8d7e4f72f685d63de7fbba2450e3cb15ad6a20a16b42195e9d335c576356f5a47cb58d1ffc115393e46d7b14b12c5d4b10029b0ec090861255866985
- languageName: node
- linkType: hard
-
-"@radix-ui/react-focus-scope@npm:1.1.7":
- version: 1.1.7
- resolution: "@radix-ui/react-focus-scope@npm:1.1.7"
- dependencies:
- "@radix-ui/react-compose-refs": "npm:1.1.2"
- "@radix-ui/react-primitive": "npm:2.1.3"
- "@radix-ui/react-use-callback-ref": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/8a6071331bdeeb79b223463de75caf759b8ad19339cab838e537b8dbb2db236891a1f4df252445c854d375d43d9d315dfcce0a6b01553a2984ec372bb8f1300e
- languageName: node
- linkType: hard
-
"@radix-ui/react-id@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-id@npm:1.0.1"
@@ -5375,41 +5266,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-id@npm:1.1.1":
- version: 1.1.1
- resolution: "@radix-ui/react-id@npm:1.1.1"
- dependencies:
- "@radix-ui/react-use-layout-effect": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/7d12e76818763d592c331277ef62b197e2e64945307e650bd058f0090e5ae48bbd07691b23b7e9e977901ef4eadcb3e2d5eaeb17a13859083384be83fc1292c7
- languageName: node
- linkType: hard
-
-"@radix-ui/react-portal@npm:1.1.9":
- version: 1.1.9
- resolution: "@radix-ui/react-portal@npm:1.1.9"
- dependencies:
- "@radix-ui/react-primitive": "npm:2.1.3"
- "@radix-ui/react-use-layout-effect": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/45b432497c722720c72c493a29ef6085bc84b50eafe79d48b45c553121b63e94f9cdb77a3a74b9c49126f8feb3feee009fe400d48b7759d3552396356b192cd7
- languageName: node
- linkType: hard
-
"@radix-ui/react-presence@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-presence@npm:1.0.1"
@@ -5451,26 +5307,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-presence@npm:1.1.5":
- version: 1.1.5
- resolution: "@radix-ui/react-presence@npm:1.1.5"
- dependencies:
- "@radix-ui/react-compose-refs": "npm:1.1.2"
- "@radix-ui/react-use-layout-effect": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/d0e61d314250eeaef5369983cb790701d667f51734bafd98cf759072755562018052c594e6cdc5389789f4543cb0a4d98f03ff4e8f37338d6b5bf51a1700c1d1
- languageName: node
- linkType: hard
-
"@radix-ui/react-primitive@npm:1.0.3":
version: 1.0.3
resolution: "@radix-ui/react-primitive@npm:1.0.3"
@@ -5510,25 +5346,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-primitive@npm:2.1.3":
- version: 2.1.3
- resolution: "@radix-ui/react-primitive@npm:2.1.3"
- dependencies:
- "@radix-ui/react-slot": "npm:1.2.3"
- peerDependencies:
- "@types/react": "*"
- "@types/react-dom": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- "@types/react-dom":
- optional: true
- checksum: 10c0/fdff9b84913bb4172ef6d3af7442fca5f9bba5f2709cba08950071f819d7057aec3a4a2d9ef44cf9cbfb8014d02573c6884a04cff175895823aaef809ebdb034
- languageName: node
- linkType: hard
-
"@radix-ui/react-roving-focus@npm:1.0.4":
version: 1.0.4
resolution: "@radix-ui/react-roving-focus@npm:1.0.4"
@@ -5615,7 +5432,7 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-slot@npm:1.2.3, @radix-ui/react-slot@npm:^1.0.2":
+"@radix-ui/react-slot@npm:^1.0.2":
version: 1.2.3
resolution: "@radix-ui/react-slot@npm:1.2.3"
dependencies:
@@ -5685,19 +5502,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-use-callback-ref@npm:1.1.1":
- version: 1.1.1
- resolution: "@radix-ui/react-use-callback-ref@npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/5f6aff8592dea6a7e46589808912aba3fb3b626cf6edd2b14f01638b61dbbe49eeb9f67cd5601f4c15b2fb547b9a7e825f7c4961acd4dd70176c969ae405f8d8
- languageName: node
- linkType: hard
-
"@radix-ui/react-use-controllable-state@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-use-controllable-state@npm:1.0.1"
@@ -5714,52 +5518,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-use-controllable-state@npm:1.2.2":
- version: 1.2.2
- resolution: "@radix-ui/react-use-controllable-state@npm:1.2.2"
- dependencies:
- "@radix-ui/react-use-effect-event": "npm:0.0.2"
- "@radix-ui/react-use-layout-effect": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/f55c4b06e895293aed4b44c9ef26fb24432539f5346fcd6519c7745800535b571058685314e83486a45bf61dc83887e24826490d3068acc317fb0a9010516e63
- languageName: node
- linkType: hard
-
-"@radix-ui/react-use-effect-event@npm:0.0.2":
- version: 0.0.2
- resolution: "@radix-ui/react-use-effect-event@npm:0.0.2"
- dependencies:
- "@radix-ui/react-use-layout-effect": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/e84ff72a3e76c5ae9c94941028bb4b6472f17d4104481b9eab773deab3da640ecea035e54da9d6f4df8d84c18ef6913baf92b7511bee06930dc58bd0c0add417
- languageName: node
- linkType: hard
-
-"@radix-ui/react-use-escape-keydown@npm:1.1.1":
- version: 1.1.1
- resolution: "@radix-ui/react-use-escape-keydown@npm:1.1.1"
- dependencies:
- "@radix-ui/react-use-callback-ref": "npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/bff53be99e940fef1d3c4df7d560e1d9133182e5a98336255d3063327d1d3dd4ec54a95dc5afe15cca4fb6c184f0a956c70de2815578c318cf995a7f9beabaa1
- languageName: node
- linkType: hard
-
"@radix-ui/react-use-layout-effect@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-use-layout-effect@npm:1.0.1"
@@ -5788,19 +5546,6 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-use-layout-effect@npm:1.1.1":
- version: 1.1.1
- resolution: "@radix-ui/react-use-layout-effect@npm:1.1.1"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/9f98fdaba008dfc58050de60a77670b885792df473cf82c1cef8daee919a5dd5a77d270209f5f0b0abfaac78cb1627396e3ff56c81b735be550409426fe8b040
- languageName: node
- linkType: hard
-
"@react-aria/autocomplete@npm:3.0.0-rc.1":
version: 3.0.0-rc.1
resolution: "@react-aria/autocomplete@npm:3.0.0-rc.1"
@@ -9861,15 +9606,6 @@ __metadata:
languageName: node
linkType: hard
-"@types/react-transition-group@npm:^4":
- version: 4.4.12
- resolution: "@types/react-transition-group@npm:4.4.12"
- peerDependencies:
- "@types/react": "*"
- checksum: 10c0/0441b8b47c69312c89ec0760ba477ba1a0808a10ceef8dc1c64b1013ed78517332c30f18681b0ec0b53542731f1ed015169fed1d127cc91222638ed955478ec7
- languageName: node
- linkType: hard
-
"@types/react@npm:^18.0.0":
version: 18.3.24
resolution: "@types/react@npm:18.3.24"
@@ -11376,15 +11112,6 @@ __metadata:
languageName: node
linkType: hard
-"aria-hidden@npm:^1.2.4":
- version: 1.2.6
- resolution: "aria-hidden@npm:1.2.6"
- dependencies:
- tslib: "npm:^2.0.0"
- checksum: 10c0/7720cb539497a9f760f68f98a4b30f22c6767aa0e72fa7d58279f7c164e258fc38b2699828f8de881aab0fc8e9c56d1313a3f1a965046fc0381a554dbc72b54a
- languageName: node
- linkType: hard
-
"aria-query@npm:5.1.3":
version: 5.1.3
resolution: "aria-query@npm:5.1.3"
@@ -14342,13 +14069,6 @@ __metadata:
languageName: node
linkType: hard
-"detect-node-es@npm:^1.1.0":
- version: 1.1.0
- resolution: "detect-node-es@npm:1.1.0"
- checksum: 10c0/e562f00de23f10c27d7119e1af0e7388407eb4b06596a25f6d79a360094a109ff285de317f02b090faae093d314cf6e73ac3214f8a5bb3a0def5bece94557fbe
- languageName: node
- linkType: hard
-
"detect-node@npm:^2.0.4":
version: 2.1.0
resolution: "detect-node@npm:2.1.0"
@@ -14476,16 +14196,6 @@ __metadata:
languageName: node
linkType: hard
-"dom-helpers@npm:^5.0.1":
- version: 5.2.1
- resolution: "dom-helpers@npm:5.2.1"
- dependencies:
- "@babel/runtime": "npm:^7.8.7"
- csstype: "npm:^3.0.2"
- checksum: 10c0/f735074d66dd759b36b158fa26e9d00c9388ee0e8c9b16af941c38f014a37fc80782de83afefd621681b19ac0501034b4f1c4a3bff5caa1b8667f0212b5e124c
- languageName: node
- linkType: hard
-
"dom-serializer@npm:^1.0.1":
version: 1.4.1
resolution: "dom-serializer@npm:1.4.1"
@@ -17253,13 +16963,6 @@ __metadata:
languageName: node
linkType: hard
-"get-nonce@npm:^1.0.0":
- version: 1.0.1
- resolution: "get-nonce@npm:1.0.1"
- checksum: 10c0/2d7df55279060bf0568549e1ffc9b84bc32a32b7541675ca092dce56317cdd1a59a98dcc4072c9f6a980779440139a3221d7486f52c488e69dc0fd27b1efb162
- languageName: node
- linkType: hard
-
"get-npm-tarball-url@npm:^2.0.3":
version: 2.1.0
resolution: "get-npm-tarball-url@npm:2.1.0"
@@ -23623,7 +23326,7 @@ __metadata:
languageName: node
linkType: hard
-"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
+"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
version: 15.8.1
resolution: "prop-types@npm:15.8.1"
dependencies:
@@ -24368,41 +24071,6 @@ __metadata:
languageName: node
linkType: hard
-"react-remove-scroll-bar@npm:^2.3.7":
- version: 2.3.8
- resolution: "react-remove-scroll-bar@npm:2.3.8"
- dependencies:
- react-style-singleton: "npm:^2.2.2"
- tslib: "npm:^2.0.0"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/9a0675c66cbb52c325bdbfaed80987a829c4504cefd8ff2dd3b6b3afc9a1500b8ec57b212e92c1fb654396d07bbe18830a8146fe77677d2a29ce40b5e1f78654
- languageName: node
- linkType: hard
-
-"react-remove-scroll@npm:^2.6.3":
- version: 2.7.1
- resolution: "react-remove-scroll@npm:2.7.1"
- dependencies:
- react-remove-scroll-bar: "npm:^2.3.7"
- react-style-singleton: "npm:^2.2.3"
- tslib: "npm:^2.1.0"
- use-callback-ref: "npm:^1.3.3"
- use-sidecar: "npm:^1.1.3"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/7ad8f6ffd3e2aedf9b3d79f0c9088a9a3d7c5332d80c923427a6d97fe0626fb4cb33a6d9174d19fad57d860be69c96f68497a0619c3a8af0e8a5332e49bdde31
- languageName: node
- linkType: hard
-
"react-resize-detector@npm:^7.1.2":
version: 7.1.2
resolution: "react-resize-detector@npm:7.1.2"
@@ -24475,22 +24143,6 @@ __metadata:
languageName: node
linkType: hard
-"react-style-singleton@npm:^2.2.2, react-style-singleton@npm:^2.2.3":
- version: 2.2.3
- resolution: "react-style-singleton@npm:2.2.3"
- dependencies:
- get-nonce: "npm:^1.0.0"
- tslib: "npm:^2.0.0"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/841938ff16d16a6b76895f4cb2e1fea957e5fe3b30febbf03a54892dae1c9153f2383e231dea0b3ba41192ad2f2849448fa859caccd288943bce32639e971bee
- languageName: node
- linkType: hard
-
"react-syntax-highlighter@npm:^15.4.5":
version: 15.6.6
resolution: "react-syntax-highlighter@npm:15.6.6"
@@ -24520,18 +24172,13 @@ __metadata:
languageName: node
linkType: hard
-"react-transition-group@npm:^4.4.5":
- version: 4.4.5
- resolution: "react-transition-group@npm:4.4.5"
- dependencies:
- "@babel/runtime": "npm:^7.5.5"
- dom-helpers: "npm:^5.0.1"
- loose-envify: "npm:^1.4.0"
- prop-types: "npm:^15.6.2"
+"react-transition-state@npm:^2.3.1":
+ version: 2.3.1
+ resolution: "react-transition-state@npm:2.3.1"
peerDependencies:
- react: ">=16.6.0"
- react-dom: ">=16.6.0"
- checksum: 10c0/2ba754ba748faefa15f87c96dfa700d5525054a0141de8c75763aae6734af0740e77e11261a1e8f4ffc08fd9ab78510122e05c21c2d79066c38bb6861a886c82
+ react: ">=16.8.0"
+ react-dom: ">=16.8.0"
+ checksum: 10c0/145f20e45c53d570f9db5fe749e0fd794b62bdf464c67c594c454df44f31fa58c16ccec705f9fdccf4c5250a309e4f7da5bd2e85cd686ba52d6b79e1c22b811f
languageName: node
linkType: hard
@@ -26458,7 +26105,6 @@ __metadata:
"@ndelangen/get-tarball": "npm:^3.0.7"
"@ngard/tiny-isequal": "npm:^1.1.0"
"@polka/compression": "npm:^1.0.0-next.28"
- "@radix-ui/react-dialog": "npm:^1.1.2"
"@radix-ui/react-scroll-area": "npm:1.2.0-rc.7"
"@radix-ui/react-slot": "npm:^1.0.2"
"@react-aria/utils": "npm:^3.30.1"
@@ -26483,7 +26129,6 @@ __metadata:
"@types/pretty-hrtime": "npm:^1.0.0"
"@types/prompts": "npm:^2.0.9"
"@types/react-syntax-highlighter": "npm:11.0.5"
- "@types/react-transition-group": "npm:^4"
"@types/semver": "npm:^7.5.8"
"@types/ws": "npm:^8"
"@vitest/expect": "npm:3.2.4"
@@ -26555,7 +26200,7 @@ __metadata:
react-stately: "npm:^3.41.0"
react-syntax-highlighter: "npm:^15.4.5"
react-textarea-autosize: "npm:^8.3.0"
- react-transition-group: "npm:^4.4.5"
+ react-transition-state: "npm:^2.3.1"
recast: "npm:^0.23.5"
require-from-string: "npm:^2.0.2"
resolve.exports: "npm:^2.0.3"
@@ -28110,21 +27755,6 @@ __metadata:
languageName: node
linkType: hard
-"use-callback-ref@npm:^1.3.3":
- version: 1.3.3
- resolution: "use-callback-ref@npm:1.3.3"
- dependencies:
- tslib: "npm:^2.0.0"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/f887488c6e6075cdad4962979da1714b217bcb1ee009a9e57ce9a844bcfc4c3a99e93983dfc2e5af9e0913824d24e730090ff255e902c516dcb58d2d3837e01c
- languageName: node
- linkType: hard
-
"use-composed-ref@npm:^1.3.0":
version: 1.4.0
resolution: "use-composed-ref@npm:1.4.0"
@@ -28175,22 +27805,6 @@ __metadata:
languageName: node
linkType: hard
-"use-sidecar@npm:^1.1.3":
- version: 1.1.3
- resolution: "use-sidecar@npm:1.1.3"
- dependencies:
- detect-node-es: "npm:^1.1.0"
- tslib: "npm:^2.0.0"
- peerDependencies:
- "@types/react": "*"
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- "@types/react":
- optional: true
- checksum: 10c0/161599bf921cfaa41c85d2b01c871975ee99260f3e874c2d41c05890d41170297bdcf314bc5185e7a700de2034ac5b888e3efc8e9f35724f4918f53538d717c9
- languageName: node
- linkType: hard
-
"use-sync-external-store@npm:^1.4.0":
version: 1.5.0
resolution: "use-sync-external-store@npm:1.5.0"
diff --git a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts
index 4305bcbfbe1a..fdafda129cfd 100644
--- a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts
+++ b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts
@@ -504,16 +504,16 @@ test.describe("component testing", () => {
.getByRole("button", { name: "test" });
await expect(storyElement).toBeVisible({ timeout: 30000 });
- // Act - Open sidebar context menu and start focused test
+ // Act - Open sidebar context menu, start focused test then close menu
await page
.locator('[data-item-id="addons-group-test--expected-failure"]')
.hover();
await page
.locator(
- '[data-item-id="addons-group-test--expected-failure"] div[data-testid="context-menu"] button'
+ '[data-item-id="addons-group-test--expected-failure"] button[data-testid="context-menu"]'
)
.click();
- const sidebarContextMenu = page.getByTestId("tooltip");
+ const sidebarContextMenu = page.getByRole('dialog');
await sidebarContextMenu.getByLabel("Start test run").click();
// Assert - Only one test is running and reported
@@ -550,12 +550,20 @@ test.describe("component testing", () => {
await page.locator('[data-item-id="example-unhandlederrors"]').hover();
await page
.locator(
- '[data-item-id="example-unhandlederrors"] div[data-testid="context-menu"] button'
+ '[data-item-id="example-unhandlederrors"] button[data-testid="context-menu"]'
)
.click();
- const sidebarContextMenu = page.getByTestId("tooltip");
+ const sidebarContextMenu = page.getByRole('dialog');
await sidebarContextMenu.getByLabel("Start test run").click();
+ // HACK: the testing module popover has poor tracking of focus due to how many disabled
+ // buttons it has and how deeply it changes its UI on events. This would be solved once
+ // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab
+ // around to reset focus.
+ await page.keyboard.press('Tab');
+ await page.keyboard.press('Escape');
+ await expect(sidebarContextMenu).not.toBeVisible();
+
// Assert - Tests are running and errors are reported
const errorLink = page.locator(
"#storybook-testing-module #testing-module-description a"
@@ -597,10 +605,10 @@ test.describe("component testing", () => {
await page.locator('[data-item-id="addons-group-test"]').hover();
await page
.locator(
- '[data-item-id="addons-group-test"] div[data-testid="context-menu"] button'
+ '[data-item-id="addons-group-test"] button[data-testid="context-menu"]'
)
.click();
- const sidebarContextMenu = page.getByTestId("tooltip");
+ const sidebarContextMenu = page.getByRole('dialog');
await sidebarContextMenu.getByLabel("Start test run").click();
// Assert - Tests are running and reported
@@ -615,6 +623,14 @@ test.describe("component testing", () => {
sidebarContextMenu.getByLabel("Component tests failed")
).toHaveCount(1);
+ // HACK: the testing module popover has poor tracking of focus due to how many disabled
+ // buttons it has and how deeply it changes its UI on events. This would be solved once
+ // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab
+ // around to reset focus.
+ await page.keyboard.press('Tab');
+ await page.keyboard.press('Escape');
+ await expect(sidebarContextMenu).not.toBeVisible();
+
await page.click("body");
await expect(
page
@@ -645,12 +661,20 @@ test.describe("component testing", () => {
await page.locator('[data-item-id="addons-group"]').hover();
await page
.locator(
- '[data-item-id="addons-group"] div[data-testid="context-menu"] button'
+ '[data-item-id="addons-group"] button[data-testid="context-menu"]'
)
.click();
- const sidebarContextMenu = page.getByTestId("tooltip");
+ const sidebarContextMenu = page.getByRole('dialog');
await sidebarContextMenu.getByLabel("Start test run").click();
+ // HACK: the testing module popover has poor tracking of focus due to how many disabled
+ // buttons it has and how deeply it changes its UI on events. This would be solved once
+ // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab
+ // around to reset focus.
+ await page.keyboard.press('Tab');
+ await page.keyboard.press('Escape');
+ await expect(sidebarContextMenu).not.toBeVisible();
+
// Assert - Tests are running and reported
await expect(
sidebarContextMenu.locator("#testing-module-description")
@@ -703,12 +727,20 @@ test.describe("component testing", () => {
.hover();
await page
.locator(
- '[data-item-id="example-button--csf-3-primary"] div[data-testid="context-menu"] button'
+ '[data-item-id="example-button--csf-3-primary"] button[data-testid="context-menu"]'
)
.click();
- const sidebarContextMenu = page.getByTestId("tooltip");
+ const sidebarContextMenu = page.getByRole('dialog');
await sidebarContextMenu.getByLabel("Start test run").click();
+ // HACK: the testing module popover has poor tracking of focus due to how many disabled
+ // buttons it has and how deeply it changes its UI on events. This would be solved once
+ // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab
+ // around to reset focus.
+ await page.keyboard.press('Tab');
+ await page.keyboard.press('Escape');
+ await expect(sidebarContextMenu).not.toBeVisible();
+
// Arrange - Wait for test to finish and unfocus sidebar context menu
await expect(
sidebarContextMenu.locator("#testing-module-description")
diff --git a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/save-from-controls.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/save-from-controls.spec.ts
index 21341d1276e8..0e093e00d614 100644
--- a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/save-from-controls.spec.ts
+++ b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/save-from-controls.spec.ts
@@ -77,7 +77,7 @@ test.describe("save-from-controls", () => {
await sbPage.page
.getByPlaceholder("Story export name")
.fill("ClonedStory" + id);
- await sbPage.page.getByRole("button", { name: "Create" }).click();
+ await sbPage.page.getByRole("button", { exact: true, name: "Create" }).click();
// Assert the file is saved
const notification2 = sbPage.page.getByTitle("Story created");
]