Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export {
useDensityMode,
useReducedMotion,
useRuntimeVisualRefresh,
isThemeActive,
Theme,
} from './visual-mode/index.js';
export { isDevelopment } from './is-development.js';
export { warnOnce, clearMessageCache } from './logging.js';
Expand Down
51 changes: 51 additions & 0 deletions src/internal/visual-mode/__tests__/is-theme-active.ssr.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @jest-environment node
*/
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { isThemeActive, Theme } from '../index';
import { awsuiGlobalFlagsSymbol, awsuiVisualRefreshFlag, FlagsHolder } from '../../global-flags';

const globalWithFlags = globalThis as FlagsHolder;

afterEach(() => {
delete globalWithFlags[awsuiVisualRefreshFlag];
delete globalWithFlags[awsuiGlobalFlagsSymbol];
});

test('ensure no window in this environment', () => {
expect(typeof window === 'undefined').toBe(true);
});

describe('Theme.VisualRefresh', () => {
test('returns false by default', () => {
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
});

test('returns true when awsui-visual-refresh-flag is set on globalThis', () => {
globalWithFlags[awsuiVisualRefreshFlag] = () => true;
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
});

test('returns false when awsui-visual-refresh-flag returns false', () => {
globalWithFlags[awsuiVisualRefreshFlag] = () => false;
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
});
});

describe('Theme.OneTheme', () => {
test('returns false by default', () => {
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});

test('returns true when oneTheme global flag is set on globalThis', () => {
globalWithFlags[awsuiGlobalFlagsSymbol] = { oneTheme: true };
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});

test('returns false when oneTheme global flag is false', () => {
globalWithFlags[awsuiGlobalFlagsSymbol] = { oneTheme: false };
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});
});
99 changes: 99 additions & 0 deletions src/internal/visual-mode/__tests__/is-theme-active.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { isThemeActive, Theme } from '../index';
import { awsuiGlobalFlagsSymbol, awsuiVisualRefreshFlag, FlagsHolder } from '../../global-flags';

declare const window: Window & FlagsHolder;

afterEach(() => {
document.body.classList.remove('awsui-visual-refresh');
document.body.classList.remove('awsui-one-theme');
delete window[awsuiVisualRefreshFlag];
delete window[awsuiGlobalFlagsSymbol];
});

describe('Theme.VisualRefresh', () => {
test('returns false when nothing is set', () => {
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
});

test('returns true when the awsui-visual-refresh class is present', () => {
document.body.classList.add('awsui-visual-refresh');
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
});

test('returns true when awsui-visual-refresh-flag returns true', () => {
window[awsuiVisualRefreshFlag] = () => true;
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
});

test('returns false when awsui-visual-refresh-flag returns false', () => {
window[awsuiVisualRefreshFlag] = () => false;
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
});

test('class presence wins over a flag returning false', () => {
document.body.classList.add('awsui-visual-refresh');
window[awsuiVisualRefreshFlag] = () => false;
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
});
});

describe('Theme.OneTheme', () => {
test('returns false when nothing is set', () => {
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});

test('returns true when the awsui-one-theme class is present', () => {
document.body.classList.add('awsui-one-theme');
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});

test('returns true when the oneTheme global flag is true', () => {
window[awsuiGlobalFlagsSymbol] = { oneTheme: true };
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});

test('returns false when the oneTheme global flag is false', () => {
window[awsuiGlobalFlagsSymbol] = { oneTheme: false };
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});

test('returns false when awsui-global-flags exists but oneTheme is unset', () => {
window[awsuiGlobalFlagsSymbol] = {};
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});

test('class presence wins over a flag set to false', () => {
document.body.classList.add('awsui-one-theme');
window[awsuiGlobalFlagsSymbol] = { oneTheme: false };
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});
});

describe('theme isolation', () => {
test('activating one theme via class does not activate visual refresh', () => {
document.body.classList.add('awsui-one-theme');
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});

test('activating visual refresh via class does not activate one theme', () => {
document.body.classList.add('awsui-visual-refresh');
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});

test('activating one theme via flag does not activate visual refresh', () => {
window[awsuiGlobalFlagsSymbol] = { oneTheme: true };
expect(isThemeActive(Theme.VisualRefresh)).toBe(false);
expect(isThemeActive(Theme.OneTheme)).toBe(true);
});

test('activating visual refresh via symbol does not activate one theme', () => {
window[awsuiVisualRefreshFlag] = () => true;
expect(isThemeActive(Theme.VisualRefresh)).toBe(true);
expect(isThemeActive(Theme.OneTheme)).toBe(false);
});
});
29 changes: 29 additions & 0 deletions src/internal/visual-mode/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,32 @@ export function useRuntimeVisualRefresh() {
}
return visualRefreshState;
}

export enum Theme {
VisualRefresh = 'visual-refresh',
OneTheme = 'one-theme',
}

interface ThemeConfig {
className: string;
isFlagActive: () => boolean;
}

const THEMES: Record<Theme, ThemeConfig> = {
[Theme.VisualRefresh]: {
className: 'awsui-visual-refresh',
isFlagActive: () => !!getGlobal()?.[awsuiVisualRefreshFlag]?.(),
},
[Theme.OneTheme]: {
className: 'awsui-one-theme',
isFlagActive: () => !!getGlobalFlag('oneTheme'),
},
};

export function isThemeActive(theme: Theme): boolean {
const config = THEMES[theme];
if (typeof document !== 'undefined' && document.querySelector(`.${config.className}`)) {
return true;
}
return config.isFlagActive();
}
Loading