diff --git a/assets/web/css/compound-design-tokens.css b/assets/web/css/compound-design-tokens.css index c992cc60..e18db829 100644 --- a/assets/web/css/compound-design-tokens.css +++ b/assets/web/css/compound-design-tokens.css @@ -1,17 +1,21 @@ -/** - * TODO: Auto-generate this file to allow for dynamic themes to be generated - */ +/* Establish a layer order that allows semantic tokens to be customized, but not base tokens */ +@layer semantic, custom, base; -@import url("./cpd-common.css"); - -@import url("./cpd-light.css") screen; -@import url("./cpd-light-hc.css") screen; -@import url("./cpd-dark.css") screen; -@import url("./cpd-dark-hc.css") screen; - -@import url("./cpd-light-mq.css") screen and (prefers-color-scheme: light); -@import url("./cpd-light-hc-mq.css") screen and (prefers-color-scheme: light) - and (prefers-contrast: more); -@import url("./cpd-dark-mq.css") screen and (prefers-color-scheme: dark); -@import url("./cpd-dark-hc-mq.css") screen and (prefers-color-scheme: dark) and - (prefers-contrast: more); +@import url("./cpd-common-base.css") layer(base) screen; +@import url("./cpd-common-semantic.css") layer(semantic) screen; +@import url("./cpd-theme-light-base.css") layer(base) screen; +@import url("./cpd-theme-light-base-mq.css") layer(base) screen and (prefers-color-scheme: light); +@import url("./cpd-theme-light-semantic.css") layer(semantic) screen; +@import url("./cpd-theme-light-semantic-mq.css") layer(semantic) screen and (prefers-color-scheme: light); +@import url("./cpd-theme-light-hc-base.css") layer(base) screen; +@import url("./cpd-theme-light-hc-base-mq.css") layer(base) screen and (prefers-color-scheme: light) and (prefers-contrast: more); +@import url("./cpd-theme-light-hc-semantic.css") layer(semantic) screen; +@import url("./cpd-theme-light-hc-semantic-mq.css") layer(semantic) screen and (prefers-color-scheme: light) and (prefers-contrast: more); +@import url("./cpd-theme-dark-base.css") layer(base) screen; +@import url("./cpd-theme-dark-base-mq.css") layer(base) screen and (prefers-color-scheme: dark); +@import url("./cpd-theme-dark-semantic.css") layer(semantic) screen; +@import url("./cpd-theme-dark-semantic-mq.css") layer(semantic) screen and (prefers-color-scheme: dark); +@import url("./cpd-theme-dark-hc-base.css") layer(base) screen; +@import url("./cpd-theme-dark-hc-base-mq.css") layer(base) screen and (prefers-color-scheme: dark) and (prefers-contrast: more); +@import url("./cpd-theme-dark-hc-semantic.css") layer(semantic) screen; +@import url("./cpd-theme-dark-hc-semantic-mq.css") layer(semantic) screen and (prefers-color-scheme: dark) and (prefers-contrast: more); diff --git a/assets/web/css/cpd-common.css b/assets/web/css/cpd-common-base.css similarity index 55% rename from assets/web/css/cpd-common.css rename to assets/web/css/cpd-common-base.css index b74b4dd4..ad38c85e 100644 --- a/assets/web/css/cpd-common.css +++ b/assets/web/css/cpd-common-base.css @@ -37,70 +37,6 @@ --cpd-space-6x: 24px; --cpd-space-0x: 0px; --cpd-space-scale: 4px; - --cpd-color-icon-on-solid-primary: var(--cpd-color-theme-bg); - --cpd-color-icon-info-primary: var(--cpd-color-blue-900); - --cpd-color-icon-success-primary: var(--cpd-color-green-900); - --cpd-color-icon-critical-primary: var(--cpd-color-red-900); - --cpd-color-icon-accent-tertiary: var(--cpd-color-green-800); - --cpd-color-icon-quaternary-alpha: var(--cpd-color-alpha-gray-700); - --cpd-color-icon-tertiary-alpha: var(--cpd-color-alpha-gray-800); - --cpd-color-icon-secondary-alpha: var(--cpd-color-alpha-gray-900); - --cpd-color-icon-primary-alpha: var(--cpd-color-alpha-gray-1400); - --cpd-color-icon-disabled: var(--cpd-color-gray-700); - --cpd-color-icon-quaternary: var(--cpd-color-gray-700); - --cpd-color-icon-tertiary: var(--cpd-color-gray-800); - --cpd-color-icon-secondary: var(--cpd-color-gray-900); - --cpd-color-icon-primary: var(--cpd-color-gray-1400); - --cpd-color-border-info-subtle: var(--cpd-color-blue-500); - --cpd-color-border-success-subtle: var(--cpd-color-green-500); - --cpd-color-border-critical-subtle: var(--cpd-color-red-500); - --cpd-color-border-critical-hovered: var(--cpd-color-red-1000); - --cpd-color-border-critical-primary: var(--cpd-color-red-900); - --cpd-color-border-interactive-hovered: var(--cpd-color-gray-1100); - --cpd-color-border-interactive-secondary: var(--cpd-color-gray-600); - --cpd-color-border-interactive-primary: var(--cpd-color-gray-800); - --cpd-color-border-focused: var(--cpd-color-blue-900); - --cpd-color-border-disabled: var(--cpd-color-gray-500); - --cpd-color-bg-decorative-6: var(--cpd-color-alpha-orange-300); - --cpd-color-bg-decorative-5: var(--cpd-color-alpha-pink-300); - --cpd-color-bg-decorative-4: var(--cpd-color-alpha-purple-300); - --cpd-color-bg-decorative-3: var(--cpd-color-alpha-fuchsia-300); - --cpd-color-bg-decorative-2: var(--cpd-color-alpha-cyan-300); - --cpd-color-bg-decorative-1: var(--cpd-color-alpha-lime-300); - --cpd-color-bg-info-subtle: var(--cpd-color-blue-200); - --cpd-color-bg-success-subtle: var(--cpd-color-green-200); - --cpd-color-bg-critical-subtle-hovered: var(--cpd-color-red-300); - --cpd-color-bg-critical-subtle: var(--cpd-color-red-200); - --cpd-color-bg-critical-hovered: var(--cpd-color-red-1000); - --cpd-color-bg-critical-primary: var(--cpd-color-red-900); - --cpd-color-bg-action-secondary-pressed: var(--cpd-color-alpha-gray-300); - --cpd-color-bg-action-secondary-hovered: var(--cpd-color-alpha-gray-200); - --cpd-color-bg-action-secondary-rest: var(--cpd-color-theme-bg); - --cpd-color-bg-action-primary-disabled: var(--cpd-color-gray-700); - --cpd-color-bg-action-primary-pressed: var(--cpd-color-gray-1100); - --cpd-color-bg-action-primary-hovered: var(--cpd-color-gray-1200); - --cpd-color-bg-action-primary-rest: var(--cpd-color-gray-1400); - --cpd-color-bg-canvas-disabled: var(--cpd-color-gray-200); - --cpd-color-bg-canvas-default: var(--cpd-color-theme-bg); - --cpd-color-bg-subtle-secondary: var(--cpd-color-gray-300); - --cpd-color-bg-subtle-primary: var(--cpd-color-gray-400); - --cpd-color-text-decorative-6: var(--cpd-color-orange-1100); - --cpd-color-text-decorative-5: var(--cpd-color-pink-1100); - --cpd-color-text-decorative-4: var(--cpd-color-purple-1100); - --cpd-color-text-decorative-3: var(--cpd-color-fuchsia-1100); - --cpd-color-text-decorative-2: var(--cpd-color-cyan-1100); - --cpd-color-text-decorative-1: var(--cpd-color-lime-1100); - --cpd-color-text-on-solid-primary: var(--cpd-color-theme-bg); - --cpd-color-text-info-primary: var(--cpd-color-blue-900); - --cpd-color-text-success-primary: var(--cpd-color-green-900); - --cpd-color-text-critical-primary: var(--cpd-color-red-900); - --cpd-color-text-link-external: var(--cpd-color-blue-900); - --cpd-color-text-action-accent: var(--cpd-color-green-900); - --cpd-color-text-action-primary: var(--cpd-color-gray-1400); - --cpd-color-text-disabled: var(--cpd-color-gray-800); - --cpd-color-text-placeholder: var(--cpd-color-gray-800); - --cpd-color-text-secondary: var(--cpd-color-gray-900); - --cpd-color-text-primary: var(--cpd-color-gray-1400); --cpd-font-heading-xl-semibold: var(--cpd-font-weight-semibold) var(--cpd-font-size-heading-xl)/var(--cpd-font-line-height-tight) var(--cpd-font-family-sans); --cpd-font-heading-xl-regular: var(--cpd-font-weight-regular) var(--cpd-font-size-heading-xl)/var(--cpd-font-line-height-tight) var(--cpd-font-family-sans); --cpd-font-heading-lg-semibold: var(--cpd-font-weight-semibold) var(--cpd-font-size-heading-lg)/var(--cpd-font-line-height-tight) var(--cpd-font-family-sans); diff --git a/assets/web/css/cpd-common-semantic.css b/assets/web/css/cpd-common-semantic.css new file mode 100644 index 00000000..6c6d3b3c --- /dev/null +++ b/assets/web/css/cpd-common-semantic.css @@ -0,0 +1,66 @@ +:root, [class*="cpd-theme-"] { + --cpd-color-icon-on-solid-primary: var(--cpd-color-theme-bg); + --cpd-color-icon-info-primary: var(--cpd-color-blue-900); + --cpd-color-icon-success-primary: var(--cpd-color-green-900); + --cpd-color-icon-critical-primary: var(--cpd-color-red-900); + --cpd-color-icon-accent-tertiary: var(--cpd-color-green-800); + --cpd-color-icon-quaternary-alpha: var(--cpd-color-alpha-gray-700); + --cpd-color-icon-tertiary-alpha: var(--cpd-color-alpha-gray-800); + --cpd-color-icon-secondary-alpha: var(--cpd-color-alpha-gray-900); + --cpd-color-icon-primary-alpha: var(--cpd-color-alpha-gray-1400); + --cpd-color-icon-disabled: var(--cpd-color-gray-700); + --cpd-color-icon-quaternary: var(--cpd-color-gray-700); + --cpd-color-icon-tertiary: var(--cpd-color-gray-800); + --cpd-color-icon-secondary: var(--cpd-color-gray-900); + --cpd-color-icon-primary: var(--cpd-color-gray-1400); + --cpd-color-border-info-subtle: var(--cpd-color-blue-500); + --cpd-color-border-success-subtle: var(--cpd-color-green-500); + --cpd-color-border-critical-subtle: var(--cpd-color-red-500); + --cpd-color-border-critical-hovered: var(--cpd-color-red-1000); + --cpd-color-border-critical-primary: var(--cpd-color-red-900); + --cpd-color-border-interactive-hovered: var(--cpd-color-gray-1100); + --cpd-color-border-interactive-secondary: var(--cpd-color-gray-600); + --cpd-color-border-interactive-primary: var(--cpd-color-gray-800); + --cpd-color-border-focused: var(--cpd-color-blue-900); + --cpd-color-border-disabled: var(--cpd-color-gray-500); + --cpd-color-bg-decorative-6: var(--cpd-color-alpha-orange-300); + --cpd-color-bg-decorative-5: var(--cpd-color-alpha-pink-300); + --cpd-color-bg-decorative-4: var(--cpd-color-alpha-purple-300); + --cpd-color-bg-decorative-3: var(--cpd-color-alpha-fuchsia-300); + --cpd-color-bg-decorative-2: var(--cpd-color-alpha-cyan-300); + --cpd-color-bg-decorative-1: var(--cpd-color-alpha-lime-300); + --cpd-color-bg-info-subtle: var(--cpd-color-blue-200); + --cpd-color-bg-success-subtle: var(--cpd-color-green-200); + --cpd-color-bg-critical-subtle-hovered: var(--cpd-color-red-300); + --cpd-color-bg-critical-subtle: var(--cpd-color-red-200); + --cpd-color-bg-critical-hovered: var(--cpd-color-red-1000); + --cpd-color-bg-critical-primary: var(--cpd-color-red-900); + --cpd-color-bg-action-secondary-pressed: var(--cpd-color-alpha-gray-300); + --cpd-color-bg-action-secondary-hovered: var(--cpd-color-alpha-gray-200); + --cpd-color-bg-action-secondary-rest: var(--cpd-color-theme-bg); + --cpd-color-bg-action-primary-disabled: var(--cpd-color-gray-700); + --cpd-color-bg-action-primary-pressed: var(--cpd-color-gray-1100); + --cpd-color-bg-action-primary-hovered: var(--cpd-color-gray-1200); + --cpd-color-bg-action-primary-rest: var(--cpd-color-gray-1400); + --cpd-color-bg-canvas-disabled: var(--cpd-color-gray-200); + --cpd-color-bg-canvas-default: var(--cpd-color-theme-bg); + --cpd-color-bg-subtle-secondary: var(--cpd-color-gray-300); + --cpd-color-bg-subtle-primary: var(--cpd-color-gray-400); + --cpd-color-text-decorative-6: var(--cpd-color-orange-1100); + --cpd-color-text-decorative-5: var(--cpd-color-pink-1100); + --cpd-color-text-decorative-4: var(--cpd-color-purple-1100); + --cpd-color-text-decorative-3: var(--cpd-color-fuchsia-1100); + --cpd-color-text-decorative-2: var(--cpd-color-cyan-1100); + --cpd-color-text-decorative-1: var(--cpd-color-lime-1100); + --cpd-color-text-on-solid-primary: var(--cpd-color-theme-bg); + --cpd-color-text-info-primary: var(--cpd-color-blue-900); + --cpd-color-text-success-primary: var(--cpd-color-green-900); + --cpd-color-text-critical-primary: var(--cpd-color-red-900); + --cpd-color-text-link-external: var(--cpd-color-blue-900); + --cpd-color-text-action-accent: var(--cpd-color-green-900); + --cpd-color-text-action-primary: var(--cpd-color-gray-1400); + --cpd-color-text-disabled: var(--cpd-color-gray-800); + --cpd-color-text-placeholder: var(--cpd-color-gray-800); + --cpd-color-text-secondary: var(--cpd-color-gray-900); + --cpd-color-text-primary: var(--cpd-color-gray-1400); +} diff --git a/assets/web/css/cpd-dark-mq.css b/assets/web/css/cpd-theme-dark-base-mq.css similarity index 99% rename from assets/web/css/cpd-dark-mq.css rename to assets/web/css/cpd-theme-dark-base-mq.css index be5d1d28..ee764f48 100644 --- a/assets/web/css/cpd-dark-mq.css +++ b/assets/web/css/cpd-theme-dark-base-mq.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #181a1f; --cpd-color-gray-100: #14171b; --cpd-color-theme-bg: #101317; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); } diff --git a/assets/web/css/cpd-dark.css b/assets/web/css/cpd-theme-dark-base.css similarity index 99% rename from assets/web/css/cpd-dark.css rename to assets/web/css/cpd-theme-dark-base.css index 8be18793..26830618 100644 --- a/assets/web/css/cpd-dark.css +++ b/assets/web/css/cpd-theme-dark-base.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #181a1f; --cpd-color-gray-100: #14171b; --cpd-color-theme-bg: #101317; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); } diff --git a/assets/web/css/cpd-dark-hc-mq.css b/assets/web/css/cpd-theme-dark-hc-base-mq.css similarity index 99% rename from assets/web/css/cpd-dark-hc-mq.css rename to assets/web/css/cpd-theme-dark-hc-base-mq.css index 9ef76e24..7b0fb6a3 100644 --- a/assets/web/css/cpd-dark-hc-mq.css +++ b/assets/web/css/cpd-theme-dark-hc-base-mq.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #1d1f24; --cpd-color-gray-100: #181a1f; --cpd-color-theme-bg: #101317; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); } diff --git a/assets/web/css/cpd-dark-hc.css b/assets/web/css/cpd-theme-dark-hc-base.css similarity index 99% rename from assets/web/css/cpd-dark-hc.css rename to assets/web/css/cpd-theme-dark-hc-base.css index ffa3c3a2..ec807a3b 100644 --- a/assets/web/css/cpd-dark-hc.css +++ b/assets/web/css/cpd-theme-dark-hc-base.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #1d1f24; --cpd-color-gray-100: #181a1f; --cpd-color-theme-bg: #101317; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); } diff --git a/assets/web/css/cpd-theme-dark-hc-semantic-mq.css b/assets/web/css/cpd-theme-dark-hc-semantic-mq.css new file mode 100644 index 00000000..87a2af73 --- /dev/null +++ b/assets/web/css/cpd-theme-dark-hc-semantic-mq.css @@ -0,0 +1,4 @@ +:root { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); +} diff --git a/assets/web/css/cpd-theme-dark-hc-semantic.css b/assets/web/css/cpd-theme-dark-hc-semantic.css new file mode 100644 index 00000000..505191fe --- /dev/null +++ b/assets/web/css/cpd-theme-dark-hc-semantic.css @@ -0,0 +1,4 @@ +.cpd-theme-dark-hc.cpd-theme-dark-hc { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); +} diff --git a/assets/web/css/cpd-theme-dark-semantic-mq.css b/assets/web/css/cpd-theme-dark-semantic-mq.css new file mode 100644 index 00000000..87a2af73 --- /dev/null +++ b/assets/web/css/cpd-theme-dark-semantic-mq.css @@ -0,0 +1,4 @@ +:root { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); +} diff --git a/assets/web/css/cpd-theme-dark-semantic.css b/assets/web/css/cpd-theme-dark-semantic.css new file mode 100644 index 00000000..d1e68dcb --- /dev/null +++ b/assets/web/css/cpd-theme-dark-semantic.css @@ -0,0 +1,4 @@ +.cpd-theme-dark.cpd-theme-dark { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-theme-bg); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-gray-300); +} diff --git a/assets/web/css/cpd-light-mq.css b/assets/web/css/cpd-theme-light-base-mq.css similarity index 99% rename from assets/web/css/cpd-light-mq.css rename to assets/web/css/cpd-theme-light-base-mq.css index 46d79149..2e556e7d 100644 --- a/assets/web/css/cpd-light-mq.css +++ b/assets/web/css/cpd-theme-light-base-mq.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #f7f9fa; --cpd-color-gray-100: #fbfcfd; --cpd-color-theme-bg: #ffffff; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); } diff --git a/assets/web/css/cpd-light.css b/assets/web/css/cpd-theme-light-base.css similarity index 99% rename from assets/web/css/cpd-light.css rename to assets/web/css/cpd-theme-light-base.css index c23ae12b..d065211e 100644 --- a/assets/web/css/cpd-light.css +++ b/assets/web/css/cpd-theme-light-base.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #f7f9fa; --cpd-color-gray-100: #fbfcfd; --cpd-color-theme-bg: #ffffff; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); } diff --git a/assets/web/css/cpd-light-hc-mq.css b/assets/web/css/cpd-theme-light-hc-base-mq.css similarity index 99% rename from assets/web/css/cpd-light-hc-mq.css rename to assets/web/css/cpd-theme-light-hc-base-mq.css index 63b31c77..dabfaf7c 100644 --- a/assets/web/css/cpd-light-hc-mq.css +++ b/assets/web/css/cpd-theme-light-hc-base-mq.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #f0f2f5; --cpd-color-gray-100: #f7f9fa; --cpd-color-theme-bg: #ffffff; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); } diff --git a/assets/web/css/cpd-light-hc.css b/assets/web/css/cpd-theme-light-hc-base.css similarity index 99% rename from assets/web/css/cpd-light-hc.css rename to assets/web/css/cpd-theme-light-hc-base.css index 51c9c431..7d8b4acb 100644 --- a/assets/web/css/cpd-light-hc.css +++ b/assets/web/css/cpd-theme-light-hc-base.css @@ -308,6 +308,4 @@ --cpd-color-gray-200: #f0f2f5; --cpd-color-gray-100: #f7f9fa; --cpd-color-theme-bg: #ffffff; - --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); - --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); } diff --git a/assets/web/css/cpd-theme-light-hc-semantic-mq.css b/assets/web/css/cpd-theme-light-hc-semantic-mq.css new file mode 100644 index 00000000..57194576 --- /dev/null +++ b/assets/web/css/cpd-theme-light-hc-semantic-mq.css @@ -0,0 +1,4 @@ +:root { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); +} diff --git a/assets/web/css/cpd-theme-light-hc-semantic.css b/assets/web/css/cpd-theme-light-hc-semantic.css new file mode 100644 index 00000000..b310d2a1 --- /dev/null +++ b/assets/web/css/cpd-theme-light-hc-semantic.css @@ -0,0 +1,4 @@ +.cpd-theme-light-hc.cpd-theme-light-hc { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); +} diff --git a/assets/web/css/cpd-theme-light-semantic-mq.css b/assets/web/css/cpd-theme-light-semantic-mq.css new file mode 100644 index 00000000..57194576 --- /dev/null +++ b/assets/web/css/cpd-theme-light-semantic-mq.css @@ -0,0 +1,4 @@ +:root { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); +} diff --git a/assets/web/css/cpd-theme-light-semantic.css b/assets/web/css/cpd-theme-light-semantic.css new file mode 100644 index 00000000..b169e31c --- /dev/null +++ b/assets/web/css/cpd-theme-light-semantic.css @@ -0,0 +1,4 @@ +.cpd-theme-light.cpd-theme-light { + --cpd-color-bg-subtle-secondary-level-0: var(--cpd-color-gray-300); + --cpd-color-bg-canvas-default-level-1: var(--cpd-color-theme-bg); +} diff --git a/build.ts b/build.ts index d94818a7..dd2df5d6 100644 --- a/build.ts +++ b/build.ts @@ -19,12 +19,14 @@ import * as setupStyleDictionary from "./src/setupStyleDictionary"; import generateIconTokens from "./src/utils/generateIconTokens"; import fs from "fs-extra"; +import { generateCssIndex } from "./src/utils/generateCssIndex"; const themes: Theme[] = ["light", "light-hc", "dark", "dark-hc"]; const platforms: Platform[] = ["web", "android", "ios"]; (async () => { generateIconTokens(); + generateCssIndex(); for (const platform of platforms) { for (const theme of themes) { const sb = await setupStyleDictionary.themed(theme, platform); diff --git a/src/configs/getWebConfig.ts b/src/configs/getWebConfig.ts index d309d1bb..4fbcb738 100644 --- a/src/configs/getWebConfig.ts +++ b/src/configs/getWebConfig.ts @@ -18,8 +18,10 @@ import { Platform } from "style-dictionary/types/Platform"; import { Theme } from "../@types"; import { File } from "style-dictionary/types/File"; import _ from "lodash"; - -const COMPOUND_TOKENS_NAMESPACE = "cpd"; +import { isSharedAcrossTheme } from "../filters/isSharedAcrossTheme"; +import isCoreToken from "../filters/isCoreToken" +import { isCoreColor } from "../filters/isCoreColor"; +import { COMPOUND_TOKENS_NAMESPACE, cssFileName, Tier } from "../utils/cssFileName"; const basePxFontSize = 16; @@ -73,43 +75,41 @@ function getFilesFormat(theme: Theme, target: "css" | "js" | "ts"): File[] { }, ]; } else { - return [ - { - destination: `${COMPOUND_TOKENS_NAMESPACE}-common.css`, - format: "css/variables", - filter: "isSharedAcrossTheme", - options: { - showFileHeader: false, - outputReferences: true, - basePxFontSize, - selector: `:root, [class*="cpd-theme-"]`, - }, + const common = (tier: Tier): File => ({ + destination: cssFileName(null, tier, false), + format: "css/variables", + filter: t => isSharedAcrossTheme.matcher(t) && isCoreToken.matcher(t) === (tier === 'base'), + options: { + showFileHeader: false, + outputReferences: true, + basePxFontSize, + selector: `:root, [class*="cpd-theme-"]`, }, + }) + + const themed = (tier: Tier, mq: boolean): File => ({ + destination: cssFileName(theme, tier, mq), + format: "css/variables", + filter: t => isCoreColor.matcher(t) && isCoreToken.matcher(t) === (tier === 'base'), + options: { + showFileHeader: false, + outputReferences: true, + selector: mq ? undefined : `.${COMPOUND_TOKENS_NAMESPACE}-theme-${theme}.${COMPOUND_TOKENS_NAMESPACE}-theme-${theme}`, + basePxFontSize, + }, + }) + + return [ + common('base'), + common('semantic'), // Generates the theme under a scoped selector // e.g. .cpd-dark-hc { /* ... */ } - { - destination: `${COMPOUND_TOKENS_NAMESPACE}-${theme}.css`, - format: "css/variables", - filter: "isCoreColor", - options: { - showFileHeader: false, - outputReferences: true, - selector: `.${COMPOUND_TOKENS_NAMESPACE}-theme-${theme}.${COMPOUND_TOKENS_NAMESPACE}-theme-${theme}`, - basePxFontSize, - }, - }, + themed('base', false), + themed('semantic', false), // Generates the theme under the :root // This file is to be imported with a media query import - { - destination: `${COMPOUND_TOKENS_NAMESPACE}-${theme}-mq.css`, - format: "css/variables", - filter: "isCoreColor", - options: { - showFileHeader: false, - outputReferences: true, - basePxFontSize, - }, - }, + themed('base', true), + themed('semantic', true), ]; } } diff --git a/src/setupStyleDictionary.ts b/src/setupStyleDictionary.ts index 01072d52..0472cf5a 100644 --- a/src/setupStyleDictionary.ts +++ b/src/setupStyleDictionary.ts @@ -19,8 +19,6 @@ import { Core } from "style-dictionary"; import { Named } from "style-dictionary/types/_helpers"; import { Transform } from "style-dictionary/types/Transform"; import { registerTransforms } from "@tokens-studio/sd-transforms"; -import * as fs from "fs"; -import * as path from "path"; import camelCaseDecimal from "./transforms/camelCaseDecimal"; import pxToCGFloat from "./transforms/swift/pxToCGFloat"; @@ -48,7 +46,6 @@ import svgToDrawable from "./transforms/kotlin/svgToDrawable"; import iconsImport from "./transforms/css/iconsImport"; import iconTICamel from "./transforms/swift/iconTICamel"; import svgToImageView from "./transforms/swift/svgToImageView"; -import * as lodash from "lodash"; import { isSharedAcrossTheme } from "./filters/isSharedAcrossTheme"; async function setupDictionary(sb: Core) { diff --git a/src/utils/cssFileName.ts b/src/utils/cssFileName.ts new file mode 100644 index 00000000..7c94873f --- /dev/null +++ b/src/utils/cssFileName.ts @@ -0,0 +1,24 @@ +/* +Copyright 2024 New Vector Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Theme } from '../@types' + +export type Tier = 'base' | 'semantic' + +export const COMPOUND_TOKENS_NAMESPACE = "cpd"; + +export const cssFileName = (theme: Theme | null, tier: Tier, mq: boolean) => + `${COMPOUND_TOKENS_NAMESPACE}-${theme === null ? 'common' : `theme-${theme}`}-${tier}${mq ? '-mq' : ''}.css` diff --git a/src/utils/generateCssIndex.ts b/src/utils/generateCssIndex.ts new file mode 100644 index 00000000..4a2863d1 --- /dev/null +++ b/src/utils/generateCssIndex.ts @@ -0,0 +1,49 @@ +/* +Copyright 2024 New Vector Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import fs from 'fs-extra' +import path from 'path' +import { Theme } from '../@types' +import { cssFileName, Tier } from './cssFileName' + +const header = `/* Establish a layer order that allows semantic tokens to be customized, but not base tokens */ +@layer semantic, custom, base;` + +const themes: (Theme | null)[] = [null, 'light', 'light-hc', 'dark', 'dark-hc'] +const tiers: Tier[] = ['base', 'semantic'] + +export function generateCssIndex(): void { + const imports = [...(function* () { + for (const theme of themes) { + for (const tier of tiers) { + for (const mq of theme === null ? [false] : [false, true]) { + let mediaQuery = 'screen' + if (mq) { + mediaQuery += ` and (prefers-color-scheme: ${theme!.includes('light') ? 'light' : 'dark'})` + if (theme!.includes('-hc')) mediaQuery += ` and (prefers-contrast: more)` + } + yield `@import url("./${cssFileName(theme, tier, mq)}") layer(${tier}) ${mediaQuery};` + } + } + } + })()] + + fs.writeFileSync( + path.join('assets', 'web', 'css', 'compound-design-tokens.css'), + `${header}\n\n${imports.join('\n')}\n`, + 'utf-8', + ) +}