Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
06f42b0
test(utils): move spec tests into test
brandyscarney Sep 23, 2025
f565952
test(themes): add basic, color and typography tests
brandyscarney Sep 23, 2025
58b006d
feat(themes): define base tokens, color functions and interfaces
brandyscarney Sep 23, 2025
5435bb7
feat(themes): remove old $colors map and functions and use new tokens
brandyscarney Sep 23, 2025
2183a24
style: lint
brandyscarney Sep 23, 2025
81e8418
fix(theme): update foreground to use proper vars and fix test
brandyscarney Sep 23, 2025
f74883d
fix(theme): don't generate rgb variables for component level overrides
brandyscarney Sep 23, 2025
82d4b82
fix(theme): use proper contrast colors
brandyscarney Sep 24, 2025
783b653
fix(themes): do not fallback to base color for foreground
brandyscarney Sep 24, 2025
92ba2c0
fix(themes): update dark palette support for other enabled values
brandyscarney Sep 24, 2025
fe5936c
docs(themes): update the examples of the ion-color function
brandyscarney Sep 24, 2025
c282d3e
refactor(themes): remove the default font family for now as it confli…
brandyscarney Sep 24, 2025
e00a7b3
fix(themes): enforce foreground as a required variant
brandyscarney Sep 25, 2025
f5bb210
test(themes): remove outdated test and
brandyscarney Sep 25, 2025
1acb123
fix(themes): set the ionic colors to avoid screenshot diffs
brandyscarney Sep 25, 2025
d7470aa
test(themes): skip failing a11y tests until we finalize colors
brandyscarney Sep 25, 2025
768cfa8
chore(theme): add warnings for an invalid color value and tests
brandyscarney Sep 29, 2025
88ff275
refactor(theme): split parseHex out to a reusable function and adds t…
brandyscarney Sep 29, 2025
fbe7afb
test(theme): add scoped element test
brandyscarney Sep 29, 2025
dab8950
test(theme): add checks for the warning messages
brandyscarney Sep 29, 2025
ca30f10
test(theme): handle mixed digit hex colors and mixed hash usage
brandyscarney Sep 29, 2025
b395238
chore(): add updated snapshots (#30699)
brandyscarney Oct 1, 2025
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
1 change: 1 addition & 0 deletions core/scripts/testing/styles.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 0 additions & 18 deletions core/src/css/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,6 @@
@import "../components/menu/menu.md.vars";
@import "../components/modal/modal.native.vars";

// Ionic Colors
// --------------------------------------------------

:root {
/**
* Set the theme colors from the
* `native.theme.default.scss` file.
*/
@include set-theme-colors($colors);
@include generate-color-variables();

@each $color-name, $value in $colors {
.ion-color-#{$color-name} {
@include generate-color($color-name);
}
}
}

// Ionic Font Family
// --------------------------------------------------

Expand Down
13 changes: 0 additions & 13 deletions core/src/css/ionic/core.ionic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,6 @@
// --------------------------------------------------

:root {
/**
* Set the theme colors from the
* `ionic.theme.default.scss` file.
*/
@include globals.set-theme-colors(globals.$ionic-colors);
@include globals.generate-color-variables();

@each $color-name, $value in globals.$ionic-colors {
.ion-color-#{$color-name} {
@include globals.generate-color($color-name);
}
}

/* Default background color of all components to default background surface token */
--background: #{globals.$ion-bg-surface-default};
}
Expand Down
1 change: 1 addition & 0 deletions core/src/css/palettes/dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ $colors: (
--ion-color-#{$color-name}-contrast-rgb: #{color-to-rgb-list(map.get($value, contrast))};
--ion-color-#{$color-name}-shade: #{map.get($value, shade)};
--ion-color-#{$color-name}-tint: #{map.get($value, tint)};
--ion-color-#{$color-name}-foreground: #{map.get($value, foreground)};
}
}
}
Expand Down
1 change: 1 addition & 0 deletions core/src/css/palettes/high-contrast-dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ $lightest-text-color: $text-color;
--ion-color-#{$color-name}-contrast-rgb: #{color-to-rgb-list(map.get($value, contrast))};
--ion-color-#{$color-name}-shade: #{map.get($value, shade)};
--ion-color-#{$color-name}-tint: #{map.get($value, tint)};
--ion-color-#{$color-name}-foreground: #{map.get($value, foreground)};
}
}
}
Expand Down
1 change: 1 addition & 0 deletions core/src/css/palettes/high-contrast.scss
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ $lightest-text-color: #888888;
--ion-color-#{$color-name}-contrast-rgb: #{color-to-rgb-list(map.get($value, contrast))};
--ion-color-#{$color-name}-shade: #{map.get($value, shade)};
--ion-color-#{$color-name}-tint: #{map.get($value, tint)};
--ion-color-#{$color-name}-foreground: #{map.get($value, foreground)};
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion core/src/global/ionic-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { applyGlobalTheme, getCustomTheme } from '@utils/theme';

