From c5b7671cf7e5fb5334cbeb76bb663d1f0d5294e0 Mon Sep 17 00:00:00 2001 From: Maximilian Schoell Date: Thu, 11 Jun 2026 11:07:26 +0200 Subject: [PATCH 1/2] fix: propagate one-theme class to portaled content --- .../__tests__/use-portal-mode-classes.test.tsx | 18 ++++++++++++++++++ .../hooks/use-portal-mode-classes/index.ts | 6 ++++-- src/internal/hooks/use-visual-mode/index.ts | 4 +++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/internal/hooks/use-portal-mode-classes/__tests__/use-portal-mode-classes.test.tsx b/src/internal/hooks/use-portal-mode-classes/__tests__/use-portal-mode-classes.test.tsx index 0412a88741..216fc23072 100644 --- a/src/internal/hooks/use-portal-mode-classes/__tests__/use-portal-mode-classes.test.tsx +++ b/src/internal/hooks/use-portal-mode-classes/__tests__/use-portal-mode-classes.test.tsx @@ -42,6 +42,24 @@ describe('usePortalModeClasses', () => { expect(screen.getByTestId('subject')).toHaveClass('awsui-visual-refresh', { exact: true }); }); + test('should detect one theme mode', () => { + document.body.classList.add('awsui-one-theme'); + + render(); + expect(screen.getByTestId('subject')).toHaveClass('awsui-one-theme', { exact: true }); + // Must not stamp the VR class, which would override One Theme tokens on portaled content. + expect(screen.getByTestId('subject')).not.toHaveClass('awsui-visual-refresh'); + }); + + test('should let one theme win when visual refresh is also active', () => { + globalWithFlags[Symbol.for('awsui-visual-refresh-flag')] = () => true; + document.body.classList.add('awsui-one-theme'); + + render(); + expect(screen.getByTestId('subject')).toHaveClass('awsui-one-theme', { exact: true }); + expect(screen.getByTestId('subject')).not.toHaveClass('awsui-visual-refresh'); + }); + test('should detect contexts', () => { render( diff --git a/src/internal/hooks/use-portal-mode-classes/index.ts b/src/internal/hooks/use-portal-mode-classes/index.ts index 606d36237f..682aa6b8a3 100644 --- a/src/internal/hooks/use-portal-mode-classes/index.ts +++ b/src/internal/hooks/use-portal-mode-classes/index.ts @@ -7,18 +7,20 @@ import { useCurrentMode, useDensityMode } from '@cloudscape-design/component-too import { useVisualContext } from '../../components/visual-context'; import { ALWAYS_VISUAL_REFRESH } from '../../environment'; -import { useVisualRefresh } from '../use-visual-mode'; +import { useOneTheme, useVisualRefresh } from '../use-visual-mode'; export function usePortalModeClasses(ref: React.RefObject, options?: { resetVisualContext?: boolean }) { const colorMode = useCurrentMode(ref); const densityMode = useDensityMode(ref); const context = useVisualContext(ref); - const visualRefreshWithClass = useVisualRefresh() && !ALWAYS_VISUAL_REFRESH; + const oneTheme = useOneTheme(); + const visualRefreshWithClass = useVisualRefresh() && !ALWAYS_VISUAL_REFRESH && !oneTheme; return clsx({ 'awsui-polaris-dark-mode awsui-dark-mode': colorMode === 'dark', 'awsui-polaris-compact-mode awsui-compact-mode': densityMode === 'compact', 'awsui-visual-refresh': visualRefreshWithClass, + 'awsui-one-theme': oneTheme, [`awsui-context-${context}`]: context && !options?.resetVisualContext, }); } diff --git a/src/internal/hooks/use-visual-mode/index.ts b/src/internal/hooks/use-visual-mode/index.ts index 6bba0d58b1..24c1965904 100644 --- a/src/internal/hooks/use-visual-mode/index.ts +++ b/src/internal/hooks/use-visual-mode/index.ts @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { useRuntimeVisualRefresh } from '@cloudscape-design/component-toolkit/internal'; +import { isThemeActive, Theme, useRuntimeVisualRefresh } from '@cloudscape-design/component-toolkit/internal'; import { ALWAYS_VISUAL_REFRESH } from '../../environment'; export const useVisualRefresh = ALWAYS_VISUAL_REFRESH ? () => true : useRuntimeVisualRefresh; + +export const useOneTheme = () => isThemeActive(Theme.OneTheme); From aaab441a70bcd9a2b7b397bf8b73119b0111e11b Mon Sep 17 00:00:00 2001 From: Maximilian Schoell Date: Thu, 11 Jun 2026 11:25:55 +0200 Subject: [PATCH 2/2] test: add useOneTheme to use-visual-mode mocks --- src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx | 1 + src/container/__tests__/sticky-header.test.tsx | 1 + src/content-layout/__tests__/content-layout.test.tsx | 1 + src/header/__tests__/sticky-responsiveness.test.tsx | 1 + src/internal/widgets/__tests__/widgets.test.tsx | 1 + src/split-panel/__tests__/widgetized-panel.test.tsx | 1 + src/wizard/__tests__/analytics-metadata.test.tsx | 1 + 7 files changed, 7 insertions(+) diff --git a/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx b/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx index 7a105d12cd..5c472771fd 100644 --- a/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx +++ b/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx @@ -47,6 +47,7 @@ function getResourceTypeElements(container: HTMLElement) { jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); describe('Classic design', () => { diff --git a/src/container/__tests__/sticky-header.test.tsx b/src/container/__tests__/sticky-header.test.tsx index 593d6eea61..c0fb8618b9 100644 --- a/src/container/__tests__/sticky-header.test.tsx +++ b/src/container/__tests__/sticky-header.test.tsx @@ -12,6 +12,7 @@ jest.mock('../../../lib/components/internal/hooks/use-mobile', () => ({ })); jest.mock('../../internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(true), + useOneTheme: jest.fn().mockReturnValue(false), })); jest.mock('@cloudscape-design/component-toolkit/dom', () => ({ diff --git a/src/content-layout/__tests__/content-layout.test.tsx b/src/content-layout/__tests__/content-layout.test.tsx index 892ccd2626..60a4fed801 100644 --- a/src/content-layout/__tests__/content-layout.test.tsx +++ b/src/content-layout/__tests__/content-layout.test.tsx @@ -13,6 +13,7 @@ import styles from '../../../lib/components/content-layout/styles.selectors.js'; jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); function renderContentLayout(props: ContentLayoutProps = {}) { diff --git a/src/header/__tests__/sticky-responsiveness.test.tsx b/src/header/__tests__/sticky-responsiveness.test.tsx index 8bb4dbbc9d..89a120af6b 100644 --- a/src/header/__tests__/sticky-responsiveness.test.tsx +++ b/src/header/__tests__/sticky-responsiveness.test.tsx @@ -12,6 +12,7 @@ import styles from '../../../lib/components/header/styles.css.js'; jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); function renderHeader(jsx: React.ReactElement) { diff --git a/src/internal/widgets/__tests__/widgets.test.tsx b/src/internal/widgets/__tests__/widgets.test.tsx index d3c58e0917..4a0634c599 100644 --- a/src/internal/widgets/__tests__/widgets.test.tsx +++ b/src/internal/widgets/__tests__/widgets.test.tsx @@ -20,6 +20,7 @@ function findContent(container: HTMLElement) { jest.mock('../../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); describe('Classic design', () => { diff --git a/src/split-panel/__tests__/widgetized-panel.test.tsx b/src/split-panel/__tests__/widgetized-panel.test.tsx index 9c49dfad95..be1a0be113 100644 --- a/src/split-panel/__tests__/widgetized-panel.test.tsx +++ b/src/split-panel/__tests__/widgetized-panel.test.tsx @@ -43,6 +43,7 @@ const defaultProps: SplitPanelImplementationProps = { jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); describe('Classic design', () => { diff --git a/src/wizard/__tests__/analytics-metadata.test.tsx b/src/wizard/__tests__/analytics-metadata.test.tsx index b64a571b53..1bb2fb080e 100644 --- a/src/wizard/__tests__/analytics-metadata.test.tsx +++ b/src/wizard/__tests__/analytics-metadata.test.tsx @@ -26,6 +26,7 @@ import labels from '../../../lib/components/wizard/analytics-metadata/styles.css jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ useVisualRefresh: jest.fn().mockReturnValue(false), + useOneTheme: jest.fn().mockReturnValue(false), })); const steps: WizardProps['steps'] = [