diff --git a/addons/rose/addon/styles/addon.scss b/addons/rose/addon/styles/addon.scss index 16d19db6c..bd18ab6c2 100644 --- a/addons/rose/addon/styles/addon.scss +++ b/addons/rose/addon/styles/addon.scss @@ -1 +1,2 @@ @import '@hashicorp/design-system-components'; +@import 'hds/themes/dark-mode'; diff --git a/addons/rose/addon/styles/hds/themes/dark-mode/_color-tokens-tier-2.scss b/addons/rose/addon/styles/hds/themes/dark-mode/_color-tokens-tier-2.scss new file mode 100644 index 000000000..6027a26a8 --- /dev/null +++ b/addons/rose/addon/styles/hds/themes/dark-mode/_color-tokens-tier-2.scss @@ -0,0 +1,162 @@ +// Second-tier token mappings to first-tier color tokens. In HDS, these are +// hard-coded in raw hex values, duplicating the first-tier colors. In order +// to simplify theming, these are refactored here to eliminate duplication. +.ember-application { + --token-color-border-primary: var(--token-color-palette-alpha-200); + --token-color-border-faint: var(--token-color-palette-alpha-100); + --token-color-border-strong: var(--token-color-palette-alpha-300); + --token-color-border-action: var(--token-color-palette-blue-100); + --token-color-border-highlight: var(--token-color-palette-purple-100); + --token-color-border-success: var(--token-color-palette-green-100); + --token-color-border-warning: var(--token-color-palette-amber-100); + --token-color-border-critical: var(--token-color-palette-red-100); + --token-color-focus-action-internal: var(--token-color-palette-blue-300); + // --token-color-focus-action-external: #5990ff; /* this is a special color used only for the focus style, to pass color contrast for a11y purpose */ + --token-color-focus-critical-internal: var(--token-color-palette-red-300); + // --token-color-focus-critical-external: #dd7578; /* this is a special color used only for the focus style, to pass color contrast for a11y purpose */ + --token-color-foreground-strong: var(--token-color-palette-neutral-700); + --token-color-foreground-primary: var(--token-color-palette-neutral-600); + --token-color-foreground-faint: var(--token-color-palette-neutral-500); + --token-color-foreground-high-contrast: var(--token-color-palette-neutral-0); + --token-color-foreground-disabled: var(--token-color-palette-neutral-400); + --token-color-foreground-action: var(--token-color-palette-blue-200); + --token-color-foreground-action-hover: var(--token-color-palette-blue-300); + --token-color-foreground-action-active: var(--token-color-palette-blue-400); + --token-color-foreground-highlight: var(--token-color-palette-purple-200); + --token-color-foreground-highlight-on-surface: var(--token-color-palette-purple-300); + --token-color-foreground-highlight-high-contrast: var(--token-color-palette-purple-500); + --token-color-foreground-success: var(--token-color-palette-green-200); + --token-color-foreground-success-on-surface: var(--token-color-palette-green-300); + --token-color-foreground-success-high-contrast: var(--token-color-palette-green-500); + --token-color-foreground-warning: var(--token-color-palette-amber-200); + --token-color-foreground-warning-on-surface: var(--token-color-palette-amber-300); + --token-color-foreground-warning-high-contrast: var(--token-color-palette-amber-500); + --token-color-foreground-critical: var(--token-color-palette-red-200); + --token-color-foreground-critical-on-surface: var(--token-color-palette-red-300); + --token-color-foreground-critical-high-contrast: var(--token-color-palette-red-500); + --token-color-page-primary: var(--token-color-palette-neutral-0); + --token-color-page-faint: var(--token-color-palette-neutral-50); + --token-color-surface-primary: var(--token-color-palette-neutral-0); + --token-color-surface-faint: var(--token-color-palette-neutral-50); + --token-color-surface-strong: var(--token-color-palette-neutral-100); + --token-color-surface-interactive: var(--token-color-palette-neutral-0); + --token-color-surface-interactive-hover: var(--token-color-palette-neutral-100); + --token-color-surface-interactive-active: var(--token-color-palette-neutral-200); + --token-color-surface-interactive-disabled: var(--token-color-palette-neutral-50); + --token-color-surface-action: var(--token-color-palette-blue-50); + --token-color-surface-highlight: var(--token-color-palette-purple-50); + --token-color-surface-success: var(--token-color-palette-green-50); + --token-color-surface-warning: var(--token-color-palette-amber-50); + --token-color-surface-critical: var(--token-color-palette-red-50); + + // --token-color-hashicorp-brand: #000000; + // --token-color-boundary-brand: #f24c53; + // --token-color-boundary-foreground: #cf2d32; + // --token-color-boundary-surface: #ffecec; + // --token-color-boundary-border: #fbd7d8; + // --token-color-boundary-gradient-primary-start: #f97076; + // --token-color-boundary-gradient-primary-stop: #db363b; + // --token-color-boundary-gradient-faint-start: #fffafa; /* this is the 'boundary-50' value at 25% opacity on white */ + // --token-color-boundary-gradient-faint-stop: #ffecec; + // --token-color-consul-brand: #e03875; + // --token-color-consul-foreground: #d01c5b; + // --token-color-consul-surface: #ffe9f1; + // --token-color-consul-border: #ffcede; + // --token-color-consul-gradient-primary-start: #ff99be; + // --token-color-consul-gradient-primary-stop: #da306e; + // --token-color-consul-gradient-faint-start: #fff9fb; /* this is the 'consul-50' value at 25% opacity on white */ + // --token-color-consul-gradient-faint-stop: #ffe9f1; + // --token-color-hcp-brand: #000000; + // --token-color-nomad-brand: #06d092; + // --token-color-nomad-foreground: #008661; + // --token-color-nomad-surface: #d3fdeb; + // --token-color-nomad-border: #bff3dd; + // --token-color-nomad-gradient-primary-start: #bff3dd; + // --token-color-nomad-gradient-primary-stop: #60dea9; + // --token-color-nomad-gradient-faint-start: #f3fff9; /* this is the 'nomad-50' value at 25% opacity on white */ + // --token-color-nomad-gradient-faint-stop: #d3fdeb; + // --token-color-packer-brand: #02a8ef; + // --token-color-packer-foreground: #007eb4; + // --token-color-packer-surface: #d4f2ff; + // --token-color-packer-border: #b4e4ff; + // --token-color-packer-gradient-primary-start: #b4e4ff; + // --token-color-packer-gradient-primary-stop: #63d0ff; + // --token-color-packer-gradient-faint-start: #f3fcff; /* this is the 'packer-50' value at 25% opacity on white */ + // --token-color-packer-gradient-faint-stop: #d4f2ff; + // --token-color-terraform-brand: #7b42bc; + // --token-color-terraform-foreground: #773cb4; + // --token-color-terraform-surface: #f4ecff; + // --token-color-terraform-border: #ebdbfc; + // --token-color-terraform-gradient-primary-start: #bb8deb; + // --token-color-terraform-gradient-primary-stop: #844fba; + // --token-color-terraform-gradient-faint-start: #fcfaff; /* this is the 'terraform-50' value at 25% opacity on white */ + // --token-color-terraform-gradient-faint-stop: #f4ecff; + // --token-color-vagrant-brand: #1868f2; + // --token-color-vagrant-foreground: #1c61d8; + // --token-color-vagrant-surface: #d6ebff; + // --token-color-vagrant-border: #c7dbfc; + // --token-color-vagrant-gradient-primary-start: #c7dbfc; + // --token-color-vagrant-gradient-primary-stop: #7dadff; + // --token-color-vagrant-gradient-faint-start: #f4faff; /* this is the 'vagrant-50' value at 25% opacity on white */ + // --token-color-vagrant-gradient-faint-stop: #d6ebff; + // --token-color-vault-brand: #ffd814; + // --token-color-vault-brand-alt: #000000; /* this is a special “alternative” color, used as an exception in some contexts where the normal “brand” color for Vault would not work */ + // --token-color-vault-foreground: #9a6f00; + // --token-color-vault-surface: #fff9cf; + // --token-color-vault-border: #feec7b; + // --token-color-vault-gradient-primary-start: #feec7b; + // --token-color-vault-gradient-primary-stop: #ffe543; + // --token-color-vault-gradient-faint-start: #fffdf2; /* this is the 'vault-50' value at 25% opacity on white */ + // --token-color-vault-gradient-faint-stop: #fff9cf; + // --token-color-waypoint-brand: #14c6cb; + // --token-color-waypoint-foreground: #008196; + // --token-color-waypoint-surface: #e0fcff; + // --token-color-waypoint-border: #cbf1f3; + // --token-color-waypoint-gradient-primary-start: #cbf1f3; + // --token-color-waypoint-gradient-primary-stop: #62d4dc; + // --token-color-waypoint-gradient-faint-start: #f6feff; /* this is the 'waypoint-50' value at 25% opacity on white */ + // --token-color-waypoint-gradient-faint-stop: #e0fcff; + + --token-elevation-inset-box-shadow: inset 0px 1px 2px 1px var(--token-color-palette-alpha-100); + --token-elevation-low-box-shadow: 0px 1px 1px 0px var(--token-color-palette-neutral-500-alpha-50), 0px 2px 2px 0px var(--token-color-palette-neutral-500-alpha-50); + --token-elevation-mid-box-shadow: 0px 2px 3px 0px var(--token-color-palette-alpha-100), 0px 8px 16px -10px var(--token-color-palette-alpha-200); + --token-elevation-high-box-shadow: 0px 2px 3px 0px var(--token-color-palette-neutral-500-alpha-100), 0px 16px 16px -10px var(--token-color-palette-alpha-200); + --token-elevation-higher-box-shadow: 0px 2px 3px 0px var(--token-color-palette-alpha-100), 0px 12px 28px 0px var(--token-color-palette-neutral-500-alpha-200); + --token-elevation-overlay-box-shadow: 0px 2px 3px 0px var(--token-color-palette-neutral-600-alpha-100), 0px 12px 24px 0px var(--token-color-palette-neutral-600-alpha-200); + --token-surface-inset-box-shadow: inset 0 0 0 1px var(--token-color-palette-neutral-500-alpha-200), inset 0px 1px 2px 1px var(--token-color-palette-alpha-100); + --token-surface-base-box-shadow: 0 0 0 1px var(--token-color-palette-alpha-200); + --token-surface-low-box-shadow: 0 0 0 1px var(--token-color-palette-neutral-500-alpha-100), 0px 1px 1px 0px var(--token-color-palette-neutral-500-alpha-50), 0px 2px 2px 0px var(--token-color-palette-neutral-500-alpha-50); + --token-surface-mid-box-shadow: 0 0 0 1px var(--token-color-palette-neutral-500-alpha-100), 0px 2px 3px 0px var(--token-color-palette-alpha-100), 0px 8px 16px -10px var(--token-color-palette-alpha-200); + --token-surface-high-box-shadow: 0 0 0 1px var(--token-color-palette-neutral-500-alpha-200), 0px 2px 3px 0px var(--token-color-palette-neutral-500-alpha-100), 0px 16px 16px -10px var(--token-color-palette-alpha-200); + --token-surface-higher-box-shadow: 0 0 0 1px var(--token-color-palette-alpha-200), 0px 2px 3px 0px var(--token-color-palette-alpha-100), 0px 12px 28px 0px var(--token-color-palette-neutral-500-alpha-200); + --token-surface-overlay-box-shadow: 0 0 0 1px var(--token-color-palette-neutral-600-alpha-100), 0px 2px 3px 0px var(--token-color-palette-neutral-600-alpha-100), 0px 12px 24px 0px var(--token-color-palette-neutral-600-alpha-200); + --token-focus-ring-action-box-shadow: inset 0 0 0 1px var(--token-color-palette-blue-300), 0 0 0 3px var(--token-color-focus-action-external); + --token-focus-ring-critical-box-shadow: inset 0 0 0 1px var(--token-color-palette-red-300), 0 0 0 3px var(--token-color-focus-critical-external); + --token-form-label-color: var(--token-color-palette-neutral-700); + --token-form-legend-color: var(--token-color-palette-neutral-700); + --token-form-helper-text-color: var(--token-color-palette-neutral-500); + --token-form-indicator-optional-color: var(--token-color-palette-neutral-500); + --token-form-error-color: var(--token-color-palette-red-300); + + --token-form-control-base-foreground-value-color: var(--token-color-palette-neutral-700); + --token-form-control-base-foreground-placeholder-color: var(--token-color-palette-neutral-500); + --token-form-control-base-surface-color-default: var(--token-color-palette-neutral-0); + --token-form-control-base-surface-color-hover: var(--token-color-palette-neutral-100); + --token-form-control-base-border-color-default: var(--token-color-palette-neutral-400); + --token-form-control-base-border-color-hover: var(--token-color-palette-neutral-500); + --token-form-control-checked-foreground-color: var(--token-color-palette-neutral-0); + --token-form-control-checked-surface-color-default: var(--token-color-palette-blue-200); + --token-form-control-checked-surface-color-hover: var(--token-color-palette-blue-300); + --token-form-control-checked-border-color-default: var(--token-color-palette-blue-300); + --token-form-control-checked-border-color-hover: var(--token-color-palette-blue-400); + --token-form-control-invalid-border-color-default: var(--token-color-palette-red-300); + --token-form-control-invalid-border-color-hover: var(--token-color-palette-red-400); + --token-form-control-readonly-foreground-color: var(--token-color-palette-neutral-600); + --token-form-control-readonly-surface-color: var(--token-color-palette-neutral-100); + --token-form-control-readonly-border-color: var(--token-color-palette-alpha-100); + --token-form-control-disabled-foreground-color: var(--token-color-palette-neutral-400); + --token-form-control-disabled-surface-color: var(--token-color-palette-neutral-50); + --token-form-control-disabled-border-color: var(--token-color-palette-alpha-200); + + --token-form-toggle-base-surface-color-default: var(--token-color-palette-neutral-100); /* the toggle has a different base surface color, compared to the other controls */ +} diff --git a/addons/rose/addon/styles/hds/themes/dark-mode/index.scss b/addons/rose/addon/styles/hds/themes/dark-mode/index.scss new file mode 100644 index 000000000..c2a7265b7 --- /dev/null +++ b/addons/rose/addon/styles/hds/themes/dark-mode/index.scss @@ -0,0 +1,100 @@ +@import 'color-tokens-tier-2'; + +// HDS Dark Mode +// This theme reverses the lightness order of shades per color for tier-1 +// color tokens. It also provides custom tier-2 mapping overrides that +// look better in dark mode. +@mixin dark-mode { + // Tier-1 (HDS) + --token-color-palette-blue-500: #f2f8ff; + --token-color-palette-blue-400: #cce3fe; + --token-color-palette-blue-300: #1060ff; + --token-color-palette-blue-200: #0c56e9; + --token-color-palette-blue-100: #0046d1; + --token-color-palette-blue-50: #1c345f; + --token-color-palette-purple-500: #f9f2ff; + --token-color-palette-purple-400: #ead2fe; + --token-color-palette-purple-300: #a737ff; + --token-color-palette-purple-200: #911ced; + --token-color-palette-purple-100: #7b00db; + --token-color-palette-purple-50: #42215b; + --token-color-palette-green-500: #f2fbf6; + --token-color-palette-green-400: #cceeda; + --token-color-palette-green-300: #008a22; + --token-color-palette-green-200: #00781e; + --token-color-palette-green-100: #006619; + --token-color-palette-green-50: #054220; + --token-color-palette-amber-500: #fff9e8; + --token-color-palette-amber-400: #fbeabf; + --token-color-palette-amber-300: #bb5a00; + --token-color-palette-amber-200: #9e4b00; + --token-color-palette-amber-100: #803d00; + --token-color-palette-amber-50: #542800; + --token-color-palette-red-500: #fff5f5; + --token-color-palette-red-400: #fbd4d4; + --token-color-palette-red-300: #e52228; + --token-color-palette-red-200: #c00005; + --token-color-palette-red-100: #940004; + --token-color-palette-red-50: #51130a; + + --token-color-palette-neutral-700: #ffffff; + --token-color-palette-neutral-600: #fafafa; + --token-color-palette-neutral-500: #f1f2f3; + --token-color-palette-neutral-400: #dedfe3; + --token-color-palette-neutral-300: #c2c5cb; + --token-color-palette-neutral-200: #8c909c; + --token-color-palette-neutral-100: #656a76; + --token-color-palette-neutral-50: #3b3d45; + --token-color-palette-neutral-0: #0c0c0e; + + --token-color-palette-alpha-300: #fafafa66; + --token-color-palette-alpha-200: #dedfe333; + --token-color-palette-alpha-100: #dedfe31a; + + // Tier-1 (Boundary custom) + // Boundary custom first-tier color tokens with alpha. + // In HDS, these correspond to the named color token, + // with the alpha identifier. However, they do not have stand-alone tokens + // associated with them and appear hard-coded alongside other styles. + // They are pulled out here for easier theming. + --token-color-palette-neutral-600-alpha-200: #fafafa59; + --token-color-palette-neutral-600-alpha-100: #fafafa40; + --token-color-palette-neutral-500-alpha-200: #f1f2f340; + --token-color-palette-neutral-500-alpha-100: #f1f2f326; + --token-color-palette-neutral-500-alpha-50: #f1f2f30d; + + // Tier 2 (HDS dark mode overrides) + // These mappings improve contrast as needed in dark mode. + --token-color-foreground-highlight-on-surface: var(--token-color-palette-purple-400); + --token-color-foreground-success-on-surface: var(--token-color-palette-green-400); + --token-color-foreground-warning-on-surface: var(--token-color-palette-amber-400); + --token-color-foreground-critical-on-surface: var(--token-color-palette-red-400); + --token-color-surface-strong: var(--token-color-palette-neutral-50); +} + +// HDS Light Mode +// This is the default HDS color theme. Only Boundary custom tokens +// are included here for completeness. +@mixin light-mode { + // Tier-1 (Boundary custom) + // Boundary custom first-tier color tokens with alpha. + // In HDS, these correspond to the named color token, + // with the alpha identifier. However, they do not have stand-alone tokens + // associated with them and appear hard-coded alongside other styles. + // They are pulled out here for easier theming. + --token-color-palette-neutral-600-alpha-200: #3b3d4559; + --token-color-palette-neutral-600-alpha-100: #3b3d4540; + --token-color-palette-neutral-500-alpha-200: #656a7640; + --token-color-palette-neutral-500-alpha-100: #656a7626; + --token-color-palette-neutral-500-alpha-50: #656a760d; +} + +@media (prefers-color-scheme: dark) { + .ember-application:not(.rose-theme-light) { + @include dark-mode; + } +} + +.ember-application.rose-theme-dark { + @include dark-mode; +} diff --git a/addons/rose/app/styles/rose/components/dialog/_dialog.scss b/addons/rose/app/styles/rose/components/dialog/_dialog.scss index bac49ec92..e6282dfd9 100644 --- a/addons/rose/app/styles/rose/components/dialog/_dialog.scss +++ b/addons/rose/app/styles/rose/components/dialog/_dialog.scss @@ -18,7 +18,7 @@ $xxxxs: sizing.rems(xxxxs); // 1 border-radius: $xxxs; background-color: var(--subtle); box-shadow: 0 $xs $s rgba(var(--stark-components), var(--opacity-2)), - 0 $xxs $xxs rgba(var(--stark-components), var(--opacity-3)); + 0 $xxs $xxs rgba(var(--stark-components), var(--opacity-3)); &.rose-dialog-success { --header-color: var(--success-starker-1); diff --git a/addons/rose/app/styles/rose/variables/color/_css.scss b/addons/rose/app/styles/rose/variables/color/_css.scss index c8937dbb7..a181a140a 100644 --- a/addons/rose/app/styles/rose/variables/color/_css.scss +++ b/addons/rose/app/styles/rose/variables/color/_css.scss @@ -1,4 +1,4 @@ -@use "sass:color"; +@use 'sass:color'; /** * CSS custom properties defining colors. These are the color variables that