Problem/Motivation

As @rkoller clearly illustrated with Gin, the accents, focus colors and for that matter "Increased contrast" mode is a real pain to set up effectively.

I almost see this as a child of a few issues, including:
#3618127: Navigation top bar action buttons in dark mode have low color contrast

It is the central color contrast issue that we do need to fix to have confidence in the colors of the Default Admin going ahead.

There are nearly 200 color combinations to juggle in the current configuration.

The goal was to improve accessibility by:

  • the distinction between light and dark surfaces;
  • visual hierarchy between primary, secondary, and supporting content;
  • the identity of accent colors;
  • distinct focus and interactive states;
  • user preferences such as Dark/Light/Auto and forced colors.

I also wanted a testable means to validate all of the combinations of foreground and background colors.

The "Increase contrast" button must compose correctly with Dark mode. It should strengthen contrast without collapsing text, icons, borders, focus indicators, and surfaces into effectively white-on-black or black-on-white presentation.

This starts by restructuring Default Admin's accent, focus, dark-mode, and increased-contrast colors around semantic roles rather than individual component fixes. The aim is to preserve the existing color hierarchy while improving measurable contrast. Automated coverage is included for the Light/Dark state combinations and accent/focus behavior.

This patch was developed with AI.

Steps to reproduce

  1. Load the Default Admin Theme
  2. Go to the settings page /admin/appearance/settings/default_admin
  3. Click on each of the colors and evaluate color contrast for each
  4. Do the same with the accent colors
  5. Then do the same with the "Enhance contrast" button
  6. Then do theis all for Dark mode

Proposed resolution

Make better use of CSS for things like:
light-dark()

Test all of the color combinations. where possible include APCA and even WCAG 2.2 AAA if we can.

Remaining tasks

Review.

User interface changes

Lots of color contrast changes. Shouldn't be any other changes.

Introduced terminology

API changes

None

Data model changes

None

Release notes snippet

Issue fork drupal-3619933

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mgifford created an issue. See original summary.

mgifford’s picture

Issue summary: View changes
mgifford’s picture

Issue summary: View changes

mgifford’s picture

Issue summary: View changes
kentr’s picture

This is a bit of a tangent, but it might make maintenance easier:

Is the "Enhance contrast" feature actually helpful? Can it be removed?

Two of the arguments against overlays is that the overlay only applies to one site and users who need certain preferences (like increased contrast) will have their side set up anyway.

their practical value is largely overstated because the end users that these features claim to serve will already have the necessary features on their computer, either as a built-in feature or as an additional piece of software that the user needs to access not only the Web but all software.

On this latter point, it is a mistake to believe that the features provided by the overlay widget will be of much use by end users because if those features were necessary to use the website, they'd be needed for all websites that the user interacts with. Instead, the widget is —at best—redundant functionality with what the user already has.

To me, the "Enhance contrast" feature looks like a similar case.

mgifford’s picture

StatusFileSize
new113.93 KB
new90.12 KB

@KentR I don't think that from an accessibility point of view, an "Increase contrast" button should be needed. Everything should default to WCAG 2.2 AA. So we could (and still may) remove:

Increase contrast Experimental
Increases text and interface contrast while preserving visual hierarchy.

Not that any of this is an overlay, but with CSS an a site-wide setting like this, there is more that could be done to highlight regions, make the content bolder and make the site easier to read.

I think it was initially added there to "meet WCAG" but it didn't work as advertised (at least as I understood it).

I changed the colors in this patch:

Accent color

  • Cobalt (Default)
  • Cerulean
  • Teal
  • Emerald
  • Olive
  • Amber
  • Orange
  • Vermilion
  • Magenta
  • Violet
  • Neutral
  • Custom

Focus color

  • Blue (Default)
  • Green
  • Amber
  • Neutral
  • Custom

Light mode accents
Dark mode accents

mgifford’s picture

Changes (from AI review of AI code):