import type { IonicConfig, Mode, Theme } from '../interface';
import { defaultTheme as baseTheme } from '../themes/base/default.tokens';
import type { Theme as BaseTheme } from '../themes/base/default.tokens';
import { defaultTheme as ionicTheme } from '../themes/ionic/default.tokens';
import type { BaseTheme } from '../themes/themes.interfaces';
import { shouldUseCloseWatcher } from '../utils/hardware-back-button';
import { isPlatform, setupPlatforms } from '../utils/platform';

Expand Down Expand Up @@ -157,6 +158,11 @@ export const initialize = (userConfig: IonicConfig = {}) => {
applyGlobalTheme(baseTheme);
}

// TODO(): remove this when we update the ionic theme
if (defaultTheme === 'ionic') {
applyGlobalTheme(ionicTheme);
}

if (config.getBoolean('_testing')) {
config.set('animated', false);
}
Expand Down
164 changes: 164 additions & 0 deletions core/src/themes/base/dark.tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { mix } from '../../utils/theme';
import type { DarkTheme } from '../themes.interfaces';

const colors = {
primary: '#4d8dff',
secondary: '#46b1ff',
tertiary: '#8482fb',
success: '#2dd55b',
warning: '#ffce31',
danger: '#f24c58',
light: '#222428',
medium: '#989aa2',
dark: '#f4f5f8',
};

