Problem/Motivation

Light/dark mode is currently owned entirely by the new Default Admin theme. The
preference lives in that theme's settings, so it only applies where that theme is
rendering. Anywhere else - the front end, the Navigation toolbar and top bar shown to a
logged-in user while browsing the front end, or a site still on Claro - the user's choice
is simply not respected.

The practical effect is a site that flips appearance as the user moves around it: a light
Navigation toolbar on the front end, then a dark admin screen one click later. That is
jarring, and for a premium CMS it reads as sloppy.

It is also more than cosmetic. Some people genuinely cannot work comfortably in one
scheme or the other, so being able to choose - and having that choice honored
consistently - is an accessibility concern, even where no specific WCAG success criterion
applies. Every browser and operating system already exposes a color-scheme preference and
users expect applications to follow it.

Today there is no place in Drupal for "this user prefers light, dark, or whatever the
system says" to live. Nothing outside one theme can read it, and no module or theme can
build on it.

Scope of this issue (read this before commenting)

The discussion in this issue has drifted repeatedly into styling, front-end toggles,
generic theming APIs and site-wide policy. To keep the issue landable, the scope has been
deliberately narrowed to infrastructure only. The UX team reviewed the
open questions in #66 and #67 and their consistent recommendation was to ship the smallest
working version and move every refinement to a follow-up. That recommendation is now
reflected below.