Default Admin now resolves more of its color system through semantic tokens that understand Light and Dark mode, instead of placing Light/Dark decisions directly inside individual components.

--admin-color-summary-text
--admin-color-summary-hover-bg
--admin-color-radio-hover
--admin-color-radio-hover-bg

The dark theme also retains several distinct surfaces rather than flattening everything into one background:

main      #1b1b1d
surface   #2a2a2d
nested    #3b3b3f
raised    #47474c
toolbar   #2d3755

The CSS now separates at least three distinct roles:

--admin-color-accent-base
--admin-color-accent-fg
--admin-color-accent-preview

--admin-color-accent-base is intended for fills and primary surfaces.

--admin-color-accent-fg is a foreground-safe version for links and other interactive foreground uses.

The tests explicitly guard that the fill and foreground tokens remain separate and use the same OKLCH color model.

The accent palette has also been redesigned as 10 chromatic choices plus Neutral rather than several closely related shades of the same hue.

The Dark-mode foreground is derived from the selected source accent rather than substituting an unrelated fixed color.

The selected accent remains recognizably the same color family throughout the interface, but it is much less likely to become unreadable.

selected Blue
   ↓
Blue button
Blue link
Blue hover state
Blue active state
Blue picker preview

but each of those is allowed to use the version of Blue appropriate for that role.

In Dark mode, the preview uses the foreground-safe accent instead of displaying the very dark accent fill. The test documentation explicitly describes this distinction and verifies the rendered swatches against their actual settings-page surface. The dark accent fill is intentionally dark because it needs to work behind light text. That made it a poor choice for showing the color in the settings picker: several swatches became difficult to distinguish from the surrounding dark UI.

The fixed focus choices are now independent color families:

The test suite describes this explicitly: focus presets are optimized for visibility rather than brand/accent identity.

Accent-filled controls such as primary buttons and checked controls use a two-part focus treatment. The CSS introduces a separate gap between the component and the outer focus ring:

accent-filled control
        ↓
surface-colored gap
        ↓
focus ring

Meaningful icons are being treated as their own contrast relationship rather than assuming that a text color automatically works for the icon.

Increased contrast

crease contrast no longer means flattening the interface into pure black and white.

The tests explicitly guard against replacing the normal surfaces with #fff or #000, and they preserve distinct text and border levels.

Accent foregrounds remain hue-preserving even when contrast is increased.

The author-controlled Increase contrast mode is also kept separate from forced-colors.

strengthen the contrast relationships while preserving semantic distinctions.

Previously, Dark mode behavior could be scattered across component styles, but now:

source color
    ↓
primitive color system
    ↓
semantic role
    ↓
light-dark()
    ↓
component

For accents:

selected accent
    ↓
--accent-base
    ├── --admin-color-accent-base
    ├── --admin-color-accent-fg
    └── --admin-color-accent-preview

For components:

semantic token
    ↓
Light / Dark resolution
    ↓
component consumes token

Modern CSS features such as light-dark(), relative oklch() colors, and color-mix() allow the theme to express those relationships directly in CSS rather than maintaining independent hard-coded palettes for every mode.

That improves maintainability because a component generally no longer needs to know:

“Am I in Dark mode, and which special color should I use?”

It instead asks:

“What is the semantic color for this role?”

The color system answers the Light/Dark question.

Overall effect

The larger change is therefore not simply “better contrast.”

It is moving Default Admin toward a semantic, mode-aware color system where:

Light, Dark, and Auto use the same underlying design language;
accents retain their identity without being forced to serve incompatible roles;
Dark mode preserves surface hierarchy;
focus is independent from branding/accent choice;
meaningful icons remain visible as controls change state;
increased contrast strengthens relationships without flattening the UI;
components consume semantic tokens instead of accumulating Dark-mode exceptions;
browser-based tests verify the colors users actually see.

That should make Default Admin both more accessible now and substantially easier to maintain as Drupal adds or changes administrative components.