export const darkTheme: DarkTheme = {
enabled: 'never',
color: {
primary: {
bold: {
base: colors.primary,
contrast: '#000',
foreground: mix(colors.primary, '#000', '4%'),
shade: mix(colors.primary, '#000', '4%'),
tint: mix(colors.primary, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.primary, '8%'),
contrast: colors.primary,
foreground: mix(colors.primary, '#000', '4%'),
shade: mix('#000', colors.primary, '4%'),
tint: mix('#000', colors.primary, '12%'),
},
},
secondary: {
bold: {
base: colors.secondary,
contrast: '#000',
foreground: mix(colors.secondary, '#000', '4%'),
shade: mix(colors.secondary, '#000', '4%'),
tint: mix(colors.secondary, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.secondary, '8%'),
contrast: colors.secondary,
foreground: mix(colors.secondary, '#000', '4%'),
shade: mix('#000', colors.secondary, '4%'),
tint: mix('#000', colors.secondary, '12%'),
},
},
tertiary: {
bold: {
base: colors.tertiary,
contrast: '#000',
foreground: mix(colors.tertiary, '#000', '4%'),
shade: mix(colors.tertiary, '#000', '4%'),
tint: mix(colors.tertiary, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.tertiary, '8%'),
contrast: colors.tertiary,
foreground: mix(colors.tertiary, '#000', '4%'),
shade: mix('#000', colors.tertiary, '4%'),
tint: mix('#000', colors.tertiary, '12%'),
},
},
success: {
bold: {
base: colors.success,
contrast: '#000',
foreground: mix(colors.success, '#000', '4%'),
shade: mix(colors.success, '#000', '4%'),
tint: mix(colors.success, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.success, '8%'),
contrast: colors.success,
foreground: mix(colors.success, '#000', '4%'),
shade: mix('#000', colors.success, '4%'),
tint: mix('#000', colors.success, '12%'),
},
},
warning: {
bold: {
base: colors.warning,
contrast: '#000',
foreground: mix(colors.warning, '#000', '4%'),
shade: mix(colors.warning, '#000', '4%'),
tint: mix(colors.warning, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.warning, '8%'),
contrast: colors.warning,
foreground: mix(colors.warning, '#000', '4%'),
shade: mix('#000', colors.warning, '4%'),
tint: mix('#000', colors.warning, '12%'),
},
},
danger: {
bold: {
base: colors.danger,
contrast: '#000',
foreground: mix(colors.danger, '#000', '4%'),
shade: mix(colors.danger, '#000', '4%'),
tint: mix(colors.danger, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.danger, '8%'),
contrast: colors.danger,
foreground: mix(colors.danger, '#000', '4%'),
shade: mix('#000', colors.danger, '4%'),
tint: mix('#000', colors.danger, '12%'),
},
},
light: {
bold: {
base: colors.light,
contrast: '#fff',
foreground: mix(colors.light, '#000', '4%'),
shade: mix(colors.light, '#000', '4%'),
tint: mix(colors.light, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.light, '8%'),
contrast: colors.light,
foreground: mix(colors.light, '#000', '4%'),
shade: mix('#000', colors.light, '4%'),
tint: mix('#000', colors.light, '12%'),
},
},
medium: {
bold: {
base: colors.medium,
contrast: '#000',
foreground: mix(colors.medium, '#000', '4%'),
shade: mix(colors.medium, '#000', '4%'),
tint: mix(colors.medium, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.medium, '8%'),
contrast: colors.medium,
foreground: mix(colors.medium, '#000', '4%'),
shade: mix('#000', colors.medium, '4%'),
tint: mix('#000', colors.medium, '12%'),
},
},
dark: {
bold: {
base: colors.dark,
contrast: '#000',
foreground: mix(colors.dark, '#000', '4%'),
shade: mix(colors.dark, '#000', '4%'),
tint: mix(colors.dark, '#fff', '12%'),
},
subtle: {
base: mix('#000', colors.dark, '8%'),
contrast: colors.dark,
foreground: mix(colors.dark, '#000', '4%'),
shade: mix('#000', colors.dark, '4%'),
tint: mix('#000', colors.dark, '12%'),
},
},
},
};
104 changes: 97 additions & 7 deletions core/src/themes/base/default.tokens.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,100 @@
export const defaultTheme = {
import type { DefaultTheme } from '../themes.interfaces';

import { darkTheme } from './dark.tokens';
import { lightTheme } from './light.tokens';

export const defaultTheme: DefaultTheme = {
palette: {
light: {},
dark: {
enabled: 'system',
},
light: lightTheme,
dark: darkTheme,
},

spacing: {
none: '0',
xxs: '4px',
xs: '6px',
sm: '8px',
md: '12px',
lg: '16px',
xl: '24px',
xxl: '32px',
},

scaling: {
0: '0',
100: '4px',
150: '6px',
200: '8px',
250: '10px',
300: '12px',
350: '14px',
400: '16px',
450: '18px',
500: '20px',
550: '22px',
600: '24px',
650: '26px',
700: '28px',
750: '30px',
800: '32px',
850: '34px',
900: '36px',
},

borderWidth: {
none: '0',
xxs: '1px',
xs: '2px',
sm: '4px',
md: '6px',
lg: '8px',
xl: '10px',
xxl: '12px',
},
};

export type Theme = typeof defaultTheme;
radii: {
none: '0',
xxs: '1px',
xs: '2px',
sm: '4px',
md: '8px',
lg: '12px',
xl: '16px',
xxl: '32px',
},

dynamicFont: '-apple-system-body',

fontSize: {
root: '16px',
xxs: '10px',
xs: '12px',
sm: '14px',
md: '16px',
lg: '18px',
xl: '20px',
xxl: '24px',
},

fontWeight: {
thin: '100',
extraLight: '200',
light: '300',
normal: '400',
medium: '500',
semiBold: '600',
bold: '700',
extraBold: '800',
black: '900',
},

lineHeight: {
xxs: '1',
xs: '1.2',
sm: '1.4',
md: '1.6',
lg: '1.8',
xl: '2',
xxl: '2.4',
},
};
Loading
Loading