diff --git a/packages/components/docs/sass.md b/packages/components/docs/sass.md
index 88111c2b1c06..4900b81535c9 100644
--- a/packages/components/docs/sass.md
+++ b/packages/components/docs/sass.md
@@ -3642,7 +3642,7 @@ Define theme variables from a map of tokens
Source code
```scss
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -3702,6 +3702,67 @@ Define theme variables from a map of tokens
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
@@ -3714,9 +3775,10 @@ Define theme variables from a map of tokens
- **Parameters**:
-| Name | Description | Type | Default value |
-| -------- | ------------------- | ----- | ---------------- |
-| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| Name | Description | Type | Default value |
+| ------------------------- | --------------------------------------------- | ------ | ---------------- |
+| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| `$emit-custom-properties` | Output CSS Custom Properties for theme tokens | `Bool` | `false` |
**Example**:
diff --git a/packages/components/src/globals/scss/vendor/@carbon/elements/scss/themes/_mixins.scss b/packages/components/src/globals/scss/vendor/@carbon/elements/scss/themes/_mixins.scss
index 572640299360..2f38345a1f9c 100644
--- a/packages/components/src/globals/scss/vendor/@carbon/elements/scss/themes/_mixins.scss
+++ b/packages/components/src/globals/scss/vendor/@carbon/elements/scss/themes/_mixins.scss
@@ -9,6 +9,7 @@
/// Define theme variables from a map of tokens
/// @access public
/// @param {Map} $theme [$carbon--theme] - Map of theme tokens
+/// @param {Bool} $emit-custom-properties [false] - Output CSS Custom Properties for theme tokens
/// @content Pass in your custom declaration blocks to be used after the token maps set theming variables.
///
/// @example scss
@@ -28,7 +29,7 @@
/// }
///
/// @group @carbon/themes
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -88,6 +89,67 @@
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
diff --git a/packages/components/src/globals/scss/vendor/@carbon/themes/scss/_mixins.scss b/packages/components/src/globals/scss/vendor/@carbon/themes/scss/_mixins.scss
index 572640299360..2f38345a1f9c 100644
--- a/packages/components/src/globals/scss/vendor/@carbon/themes/scss/_mixins.scss
+++ b/packages/components/src/globals/scss/vendor/@carbon/themes/scss/_mixins.scss
@@ -9,6 +9,7 @@
/// Define theme variables from a map of tokens
/// @access public
/// @param {Map} $theme [$carbon--theme] - Map of theme tokens
+/// @param {Bool} $emit-custom-properties [false] - Output CSS Custom Properties for theme tokens
/// @content Pass in your custom declaration blocks to be used after the token maps set theming variables.
///
/// @example scss
@@ -28,7 +29,7 @@
/// }
///
/// @group @carbon/themes
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -88,6 +89,67 @@
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
diff --git a/packages/elements/docs/sass.md b/packages/elements/docs/sass.md
index 77de23fb2a8d..6638848c9f53 100644
--- a/packages/elements/docs/sass.md
+++ b/packages/elements/docs/sass.md
@@ -3291,7 +3291,7 @@ Define theme variables from a map of tokens
Source code
```scss
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -3351,6 +3351,67 @@ Define theme variables from a map of tokens
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
@@ -3363,9 +3424,10 @@ Define theme variables from a map of tokens
- **Parameters**:
-| Name | Description | Type | Default value |
-| -------- | ------------------- | ----- | ---------------- |
-| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| Name | Description | Type | Default value |
+| ------------------------- | --------------------------------------------- | ------ | ---------------- |
+| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| `$emit-custom-properties` | Output CSS Custom Properties for theme tokens | `Bool` | `false` |
**Example**:
diff --git a/packages/scss-generator/src/types/definitions.js b/packages/scss-generator/src/types/definitions.js
index 2f7f19bf5782..43decfd23d29 100644
--- a/packages/scss-generator/src/types/definitions.js
+++ b/packages/scss-generator/src/types/definitions.js
@@ -372,14 +372,19 @@ const Declaration = defineType('Declaration', {
validate: assertValueType('string'),
},
value: {
- validate: assertValueType('string'),
+ validate: () =>
+ assertOneOf([assertValueType('string'), assertType(CallExpression)]),
},
},
generate(printer, node) {
printer.token(node.property);
printer.token(':');
printer.space();
- printer.token(node.value);
+ if (typeof node.value === 'string') {
+ printer.token(node.value);
+ } else {
+ printer.print(node.value);
+ }
printer.token(';');
},
});
diff --git a/packages/themes/docs/sass.md b/packages/themes/docs/sass.md
index 9038285fcb34..d8e90349d326 100644
--- a/packages/themes/docs/sass.md
+++ b/packages/themes/docs/sass.md
@@ -86,7 +86,7 @@ Define theme variables from a map of tokens
Source code
```scss
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -146,6 +146,67 @@ Define theme variables from a map of tokens
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
@@ -158,9 +219,10 @@ Define theme variables from a map of tokens
- **Parameters**:
-| Name | Description | Type | Default value |
-| -------- | ------------------- | ----- | ---------------- |
-| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| Name | Description | Type | Default value |
+| ------------------------- | --------------------------------------------- | ------ | ---------------- |
+| `$theme` | Map of theme tokens | `Map` | `$carbon--theme` |
+| `$emit-custom-properties` | Output CSS Custom Properties for theme tokens | `Bool` | `false` |
**Example**:
diff --git a/packages/themes/examples/preview/index.js b/packages/themes/examples/preview/index.js
index b614c64f019b..cfd01beaf4db 100644
--- a/packages/themes/examples/preview/index.js
+++ b/packages/themes/examples/preview/index.js
@@ -5,7 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
-import React from 'react';
+import cx from 'classnames';
+import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import * as colors from '@carbon/colors';
import { themes, formatTokenName } from '@carbon/themes';
@@ -44,6 +45,9 @@ function App() {
Theming
+
+ Custom Properties
+
@@ -229,8 +233,54 @@ $custom-theme: map-merge(
+
);
}
+function ThemeSwitcher() {
+ const [theme, setTheme] = useState('white');
+ const className = cx({
+ 'theme--white': theme === 'white',
+ 'theme--g10': theme === 'g10',
+ 'theme--g90': theme === 'g90',
+ 'theme--g100': theme === 'g100',
+ });
+
+ return (
+
+
+
+
Custom Properties
+
+
+
+
+
Current theme: {theme}
+
+
Change theme
+
+
+
+
+
+
+
Tokens
+ {['field-01', 'field-02', 'inverse-01', 'inverse-02'].map(token => (
+
+ {token}
+
+ ))}
+
+
+
+
+ );
+}
+
+
render();
diff --git a/packages/themes/examples/preview/package.json b/packages/themes/examples/preview/package.json
index af14f6a220e1..0ebe49a38190 100644
--- a/packages/themes/examples/preview/package.json
+++ b/packages/themes/examples/preview/package.json
@@ -8,6 +8,7 @@
"develop": "parcel index.html --no-cache"
},
"dependencies": {
+ "classnames": "^2.2.6",
"parcel-bundler": "^1.12.2",
"react": "^16.8.4",
"react-dom": "^16.8.4"
diff --git a/packages/themes/examples/preview/styles.scss b/packages/themes/examples/preview/styles.scss
index dda5759b8c71..12302cb295a6 100644
--- a/packages/themes/examples/preview/styles.scss
+++ b/packages/themes/examples/preview/styles.scss
@@ -107,3 +107,16 @@ $custom-theme: map-merge(
@include my-custom-token-component();
}
}
+
+.theme--white {
+ @include carbon--theme($carbon--theme--white, true);
+}
+.theme--g10 {
+ @include carbon--theme($carbon--theme--g10, true);
+}
+.theme--g90 {
+ @include carbon--theme($carbon--theme--g90, true);
+}
+.theme--g100 {
+ @include carbon--theme($carbon--theme--g100, true);
+}
diff --git a/packages/themes/examples/preview/yarn.lock b/packages/themes/examples/preview/yarn.lock
index b3d79cf36e19..c50c5118188a 100644
--- a/packages/themes/examples/preview/yarn.lock
+++ b/packages/themes/examples/preview/yarn.lock
@@ -1236,6 +1236,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classnames@^2.2.6:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+ integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
+
cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
diff --git a/packages/themes/scss/_mixins.scss b/packages/themes/scss/_mixins.scss
index 572640299360..2f38345a1f9c 100644
--- a/packages/themes/scss/_mixins.scss
+++ b/packages/themes/scss/_mixins.scss
@@ -9,6 +9,7 @@
/// Define theme variables from a map of tokens
/// @access public
/// @param {Map} $theme [$carbon--theme] - Map of theme tokens
+/// @param {Bool} $emit-custom-properties [false] - Output CSS Custom Properties for theme tokens
/// @content Pass in your custom declaration blocks to be used after the token maps set theming variables.
///
/// @example scss
@@ -28,7 +29,7 @@
/// }
///
/// @group @carbon/themes
-@mixin carbon--theme($theme: $carbon--theme) {
+@mixin carbon--theme($theme: $carbon--theme, $emit-custom-properties: false) {
$interactive-01: map-get($theme, 'interactive-01') !global;
$interactive-02: map-get($theme, 'interactive-02') !global;
$interactive-03: map-get($theme, 'interactive-03') !global;
@@ -88,6 +89,67 @@
$active-01: map-get($theme, 'active-01') !global;
$hover-field: map-get($theme, 'hover-field') !global;
+ @if $emit-custom-properties == true {
+ --interactive-01: #{map-get($theme, 'interactive-01')};
+ --interactive-02: #{map-get($theme, 'interactive-02')};
+ --interactive-03: #{map-get($theme, 'interactive-03')};
+ --interactive-04: #{map-get($theme, 'interactive-04')};
+ --ui-background: #{map-get($theme, 'ui-background')};
+ --ui-01: #{map-get($theme, 'ui-01')};
+ --ui-02: #{map-get($theme, 'ui-02')};
+ --ui-03: #{map-get($theme, 'ui-03')};
+ --ui-04: #{map-get($theme, 'ui-04')};
+ --ui-05: #{map-get($theme, 'ui-05')};
+ --text-01: #{map-get($theme, 'text-01')};
+ --text-02: #{map-get($theme, 'text-02')};
+ --text-03: #{map-get($theme, 'text-03')};
+ --text-04: #{map-get($theme, 'text-04')};
+ --icon-01: #{map-get($theme, 'icon-01')};
+ --icon-02: #{map-get($theme, 'icon-02')};
+ --icon-03: #{map-get($theme, 'icon-03')};
+ --link-01: #{map-get($theme, 'link-01')};
+ --field-01: #{map-get($theme, 'field-01')};
+ --field-02: #{map-get($theme, 'field-02')};
+ --inverse-01: #{map-get($theme, 'inverse-01')};
+ --inverse-02: #{map-get($theme, 'inverse-02')};
+ --support-01: #{map-get($theme, 'support-01')};
+ --support-02: #{map-get($theme, 'support-02')};
+ --support-03: #{map-get($theme, 'support-03')};
+ --support-04: #{map-get($theme, 'support-04')};
+ --inverse-support-01: #{map-get($theme, 'inverse-support-01')};
+ --inverse-support-02: #{map-get($theme, 'inverse-support-02')};
+ --inverse-support-03: #{map-get($theme, 'inverse-support-03')};
+ --inverse-support-04: #{map-get($theme, 'inverse-support-04')};
+ --overlay-01: #{map-get($theme, 'overlay-01')};
+ --focus: #{map-get($theme, 'focus')};
+ --hover-primary: #{map-get($theme, 'hover-primary')};
+ --active-primary: #{map-get($theme, 'active-primary')};
+ --hover-primary-text: #{map-get($theme, 'hover-primary-text')};
+ --hover-secondary: #{map-get($theme, 'hover-secondary')};
+ --active-secondary: #{map-get($theme, 'active-secondary')};
+ --hover-tertiary: #{map-get($theme, 'hover-tertiary')};
+ --active-tertiary: #{map-get($theme, 'active-tertiary')};
+ --hover-ui: #{map-get($theme, 'hover-ui')};
+ --active-ui: #{map-get($theme, 'active-ui')};
+ --selected-ui: #{map-get($theme, 'selected-ui')};
+ --hover-selected-ui: #{map-get($theme, 'hover-selected-ui')};
+ --hover-danger: #{map-get($theme, 'hover-danger')};
+ --active-danger: #{map-get($theme, 'active-danger')};
+ --hover-row: #{map-get($theme, 'hover-row')};
+ --visited-link: #{map-get($theme, 'visited-link')};
+ --disabled-01: #{map-get($theme, 'disabled-01')};
+ --disabled-02: #{map-get($theme, 'disabled-02')};
+ --disabled-03: #{map-get($theme, 'disabled-03')};
+ --highlight: #{map-get($theme, 'highlight')};
+ --skeleton-01: #{map-get($theme, 'skeleton-01')};
+ --skeleton-02: #{map-get($theme, 'skeleton-02')};
+ --brand-01: #{map-get($theme, 'brand-01')};
+ --brand-02: #{map-get($theme, 'brand-02')};
+ --brand-03: #{map-get($theme, 'brand-03')};
+ --active-01: #{map-get($theme, 'active-01')};
+ --hover-field: #{map-get($theme, 'hover-field')};
+ }
+
@content;
// Reset to default theme after apply in content
@if $theme != $carbon--theme {
diff --git a/packages/themes/tasks/build.js b/packages/themes/tasks/build.js
index 4937f9be2738..fbba066fcfa1 100644
--- a/packages/themes/tasks/build.js
+++ b/packages/themes/tasks/build.js
@@ -74,6 +74,7 @@ async function build() {
t.Comment(`/ Define theme variables from a map of tokens
/ @access public
/ @param {Map} $theme [$${defaultThemeMapName}] - Map of theme tokens
+/ @param {Bool} $emit-custom-properties [false] - Output CSS Custom Properties for theme tokens
/ @content Pass in your custom declaration blocks to be used after the token maps set theming variables.
/
/ @example scss
@@ -100,6 +101,10 @@ async function build() {
left: t.Identifier('theme'),
right: t.Identifier(defaultThemeMapName),
}),
+ t.AssignmentPattern({
+ left: t.Identifier('emit-custom-properties'),
+ right: t.SassBoolean(false),
+ }),
],
body: t.BlockStatement({
body: [
@@ -115,6 +120,22 @@ async function build() {
global: true,
});
}),
+ t.IfStatement({
+ test: t.LogicalExpression({
+ left: t.Identifier('emit-custom-properties'),
+ operator: '==',
+ right: t.SassBoolean(true),
+ }),
+ consequent: t.BlockStatement(
+ tokenColors.map(token => {
+ const name = formatTokenName(token);
+ return t.Declaration({
+ property: `--${name}`,
+ value: `#{map-get($theme, '${name}')}`,
+ });
+ })
+ ),
+ }),
t.AtContent(),
t.Comment(' Reset to default theme after apply in content'),
t.IfStatement({