In scope

  • A per-user color-scheme preference, stored on the user entity and handled the same way
    as the existing timezone and language preferences.
  • Values: light, dark, auto, presented in that
    order and labelled Light, Dark, System. auto is
    the default (agreed separately in #3604071: Change default to auto for light/dark mode). The UX
    review changed the label of that option only; the stored value stays
    auto.
  • Exposing that value to every rendered page, so that any theme - front end or
    admin - can act on it:
    a data-color-scheme attribute on the <html> element,
    plus a color_scheme variable for themers who need it elsewhere.
  • The editing UI for the preference, on the existing user profile form: three radios
    with a short description.
  • A theme capability declaration, so that the attribute and the cache context are only
    added when a theme in play actually honors the value.
  • Removing the now-superseded dark-mode settings from the default_admin
    theme.

Explicitly out of scope (each has its own issue, see below)

  • Any CSS or JS work - actually making core themes and the Navigation module look
    dark. This issue only ships the signal; nothing will visually change from it alone.
  • A front-end toggle widget or block, and support for anonymous visitors.
  • Icons, segmented controls, or any other visual refinement of the form element.
  • Hiding the setting from users for whom no theme in play supports it.
  • Other appearance settings (accent color, focus color, etc.).
  • A generic, mode-agnostic style/utility API (branding, high contrast, seasonal modes).
  • Letting a site administrator set a site-wide default or switch the feature off.
  • Live preview of the setting.

Proposed resolution

  1. Add a color-scheme base field to the user entity, with an update hook, modeled on
    timezone/language.
  2. Add the preference to the user profile form, alongside the other per-user rendering
    preferences. Label: Color scheme. Control: three radios, ordered
    Light, Dark, System, no icons. A short
    description explains what System does and that support is theme-dependent.
  3. In ThemePreprocess (core's canonical place for this), set
    data-color-scheme on the <html> element and also pass a
    color_scheme Twig variable, defaulting to auto when no
    preference is available.
  4. Add a theme .info.yml declaration along the lines of
    supports color scheme. Add the attribute and the user cache context
    only when a theme in play declares support, so that sites whose themes do not honor the
    value pay nothing for the feature.
  5. Remove the dark-mode settings from default_admin, which now consumes the
    global preference instead of owning it.
  6. Do not emit <meta name="color-scheme">. Changing native
    browser UI (form controls, scrollbars) is the theme's decision, via the
    color-scheme CSS property.
  7. Add test coverage.

Steps 1-3, 5 and 6 are implemented in the merge request and have been reviewed favorably.
Step 4 is the outstanding work.

Where the issue currently stands

The MR reached RTBC twice. It was set back to Needs work by a late round of review
(comments #53-#65) raising two coupled objections:

  1. Relevance. As written, every user on every site gets the setting -
    including sites whose front-end theme has no dark mode and whose users have no admin
    access. Offering a control that demonstrably does nothing is worse than offering
    nothing.
  2. Performance. The new cache context is added unconditionally, including
    on themes that will never honor the value. On sites where render-cache size has been
    carefully managed, that multiplies cache entries for no benefit.

The UX review in #66/#67 has since separated these two. The relevance half -
hiding the control from users it cannot help - is a nice-to-have and belongs in a
follow-up; a plain description that sets expectations is enough for now. The
performance half is not deferrable, because it is the one thing that cannot be
retrofitted without a behavior change. So the theme capability declaration still lands
here, but it gates the attribute and the cache context, not the visibility
of the form element.

The decision table for the capability declaration, once conditional visibility is
implemented in the follow-up:

  • Neither the front-end nor the admin theme supports it: no setting, no attribute, no
    cache context.
  • Both support it: setting available.
  • Front end supports it, admin theme does not: setting available.
  • Admin theme supports it, front end does not: setting available only to users who may
    use the administration theme, with a description explaining the limitation.

Alternatives raised but not adopted: gating on a new "edit dark mode setting" permission;
reusing the existing "use the administration theme" permission; storing the value
client-side instead of on the account; shipping the control in a separate (possibly
experimental) module.

Target branch: main. Whether the change is also backported
to 11.4.x is deliberately left open and will be decided later in the process. The argument for
backporting is that keeping 11.4.x/11.5.x/main close lets module and theme maintainers test
against a stable Default Admin theme before 12.0.0, rather than meeting the change as brand new
in 12.0.0.

UX decisions (answered in #66 and #67)

The ten open questions raised in the previous revision of this summary were answered by
the UX team - ckrina in #66 and Emma Horrell in #67, who
agreed with each of ckrina's answers and sharpened three of them. Those answers are settled
and are reflected in the scope and proposed resolution above. Recorded here so the reasoning
is not lost in comment prose.

  1. Name of the feature in the UI: "Color scheme." It matches the accepted
    convention, the CSS property and the attribute; no need to reinvent it. A short
    description carries any extra explanation.
  2. Third option: "System," and the order is Light, Dark, System. "Auto" is
    ambiguous about where the automation comes from - on macOS it means time-of-day -
    whereas "System" says plainly that it follows the operating system or browser. Ship a
    very short clarification such as "System follows the setting from your operating system
    or browser." This is a label change only - the value stored for that option remains
    auto.
  3. Control: three radio buttons plus a description. No icons, no extras.
    A one-of-three choice is exactly what radios are for. Visual refinement is a
    follow-up; the point of this issue is to make the control exist.
  4. Home: the user profile form. Not a stopgap. It is where a user applies
    their preferences, so it sits naturally with timezone and language. No dedicated tab. If
    the form eventually becomes crowded, that is a separate problem for a separate issue.
  5. Partial-support wording: name the theme as the dependency. ckrina
    proposed "Applies wherever this site supports it"; Emma Horrell refined it to
    "Applies where supported by site theme", on the grounds that the user
    should be told what determines support, not merely that support varies. The
    refined wording is the recommendation.
  6. Hide vs. show-disabled: neither, for now. Hiding the control where no
    theme supports it is agreed to be the better end state, but it is a nice-to-have and
    should not hold up the core feature. Ship the control unconditionally with the
    description from question 5, and move conditional visibility to a follow-up. (ckrina
    explicitly scoped this answer to UX and took no position on the cache-context question,
    which is why the two are now separated above.)
  7. Administrator default: worth having, but not a blocker, and it must not
    override the user.
    A site-wide administrator setting should exist - site
    builders are the ones who will field the complaints when dark mode looks wrong in a
    contrib theme or module - but it does not block the user-facing feature. An
    administrator setting must not silently override a user's stored preference; if a site
    cannot support the feature, switching it off site-wide is the sensible lever, not
    overriding individuals. The label stays "Color scheme" either way, with the description
    indicating that it is a preference where an administrator can override it. Tracked at
    #3618721: Consider allowing site admins to set global values for light/dark mode.
  8. Capability declaration: "supports color scheme." Confirmed by both
    reviewers.
  9. Themes only; modules do not declare support. Modules should instead
    make their styling compatible, which is what shared color custom properties (see #11)
    enable. That makes #3517033: Add a style utility API (style
    utility API) valuable but explicitly not a blocker for this issue.
  10. Live preview: on save, and the preview itself is a follow-up. Applying
    on save is the expected behavior for a settings form. Tracked at #3614866: Implement live preview for the dark mode setting in the user profile.

Decisions taken on the remaining questions

The four questions left after the UX review have been answered by the issue's maintainers.
Nothing in this summary is open for decision; what is left is implementation and review.

  1. Exact English wording of the description text: settled during review.
    Both UX reviewers deferred to native speakers, and the wording is easiest to judge once
    reviewers can see what the strings say and where they appear. The two ideas that must be
    conveyed are what System does, and that the effect depends on the theme
    ("Applies where supported by site theme"); the final phrasing is a review-time
    decision.
  2. The theme capability declaration lands in this issue. It is not a
    follow-up. This is what answers the performance objection from #53-#65: the
    data-color-scheme attribute and the cache context are added only when a
    theme in play declares support.
  3. The stored value stays auto. The UX change to "System" is a
    label change only. No rename of the stored value, and therefore nothing to revisit in
    #3604071: Change default to auto for light/dark mode.
  4. Target branch is main. A backport to 11.4.x is not ruled
    out and will be decided later in the process.

Remaining tasks

  • Relabel the third option to System (stored value stays auto) and
    reorder the options to Light, Dark, System.
  • Relabel the form element to Color scheme and add the description text.
  • Add the "supports color scheme" theme declaration and make the attribute and the cache
    context conditional on it.
  • Declare support in default_admin.
  • Confirm the update function naming raised in review.
  • Finish and green the test coverage, including coverage of the conditional cache
    context.
  • Open the follow-up for conditional visibility of the setting.
  • Re-review and RTBC against main; decide on an 11.4.x backport separately.

User interface changes

  • A new Color scheme preference on the user profile form: three radios - Light,
    Dark, System - with a short description.
  • The dark-mode settings are removed from the Default Admin theme settings form.
  • No visual change to any theme results from this issue alone - the styling work is
    separate.

API changes

  • New accessor on the current-user/account API returning the color scheme.
  • New data-color-scheme attribute on the <html> element,
    added only when a theme in play declares support.
  • New color_scheme variable available to html.html.twig.
  • A new cache context, added under the same condition.
  • A new theme .info.yml key by which a theme declares color-scheme support.

Data model changes

  • A new base field on the user entity storing the color-scheme preference, with an update
    hook to install it.

Release notes snippet

Users can now choose a light, dark, or system-matched color scheme in their account
settings. The choice is exposed to every theme that declares support for it through a
data-color-scheme attribute on the <html> element, so it is
honored consistently across the front end and the administration interface rather than by the
administration theme alone.

Related issues

Change record

Follow-ups:

Context and prior decisions:

Disclosure: I've used help from Opus 5 to summarize and rewrite this IS.

Issue fork drupal-3606655

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

mherchel created an issue. See original summary.

gábor hojtsy’s picture

As a Drupal core product manager, I think having first class support for this would be great. Where to put it I'm not sure, it may depend on what other frontend settings we need. Currently the main appearance settings are handled by system module.

kentr’s picture

Issue tags: +Accessibility

My understanding is that some people struggle with one or the other, so I think there's an accessibility piece to it.

+1 to making it per user.

To me, it would be equally disconcerting / sloppy if the Navigation UI is dark while the rest of the front-end page is light.

Of course, themes can opt to get the setting and use it. However, I think it would be misleading to provide the setting when the theme doesn't use it.

So, maybe include a way for themes to indicate support for it and only present the setting when they do, or display a notice that the theme doesn't support it.

mherchel’s picture

However, I think it would be misleading to provide the setting when the theme doesn't use it.

I think we'd need to phrase the description of the checkboxes to indicate what it affects and does not.

include a way for themes to indicate support for it and only present the setting when they do

This is a bad idea IMO, because it takes away functionality from the backend. There are certain users who (content editors) who do the majority of the work in the backend.

tolstoydotcom’s picture

I don't know what "auto by default" means, but please don't force dark mode on people. Here's a starting point:

https://medium.com/@h_locke/why-dark-mode-causes-more-accessibility-issues-than-it-solves-54cddf6466f5

Light mode/day mode should be the default. Those who want dark/night mode can easily select it.

mherchel’s picture

I don't know what "auto by default" means, but please don't force dark mode on people.

It means that Drupal will respect the OS/Browser preferences by default.

kentr’s picture

I just noticed @mgifford's "Light/Dark Mode Accessibility Best Practices" linked from the a11y office hour notes.

The User override pattern section is pertinent to this issue:

User override pattern

Toggle control design

Use a single toggle button that switches between light and dark modes:

  • Visual affordance: Use sun/moon icons to provide clear indication of theme switching functionality
  • Placement: Position in the top-right corner of the header in both desktop and mobile views
  • Scroll behavior: Do not make the toggle fixed/sticky; it should remain in normal document flow within the header
  • Keyboard navigation: Place the toggle in the DOM after navigation/menu items so it appears later in the tab order
  • Language consideration: This guidance assumes left-to-right (LTR) languages
mherchel’s picture

Issue summary: View changes
tobiasb’s picture

Our journey in OpenCulturas with light/darkmode:

We used prefers-color-scheme to set the color for dark-mode.

And I hate it. My system is per default dark, but when a theme is half-baked for a dark-mode, or just not all pages looks good, I want to switch it, without hacking tools.

So I searched for better way and found the contrib module dark_mode_toggle.

We forked the module into OpenCulturas, customized it to allow us to reuse the same code for frontend (block) and backend (Toolbar).

The toggle does also toggle the gin dark/light mode, on some pages I wish I could make an exception. :D

kentr’s picture

What about other UI settings within the Admin theme (accent color, focus color, etc)?

I suggest making that a separate issue.

If we're providing sensible & accessible defaults for light & dark themes, then I view the ability to fine-tune the colors as a lower priority than the ability to control light / dark.

hexabinaer’s picture

First of all: Great move, thanks for emphasizing the importance of an accessibility feature!

If we're providing sensible & accessible defaults for light & dark themes, then I view the ability to fine-tune the colors as a lower priority than the ability to control light / dark.

IMHO it is not a matter of "fine-tuning". Colors convey meaning and they need to have accessible and understandable contrasts, otherwise we sacrifice a strength of Drupal (overall accessibility) for the sake of one related feature. Futhermore, the design is vital for decision-makers, and that includes dark-mode design.

I'd like to share or learnings from making OpenCulturas dark-mode compatible and what should be considered beyond that for moving ahead in core:

Recommendations

  • Promote boldly. Themers need to become aware of the initiative, otherwise their projects might inherit a dark mode from a base theme they hadn't been aware of with the risk of unsatisfied customers.
  • Allow for deliberate user choices. Some might be happy with OS inheritance, others are not. I mean: offer a toggle, do not silently inherit from the OS. Auto-inheritance may become a default in a future release but it's not a good idea for a feature introduction (see above)
  • First, let's deliver a system-wide toggle first ("experimental", allowing to place a block in both front-end and back-end theme). It can help a lot to prepare a theme when you know what CSS class (preferable) to work with
  • Second, core theme maintainers should agree on principles and publish them to help the odd contrib theme developer to adapt these principles
  • Promote the usage of custom properties everywhere. It would be good to have a set of drupal core-prefixed custom properties for colors that any module and theme developer can rely on in the future. Example: many modules still set #efefef or the like as the background color for a field widget. A common --dr-color-background-light property could foster a lot of low-hanging contributions

How we approached it

As @tobiasb stated, we started with prefers-color-scheme in OpenCulturas. We already had defined custom properties for all colors and thus it was a no-brainer to re-fill them with adapted colors under this condition. This had put some pressure on setups that inherited from the base theme (the need to adjust colors inherited from the base theme's dark mode to the brand colors).

Then we moved on to a dark-mode toggle (keeping the front-end default theme and Gin as the back-end theme in sync. This adds the class "dark" to the html tag. With :root.dark { } we are then re-defining the color set, that's it. In one instance I know of, that class was simply globally set because the designer wanted a "dark mode only" theme anyways.

Themers may have opinions about our approach to deliver the dark-mode and any objection may be valid.

TL;DR

My point is: let's define standards. Contributed modules and themes need a little preparation.

This may slow down this initiative a bit but it will save so much time for implementers.

hexabinaer’s picture

  • Placement: Position in the top-right corner of the header ...
  • Language consideration: This guidance assumes left-to-right (LTR) languages

Assuming the latter refers to the first: Using logical properties (inset-block-start, inset-inline-end) instead of physical properties (top, right) would be another standard I'd like to promote. That way we can get rid of [ltr] selectors adding specificity and positioning automatically follows the reading direction.

catch’s picture

mherchel’s picture

@hexabinaer Note that the admin theme (derived from Gin) already supports and implements dark mode. You can see the current variable structure at https://git.drupalcode.org/project/drupal/-/blob/main/core/themes/defaul... (note this will continue to evolve over the next few months).

I suggest making that a separate issue. - @kentr

We need to think about this now. We'll need to figure out the UI and where the toggle(s) are kept.

mherchel’s picture

Issue summary: View changes

Per @catch in https://drupal.slack.com/archives/C079NQPQUEN/p1783429146306869

Wouldn't normally say system module because ideally we'd get rid of it, but in this case, probably system module because it also has all the admin routes including theme config etc.

[ css ] could possibly go in core/libraries instead of system.

Updating IS

mherchel’s picture

Issue summary: View changes
mherchel’s picture

Issue summary: View changes
kentr’s picture

@mherchel,

We need to think about this now. We'll need to figure out the UI and where the toggle(s) are kept.

I was referring to the implementation of other UI settings within the Admin theme (accent color, focus color, etc).

Planning and designing first, definitely. But please don't delay deployment of the dark mode toggle feature on the deployment of a feature for the other UI settings. They're independent features (though related) and for me the dark mode toggle is higher priority.

@hexabiner,

IMHO it is not a matter of "fine-tuning". Colors convey meaning and they need to have accessible and understandable contrasts, otherwise we sacrifice a strength of Drupal (overall accessibility) for the sake of one related feature. Futhermore, the design is vital for decision-makers, and that includes dark-mode design.

It sounds like you thought I was referring to dark mode, or dark mode toggling, as fine-tuning. I wasn't.

I was referring to a user choosing personal values for accent color, focus color, etc as fine-tuning. From Webster:

fine-tune
verb
: to make small changes to (something) in order to improve the way it works or to make it exactly right
fine-tune a TV set
fine-tune the temperature of the room
They're fine-tuning interest rates to achieve economic growth without inflation.

Take heart that Drupal policy states that core changes must pass through the core gates quality gates—which include usability and accessibility—and for accessibility we generally use WCAG 2.2 AA as a standard (even though the accessibility gate still officially declares WCAG 2.1 AA. Some things slip through the cracks, but @mherchel is on the accessibility team (from my POV 🙂).

The accessibility team is already tracking bugs for the new dark theme.

Can't speak for @mherchel, but the reason I voted for per-user selection of dark mode is exactly because of the user choice that you mentioned.

My point is: let's define standards. Contributed modules and themes need a little preparation.

This may slow down this initiative a bit but it will save so much time for implementers

It's not my bailiwick, but I thought there was already an initiative to define standards. IIRC I've seen it discussed.

AFAICT this issue is only about moving the existing controls in the new Default Admin theme out of theme and into a standalone feature.

mgifford’s picture

Great to see this discussion. I love that this is something that we might be able to start providing support for, as this is definitely an accessibility issue (even if it isn't a WCAG issue). It is definitely a best practice.

I would argue for support for a Light/Dark/System mode. Defaulting to the browser default, but over-ruled by user preferences. This could be something stored with a users account, but not all users will have an account, so it should also be something we consider as something we store in a cookie.

I've tried to aggregate some best practices here:
https://github.com/mgifford/accessibility-skills/blob/main/skills/light-...

or, another view of the same content:
https://mgifford.github.io/ACCESSIBILITY.md/examples/LIGHT_DARK_MODE_ACC...

There are so many great guides on light/dark mode, it is hard to keep up.

Every browser and every operating system supports light/dark mode. Users expect it, but it is so poorly done.

It does add complexity to both creating style guides and testing accessibility compliance.

I think partly it is about not just choosing colors, but choosing types of functionality and ideas expressed by the choice of color.

It's done quite well here:
https://www.radix-ui.com/colors
https://github.com/radix-ui/colors

I've developed something like it here:
https://mgifford.github.io/ui-palette-generator/

I tried to move beyond simply looking at the seed value. This code definitely needs work.

But yes, this should be something that is moved out of the Default Admin theme and into something that is supported system-wide.

catch’s picture

This could be something stored with a users account, but not all users will have an account, so it should also be something we consider as something we store in a cookie.

If this is done, the mode will have to be controlled via JavaScript, otherwise it can't be compatible with page caching. I'm not sure we need to do that in core, especially since core won't provide a UI to switch mode for anonymous users.

kentr’s picture

especially since core won't provide a UI to switch mode for anonymous users.

To me, providing this for anonymous users is desirable, so that there's a seamless experience that FE themes can use regardless of whether the user is logged in. For example, the login page should respect the user's preferences also IMO.

We can't make themes use the setting, but since it's a best practice hopefully more and more themes would.

Couldn't it be a theme-able JavaScript widget in a block that FE themes can put in their page header?

mherchel’s picture

Spoke to User Experience maintainer @ckrina via DM in Slack and have some answers to questions:

Where should the UI (per user) for enabling dark mode be? What is the path?

The option for the user should live under /user o user/settings?. That page is a mess now, but let's try not to solve all the things in one issue.

Should the UI above include things like accent color, etc?

That user UI should not have accent color. At least not as a core feature. That's a whole site/theme feature.

What should the UI look like?

The simpler form possible to start:
Page title: "User settings" or "UI user settings" (for example, not a copy expert)
Form > Dark mode toogle

mherchel’s picture

From @kentr

Couldn't it be a theme-able JavaScript widget in a block that FE themes can put in their page header?

I don't think this is in scope for this issue. This issue is specifically about the admin /editorial experience including the navigation sidebar and top bar when logged in and viewing the site's front-end.

I don't think a block helps front-end themes much. It's extremely simple to code a dark mode toggle button, and have it change a CSS class. The hard part is the front-end to have a theme that supports dark mode. And we don't have the capability to do that.

mherchel’s picture

I think if we want to do this for general front-end themes or anonymous sessions, we should do this in a followup, since that dramatically increases scope and might not be realistic (though it might be, too).

mherchel’s picture

Issue summary: View changes

Updating IS.

kentr’s picture

Regarding frontend: Looks like the Dark Mode Toggle module has an issue related to this: #3554120: Add functionality to persist a user's preferred dark mode setting in their account.

I suggested that they coordinate with the setting that we're talking about in this issue.

nevergone’s picture

mherchel’s picture

jurgenhaas’s picture

jurgenhaas’s picture

Assigned: Unassigned » jurgenhaas
jurgenhaas’s picture

@mherchel regarding the location of that user setting:

Where should the UI (per user) for enabling dark mode be? What is the path?

The option for the user should live under /user o user/settings?. That page is a mess now, but let's try not to solve all the things in one issue.

Does that have to be a separate tab in the user profile, or could this be included in the user profile form? I mean, there are already settings about language preference, timezone, and other settings that impact the rendering for each user. Selecting their dark mode preference there would feel like a natural choice. Any objections?

kentr’s picture

Seems like it would be simpler / easier / quicker to put it on the user profile form, also. Doesn't Default Admin already do that when the per-user changes setting is enabled?

jurgenhaas’s picture

Yes, we would build back the settings from default_admin as part of this issue anyway.

mherchel’s picture

Yeah, go the easy route for now. Once its built, I'll run it by the UX maintainers again and they can suggest tweaks.

hexabinaer’s picture

Trying to keep my points concise this time ;-)

We should offer an option to keep front-end and back-end theme color scheme in sync.

Gin sets a class gin--dark-mode and only handles the theme's dark mode. What would be soothing for any theme: define and set a theme-agnostic class (dark|light|auto) with any color scheme toggle.

Of course, we could leave that to respective theme development but then users would have to make their choice for each theme separately and would probably find different, incompatible solutions.

kentr’s picture

@hexabinaer

Yeah, I was pushing for that also. But it was determined out of scope for this issue.

I'm planning to work on it from another angle.

pdureau’s picture

Hello all,

This topic is related to #3517033: Add a style utility API because, from a design system point of view, dark mode is a "special" case (with the browser and the CSS having a specific knowledge) of mode switching.

Example of other modes:

  • branding (for multi-brands designs)
  • event (summer vibe, Halloween...)
  • high/low contrast (and other accessibility alterations...)
  • celebration/mourning
  • ...

Ping @grimreaper

mherchel’s picture

Yeah, I have a feeling once that gets in, we'll need to rework the UI a lot to make things usable, accessible, and beautiful.

In the meantime, we'll proceed with adding the setting to the user settings form per @ckrina in #22.

jurgenhaas’s picture

Status: Active » Needs review

The MR now provides the following parts:

  • The color scheme user setting is handled similarly to timezone and language
  • The user setting gets output as data-color-scheme attribute in the html element, defaulting to auto if no setting is available; the user cache context is added
  • The setting is stored in the user entity, similar to timezone and language; an update hook to add this new field is included
  • The dark-mode settings in default_admin are removed

Here are a couple of questions:

  • Should we also add a <meta name="color-scheme"> to the page header? That would tell the browser to render native UI (form controls, scrollbars) in light or dark. Or should that be delegated to the themes?
  • Should this MR also adjust the CSS and JS part of things, or should that be a follow-up for the frontend experts?

As soon as the approach of this MR gets approved, I'll also add tests to it.

mherchel’s picture

Should we also add a to the page header? That would tell the browser to render native UI (form controls, scrollbars) in light or dark. Or should that be delegated to the themes?

No. I don't want to change native front-end UI elements, because the front-end theme might not support dark mode. Themes can rely on the color-scheme CSS property

Should this MR also adjust the CSS and JS part of things, or should that be a follow-up for the frontend experts?

Lets keep it simple for now, and leave the front-end to a different issue.

mherchel’s picture

Status: Needs review » Needs work

Reviewed while on a call today. Changes needed:

  • "Auto" should be first in the list
  • The label should be changed to "Light / dark mode"
  • Instead of outputting the attribute directly on html_attributes, lets output a color_scheme variable in the html.html.twig, and then do the work in that template.

Also, tests are failing :)

jurgenhaas’s picture

Assigned: jurgenhaas » Unassigned
Status: Needs work » Needs review

Addressed all review items from #42 except for the handling of the html attribute. We've discussed that on Slack:

jurgenhaas

@mherchel regarding the dark mode change to explicitly set the data attribute in Twig templates, it feels a bit awkward now that I look into the required change. Current:

# In the hook
$variables['html_attributes']['data-color-scheme'] = $this->currentUser->getColorScheme();

# In Twig
<html{{ html_attributes }}>Making this explicit would look like this:
# In the hook
$variables['color_scheme'] = $this->currentUser->getColorScheme();

# In Twig
<html{{ html_attributes.setAttritbute('data-color-scheme', color_scheme) }}>

So, instead of setting the attribute directly, we still set a variable at the same place in the code, only to make the Twig code significantly more complex. Really?

mherchel

My thought process is that the themer might want to use the variable in other places

can we change $this->currentUser->getColorScheme() to just color_scheme?

jurgenhaas

$this->currentUser->getColorScheme() is needed to get the value in the hook. And this value is either passed to html_attributes/color_scheme or to color_scheme. For the latter, we then need to do extra work in every html twig template. For the former, nothing else is needed.

I see your point that themers may want to use that elsewhere, but would that even be required if the root element has the data attribute?

mherchel

Maybe? Maybe not. If you feel strongly, you can leave as-is. We can always change stuff around later, or people can do it in proprocess

I left it for now as the code is significantly simpler, and the other use case is (a) unclear and (b) may be achievable anyway.

Also, all tests are now green and this issue is ready for another review.

pdureau’s picture

I agree $variables['html_attributes']['data-color-scheme'] is too specific. This attributes will depend of the design (system) implementation in the theme.

Examples:

Sometimes this attribute or class can be added only on specific elements, like HTML or BODY, HTML, sometimes anywhere.

That's why I believe ticket must be done and merged hand-to-hand with #3517033: Add a style utility API. Here, we manage:

  • User specific value, extending User/Account/Session API and managing the related cache
  • Specific settings for admin_theme

In #3517033: Add a style utility API, we miss the user related part, but we manage:

  • declaration of modes in theme (with plugin definition): the values, the meta, the renderable alterations...
  • in a more generic way (not only dark/light)
kentr’s picture

I agree with everyone else about the importance of exposing the setting to frontend themes, with @pdureau about the value of making it more agnostic, and with @mherchal and @jurgenhaas that it can be done later and that there's a workaround available (aka, preprocess, possibly even twig).

I opened #3613964: [PP-2] Make dark mode a first class citizen of Drupal core, Part 2 for making those improvements.

jurgenhaas’s picture

In my view, the dark-mode setting is different from all other theme and style settings: it is a global preference that's important for both the admin and the default theme. That's not the case for other preferences. And whether a theme (again, either admin or default, i.e. frontend) will leverage that data attribute or not, is not being enforced.

Therefore, the narrow scope of this issue seems like what would be an important improvement to core in its own right.

kentr’s picture

Is this issue supposed to affect the color scheme for the Navigation UI, or just move the setting?

For me, the Navigation UI is still light when I choose dark mode and go to the frontend.

In my view, the dark-mode setting is different from all other theme and style settings: it is a global preference that's important for both the admin and the default theme. That's not the case for other preferences. And whether a theme (again, either admin or default, i.e. frontend) will leverage that data attribute or not, is not being enforced.

Yeah, for me it's not about treating this like the other preferences but about exposing this one as a template variable instead of a data attribute on the html element (pretty much what @mherchel suggested).

But I do think that can be done in a followup. That was my intention with #3613964: [PP-2] Make dark mode a first class citizen of Drupal core, Part 2.

kentr’s picture

Or maybe a template variable in addition to a data attribute on the html element.

jurgenhaas’s picture

Issue summary: View changes

Is this issue supposed to affect the color scheme for the Navigation UI, or just move the setting?

For me, the Navigation UI is still light when I choose dark mode and go to the frontend.

This issue is just about the infrastructure of all this. The styling part will have to be addressed in separate issues, see #41.

Or maybe a template variable in addition to a data attribute on the html element.

I think that's a nice idea: let's be code efficient by leveraging the available html attribute handling, but also provide the tools for theme developers to do extra stuff if they want to. Best of both worlds.

I've implemented that and added this in a new commit to the MR which is still NR. At the same time, I've moved the attribute handling away from SystemThemeHooks to ThemePreprocess which is core's canonical place for doing this. The previous approach was not ideal.

mherchel’s picture

Status: Needs review » Reviewed & tested by the community

This looks absolutely fantastic.

I ran through lots of testing trying to break anything and I could not.

I tested this by:

  • Verifying the value within the data-color-scheme attribute on the HTML element.
  • Changing the value and reverifying it.
  • Opening in an incognito window and verifying that anonymous is still set to auto
  • Manually tested the new color_scheme variable within the Olivero theme to verify that it outputted as expected.

In addition @jurgenhaas has followup issues created for themes and the navigation to implement the styling for this:

And we have a change record at https://www.drupal.org/node/3614867 !

amateescu’s picture

Status: Reviewed & tested by the community » Needs review

Reviewed and posted a couple of comments.

jurgenhaas’s picture

Status: Needs review » Reviewed & tested by the community

Thank you @amateescu for your comments in the MR. I've responded to both threads, and as I think there's nothing to change, I've sent this issue back to RTBC as it was before. Please switch back if you disagree with any of that.

gábor hojtsy’s picture

I reviewed the whole thing top to bottom and it looks good to me, other than the one comment about update function naming that I left :) Let's confirm that.

poker10’s picture

Status: Reviewed & tested by the community » Needs review

Thanks for working on this.

I have a few questions and points to consider:

  1. I think we should allow a site admin to set the default value without allowing to override it on a per-user basis (currently in the MR it seems like it is always possible to set it per-user). There are different use-cases where admins might want this. One of these may be, that we are adding a new cache context, which will multiply cache records and therefore a site admin may want to keept it as light as possible.
  2. Is the default value of "auto" correct? Currently the default value is light, as we do not have dark mode in Claro. If we are going to switch to stable Default admin, then correct default value for me would be "light" to keep BC/consistency.

The point 1 seems most important to me and I think we should consider all consequences, as we are adding a new base field to the User entity and a new cache context.

mherchel’s picture

@poker10 Great questions:

I think we should allow a site admin to set the default value without allowing to override it on a per-user basis (currently in the MR it seems like it is always possible to set it per-user).

We discussed this (me @jurgenhaas, @mgifford, and there may have been others). There's a number of questions that we'd have to figure out, and the implementation would be much trickier. IIRC @mgifford had some accessibility concerns about letting admins hard code it. That all being said, I agree with you that admins should be able to hard code it (although I don't feel super strongly). We might have a followup already created, but if not, I'm happy to create one. Edit: Followup is at #3618721: Consider allowing site admins to set global values for light/dark mode

Is the default value of "auto" correct?

We actually changed this to "auto" by default in #3604071: Change default to auto for light/dark mode. You can checkout the discussion there, but it mainly comes down to accessibility.

mherchel’s picture

Status: Needs review » Reviewed & tested by the community

I couldn't find a that issue so I opened up #3618721: Consider allowing site admins to set global values for light/dark mode as a followup.

Setting back to RTBC per #52

mherchel’s picture

And getting that into 11.4 to receive real user feedback before it becomes stable would be important. Getting that no sooner than 11.5, which happens at the same time as 12, would be too late for that. But I'm not sure if that's achievable.

I this does not go into 11.4.x, that means the theme will diverge a bit, which (while not impossible), will make continuing improvements more difficult.

As @jurgenhaas said, anything not going into 11.4.x will be brand new to module maintainers for 12.0.0, and they may not be ready for that.

So ideally, I'd like to keep 11.4.x, 11.5.x, and main as close as possible, so maintainers can test out their projects in anticipation of a stable theme in 12.0.0.

longwave’s picture

I haven't tested the MR but it looks like this will add the setting unconditionally for all users - on many sites this might not make sense if the front end theme does not support dark mode and the user has no admin access. Should this be gated behind a permission, or a theme flag where the theme actually specifies whether it supports dark mode?

longwave’s picture

Status: Reviewed & tested by the community » Needs work

Discussed with @mherchel in Slack who will consider the UX issues I raised above.

The two simple ways I see are a "edit dark mode setting" permission, or only considering admin theme dark mode for now and reusing the "use the administration theme" setting, although even the latter risks confusion if a site is still using Claro.

poker10’s picture

My concern about the performance somehow overlaps with @longwave's question about the relevance of this settings for users without access to a theme that will support it. If I am not mistaken, the hook page_attachments will add the new cache context also on frontend themes which will not support dark mode (like a lot of custom themes) and it will unnecessarily multiply cache records in some cases (when users will change the setting).

In case we will limit this by a new permission (like the "edit dark mode setting"), we can somehow mitigate this until the follow-up #3618721: Consider allowing site admins to set global values for light/dark mode is done. But if we change the scope only to Default admin and we will use the "use the administration theme" permission, then I am not sure this will be enough to mitigate the possible performace impact on some sites. So I do not think this can be fully moved to a follow-up, we probably need to think about it here too.

longwave’s picture

@poker10 what if themes explicitly have to declare dark mode support, then we only add the data attribute and the context if such a theme is in use?

kentr’s picture

Individual user choice is very important.

@mgifford also commented in #19.

Maybe changing the label for the "Auto" option to "System" would make it clearer what it actually does.

The UX team also discussed this in last Friday's usability meeting. I don't speak for them, but here's the recording.

what if themes explicitly have to declare dark mode support, then we only add the data attribute and the context if such a theme is in use?

+1

Other thoughts:

  • Store the setting client-side, like the Dark Mode Toggle module and admin compact mode (#3584347: Deprecate and replace system_admin_compact_mode()).
  • Put the control in a separate module (possibly experimental for now).
    Can the module depend on the Default Admin theme until some sort of API for per-theme declaration of support is built?
jurgenhaas’s picture

Status: Needs work » Reviewed & tested by the community

As this is foremost a UX improvement, and user expect dark-mode support from systems they use, I don't see why an admin should limit the options a user can choose from.

However, making this more fine-grained by determining if and how the setting should be offered to users. This would require the themes to declare what they support, very much like proposed in #61. The map would then look like this:

  • If neither the frontend nor admin theme supports dark mode: no setting available
  • If both themes support dark mode: setting available
  • If either the frontend or the admin theme supports dark mode:
    • If frontend supports it but not admin theme: setting available
    • If admin supports it but not frontend: setting available if the user has the permission to access the admin theme

    The setting, if available in this scenario, gets an additional information in the description that explains that situation to the user.

This seems a fairly simple and straight forward enhancement of the current implementation. I just wonder if the new theme declaration should be called "supports dark mode" or if it should rather be "support color scheme" as the latter is the attribute that goes into the html tag.

jurgenhaas’s picture

Status: Reviewed & tested by the community » Needs work
poker10’s picture

Re #61 - Yes, I think that this might work until the follow-up is done.

As this is foremost a UX improvement, and user expect dark-mode support from systems they use, I don't see why an admin should limit the options a user can choose from.

@jurgenhaas The why may be a pure performance point of view. On some sites, the performance is way more important than usability. For example we have few sites where the performance was crucial and we needed to optimize a lot of things beyond what is done on "standard" sites. I think that keeping the cache as small as possible is a reasonable requirement on some sites.

We try to make the Drupal core as thin as possible, removing modules, optimizing queries and so, so I do not see a reason why whe should introduce here a new unconditional feature, that will affect performance, without possibility to turn it off where needed. Though I agree that it could be done in a follow-up already created by @mherchel (#3618721: Consider allowing site admins to set global values for light/dark mode) - if the implementation here, in this issue, will not add the new cache context unconditionally.

mgifford’s picture

This should be a user choice. It is ultimately about user preference. And admin may prefer dark mode, but others prefer light mode. It may affect their ability to use the site, especially sticking to the status quo of light mode.

However, I'm now starting to think that the site admin should be able to set the default value. Caching might be an issue as @poker10 suggested, but I think a bigger one is that the site might just not work well in dark mode. We might get Drupal Core working great, but what about the site theme. What about the modules that are involved.

It seems more practical to set light/dark to auto by default, but allow the site admin to turn it off. Possibly per theme or per site. Ultimately, I think that site admins are going to hear if light/dark mode doesn't work. I also expect the more control we give to the site admins to address this the better it will be to handle the transition to better supporting user preferences.

I don't have a preference about changing the label for the "Auto" option to "System".

@jurgenhaas should modules have the ability to declare light/dark mode support?

@poker10 what are the light/dark mode patterns that cause the largest performance issues? Surely there are many, if built correctly, have little or no impact. SVGs for instance.

jurgenhaas’s picture

Issue summary: View changes

I've updated the IS, mainly because we need a clean summary for our UX team to digest the issue and help us find the answers to outstanding questions.

ckrina’s picture

In general, I'd really try to move things to follow-ups:

  1. What is this feature called in the UI? Color scheme for the label should be enough, no need to reinvent the wheel. A (short) description can be added with more info.
  2. What should the third option be called? "Auto" is the value in Mac changes the setting based on the time of the day, so I’d go with System (but I don't think it's a big deal). And I’d just make it easy to clarify with a (very short) description like “System follows the setting from your operating system or browser.” I’d just order it Light, Dark, System as most conventions.
  3. What should the control look like? I’d really recommend starting simple and add improvements later on. 3 radios + description. No icons, no extras. UI improvements can be a follow-up, let’s focus on making the controls available here.
  4. Is the user profile form the right home? Yes. No tabs, UI improvements can con later in a follow-up if eventually gets crowded and someone comes up with a better proposal.
  5. How do we word the partial-support case? Again, I’d just ship the basics: I’d go with a “Applies wherever this site supports it.” (I’ll let the English native speakers come up with appropriate wording). Even the control of hiding/showing the setting if not available on any theme could go into a follow-up, so the essential work gets in faster.
  6. Hide the setting, or show it disabled with an explanation? Agreed that not showing it if not available would the best in terms of UX, but I’d recommend a follow-up for it. It’s a really cool nice to have, but the core feature can be shipped without this. Either way, I won't get into cache, only UX.
  7. Should a site administrator be able to set the default, or lock it? This one is tricky. I’d say this is not the admin theme responsibility: we should provide the tools for admins to change it, but I’d argue the wording of the label should always be “Color scheme “ plus a description that suggests it's a preference if the admin has the capacity to override it. So:
    • - yes, in favor of making a setting for an admin. I’d argue not a blocker for the user feature though.
    • - agreed on the admin setting not overriding the user preference by default. Turning off the feature for the site as an alternative seems more sensible.
  8. Naming the capability declaration. “supports color scheme”+1
  9. Should modules be able to declare support too, I'd argue themes only, and modules should make styling compatible. Shared color custom properties (#11) are what will let them do that, which makes #3517033: Add a style utility API a really nice to have, but not a blocker.
  10. Live preview. Great follow-up :)
emma horrell’s picture

Adding to Cristina’s comments:

1. What is this feature called in the UI? Color scheme for the label should be enough, no need to reinvent the wheel. A (short) description can be added with more info.

Agreed – color scheme fits with the accepted convention

2. What should the third option be called? "Auto" is the value in Mac changes the setting based on the time of the day, so I’d go with System (but I don't think it's a big deal). And I’d just make it easy to clarify with a (very short) description like “System follows the setting from your operating system or browser.” I’d just order it Light, Dark, System as most conventions.

Agreed – Light/Dark/System – think System is better than Auto as it implies following what the system has set (rather than being ambiguous about where the ‘auto’ is coming from)

3. What should the control look like? I’d really recommend starting simple and add improvements later on. 3 radios + description. No icons, no extras. UI improvements can be a follow-up, let’s focus on making the controls available here.

Agreed use existing patterns – since it’s a choice of one of 3 then radio buttons seem a good fit

4. Is the user profile form the right home? Yes. No tabs, UI improvements can con later in a follow-up if eventually gets crowded and someone comes up with a better proposal.

Agreed – fits with this being something the user applies preferences to, so sits with their profile

5. How do we word the partial-support case? Again, I’d just ship the basics: I’d go with a “Applies wherever this site supports it.” (I’ll let the English native speakers come up with appropriate wording). Even the control of hiding/showing the setting if not available on any theme could go into a follow-up, so the essential work gets in faster.

The user needs to know that it’s partially supported and needs to be directed to where it’s not supported so they can address this – so if it’s theme dependent I would go with: “Applies where supported by site theme”

6. Hide the setting, or show it disabled with an explanation? Agreed that not showing it if not available would the best in terms of UX, but I’d recommend a follow-up for it. It’s a really cool nice to have, but the core feature can be shipped without this. Either way, I won't get into cache, only UX.

Unclear exactly which setting is referred to here, but individual users should be able to change their interface from light/dark based on preference (and user profile is a logical place to do this) and this should apply consistently across their interfaces.

7. Should a site administrator be able to set the default, or lock it? This one is tricky. I’d say this is not the admin theme responsibility: we should provide the tools for admins to change it, but I’d argue the wording of the label should always be “Color scheme “ plus a description that suggests it's a preference if the admin has the capacity to override it. So:
• - yes, in favor of making a setting for an admin. I’d argue not a blocker for the user feature though.
• - agreed on the admin setting not overriding the user preference by default. Turning off the feature for the site as an alternative seems more sensible.

Agreed admin setting good to have but user preference takes priority

8. Naming the capability declaration. “supports color scheme”+1
Agreed

9. Should modules be able to declare support too, I'd argue themes only, and modules should make styling compatible. Shared color custom properties (#11) are what will let them do that, which makes #3517033: Add a style utility API a really nice to have, but not a blocker.
I would say this lives with themes.

10. Live preview. Great follow-up :)
I would say on save would be the expected behaviour here.

jurgenhaas’s picture

Assigned: Unassigned » jurgenhaas
Issue summary: View changes

Thank you @ckrina and @emma horrell for your real quick response. I've updated the IS once again by including your response in there, and will now start working on the implementation.

jurgenhaas’s picture

Assigned: jurgenhaas » Unassigned
Status: Needs work » Needs review

This is now implemented as described in the IS.

Note for testers and reviewers

If you have an existing site to which you apply the patch or MR, please run drush updatedb. This creates a new base field for users in the database. Without that, the new settings in the user profile will not be stored.

Note for UX/UI tests

The only visible change you can see and what needs the input of a native english speking UX expert is in the user profile edit form at the bottom before the submit buttons. If a site support color-scheme, the widget will be enabled, or disabled otherwise. The only way right now to enable it is to use the default_admin theme.

The description to that widget depends upon the context:

  • Frontend and admin support color scheme: "System follows your operating system or browser setting. Applies where supported by site theme."
  • Only frontend supports color scheme: "System follows your operating system or browser setting. The site follows this setting, administration pages do not."
  • Only admin support color scheme and current user has permission to use it: "System follows your operating system or browser setting. Administration pages follow this setting, the rest of the site does not."
  • Only admin support color scheme and current user DOES NOT have permission to use it: "Only administration pages follow this setting, and this account does not use the administration theme. The setting has no effect."
  • Otherwise: "Neither the site theme nor the administration theme follows this setting. The setting has no effect."

Please let us know if and how we should adjust those descriptions.

Note for code reviews and technical tests

Please refer to the decision-tree in the IS to see the various scenarios that can happen. For all scenarios where the setting in the user profile is enabled, you should expect the data-color-scheme attribute in the html-element of every page you visit. Yes, also in the frontend even if the frontend theme doesn't support color-scheme. This is necessary in order to style the navigation and the top bar correctly. For scenarios where the settings in the profile will be disabled, there should never be any such attribute in the html-tag.

For those who wonder why the MR has to change so many test files, this is necessary to cover all the cache tag tests. More details about that in the MR description.

emma horrell’s picture

Reviewing the descriptions:

It is good UX practice that, as the user seeks to choose between system, light and dark mode they know the dependencies associated with their choices, and they know the options that are unavailable to them and the reasons why (instead of these just being hidden)

Reviewing the wording as a native English speaker, I recommend some tweaks to follow a consistent pattern of wording, as below in bold:

  • Use case 1: Where frontend and admin support color scheme: System follows your operating system or browser setting. Applies wherever your site’s theme supports it.
  • Use case 2: Where only frontend supports color scheme: System follows your operating system or browser setting. The site follows this setting, administrative pages do not.
  • Use case 3: Where only admin supports color scheme and the user has permission to use it: System follows your operating system or browser setting. Administrative pages follow this setting, the rest of the site does not.
  • Use case 4: Where only admin supports color scheme and the user does not have permission to use it: This setting has no effect on your account. Only administration pages support it, and this account does not use the administration theme.
  • Use case 5: Where admin does not support color scheme and the user does not have permission to use it: This setting has no effect. Neither the site nor the administration pages support it.
poker10’s picture

Component: other » theme system
Category: Task » Feature request
Status: Needs review » Needs work
Issue tags: +Performance, +Needs change record, +Needs release manager review

Thanks everyone for great work here so far!

For all scenarios where the setting in the user profile is enabled, you should expect the data-color-scheme attribute in the html-element of every page you visit. Yes, also in the frontend even if the frontend theme doesn't support color-scheme. This is necessary in order to style the navigation and the top bar correctly.

From the performance point of view it looks better than it was before - it now adds the cache context for all pages (even the frontend ones) only for users with "view the administration theme" permission.

But still, what are the options how to solve this fully and do not add the cache context if the active theme does not support the dark mode (looking at this in regards of passing the performance gate when considering the theme stable)? It is definitelly not good to multiply cache size/records on pages of themes, which does not support this new feature (and for this to happen with the current MR, all it takes is three editors with "view the administration theme" permission, each of whom sets a different value for the new field).

When looking at the Default admin now - if I set the dark mode, the Navigation is not dark on frontend theme/Olivero (only on admin theme). So probably we are out of scope here, when considering the cache context for frontend themes due to Navigation/Topbar look? Should the support for Navigation/Topbar dark mode be fully moved to a follow-up (including the specific part of the cache context addition)? Then we will be able to skip the context addition for the anything exept the actual active theme with dark mode support for now (and we can figure it out later). See also this from issue summary:

Explicitly out of scope (each has its own issue, see below)
- Any CSS or JS work - actually making core themes and the Navigation module look dark. This issue only ships the signal; nothing will visually change from it alone.

Adding some additional tags and updating the category, as this no longer seems to be a task.

PS: Please also note, that as per current policies, it is required to disclose the use of AI in MRs/descriptions/comments - see here: https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquett... .

Thanks!

jurgenhaas’s picture

@poker10, getting the navigation and top bar following dark-mode has been the advent for this issue in the first place. That's how all this began. There has been the agreement, that if a user switched to dark-mode and see those components in dark when visiting admin pages, then that should be maintained when going to frontend pages as well.

You're right, default admin doesn't do that yet, which is a regression.

Gin does it by leveraging the gin_toolbar module. This is because an admin theme cannot inject anything into a frontend theme. But the helper module gin_toolbar can.

Please also note, that as per current policies, it is required to disclose the use of AI

You can find that disclosure in the IS. If this is required for the MR likewise, I do apologize and will of course add it there as well.

I'm not sure about the status of the issue and leave it at NW for now.

poker10’s picture

@poker10, getting the navigation and top bar following dark-mode has been the advent for this issue in the first place. That's how all this began. There has been the agreement, that if a user switched to dark-mode and see those components in dark when visiting admin pages, then that should be maintained when going to frontend pages as well.

Thanks for pointing that out, I missed this when re-reading the issue today. There was a point raised in #3, how it will look when the Navigation is in dark mode on a frontend theme, which does not support dark mode. Was this discussed/addressed within the UX team? Is it better to have light frontend theme with dark Navigation (like the MR proposes) or is it better to keep dark Navigation only on themes which support dark mode?

For me (but I am not an UX expert) it will be better if the Navigation/Topbar align with the settings of the currently active theme. That means, if a user has the dark mode set, Default admin will be dark (and Navigation/Topbar on backend pages will be dark too), but if the frontend theme does not support dark mode, it will stay light (both the theme, and the Navigation/Topbar on frontend pages). It will be still an improvement to the current state, because now is the frontend theme/Navigation/Topbar light regardless of the fact whether the frontend theme supports dark mode.

You're right, default admin doesn't do that yet, which is a regression.

Gin does it by leveraging the gin_toolbar module. This is because an admin theme cannot inject anything into a frontend theme. But the helper module gin_toolbar can.

Not sure this is a regression in Drupal core, as Drupal core did not have this in the past and Gin is not a core theme. I see that more as a feature request. But if it was planned for this issue, then OK.

Also correcting the tags - I meant to add a different tag for CR (there is a change record, but needs to be updated for latest changes).

Thanks!

jurgenhaas’s picture

Assigned: Unassigned » jurgenhaas

Thanks for pointing that out, I missed this when re-reading the issue today. There was a point raised in #3, how it will look when the Navigation is in dark mode on a frontend theme, which does not support dark mode. Was this discussed/addressed within the UX team?

Yes, and my rewrite in #67 probably lost this important point. You can still see it in the first paragraph of the diff. That was triggered by discussions with UX. I we need to, we can ask @ckrina or @emma horrell to re-clarify that once more.

I'll get to the CR update later today.

gábor hojtsy’s picture

@poker10: re what Navigation and toolbar should follow there is lots of effort in #2313309: Admin toolbar, Navigation and contextual links should always be rendered in the admin language (if set) to make those follow the admin language on frontend pages. I think the more we make the admin pieces of UI consistent across Drupal, the more it will make sense if the design of it also follows the admin theme.

lauriii’s picture

Coming to this late as product manager. I want to make sure we have clarity on the expected behavior.

One user preference is right and Navigation has to honor it whether or not the front-end theme does. So the expected behavior:

  • An editor who chooses dark gets a dark Navigation, top bar, and admin UI everywhere, including over a front-end theme that isn't compatible with color schemes.
  • The front-end theme itself changes only if it has opted in.

Without the first point we still get the flip described in the issue summary; light toolbar on the front end, dark admin screen one click later. That's the thing the issue set out to fix, and most sites will have a front-end theme that doesn't opt in for a long while.


On the cache context: is the variation actually server-side, or only in the emitted attribute? If nothing depends on the value in PHP, could we implement this purely on the client-side? Worth establishing whether we need it at all because much of #54–#65 is spent mitigating a cost we may not have to pay.

catch’s picture

The cache context is being added because the html attribute is being added directly in preprocess, but it ought to be possible to use a render placeholder instead. If it's a render placeholder, we don't need the cache context.

Render placeholders for attributes are slightly fiddly but we did them for CSRF tokens for example: #2351015: URL generation does not bubble cache contexts.

edit: I crossposted with @lauriii but implementing it client side would also solve this if we put it in a cookie or local storage or similar.

mherchel’s picture

My main concern about clientside or a placeholder is a flash of unstyled content.

If in dark mode, we don't want the site to briefly flash white on every page navigation.

quietone’s picture

nevergone’s picture

@mherchel The content does not flash, for example, we actively use the Dark Mode User module on the https://hup.hu/ portal. User feedback has been very positive so far.

mherchel’s picture

@nevergone Do you use a render placeholder or clientside JS?

catch’s picture

The render placeholder can be excluded from big pipe, so that it's always rendered blocking in the main page request, iirc this is the case for any HTML attribute and big pipe, but even if it wasn't, we've got an explicit opt-out available https://www.drupal.org/node/3511562

The only difference is that dynamic page cache entries won't need to vary by the cache context, because they'll cache a placeholder which is swapped in later, but in terms of what the browser gets, it's exactly the same.

nevergone’s picture

@mherchel: We store user settings in userData and pass them to display using hook_js_settings_alter(). So far, no one has reported any performance issues.

larowlan’s picture

Late to the party but I am also surprised to see this was implemented in the theme layer/as a backend option.

Given the approach in #3584347: Deprecate and replace system_admin_compact_mode() to move away from doing this sort of user-level customisation at the backend layer I was expecting this would have been a pure front-end implementation - e.g. something with local storage and drupalSettings.

I see @catch and @lauriii have also expressed that.

I see @mherchel pointed out there would be a flash of the wrong style content if that were the case - is that the only reason?

I'm concerned about the cache fragmentation with this being a largely global cache context.

mherchel’s picture

is that the only reason?

The primary reason we need it in a module is that when the theme is set to dark mode, the Navigation Toolbar will switch between light and dark.

We'd like the settings to render server-side, so we don't have a flash of unstyled content. From my untrained eye, it looks like @catch's solution in #84 might be the solution.

Feel free to post comments.

longwave’s picture

Another thought is does this have to be a core feature enabled for everyone, or should it be a module?

If auto mode is supported by a theme and that is the default then we already just follow the preference set in the browser; this might be enough for some/many sites? Moving the user preference setting to a module would mean the site owner can easily enable this feature if they want it for their users, but it's not forced on them.

In turn this sidesteps some of the performance concerns because it becomes optional, although it would be good to still solve the cache issues described here.

@mherchel as I understand it it's not exactly unstyled content, more that if the default is light and the user selects dark (but not via auto mode) there might be a flash of light before the page settles, because we can't guarantee to inject the data attribute from JS before first paint?

catch’s picture

I would expect that if we use inline js for this in the header then it will be fully render blocking, however it would probably also cause a recalculate styles?

Got an issue somewhere to try to remove the .js class for similar reasons, will try to find that later.

mherchel’s picture

If auto mode is supported by a theme and that is the default then we already just follow the preference set in the browser; this might be enough for some/many sites?

The problem is that the Navigation module should also support dark mode. And it needs to be consistent whether the Admin theme is active or not.

I would expect that if we use inline js for this in the header then it will be fully render blocking, however it would probably also cause a recalculate styles?

Yeah we could use render blocking inline JS in the header that would work and would probably negate. It'd be super quick. I don't think it'd recalculate styles, but it would delay them (milliseconds though. It'd be 3 lines of inline JS)

mherchel’s picture

Something like this would be super fast.

<script>
document.documentElement.setAttribute('data-color-scheme', localStorage.getItem('colorScheme') ? 'auto');
<script>
catch’s picture

I got recalculate styles and layout invalidation mixed up. #2413847: Remove usages of .js class from core is the issue about the .js class.

However, could we default to 'auto' in the HTML, and then only change the attribute if it's customized? That ought to prevent layout invalidation unless it's customised, and would also ensure the class is there if someone has js actively disabled in their browser then - and auto seems fine for graceful degradation in that case.

kentr’s picture

If auto mode is supported by a theme and that is the default then we already just follow the preference set in the browser; this might be enough for some/many sites?

It's also about individual users.

When one of the modes is poorly-implemented by a given theme, it may be fine for one user but not for another. Users might need to deviate from their system settings to make the site usable. We can do our best, but there's a decent chance that we won't make our light & dark modes work for everyone who would prefer that color mode on another site.

Other users may prefer to have their system in one mode but use websites in another.

mgifford’s picture

There are definitely people who are light sensitive who may be affected by this.

Some useful resources:

It is definitely an overlooked accessibility issue. Flashing 3X is a WCAG issue, but not once.

It is just unpleasant for most folks though to be in dark mode. To have dark mode and then just have a momentary flash of light when you've specifically set your browser (and the site) not to have one.

It would be good to avoid this for usability.

pdureau’s picture

StatusFileSize
new49 KB

Hello all,

The ongoing work here is so exciting 🤩 can't wait to use this feature in my projects

For information, we are currently adding a notion of "mode" to #3517033: Add a style utility API in order to be able to conciliate in #3613964: [PP-2] Make dark mode a first class citizen of Drupal core, Part 2:

  • the work done here (light/dark color scheme as a site setting and an user preference)
  • with the design system methodology promoted by the Style API, with:
    • the ability to have other modes than light/dark color scheme, like low/high contrast, reduce motion...
    • the decoupling between modes and themes ("themes" as design system themes, not as Drupal themes)

About this decoupling, for example, Daisy UI has many themes: https://daisyui.com/docs/themes/, some are suitable for light mode, some for dark modes, some for both (with a clever usage of @media (prefers-color-scheme: XXX) {} by the front dev):

  • cupcake: light
  • synthwave: dark
  • corporate: light
  • pastel: light
  • coffee: dark
  • ...

Such decoupling will allow to map, in theme settings, the modes selected by the user and/or the site owner with the corresponding themes from the design system implementation (mockup to explain the mechanism, not an UX proposal for Core):
modes & themes

As far as we know, #3606655: Make dark mode a first class citizen of Drupal core & #3517033: Add a style utility API are compatible and complementary, except one little thing: supports color scheme: true in info.yml may become redundant once the corresponding Style API definition will be added:

# file: default_admin.styles.yml
color_scheme:
  attribute: "data-color-scheme"
  target: html
  type: theme
  options:
    light:
      label: "Light"
      modes: {color: light}
    dark:
      label: "Dark"
      modes: {color: dark}

If you have questions or feedback, I would be happy to discuss about this in the dedicated ticket #3613964: [PP-2] Make dark mode a first class citizen of Drupal core, Part 2 or in slack 🤗

jurgenhaas’s picture

@catch am I getting #92 right by saying we always add the data-color-scheme="auto" server-side without setting a cache context. And only if a user decides to change their settings, we either set the different data attribute or use the javascript approach? The assumption would be, that this shouldn't happen too often anyway.

catch’s picture

#96 yes that was my suggestion - that way we both get a non-js fallback and we only update the DOM if it's customised, which should hopefully avoid a layout invalidation.

jurgenhaas’s picture

Assigned: jurgenhaas » Unassigned
Status: Needs work » Needs review

This is back to NR. The implementation no longer requires any cache context. Instead, it sets the data attribute in the html-tag always to auto. A cookie exposes the chosen user setting for the color scheme, and a tiny embedded javascript in the DOM's head will switch the data attribute to light or dark if needed.

longwave’s picture

Status: Needs review » Needs work

Added several questions to the MR.

jurgenhaas’s picture

Status: Needs work » Needs review

Addressed all the questions and updated the MR.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new98 bytes

The Needs Review Queue Bot tested this issue. The merge request has merge conflicts and cannot be merged. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

jurgenhaas’s picture

Status: Needs work » Needs review

I've addressed @poker10's review and rebased the MR. Back to NR.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

jurgenhaas’s picture

Status: Needs work » Needs review

Rebased the MR and resolved all new conflicts.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

jurgenhaas’s picture

Status: Needs work » Needs review

Rebased the MR and resolved all new conflicts.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new98 bytes

The Needs Review Queue Bot tested this issue. The merge request has merge conflicts and cannot be merged. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

jurgenhaas’s picture

Status: Needs work » Needs review

Rebased the MR and resolved all new conflicts.