Skip to content

[Bug]: Custom theme tokens in top-navigation context are overridden by dark mode defaults due to CSS specificity #4189

@GoranMandic91

Description

@GoranMandic91

When using applyTheme() with custom tokens in the top-navigation context, the custom values work correctly in light mode but are overridden by Cloudscape's default dark mode styles when switching to dark mode via applyMode(Mode.Dark).

Steps to Reproduce:

  1. Apply a custom theme with tokens in the top-navigation context:
import { applyTheme } from '@cloudscape-design/components/theming';
import { Theme } from '@cloudscape-design/components/theming';

const theme: Theme = {
  tokens: {},
  contexts: {
    'top-navigation': {
      tokens: {
        colorTextAccent: { light: '#FFAC00', dark: '#FFAC01' },
        colorTextInteractiveHover: { light: '#FFAC00', dark: '#FFAC01' },
      },
    },
  },
};

applyTheme({ theme });
  1. Switch to dark mode:
import { applyMode, Mode } from '@cloudscape-design/global-styles';
applyMode(Mode.Dark);
  1. Observe the TopNavigation component - elements like the expanded dropdown button and identity link hover state show the default blue (#42b4ff) instead of the custom color (#FFAC00).

Expected Behavior:
Custom theme tokens should take precedence over default dark mode styles. The top navigation elements should display #FFAC00 in both light and dark modes.

Actual Behavior:
In dark mode, the custom theme values are overridden by Cloudscape's default dark mode styles. The elements display #42b4ff (default blue) instead of #FFAC00.

Root Cause Analysis:
The issue is CSS specificity. The theme runtime injects CSS like:

.awsui-context-top-navigation:not(#\9) {
  --color-text-accent-n1kmht: #FFAC00;
  --color-text-accent-n1kmht: #FFAC01;
}

But Cloudscape's dark mode defaults use a doubled selector with higher specificity:

.awsui-dark-mode.awsui-dark-mode .awsui-context-top-navigation:not(#\9) {
  --color-text-accent-n1kmht: #42b4ff;
}

The .awsui-dark-mode.awsui-dark-mode selector has higher specificity than the theme-injected selector, causing the custom values to be overridden.

Workaround:
Using CSS overrides with !important:

.awsui-context-top-navigation button[aria-expanded='true'] {
  color: var(--custom-primary-color) !important;
}

Environment:

  • @cloudscape-design/components: 3.0.1171
  • @cloudscape-design/global-styles: 1.0.49
  • @cloudscape-design/theming-runtime: 1.0.90 (transitive)
  • Browser: Chrome (latest)
  • OS: macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions