From 9b25ed0d7004249bbb5a8b10670658ba0ae8cd82 Mon Sep 17 00:00:00 2001
From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Date: Wed, 26 Mar 2025 10:00:14 -0400
Subject: [PATCH 01/25] feat(css): add support for the subtle color map
---
core/src/themes/functions.color.scss | 172 +++++++++++---
.../src/themes/ionic/ionic.theme.default.scss | 209 +++++++++++++-----
core/src/themes/ionic/test/colors/index.html | 10 +-
.../themes/native/native.theme.default.scss | 109 ++++++---
4 files changed, 371 insertions(+), 129 deletions(-)
diff --git a/core/src/themes/functions.color.scss b/core/src/themes/functions.color.scss
index 702bdf0bcf4..62d1148b02e 100644
--- a/core/src/themes/functions.color.scss
+++ b/core/src/themes/functions.color.scss
@@ -1,3 +1,5 @@
+@use "sass:map";
+
// Set the theme colors map to be used by the color functions
// --------------------------------------------------------------------------------------------
@mixin set-theme-colors($colorsMap) {
@@ -10,11 +12,13 @@
// current-color(base) => var(--ion-color-base)
// current-color(contrast, 0.1) => rgba(var(--ion-color-contrast-rgb), 0.1)
// --------------------------------------------------------------------------------------------
-@function current-color($variation, $alpha: null) {
+@function current-color($variation, $alpha: null, $subtle: false) {
+ $variable: if($subtle, "--ion-color-subtle-#{$variation}", "--ion-color-#{$variation}");
+
@if $alpha == null {
- @return var(--ion-color-#{$variation});
+ @return var(#{$variable});
} @else {
- @return rgba(var(--ion-color-#{$variation}-rgb), #{$alpha});
+ @return rgba(var(#{$variable}-rgb), #{$alpha});
}
}
@@ -25,17 +29,25 @@
// ion-color(secondary, contrast) => var(--ion-color-secondary-contrast)
// ion-color(primary, base, 0.5) => rgba(var(--ion-color-primary-rgb, 56, 128, 255), 0.5)
// --------------------------------------------------------------------------------------------
-@function ion-color($name, $variation, $alpha: null, $rgb: null) {
+@function ion-color($name, $variation, $alpha: null, $rgb: null, $subtle: false) {
@if not($theme-colors) {
@error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color()';
}
- $values: map-get($theme-colors, $name);
- $value: map-get($values, $variation);
- $variable: --ion-color-#{$name}-#{$variation};
+ $values: map.get($theme-colors, $name);
+ $values: map.get($values, if($subtle, subtle, bold));
+
+ $value: map.get($values, $variation);
+
+ // If the color requested is subtle we return `--ion-color-primary-subtle-contrast`
+ // Otherwise we return `--ion-color-primary-contrast`
+ $variable: if($subtle, "--ion-color-#{$name}-subtle-#{$variation}", "--ion-color-#{$name}-#{$variation}");
+ // If the variation being used is base, we do not include the variant so
+ // If the color requested is subtle we return `--ion-color-primary-subtle`
+ // Otherwise we return `--ion-color-primary`
@if ($variation == base) {
- $variable: --ion-color-#{$name};
+ $variable: if($subtle, "--ion-color-#{$name}-subtle", "--ion-color-#{$name}");
}
@if ($alpha) {
@@ -79,43 +91,139 @@
@return #{red($color)}, #{green($color)}, #{blue($color)};
}
-// Generates the color classes and variables
-// based on the colors map
+// Generates color variants for the specified color based on the
+// colors map for whichever hue is passed (bold, subtle).
// --------------------------------------------------------------------------------------------
-@mixin generate-color($color-name) {
+// Example usage (bold):
+// .ion-color-primary {
+// @include generate-color-variants("primary");
+// }
+//
+// Example output (bold):
+// .ion-color-primary {
+// --ion-color-base: var(--ion-color-primary-base, #105cef) !important;
+// --ion-color-base-rgb: var(--ion-color-primary-base-rgb, 16, 92, 239) !important;
+// --ion-color-contrast: var(--ion-color-primary-contrast, #fff) !important;
+// --ion-color-contrast-rgb: var(--ion-color-primary-contrast-rgb, 255, 255, 255) !important;
+// --ion-color-shade: var(--ion-color-primary-shade, #0f54da) !important;
+// --ion-color-tint: var(--ion-color-primary-tint, #94a5f4) !important;
+// }
+// --------------------------------------------------------------------------------------------
+// Example usage (subtle):
+// .ion-color-primary {
+// @include generate-color-variants("primary", "subtle")
+// }
+//
+// Example output (subtle):
+// .ion-color-primary {
+// --ion-color-subtle-base: var(--ion-color-primary-subtle-base, #f2f4fd) !important;
+// --ion-color-subtle-base-rgb: var(--ion-color-primary-subtle-base-rgb, 242, 244, 253) !important;
+// --ion-color-subtle-contrast: var(--ion-color-primary-subtle-contrast, #105cef) !important;
+// --ion-color-subtle-contrast-rgb: var(--ion-color-primary-subtle-contrast-rgb, 16, 92, 239) !important;
+// --ion-color-subtle-shade: var(--ion-color-primary-subtle-shade, #d0d7fa) !important;
+// --ion-color-subtle-tint: var(--ion-color-primary-subtle-tint, #e9ecfc) !important;
+// }
+// --------------------------------------------------------------------------------------------
+@mixin generate-color-variants($color-name, $hue: "bold") {
@if not($theme-colors) {
@error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color()';
}
- $value: map-get($theme-colors, $color-name);
-
- $base: map-get($value, base);
- $contrast: map-get($value, contrast);
- $shade: map-get($value, shade);
- $tint: map-get($value, tint);
+ // Grab the different hue color maps for the
+ // specified color and then grab the map of color variants
+ $hue-colors: map.get($theme-colors, $color-name);
+ $color-variants: map.get($hue-colors, $hue);
+
+ // Determine prefix based on hue value
+ $prefix: if($hue == "subtle", "-subtle", "");
+
+ // TODO this @if can be removed if we add subtle colors for ios and md
+ // Only proceed if the color variants exist
+ @if $color-variants {
+ // Grab the individual color variants
+ $base: map.get($color-variants, base);
+ $base-rgb: map.get($color-variants, base-rgb);
+ $contrast: map.get($color-variants, contrast);
+ $contrast-rgb: map.get($color-variants, contrast-rgb);
+ $shade: map.get($color-variants, shade);
+ $tint: map.get($color-variants, tint);
+
+ // Generate CSS variables dynamically
+ --ion-color#{$prefix}-base: var(--ion-color-#{$color-name}#{$prefix}, #{$base}) !important;
+ --ion-color#{$prefix}-base-rgb: var(--ion-color-#{$color-name}#{$prefix}-rgb, #{$base-rgb}) !important;
+ --ion-color#{$prefix}-contrast: var(--ion-color-#{$color-name}#{$prefix}-contrast, #{$contrast}) !important;
+ --ion-color#{$prefix}-contrast-rgb: var(
+ --ion-color-#{$color-name}#{$prefix}-contrast-rgb,
+ #{$contrast-rgb}
+ ) !important;
+ --ion-color#{$prefix}-shade: var(--ion-color-#{$color-name}#{$prefix}-shade, #{$shade}) !important;
+ --ion-color#{$prefix}-tint: var(--ion-color-#{$color-name}#{$prefix}-tint, #{$tint}) !important;
+ }
+}
- --ion-color-base: var(--ion-color-#{$color-name}, #{$base}) !important;
- --ion-color-base-rgb: var(--ion-color-#{$color-name}-rgb, #{color-to-rgb-list($base)}) !important;
- --ion-color-contrast: var(--ion-color-#{$color-name}-contrast, #{$contrast}) !important;
- --ion-color-contrast-rgb: var(--ion-color-#{$color-name}-contrast-rgb, #{color-to-rgb-list($contrast)}) !important;
- --ion-color-shade: var(--ion-color-#{$color-name}-shade, #{$shade}) !important;
- --ion-color-tint: var(--ion-color-#{$color-name}-tint, #{$tint}) !important;
+// Generates both bold and subtle color variables
+// for the specified color in the colors map.
+// --------------------------------------------------------------------------------------------
+@mixin generate-color($color-name) {
+ @include generate-color-variants($color-name);
+ @include generate-color-variants($color-name, "subtle");
}
-// Generates the CSS variables for each color
-// based on the colors map
+// Generates color variables for all colors in the colors map for both hues (bold, subtle).
+// --------------------------------------------------------------------------------------------
+// Example usage:
+// :root {
+// generate-color-variables()
+// }
+//
+// Example output:
+// :root {
+// --ion-color-primary: #105cef;
+// --ion-color-primary-rgb: 16, 92, 239;
+// --ion-color-primary-contrast: #ffffff;
+// --ion-color-primary-contrast-rgb: 255, 255, 255;
+// --ion-color-primary-shade: #0f54da;
+// --ion-color-primary-tint: #94a5f4;
+// --ion-color-primary-subtle: #f2f4fd;
+// --ion-color-primary-subtle-rgb: 242, 244, 253;
+// --ion-color-primary-subtle-contrast: #105cef;
+// --ion-color-primary-subtle-contrast-rgb: 16, 92, 239;
+// --ion-color-primary-subtle-shade: #d0d7fa;
+// --ion-color-primary-subtle-tint: #e9ecfc;
+// ...
+// --ion-color-dark: #292929;
+// --ion-color-dark-rgb: 41, 41, 41;
+// --ion-color-dark-contrast: #ffffff;
+// --ion-color-dark-contrast-rgb: 255, 255, 255;
+// --ion-color-dark-shade: #242424;
+// --ion-color-dark-tint: #4e4e4e;
+// --ion-color-dark-subtle: #f5f5f5;
+// --ion-color-dark-subtle-rgb: 245, 245, 245;
+// --ion-color-dark-subtle-contrast: #292929;
+// --ion-color-dark-subtle-contrast-rgb: 41, 41, 41;
+// --ion-color-dark-subtle-shade: #e0e0e0;
+// --ion-color-dark-subtle-tint: #efefef;
+// }
// --------------------------------------------------------------------------------------------
@mixin generate-color-variables() {
@if not($theme-colors) {
- @error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color()';
+ @error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color().';
}
@each $color-name, $value in $theme-colors {
- --ion-color-#{$color-name}: #{map-get($value, base)};
- --ion-color-#{$color-name}-rgb: #{color-to-rgb-list(map-get($value, base))};
- --ion-color-#{$color-name}-contrast: #{map-get($value, contrast)};
- --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)};
+ @each $hue in (bold, subtle) {
+ $colors: map.get($value, $hue);
+
+ @if $colors != null {
+ $prefix: if($hue == subtle, "-subtle", "");
+
+ --ion-color-#{$color-name}#{$prefix}: #{map.get($colors, base)};
+ --ion-color-#{$color-name}#{$prefix}-rgb: #{map.get($colors, base-rgb)};
+ --ion-color-#{$color-name}#{$prefix}-contrast: #{map.get($colors, contrast)};
+ --ion-color-#{$color-name}#{$prefix}-contrast-rgb: #{map.get($colors, contrast-rgb)};
+ --ion-color-#{$color-name}#{$prefix}-shade: #{map.get($colors, shade)};
+ --ion-color-#{$color-name}#{$prefix}-tint: #{map.get($colors, tint)};
+ }
+ }
}
}
diff --git a/core/src/themes/ionic/ionic.theme.default.scss b/core/src/themes/ionic/ionic.theme.default.scss
index cd702ae9842..2d77e7a25da 100644
--- a/core/src/themes/ionic/ionic.theme.default.scss
+++ b/core/src/themes/ionic/ionic.theme.default.scss
@@ -10,84 +10,181 @@
// Default Ionic Colors
// -------------------------------------------------------------------------------------------
// Color map should provide
-// - base: main color to be used.
+// - bold: a map of the bold color variations
+// - subtle: a map of the subtle color variations
+//
+// Each hue color map should provide
+// - base: Color that will be primarily used
+// - base-rgb: The base color in rgb format
// - contrast: Color that will provide readable text against the base color
-// - shade: 12% darker version of the base color (mix with black)
-// - tint: 10% lighter version of the base color (mix with white)
+// - contrast-rgb: The contrast color in rgb format
+// - shade: Darker version of the base color
+// - tint: Lighter version of the base color
// TODO(ROU-10778, ROU-10875): Sync the color names to the design system of
// ios and md. This will allow us to have a single color map.
-$primary: #105cef;
-$secondary: initial;
-$tertiary: initial;
-$success: #1fbd3b;
-$warning: #e18300;
-$danger: #bf2222;
-$light: #f2f4fd;
-$medium: initial;
-$neutral: #626262;
-$dark: initial;
-
$ionic-colors: (
primary: (
- base: $primary,
- contrast: #fff,
- shade: color.get-color-shade($primary),
- tint: color.get-color-tint($primary),
+ bold: (
+ base: globals.$ion-semantics-primary-base,
+ base-rgb: globals.$ion-semantics-primary-base-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-semantics-primary-800,
+ tint: globals.$ion-semantics-primary-500,
+ ),
+ subtle: (
+ base: globals.$ion-semantics-primary-100,
+ base-rgb: globals.$ion-semantics-primary-100-rgb,
+ contrast: globals.$ion-semantics-primary-base,
+ contrast-rgb: globals.$ion-semantics-primary-base-rgb,
+ shade: globals.$ion-semantics-primary-300,
+ tint: globals.$ion-semantics-primary-200,
+ ),
),
secondary: (
- base: $secondary,
- contrast: $secondary,
- shade: color.get-color-shade($secondary),
- tint: color.get-color-tint($secondary),
+ bold: (
+ base: globals.$ion-semantics-info-base,
+ base-rgb: globals.$ion-semantics-info-base-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-semantics-info-800,
+ tint: globals.$ion-semantics-info-500,
+ ),
+ subtle: (
+ base: globals.$ion-semantics-info-100,
+ base-rgb: globals.$ion-semantics-info-100-rgb,
+ contrast: globals.$ion-semantics-info-base,
+ contrast-rgb: globals.$ion-semantics-info-base-rgb,
+ shade: globals.$ion-semantics-info-300,
+ tint: globals.$ion-semantics-info-200,
+ ),
),
tertiary: (
- base: $tertiary,
- contrast: $tertiary,
- shade: color.get-color-shade($tertiary),
- tint: color.get-color-tint($tertiary),
+ bold: (
+ base: globals.$ion-primitives-violet-700,
+ base-rgb: globals.$ion-primitives-violet-700-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-primitives-violet-800,
+ tint: globals.$ion-primitives-violet-500,
+ ),
+ subtle: (
+ base: globals.$ion-primitives-violet-100,
+ base-rgb: globals.$ion-primitives-violet-100-rgb,
+ contrast: globals.$ion-primitives-violet-700,
+ contrast-rgb: globals.$ion-primitives-violet-700-rgb,
+ shade: globals.$ion-primitives-violet-300,
+ tint: globals.$ion-primitives-violet-200,
+ ),
),
success: (
- base: $success,
- contrast: #000,
- shade: color.get-color-shade($success),
- tint: color.get-color-tint($success),
+ bold: (
+ base: globals.$ion-semantics-success-base,
+ base-rgb: globals.$ion-semantics-success-base-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-semantics-success-800,
+ tint: globals.$ion-semantics-success-500,
+ ),
+ subtle: (
+ base: globals.$ion-semantics-success-100,
+ base-rgb: globals.$ion-semantics-success-100-rgb,
+ contrast: globals.$ion-semantics-success-base,
+ contrast-rgb: globals.$ion-semantics-success-base-rgb,
+ shade: globals.$ion-semantics-success-300,
+ tint: globals.$ion-semantics-success-200,
+ ),
),
warning: (
- base: $warning,
- contrast: #000,
- shade: color.get-color-shade($warning),
- tint: color.get-color-tint($warning),
+ bold: (
+ base: globals.$ion-semantics-warning-base,
+ base-rgb: globals.$ion-semantics-warning-base-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-semantics-warning-800,
+ tint: globals.$ion-semantics-warning-500,
+ ),
+ subtle: (
+ base: globals.$ion-semantics-warning-100,
+ base-rgb: globals.$ion-semantics-warning-100-rgb,
+ contrast: globals.$ion-semantics-warning-base,
+ contrast-rgb: globals.$ion-semantics-warning-base-rgb,
+ shade: globals.$ion-semantics-warning-300,
+ tint: globals.$ion-semantics-warning-200,
+ ),
),
danger: (
- base: $danger,
- contrast: #fff,
- shade: color.get-color-shade($danger),
- tint: color.get-color-tint($danger),
+ bold: (
+ base: globals.$ion-semantics-danger-base,
+ base-rgb: globals.$ion-semantics-danger-base-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-semantics-danger-800,
+ tint: globals.$ion-semantics-danger-500,
+ ),
+ subtle: (
+ base: globals.$ion-semantics-danger-100,
+ base-rgb: globals.$ion-semantics-danger-100-rgb,
+ contrast: globals.$ion-semantics-danger-base,
+ contrast-rgb: globals.$ion-semantics-danger-base-rgb,
+ shade: globals.$ion-semantics-danger-300,
+ tint: globals.$ion-semantics-danger-200,
+ ),
),
light: (
- base: $light,
- contrast: #000,
- shade: color.get-color-shade($light),
- tint: color.get-color-tint($light),
+ bold: (
+ base: globals.$ion-primitives-neutral-200,
+ base-rgb: globals.$ion-primitives-neutral-200-rgb,
+ contrast: globals.$ion-primitives-base-black,
+ contrast-rgb: globals.$ion-primitives-base-black-rgb,
+ shade: globals.$ion-primitives-neutral-300,
+ tint: globals.$ion-primitives-neutral-100,
+ ),
+ subtle: (
+ base: globals.$ion-primitives-neutral-100,
+ base-rgb: globals.$ion-primitives-neutral-100-rgb,
+ contrast: globals.$ion-primitives-neutral-700,
+ contrast-rgb: globals.$ion-primitives-neutral-700-rgb,
+ shade: globals.$ion-primitives-neutral-300,
+ tint: globals.$ion-primitives-neutral-200,
+ ),
),
medium: (
- base: $medium,
- contrast: $medium,
- shade: color.get-color-shade($medium),
- tint: color.get-color-tint($medium),
- ),
- neutral: (
- base: $neutral,
- contrast: #fff,
- shade: color.get-color-shade($neutral),
- tint: color.get-color-tint($neutral),
+ bold: (
+ base: globals.$ion-primitives-neutral-700,
+ base-rgb: globals.$ion-primitives-neutral-700-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-primitives-neutral-800,
+ tint: globals.$ion-primitives-neutral-500,
+ ),
+ subtle: (
+ base: globals.$ion-primitives-neutral-100,
+ base-rgb: globals.$ion-primitives-neutral-100-rgb,
+ contrast: globals.$ion-primitives-neutral-700,
+ contrast-rgb: globals.$ion-primitives-neutral-700-rgb,
+ shade: globals.$ion-primitives-neutral-300,
+ tint: globals.$ion-primitives-neutral-200,
+ ),
),
dark: (
- base: $dark,
- contrast: $dark,
- shade: color.get-color-shade($dark),
- tint: color.get-color-tint($dark),
+ bold: (
+ base: globals.$ion-primitives-neutral-1100,
+ base-rgb: globals.$ion-primitives-neutral-1100-rgb,
+ contrast: globals.$ion-primitives-base-white,
+ contrast-rgb: globals.$ion-primitives-base-white-rgb,
+ shade: globals.$ion-primitives-neutral-1200,
+ tint: globals.$ion-primitives-neutral-900,
+ ),
+ subtle: (
+ base: globals.$ion-primitives-neutral-100,
+ base-rgb: globals.$ion-primitives-neutral-100-rgb,
+ contrast: globals.$ion-primitives-neutral-1100,
+ contrast-rgb: globals.$ion-primitives-neutral-1100-rgb,
+ shade: globals.$ion-primitives-neutral-300,
+ tint: globals.$ion-primitives-neutral-200,
+ ),
),
);
diff --git a/core/src/themes/ionic/test/colors/index.html b/core/src/themes/ionic/test/colors/index.html
index 5f990e1fe12..759bfee4ac4 100644
--- a/core/src/themes/ionic/test/colors/index.html
+++ b/core/src/themes/ionic/test/colors/index.html
@@ -7,11 +7,11 @@
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
-
-
-
-
-
+
+
+
+
+