diff --git a/src/internal/hooks/use-base-component/__tests__/init-themes.test.tsx b/src/internal/hooks/use-base-component/__tests__/init-themes.test.tsx
new file mode 100644
index 0000000000..63b497c43b
--- /dev/null
+++ b/src/internal/hooks/use-base-component/__tests__/init-themes.test.tsx
@@ -0,0 +1,54 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import React from 'react';
+import { render } from '@testing-library/react';
+
+import useBaseComponent, {
+ clearThemesInitialized,
+ InternalBaseComponentProps,
+} from '../../../../../lib/components/internal/hooks/use-base-component';
+
+const awsuiGlobalFlagsSymbol = Symbol.for('awsui-global-flags');
+
+jest.mock('../../../../../lib/components/internal/environment', () => ({
+ ALWAYS_VISUAL_REFRESH: true,
+ PACKAGE_SOURCE: 'components',
+ PACKAGE_VERSION: '3.0.0',
+ THEME: 'console',
+}));
+
+function InternalDemo({ __internalRootRef }: InternalBaseComponentProps) {
+ return
Demo
;
+}
+
+function Demo() {
+ const baseComponentProps = useBaseComponent('DemoComponent');
+ return ;
+}
+
+describe('useBaseComponent initThemes with ALWAYS_VISUAL_REFRESH=true', () => {
+ afterEach(() => {
+ clearThemesInitialized();
+ document.body.classList.remove('awsui-one-theme');
+ document.body.classList.remove('awsui-visual-refresh');
+ delete (window as any)[awsuiGlobalFlagsSymbol];
+ });
+
+ test('should add awsui-one-theme class when oneTheme flag is set', () => {
+ (window as any)[awsuiGlobalFlagsSymbol] = { oneTheme: true };
+ render();
+ expect(document.body).toHaveClass('awsui-one-theme');
+ });
+
+ test('should not add awsui-visual-refresh class', () => {
+ (window as any)[awsuiGlobalFlagsSymbol] = { oneTheme: true };
+ render();
+ expect(document.body).not.toHaveClass('awsui-visual-refresh');
+ });
+
+ test('should not add any theme class when no flag is set', () => {
+ render();
+ expect(document.body).not.toHaveClass('awsui-one-theme');
+ expect(document.body).not.toHaveClass('awsui-visual-refresh');
+ });
+});
diff --git a/src/internal/hooks/use-base-component/index.ts b/src/internal/hooks/use-base-component/index.ts
index a549ddc347..a2fff153b0 100644
--- a/src/internal/hooks/use-base-component/index.ts
+++ b/src/internal/hooks/use-base-component/index.ts
@@ -4,13 +4,14 @@ import React from 'react';
import {
ComponentConfiguration,
+ initThemes,
useComponentMetadata,
useComponentMetrics,
useFocusVisible,
} from '@cloudscape-design/component-toolkit/internal';
import { AnalyticsMetadata } from '../../../types/analytics';
-import { PACKAGE_SOURCE, PACKAGE_VERSION, THEME } from '../../environment';
+import { ALWAYS_VISUAL_REFRESH, PACKAGE_SOURCE, PACKAGE_VERSION, THEME } from '../../environment';
import { getVisualTheme } from '../../utils/get-visual-theme';
import { useVisualRefresh } from '../use-visual-mode';
import { useMissingStylesCheck } from './styles-check';
@@ -28,11 +29,24 @@ export interface InternalBaseComponentProps {
* attached to the (internal) component's root DOM node. The hook takes care of attaching the metadata to this
* root DOM node and emits the telemetry for this component.
*/
+
+let themesInitialized = false;
+
+/** for testing only */
+export function clearThemesInitialized() {
+ themesInitialized = false;
+}
+
export default function useBaseComponent(
componentName: string,
config?: ComponentConfiguration,
analyticsMetadata?: AnalyticsMetadata
) {
+ if (!themesInitialized) {
+ initThemes({ skipVisualRefresh: ALWAYS_VISUAL_REFRESH });
+ themesInitialized = true;
+ }
+
const isVisualRefresh = useVisualRefresh();
const theme = getVisualTheme(THEME, isVisualRefresh);
useComponentMetrics(componentName, { packageSource: PACKAGE_SOURCE, packageVersion: PACKAGE_VERSION, theme }, config);