feat(themes): enable all palettes (#30874)
Issue number: internal --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> The new theming structure does not allow high contrast and high contrast dark to render properly. This can be seen when running a test that uses `set-content`. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - High contrast and high contrast dark have been enabled to the testing environments - The theme files for high contrast and high contrast dark have been added under `themes`. ## Does this introduce a breaking change? - [x] Yes - [ ] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> [Colors preview](https://ionic-framework-git-set-content-ionic1.vercel.app/src/themes/test/color/) How to test: 1. Verify that tests related to palettes are passing especially those that use `setContent` 2. Verify that the preview page renders the right colors for each possible variation of palettes and themes --------- Co-authored-by: ionitron <hi@ionicframework.com> Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
const DEFAULT_THEME = 'md';
|
||||
const DEFAULT_PALETTE = 'light';
|
||||
|
||||
(function() {
|
||||
|
||||
@@ -88,17 +89,33 @@ const DEFAULT_THEME = 'md';
|
||||
* or `high-contrast-dark`. Default to `light` for tests.
|
||||
*/
|
||||
const validPalettes = ['light', 'dark', 'high-contrast', 'high-contrast-dark'];
|
||||
|
||||
const configDarkMode = window.Ionic?.config?.customTheme?.palette?.dark?.enabled === 'always' ? 'dark' : null;
|
||||
const configHighContrastMode = window.Ionic?.config?.customTheme?.palette?.highContrast?.enabled === 'always' ? 'high-contrast' : null;
|
||||
const configHighContrastDarkMode = window.Ionic?.config?.customTheme?.palette?.highContrastDark?.enabled === 'always' ? 'high-contrast-dark' : null;
|
||||
/**
|
||||
* Ensure window.Ionic.config is defined before importing 'testing/scripts'
|
||||
* in the test HTML to properly initialize the palette configuration below.
|
||||
*
|
||||
* Example:
|
||||
* <script>
|
||||
* window.Ionic = { config: { customTheme: { palette: { ... } } } };
|
||||
* </script>
|
||||
* <script src="testing/scripts.js"></script>
|
||||
*/
|
||||
const configPalette = configDarkMode || configHighContrastMode || configHighContrastDarkMode;
|
||||
const paletteQuery = window.location.search.match(/palette=([a-z-]+)/);
|
||||
const paletteHash = window.location.hash.match(/palette=([a-z-]+)/);
|
||||
const darkClass = document.body?.classList.contains('ion-palette-dark') ? 'dark' : null;
|
||||
const highContrastClass = document.body?.classList.contains('ion-palette-high-contrast') ? 'high-contrast' : null;
|
||||
const highContrastDarkClass = darkClass && highContrastClass ? 'high-contrast-dark' : null;
|
||||
const paletteClass = highContrastDarkClass || highContrastClass || darkClass;
|
||||
|
||||
let paletteName = paletteQuery?.[1] || paletteHash?.[1] || highContrastDarkClass || darkClass || highContrastClass || 'light';
|
||||
let paletteName = configPalette || paletteQuery?.[1] || paletteHash?.[1] || paletteClass || DEFAULT_PALETTE;
|
||||
|
||||
if (!validPalettes.includes(paletteName)) {
|
||||
console.warn(`Invalid palette name: '${paletteName}'. Falling back to 'light' palette.`);
|
||||
paletteName = 'light';
|
||||
paletteName = DEFAULT_PALETTE;
|
||||
}
|
||||
|
||||
// Load theme tokens if the theme is valid
|
||||
@@ -119,8 +136,15 @@ const DEFAULT_THEME = 'md';
|
||||
|
||||
// If a specific palette is requested, modify the palette structure
|
||||
// to set the enabled property to 'always'
|
||||
// TODO(FW-4004): Implement dark palette
|
||||
if (paletteName === 'dark' && theme.palette?.dark) {
|
||||
theme.palette.dark.enabled = 'always';
|
||||
// TODO(FW-4005): Implement high contrast palette
|
||||
} else if (paletteName === 'high-contrast' && theme.palette?.highContrast) {
|
||||
theme.palette.highContrast.enabled = 'always';
|
||||
// TODO(FW-4005): Implement high contrast dark palette
|
||||
} else if (paletteName === 'high-contrast-dark' && theme.palette?.highContrastDark) {
|
||||
theme.palette.highContrastDark.enabled = 'always';
|
||||
}
|
||||
|
||||
// Apply the theme tokens to Ionic config
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<!-- TODO(FW-4004): Remove page and test it through the basic page tests -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
@@ -10,6 +12,21 @@
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../css/palettes/dark.always.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script>
|
||||
// Need to be called before loading Ionic else
|
||||
// the scripts.js logic runs too early.
|
||||
window.Ionic = {
|
||||
config: {
|
||||
customTheme: {
|
||||
palette: {
|
||||
dark: {
|
||||
enabled: 'always',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
|
||||
@@ -236,7 +236,8 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
*/
|
||||
configs({ directions: ['ltr'], palettes: ['high-contrast-dark', 'high-contrast'] }).forEach(
|
||||
({ title, config, screenshot }) => {
|
||||
test.describe(title('toast: high contrast: buttons'), () => {
|
||||
// TODO(FW-4005): Once high contrast themes are fully implemented in ionic modular, remove the skips from these tests
|
||||
test.describe.skip(title('toast: high contrast: buttons'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -1,6 +1,8 @@
|
||||
import type { DefaultTheme } from '../themes.interfaces';
|
||||
|
||||
import { darkTheme } from './dark.tokens';
|
||||
import { highContrastDarkTheme } from './high-contrast-dark.tokens';
|
||||
import { highContrastTheme } from './high-contrast.tokens';
|
||||
import { lightTheme } from './light.tokens';
|
||||
|
||||
export const defaultTheme: DefaultTheme = {
|
||||
@@ -9,6 +11,8 @@ export const defaultTheme: DefaultTheme = {
|
||||
palette: {
|
||||
light: lightTheme,
|
||||
dark: darkTheme,
|
||||
highContrast: highContrastTheme,
|
||||
highContrastDark: highContrastDarkTheme,
|
||||
},
|
||||
|
||||
config: {
|
||||
|
||||
213
core/src/themes/base/high-contrast-dark.tokens.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import { mix } from '../../utils/theme';
|
||||
import type { HighContrastDarkTheme } from '../themes.interfaces';
|
||||
|
||||
const colors = {
|
||||
primary: '#7cabff',
|
||||
secondary: '#62bdff',
|
||||
tertiary: '#b6b9f9',
|
||||
success: '#4ada71',
|
||||
warning: '#ffce31',
|
||||
danger: '#fc9aa2',
|
||||
light: '#222428',
|
||||
medium: '#a8aab3',
|
||||
dark: '#f4f5f8',
|
||||
};
|
||||
|
||||
export const highContrastDarkTheme: HighContrastDarkTheme = {
|
||||
enabled: 'never',
|
||||
color: {
|
||||
primary: {
|
||||
bold: {
|
||||
base: colors.primary,
|
||||
contrast: '#000',
|
||||
foreground: colors.primary,
|
||||
shade: mix(colors.primary, '#000', '12%'),
|
||||
tint: mix(colors.primary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.primary, '8%'),
|
||||
contrast: colors.primary,
|
||||
foreground: mix(colors.primary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.primary, '12%'),
|
||||
tint: mix('#fff', colors.primary, '4%'),
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
bold: {
|
||||
base: colors.secondary,
|
||||
contrast: '#000',
|
||||
foreground: colors.secondary,
|
||||
shade: mix(colors.secondary, '#000', '12%'),
|
||||
tint: mix(colors.secondary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.secondary, '8%'),
|
||||
contrast: colors.secondary,
|
||||
foreground: mix(colors.secondary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.secondary, '12%'),
|
||||
tint: mix('#fff', colors.secondary, '4%'),
|
||||
},
|
||||
},
|
||||
tertiary: {
|
||||
bold: {
|
||||
base: colors.tertiary,
|
||||
contrast: '#000',
|
||||
foreground: colors.tertiary,
|
||||
shade: mix(colors.tertiary, '#000', '12%'),
|
||||
tint: mix(colors.tertiary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.tertiary, '8%'),
|
||||
contrast: colors.tertiary,
|
||||
foreground: mix(colors.tertiary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.tertiary, '12%'),
|
||||
tint: mix('#fff', colors.tertiary, '4%'),
|
||||
},
|
||||
},
|
||||
success: {
|
||||
bold: {
|
||||
base: colors.success,
|
||||
contrast: '#000',
|
||||
foreground: colors.success,
|
||||
shade: mix(colors.success, '#000', '12%'),
|
||||
tint: mix(colors.success, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.success, '8%'),
|
||||
contrast: colors.success,
|
||||
foreground: mix(colors.success, '#000', '12%'),
|
||||
shade: mix('#fff', colors.success, '12%'),
|
||||
tint: mix('#fff', colors.success, '4%'),
|
||||
},
|
||||
},
|
||||
warning: {
|
||||
bold: {
|
||||
base: colors.warning,
|
||||
contrast: '#000',
|
||||
foreground: colors.warning,
|
||||
shade: mix(colors.warning, '#000', '12%'),
|
||||
tint: mix(colors.warning, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.warning, '8%'),
|
||||
contrast: colors.warning,
|
||||
foreground: mix(colors.warning, '#000', '12%'),
|
||||
shade: mix('#fff', colors.warning, '12%'),
|
||||
tint: mix('#fff', colors.warning, '4%'),
|
||||
},
|
||||
},
|
||||
danger: {
|
||||
bold: {
|
||||
base: colors.danger,
|
||||
contrast: '#000',
|
||||
foreground: colors.danger,
|
||||
shade: mix(colors.danger, '#000', '12%'),
|
||||
tint: mix(colors.danger, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.danger, '8%'),
|
||||
contrast: colors.danger,
|
||||
foreground: mix(colors.danger, '#000', '12%'),
|
||||
shade: mix('#fff', colors.danger, '12%'),
|
||||
tint: mix('#fff', colors.danger, '4%'),
|
||||
},
|
||||
},
|
||||
light: {
|
||||
bold: {
|
||||
base: colors.light,
|
||||
contrast: '#fff',
|
||||
foreground: colors.light,
|
||||
shade: mix(colors.light, '#000', '12%'),
|
||||
tint: mix(colors.light, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.light, '8%'),
|
||||
contrast: colors.light,
|
||||
foreground: mix(colors.light, '#000', '12%'),
|
||||
shade: mix('#fff', colors.light, '12%'),
|
||||
tint: mix('#fff', colors.light, '4%'),
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
bold: {
|
||||
base: colors.medium,
|
||||
contrast: '#000',
|
||||
foreground: colors.medium,
|
||||
shade: mix(colors.medium, '#000', '12%'),
|
||||
tint: mix(colors.medium, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.medium, '8%'),
|
||||
contrast: colors.medium,
|
||||
foreground: mix(colors.medium, '#000', '12%'),
|
||||
shade: mix('#fff', colors.medium, '12%'),
|
||||
tint: mix('#fff', colors.medium, '4%'),
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
bold: {
|
||||
base: colors.dark,
|
||||
contrast: '#000',
|
||||
foreground: colors.dark,
|
||||
shade: mix(colors.dark, '#000', '12%'),
|
||||
tint: mix(colors.dark, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.dark, '8%'),
|
||||
contrast: colors.dark,
|
||||
foreground: mix(colors.dark, '#000', '12%'),
|
||||
shade: mix('#fff', colors.dark, '12%'),
|
||||
tint: mix('#fff', colors.dark, '4%'),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
backgroundColor: '#000000',
|
||||
backgroundColorRgb: '0, 0, 0',
|
||||
textColor: '#ffffff',
|
||||
textColorRgb: '255, 255, 255',
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#0d0d0d',
|
||||
100: '#1a1a1a',
|
||||
150: '#262626',
|
||||
200: '#333333',
|
||||
250: '#404040',
|
||||
300: '#4d4d4d',
|
||||
350: '#595959',
|
||||
400: '#666666',
|
||||
450: '#737373',
|
||||
500: '#808080',
|
||||
550: '#8c8c8c',
|
||||
600: '#999999',
|
||||
650: '#a6a6a6',
|
||||
700: '#b3b3b3',
|
||||
750: '#bfbfbf',
|
||||
800: '#cccccc',
|
||||
850: '#d9d9d9',
|
||||
900: '#e6e6e6',
|
||||
950: '#f2f2f2',
|
||||
},
|
||||
|
||||
textColorStep: {
|
||||
50: '#f9f9f9',
|
||||
100: '#f3f3f3',
|
||||
150: '#ededed',
|
||||
200: '#e7e7e7',
|
||||
250: '#e1e1e1',
|
||||
300: '#dbdbdb',
|
||||
350: '#d5d5d5',
|
||||
400: '#cfcfcf',
|
||||
450: '#c9c9c9',
|
||||
500: '#c4c4c4',
|
||||
550: '#bebebe',
|
||||
600: '#b8b8b8',
|
||||
650: '#b2b2b2',
|
||||
700: '#acacac',
|
||||
750: '#a6a6a6',
|
||||
800: '#a0a0a0',
|
||||
850: '#9a9a9a',
|
||||
900: '#949494',
|
||||
950: '#8e8e8e',
|
||||
},
|
||||
};
|
||||
213
core/src/themes/base/high-contrast.tokens.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import { mix } from '../../utils/theme';
|
||||
import type { HighContrastTheme } from '../themes.interfaces';
|
||||
|
||||
const colors = {
|
||||
primary: '#003fae',
|
||||
secondary: '#01487b',
|
||||
tertiary: '#3400e6',
|
||||
success: '#004314',
|
||||
warning: '#5f4100',
|
||||
danger: '#9c000c',
|
||||
light: '#f4f5f8',
|
||||
medium: '#444446',
|
||||
dark: '#222428',
|
||||
};
|
||||
|
||||
export const highContrastTheme: HighContrastTheme = {
|
||||
enabled: 'never',
|
||||
color: {
|
||||
primary: {
|
||||
bold: {
|
||||
base: colors.primary,
|
||||
contrast: '#fff',
|
||||
foreground: colors.primary,
|
||||
shade: mix(colors.primary, '#000', '12%'),
|
||||
tint: mix(colors.primary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.primary, '8%'),
|
||||
contrast: colors.primary,
|
||||
foreground: mix(colors.primary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.primary, '12%'),
|
||||
tint: mix('#fff', colors.primary, '4%'),
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
bold: {
|
||||
base: colors.secondary,
|
||||
contrast: '#fff',
|
||||
foreground: colors.secondary,
|
||||
shade: mix(colors.secondary, '#000', '12%'),
|
||||
tint: mix(colors.secondary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.secondary, '8%'),
|
||||
contrast: colors.secondary,
|
||||
foreground: mix(colors.secondary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.secondary, '12%'),
|
||||
tint: mix('#fff', colors.secondary, '4%'),
|
||||
},
|
||||
},
|
||||
tertiary: {
|
||||
bold: {
|
||||
base: colors.tertiary,
|
||||
contrast: '#fff',
|
||||
foreground: colors.tertiary,
|
||||
shade: mix(colors.tertiary, '#000', '12%'),
|
||||
tint: mix(colors.tertiary, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.tertiary, '8%'),
|
||||
contrast: colors.tertiary,
|
||||
foreground: mix(colors.tertiary, '#000', '12%'),
|
||||
shade: mix('#fff', colors.tertiary, '12%'),
|
||||
tint: mix('#fff', colors.tertiary, '4%'),
|
||||
},
|
||||
},
|
||||
success: {
|
||||
bold: {
|
||||
base: colors.success,
|
||||
contrast: '#fff',
|
||||
foreground: colors.success,
|
||||
shade: mix(colors.success, '#000', '12%'),
|
||||
tint: mix(colors.success, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.success, '8%'),
|
||||
contrast: colors.success,
|
||||
foreground: mix(colors.success, '#000', '12%'),
|
||||
shade: mix('#fff', colors.success, '12%'),
|
||||
tint: mix('#fff', colors.success, '4%'),
|
||||
},
|
||||
},
|
||||
warning: {
|
||||
bold: {
|
||||
base: colors.warning,
|
||||
contrast: '#fff',
|
||||
foreground: colors.warning,
|
||||
shade: mix(colors.warning, '#000', '12%'),
|
||||
tint: mix(colors.warning, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.warning, '8%'),
|
||||
contrast: colors.warning,
|
||||
foreground: mix(colors.warning, '#000', '12%'),
|
||||
shade: mix('#fff', colors.warning, '12%'),
|
||||
tint: mix('#fff', colors.warning, '4%'),
|
||||
},
|
||||
},
|
||||
danger: {
|
||||
bold: {
|
||||
base: colors.danger,
|
||||
contrast: '#fff',
|
||||
foreground: colors.danger,
|
||||
shade: mix(colors.danger, '#000', '12%'),
|
||||
tint: mix(colors.danger, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.danger, '8%'),
|
||||
contrast: colors.danger,
|
||||
foreground: mix(colors.danger, '#000', '12%'),
|
||||
shade: mix('#fff', colors.danger, '12%'),
|
||||
tint: mix('#fff', colors.danger, '4%'),
|
||||
},
|
||||
},
|
||||
light: {
|
||||
bold: {
|
||||
base: colors.light,
|
||||
contrast: '#000',
|
||||
foreground: colors.light,
|
||||
shade: mix(colors.light, '#000', '12%'),
|
||||
tint: mix(colors.light, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.light, '8%'),
|
||||
contrast: colors.light,
|
||||
foreground: mix(colors.light, '#000', '12%'),
|
||||
shade: mix('#fff', colors.light, '12%'),
|
||||
tint: mix('#fff', colors.light, '4%'),
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
bold: {
|
||||
base: colors.medium,
|
||||
contrast: '#fff',
|
||||
foreground: colors.medium,
|
||||
shade: mix(colors.medium, '#000', '12%'),
|
||||
tint: mix(colors.medium, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.medium, '8%'),
|
||||
contrast: colors.medium,
|
||||
foreground: mix(colors.medium, '#000', '12%'),
|
||||
shade: mix('#fff', colors.medium, '12%'),
|
||||
tint: mix('#fff', colors.medium, '4%'),
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
bold: {
|
||||
base: colors.dark,
|
||||
contrast: '#fff',
|
||||
foreground: colors.dark,
|
||||
shade: mix(colors.dark, '#000', '12%'),
|
||||
tint: mix(colors.dark, '#fff', '10%'),
|
||||
},
|
||||
subtle: {
|
||||
base: mix('#fff', colors.dark, '8%'),
|
||||
contrast: colors.dark,
|
||||
foreground: mix(colors.dark, '#000', '12%'),
|
||||
shade: mix('#fff', colors.dark, '12%'),
|
||||
tint: mix('#fff', colors.dark, '4%'),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
backgroundColor: '#ffffff',
|
||||
backgroundColorRgb: '255, 255, 255',
|
||||
textColor: '#000000',
|
||||
textColorRgb: '0, 0, 0',
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#818181',
|
||||
100: '#7a7a7a',
|
||||
150: '#747474',
|
||||
200: '#6d6d6d',
|
||||
250: '#666666',
|
||||
300: '#5f5f5f',
|
||||
350: '#585858',
|
||||
400: '#525252',
|
||||
450: '#4b4b4b',
|
||||
500: '#444444',
|
||||
550: '#3d3d3d',
|
||||
600: '#363636',
|
||||
650: '#303030',
|
||||
700: '#292929',
|
||||
750: '#222222',
|
||||
800: '#1b1b1b',
|
||||
850: '#141414',
|
||||
900: '#0e0e0e',
|
||||
950: '#070707',
|
||||
},
|
||||
|
||||
textColorStep: {
|
||||
50: '#070707',
|
||||
100: '#0e0e0e',
|
||||
150: '#141414',
|
||||
200: '#1b1b1b',
|
||||
250: '#222222',
|
||||
300: '#292929',
|
||||
350: '#303030',
|
||||
400: '#363636',
|
||||
450: '#3d3d3d',
|
||||
500: '#444444',
|
||||
550: '#4b4b4b',
|
||||
600: '#525252',
|
||||
650: '#585858',
|
||||
700: '#5f5f5f',
|
||||
750: '#666666',
|
||||
800: '#6d6d6d',
|
||||
850: '#747474',
|
||||
900: '#7a7a7a',
|
||||
950: '#818181',
|
||||
},
|
||||
};
|
||||
@@ -2,6 +2,8 @@ import { defaultTheme as baseDefaultTheme } from '../base/default.tokens';
|
||||
import type { DefaultTheme } from '../themes.interfaces';
|
||||
|
||||
import { darkTheme } from './dark.tokens';
|
||||
import { highContrastDarkTheme } from './high-contrast-dark.tokens';
|
||||
import { highContrastTheme } from './high-contrast.tokens';
|
||||
import { lightTheme } from './light.tokens';
|
||||
|
||||
export const defaultTheme: DefaultTheme = {
|
||||
@@ -12,6 +14,8 @@ export const defaultTheme: DefaultTheme = {
|
||||
palette: {
|
||||
light: lightTheme,
|
||||
dark: darkTheme,
|
||||
highContrast: highContrastTheme,
|
||||
highContrastDark: highContrastDarkTheme,
|
||||
},
|
||||
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Roboto", sans-serif',
|
||||
|
||||
6
core/src/themes/ios/high-contrast-dark.tokens.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { highContrastDarkTheme as baseHighContrastDarkTheme } from '../base/high-contrast-dark.tokens';
|
||||
import type { HighContrastDarkTheme } from '../themes.interfaces';
|
||||
|
||||
export const highContrastDarkTheme: HighContrastDarkTheme = {
|
||||
...baseHighContrastDarkTheme,
|
||||
};
|
||||
53
core/src/themes/ios/high-contrast.tokens.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { highContrastTheme as baseHighContrastTheme } from '../base/high-contrast.tokens';
|
||||
import type { HighContrastTheme } from '../themes.interfaces';
|
||||
|
||||
export const highContrastTheme: HighContrastTheme = {
|
||||
...baseHighContrastTheme,
|
||||
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#000000',
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#818181',
|
||||
100: '#7a7a7a',
|
||||
150: '#747474',
|
||||
200: '#6d6d6d',
|
||||
250: '#666666',
|
||||
300: '#5f5f5f',
|
||||
350: '#585858',
|
||||
400: '#525252',
|
||||
450: '#4b4b4b',
|
||||
500: '#444444',
|
||||
550: '#3d3d3d',
|
||||
600: '#363636',
|
||||
650: '#303030',
|
||||
700: '#292929',
|
||||
750: '#222222',
|
||||
800: '#1b1b1b',
|
||||
850: '#141414',
|
||||
900: '#0e0e0e',
|
||||
950: '#070707',
|
||||
},
|
||||
|
||||
textColorStep: {
|
||||
50: '#070707',
|
||||
100: '#0e0e0e',
|
||||
150: '#141414',
|
||||
200: '#1b1b1b',
|
||||
250: '#222222',
|
||||
300: '#292929',
|
||||
350: '#303030',
|
||||
400: '#363636',
|
||||
450: '#3d3d3d',
|
||||
500: '#444444',
|
||||
550: '#4b4b4b',
|
||||
600: '#525252',
|
||||
650: '#585858',
|
||||
700: '#5f5f5f',
|
||||
750: '#666666',
|
||||
800: '#6d6d6d',
|
||||
850: '#747474',
|
||||
900: '#7a7a7a',
|
||||
950: '#818181',
|
||||
},
|
||||
};
|
||||
@@ -9,6 +9,11 @@ export const darkTheme: DarkTheme = {
|
||||
textColor: '#ffffff',
|
||||
textColorRgb: '255, 255, 255',
|
||||
|
||||
// TODO(FW-6864): Remove once IonToolbar themes are added
|
||||
toolbar: {
|
||||
background: '#1f1f1f',
|
||||
},
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#1e1e1e',
|
||||
100: '#2a2a2a',
|
||||
|
||||
@@ -2,6 +2,8 @@ import { defaultTheme as baseDefaultTheme } from '../base/default.tokens';
|
||||
import type { DefaultTheme } from '../themes.interfaces';
|
||||
|
||||
import { darkTheme } from './dark.tokens';
|
||||
import { highContrastDarkTheme } from './high-contrast-dark.tokens';
|
||||
import { highContrastTheme } from './high-contrast.tokens';
|
||||
import { lightTheme } from './light.tokens';
|
||||
|
||||
export const defaultTheme: DefaultTheme = {
|
||||
@@ -12,6 +14,8 @@ export const defaultTheme: DefaultTheme = {
|
||||
palette: {
|
||||
light: lightTheme,
|
||||
dark: darkTheme,
|
||||
highContrast: highContrastTheme,
|
||||
highContrastDark: highContrastDarkTheme,
|
||||
},
|
||||
|
||||
config: {
|
||||
|
||||
36
core/src/themes/md/high-contrast-dark.tokens.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { highContrastDarkTheme as baseHighContrastDarkTheme } from '../base/high-contrast-dark.tokens';
|
||||
import type { HighContrastDarkTheme } from '../themes.interfaces';
|
||||
|
||||
export const highContrastDarkTheme: HighContrastDarkTheme = {
|
||||
...baseHighContrastDarkTheme,
|
||||
|
||||
backgroundColor: '#121212',
|
||||
textColor: '#000000',
|
||||
|
||||
// TODO(FW-6864): Remove once IonToolbar themes are added
|
||||
toolbar: {
|
||||
background: '#1f1f1f',
|
||||
},
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#1e1e1e',
|
||||
100: '#2a2a2a',
|
||||
150: '#363636',
|
||||
200: '#414141',
|
||||
250: '#4d4d4d',
|
||||
300: '#595959',
|
||||
350: '#656565',
|
||||
400: '#717171',
|
||||
450: '#7d7d7d',
|
||||
500: '#898989',
|
||||
550: '#949494',
|
||||
600: '#a0a0a0',
|
||||
650: '#acacac',
|
||||
700: '#b8b8b8',
|
||||
750: '#c4c4c4',
|
||||
800: '#d0d0d0',
|
||||
850: '#dbdbdb',
|
||||
900: '#e7e7e7',
|
||||
950: '#f3f3f3',
|
||||
},
|
||||
};
|
||||
53
core/src/themes/md/high-contrast.tokens.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { highContrastTheme as baseHighContrastTheme } from '../base/high-contrast.tokens';
|
||||
import type { HighContrastTheme } from '../themes.interfaces';
|
||||
|
||||
export const highContrastTheme: HighContrastTheme = {
|
||||
...baseHighContrastTheme,
|
||||
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#000000',
|
||||
|
||||
backgroundColorStep: {
|
||||
50: '#818181',
|
||||
100: '#7a7a7a',
|
||||
150: '#747474',
|
||||
200: '#6d6d6d',
|
||||
250: '#666666',
|
||||
300: '#5f5f5f',
|
||||
350: '#585858',
|
||||
400: '#525252',
|
||||
450: '#4b4b4b',
|
||||
500: '#444444',
|
||||
550: '#3d3d3d',
|
||||
600: '#363636',
|
||||
650: '#303030',
|
||||
700: '#292929',
|
||||
750: '#222222',
|
||||
800: '#1b1b1b',
|
||||
850: '#141414',
|
||||
900: '#0e0e0e',
|
||||
950: '#070707',
|
||||
},
|
||||
|
||||
textColorStep: {
|
||||
50: '#070707',
|
||||
100: '#0e0e0e',
|
||||
150: '#141414',
|
||||
200: '#1b1b1b',
|
||||
250: '#222222',
|
||||
300: '#292929',
|
||||
350: '#303030',
|
||||
400: '#363636',
|
||||
450: '#3d3d3d',
|
||||
500: '#444444',
|
||||
550: '#4b4b4b',
|
||||
600: '#525252',
|
||||
650: '#585858',
|
||||
700: '#5f5f5f',
|
||||
750: '#666666',
|
||||
800: '#6d6d6d',
|
||||
850: '#747474',
|
||||
900: '#7a7a7a',
|
||||
950: '#818181',
|
||||
},
|
||||
};
|
||||
@@ -974,7 +974,7 @@
|
||||
function togglePalette(palette) {
|
||||
// The path to the directory containing the
|
||||
// custom palette files for this test
|
||||
var paletteFilesDir = '/src/themes/test/css-variables/css';
|
||||
var paletteFilesDir = '/src/themes/native/test/css-variables/css';
|
||||
let modifier = '';
|
||||
|
||||
// The default and dark palettes are official Ionic
|
||||
|
||||
@@ -17,6 +17,9 @@ export type BaseTheme = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
// TODO(FW-6864): Remove once IonToolbar themes are added
|
||||
toolbar?: any;
|
||||
|
||||
// SPACE TOKENS
|
||||
spacing?: {
|
||||
0?: string;
|
||||
@@ -247,6 +250,16 @@ export type DarkTheme = BaseTheme & {
|
||||
enabled: 'system' | 'always' | 'never' | 'class';
|
||||
};
|
||||
|
||||
// High Contrast theme interface
|
||||
export type HighContrastTheme = BaseTheme & {
|
||||
enabled: 'system' | 'always' | 'never' | 'class';
|
||||
};
|
||||
|
||||
// High Contrast Dark theme interface
|
||||
export type HighContrastDarkTheme = BaseTheme & {
|
||||
enabled: 'system' | 'always' | 'never' | 'class';
|
||||
};
|
||||
|
||||
// Light theme interface
|
||||
export type LightTheme = BaseTheme;
|
||||
|
||||
@@ -257,6 +270,8 @@ export type DefaultTheme = BaseTheme & {
|
||||
palette?: {
|
||||
light?: LightTheme;
|
||||
dark?: DarkTheme;
|
||||
highContrast?: HighContrastTheme;
|
||||
highContrastDark?: HighContrastDarkTheme;
|
||||
};
|
||||
|
||||
config?: IonicConfig;
|
||||
|
||||
@@ -68,6 +68,34 @@ export const setContent = async (page: Page, html: string, testInfo: TestInfo, o
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This object is CRITICAL for Playwright stability.
|
||||
*
|
||||
* WHY IT'S NEEDED:
|
||||
* 1. Bypasses Dynamic Loading: It avoids the consistent import
|
||||
* failure 'await import(...)' when the global theme needed to be
|
||||
* re-applied after the initial Ionic framework load.
|
||||
* 2. Prevents Incorrect Palettes: It directly initializes with the
|
||||
* required 'enabled: "always"' palette before any scripts run. This guarantees that correct CSS variables are loaded from the start.
|
||||
* Otherwise, it would load the default light palette.
|
||||
*
|
||||
* These issues were only happening in Playwright Firefox tests
|
||||
* that use `setContent`.
|
||||
*/
|
||||
const customTheme = {
|
||||
palette: {
|
||||
dark: {
|
||||
enabled: palette === 'dark' ? 'always' : 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: palette === 'high-contrast' ? 'always' : 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: palette === 'high-contrast-dark' ? 'always' : 'never',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const output = `
|
||||
<!DOCTYPE html>
|
||||
<html dir="${direction}" lang="en">
|
||||
@@ -77,14 +105,14 @@ export const setContent = async (page: Page, html: string, testInfo: TestInfo, o
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
${ionicCSSImports}
|
||||
<link href="${baseUrl}/scripts/testing/styles.css" rel="stylesheet" />
|
||||
${palette !== 'light' ? `<link href="${baseUrl}/css/palettes/${palette}.always.css" rel="stylesheet" />` : ''}
|
||||
<script src="${baseUrl}/scripts/testing/scripts.js"></script>
|
||||
${ionicJSImports}
|
||||
<script>
|
||||
window.Ionic = {
|
||||
config: {
|
||||
mode: '${mode}',
|
||||
theme: '${theme}'
|
||||
theme: '${theme}',
|
||||
customTheme: ${JSON.stringify(customTheme)}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -205,6 +205,12 @@ describe('generateCSSVars', () => {
|
||||
dark: {
|
||||
enabled: 'system',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
config: {
|
||||
rippleEffect: true,
|
||||
@@ -319,6 +325,12 @@ describe('generateGlobalThemeCSS', () => {
|
||||
dark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
@@ -372,6 +384,12 @@ describe('generateGlobalThemeCSS', () => {
|
||||
dark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
@@ -437,6 +455,12 @@ describe('generateGlobalThemeCSS', () => {
|
||||
dark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
@@ -513,6 +537,12 @@ describe('generateGlobalThemeCSS', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
@@ -555,6 +585,162 @@ describe('generateGlobalThemeCSS', () => {
|
||||
|
||||
expect(css).toBe(expectedCSS);
|
||||
});
|
||||
|
||||
it('should generate global CSS for a given theme with high contrast palette enabled for system preference', () => {
|
||||
const theme = {
|
||||
name: 'test',
|
||||
palette: {
|
||||
light: {},
|
||||
dark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'system',
|
||||
color: {
|
||||
primary: {
|
||||
bold: {
|
||||
base: '#0054e9',
|
||||
contrast: '#ffffff',
|
||||
shade: '#0041c4',
|
||||
tint: '#0065ff',
|
||||
},
|
||||
subtle: {
|
||||
base: '#0054e9',
|
||||
contrast: '#ffffff',
|
||||
shade: '#0041c4',
|
||||
tint: '#0065ff',
|
||||
},
|
||||
},
|
||||
red: {
|
||||
50: '#ffebee',
|
||||
100: '#ffcdd2',
|
||||
200: '#ef9a9a',
|
||||
},
|
||||
},
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
},
|
||||
spacing: {
|
||||
md: '12px',
|
||||
},
|
||||
dynamicFont: '-apple-system-body',
|
||||
};
|
||||
|
||||
const css = generateGlobalThemeCSS(theme).replace(/\s/g, '');
|
||||
|
||||
const expectedCSS = `
|
||||
:root {
|
||||
--ion-border-width-sm: 4px;
|
||||
--ion-spacing-md: 12px;
|
||||
--ion-dynamic-font: -apple-system-body;
|
||||
}
|
||||
|
||||
@media(prefers-contrast: more) {
|
||||
:root {
|
||||
--ion-color-primary-bold: #0054e9;
|
||||
--ion-color-primary-bold-rgb: 0, 84, 233;
|
||||
--ion-color-primary-bold-contrast: #ffffff;
|
||||
--ion-color-primary-bold-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-bold-shade: #0041c4;
|
||||
--ion-color-primary-bold-tint: #0065ff;
|
||||
--ion-color-primary-subtle: #0054e9;
|
||||
--ion-color-primary-subtle-rgb: 0, 84, 233;
|
||||
--ion-color-primary-subtle-contrast: #ffffff;
|
||||
--ion-color-primary-subtle-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-subtle-shade: #0041c4;
|
||||
--ion-color-primary-subtle-tint: #0065ff;
|
||||
--ion-color-red-50: #ffebee;
|
||||
--ion-color-red-100: #ffcdd2;
|
||||
--ion-color-red-200: #ef9a9a;
|
||||
}
|
||||
}
|
||||
`.replace(/\s/g, '');
|
||||
|
||||
expect(css).toBe(expectedCSS);
|
||||
});
|
||||
|
||||
it('should generate global CSS for a given theme with high contrast dark palette enabled for system preference', () => {
|
||||
const theme = {
|
||||
name: 'test',
|
||||
palette: {
|
||||
light: {},
|
||||
dark: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrast: {
|
||||
enabled: 'never',
|
||||
},
|
||||
highContrastDark: {
|
||||
enabled: 'system',
|
||||
color: {
|
||||
primary: {
|
||||
bold: {
|
||||
base: '#0054e9',
|
||||
contrast: '#ffffff',
|
||||
shade: '#0041c4',
|
||||
tint: '#0065ff',
|
||||
},
|
||||
subtle: {
|
||||
base: '#0054e9',
|
||||
contrast: '#ffffff',
|
||||
shade: '#0041c4',
|
||||
tint: '#0065ff',
|
||||
},
|
||||
},
|
||||
red: {
|
||||
50: '#ffebee',
|
||||
100: '#ffcdd2',
|
||||
200: '#ef9a9a',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
borderWidth: {
|
||||
sm: '4px',
|
||||
},
|
||||
spacing: {
|
||||
md: '12px',
|
||||
},
|
||||
dynamicFont: '-apple-system-body',
|
||||
};
|
||||
|
||||
const css = generateGlobalThemeCSS(theme).replace(/\s/g, '');
|
||||
|
||||
const expectedCSS = `
|
||||
:root {
|
||||
--ion-border-width-sm: 4px;
|
||||
--ion-spacing-md: 12px;
|
||||
--ion-dynamic-font: -apple-system-body;
|
||||
}
|
||||
|
||||
@media(prefers-contrast: more) and (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--ion-color-primary-bold: #0054e9;
|
||||
--ion-color-primary-bold-rgb: 0, 84, 233;
|
||||
--ion-color-primary-bold-contrast: #ffffff;
|
||||
--ion-color-primary-bold-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-bold-shade: #0041c4;
|
||||
--ion-color-primary-bold-tint: #0065ff;
|
||||
--ion-color-primary-subtle: #0054e9;
|
||||
--ion-color-primary-subtle-rgb: 0, 84, 233;
|
||||
--ion-color-primary-subtle-contrast: #ffffff;
|
||||
--ion-color-primary-subtle-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-subtle-shade: #0041c4;
|
||||
--ion-color-primary-subtle-tint: #0065ff;
|
||||
--ion-color-red-50: #ffebee;
|
||||
--ion-color-red-100: #ffcdd2;
|
||||
--ion-color-red-200: #ef9a9a;
|
||||
}
|
||||
}
|
||||
`.replace(/\s/g, '');
|
||||
|
||||
expect(css).toBe(expectedCSS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateComponentThemeCSS', () => {
|
||||
|
||||
@@ -287,9 +287,27 @@ export const generateGlobalThemeCSS = (theme: any): string => {
|
||||
// Generate CSS variables for the dark color palette
|
||||
const darkTokensCSS = generateCSSVars(palette.dark);
|
||||
|
||||
// Include CSS variables for the dark color palette instead of
|
||||
// the light palette if dark palette enabled is 'always'
|
||||
const paletteTokensCSS = palette.dark.enabled === 'always' ? darkTokensCSS : lightTokensCSS;
|
||||
// Generate CSS variable for the high contrast color palette
|
||||
const highContrastTokensCSS = generateCSSVars(palette.highContrast);
|
||||
|
||||
// Generate CSS variable for the high contrast dark color palette
|
||||
const highContrastDarkTokensCSS = generateCSSVars(palette.highContrastDark);
|
||||
|
||||
let paletteTokensCSS = lightTokensCSS;
|
||||
|
||||
if (palette.highContrastDark?.enabled === 'always') {
|
||||
// Include CSS variables for the high contrast dark color palette instead of
|
||||
// the light palette if high contrast dark palette enabled is 'always'
|
||||
paletteTokensCSS = highContrastDarkTokensCSS;
|
||||
} else if (palette.highContrast?.enabled === 'always') {
|
||||
// Include CSS variables for the dark color palette instead of
|
||||
// the light palette if dark palette enabled is 'always'
|
||||
paletteTokensCSS = highContrastTokensCSS;
|
||||
} else if (palette.dark.enabled === 'always') {
|
||||
// Include CSS variables for the dark color palette instead of
|
||||
// the light palette if dark palette enabled is 'always'
|
||||
paletteTokensCSS = darkTokensCSS;
|
||||
}
|
||||
|
||||
let css = `
|
||||
${CSS_ROOT_SELECTOR} {
|
||||
@@ -298,9 +316,25 @@ export const generateGlobalThemeCSS = (theme: any): string => {
|
||||
}
|
||||
`;
|
||||
|
||||
// Include CSS variables for the dark color palette inside of a
|
||||
// class if dark palette enabled is 'class'
|
||||
if (palette.dark.enabled === 'class') {
|
||||
if (palette.highContrastDark.enabled === 'class') {
|
||||
// Include CSS variables for the high contrast dark color palette inside of a
|
||||
// class if high contrast dark palette enabled is 'class'
|
||||
css += `
|
||||
.ion-palette-high-contrast.ion-palette-dark {
|
||||
${highContrastDarkTokensCSS}
|
||||
}
|
||||
`;
|
||||
} else if (palette.highContrast.enabled === 'class') {
|
||||
// Include CSS variables for the high contrast color palette inside of a
|
||||
// class if high contrast palette enabled is 'class'
|
||||
css += `
|
||||
.ion-palette-high-contrast {
|
||||
${highContrastTokensCSS}
|
||||
}
|
||||
`;
|
||||
} else if (palette.dark.enabled === 'class') {
|
||||
// Include CSS variables for the dark color palette inside of a
|
||||
// class if dark palette enabled is 'class'
|
||||
css += `
|
||||
.ion-palette-dark {
|
||||
${darkTokensCSS}
|
||||
@@ -308,9 +342,29 @@ export const generateGlobalThemeCSS = (theme: any): string => {
|
||||
`;
|
||||
}
|
||||
|
||||
// Include CSS variables for the dark color palette inside of the
|
||||
// dark color scheme media query if dark palette enabled is 'system'
|
||||
if (palette.dark.enabled === 'system') {
|
||||
if (palette.highContrastDark.enabled === 'system') {
|
||||
// Include CSS variables for the high contrast dark color palette inside of the
|
||||
// high contrast dark media query if high contrast dark palette enabled is 'system'
|
||||
css += `
|
||||
@media (prefers-contrast: more) and (prefers-color-scheme: dark) {
|
||||
${CSS_ROOT_SELECTOR} {
|
||||
${highContrastDarkTokensCSS}
|
||||
}
|
||||
}
|
||||
`;
|
||||
} else if (palette.highContrast.enabled === 'system') {
|
||||
// Include CSS variables for the high contrast color palette inside of the
|
||||
// high contrast media query if high contrast palette enabled is 'system'
|
||||
css += `
|
||||
@media (prefers-contrast: more) {
|
||||
${CSS_ROOT_SELECTOR} {
|
||||
${highContrastTokensCSS}
|
||||
}
|
||||
}
|
||||
`;
|
||||
} else if (palette.dark.enabled === 'system') {
|
||||
// Include CSS variables for the dark color palette inside of the
|
||||
// dark color scheme media query if dark palette enabled is 'system'
|
||||
css += `
|
||||
@media (prefers-color-scheme: dark) {
|
||||
${CSS_ROOT_SELECTOR} {
|
||||
|
||||