Page MenuHomePhabricator

[OOUI] Icons: Add support for use in dark mode
Open, HighPublic2 Estimated Story Points

Description

NOTE: Fixing VisualEditor to appear in night mode will be done as part of T366737

Background

Once OOUI is updated to use the latest version of the Codex design tokens (v1.5 or later), many elements/widgets will be able to automatically adapt to dark mode if MediaWiki users opt in to the alternate color scheme. By default any element which already has the notheme class will get light mode.

For various experiences, where we already enabled night theme for the page, such as https://en.wikipedia.org/wiki/Special:Categories this will result in a dark theme where icons are not legible.

However, OOUI icons currently remain black even on dark backgrounds.

Below is a screenshot of Visual Editor in dark mode if the notheme class is removed (T366737). Many elements of the interface correctly switch colors, but icons in the toolbar remain dark.

Screenshot 2024-05-23 at 2.12.30 PM.png (1×1 px, 208 KB)

User story

As a reader I must be able to see all icons in dark mode.

Acceptance Criteria
  • OOUI icons should not appear white on white in the VisualEditor toolbar (note fixing VisualEditor will occur in T366737)
  • OOUI icons should be inverted in dark mode.
  • Progressive icons should never be inverted
  • Destructive icons should never be inverted
  • Elements which use the notheme class to restrict display to light mode, should not be impacted by the change. e.g. icons inside desktop Echo overlay
  • Elements which use the skin-invert class to restrict display to light mode, should not be impacted by the change. e.g. icons inside mobile Echo overlay
  • Fix needs to apply to Vector and Minerva
  • [ -] Any icons that are broken that are not using standard classes for progressive/destructive icons; not using notheme or skin-invert class should be considered out of scope for sign off of this ticket, and new tickets should be created.

Communication criteria - does this need an announcement or discussion?

N/A

Rollback plan

N/A - beta feature.

This task was created by Version 1.0.0 of the Web team task template using phabulous

Related Objects

StatusSubtypeAssignedTask
OpenJdrewniak
OpenJdrewniak
Openovasileva
ResolvedJdlrobson
Openovasileva
Openovasileva
ResolvedJScherer-WMF
Resolvedovasileva
ResolvedSpikeSToyofuku-WMF
Openovasileva
Openovasileva
OpenNone
OpenBUG REPORTNone
Resolvedovasileva
Openovasileva
Resolvedovasileva
Resolvedovasileva
Resolvedovasileva
Resolvedovasileva
ResolvedFeatureNone
OpenNone
Resolvedovasileva
Resolvedovasileva
Resolvedovasileva
Openovasileva
Resolvedovasileva
Resolvedovasileva
ResolvedBUG REPORTovasileva
ResolvedJdlrobson
ResolvedJdlrobson
ResolvedNone
ResolvedJdrewniak
Resolvedovasileva
ResolvedBUG REPORTovasileva
Resolvedovasileva
Resolvedovasileva
ResolvedJdlrobson
ResolvedJdlrobson
Resolvedovasileva
ResolvedJdrewniak
ResolvedJScherer-WMF
Resolvedovasileva
Resolvedovasileva
ResolvedBUG REPORTovasileva
ResolvedBUG REPORTovasileva
Stalledbwang
OpenNone
Resolvedovasileva
OpenNone
OpenJdlrobson
Openovasileva
OpenBUG REPORTNone
OpenNone
OpenBUG REPORTNone
In ProgressDTorsani-WMF
ResolvedVolker_E
OpenJdlrobson
OpenBUG REPORTNone
OpenNone
OpenNone
Openovasileva
ResolvedNBaca-WMF

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

We've got the inverted icons for any in the icon collection already distributed.
I could see a number of (complex or maintenance risky) ways:
Either use the invert icons for all icon calls by some OOUI JS magic.
Or add a filter to non-progressive and -destructive icons (only grayscale), which would be simple code-wise, but it would only work for one mode (not sepia for example) and only in simple manner for greyscale icons. There it shines as it would let the opacities needed for interactions untouched. On a dark mode skin level

.oo-ui-iconElement-icon:not( .oo-ui-image-progressive ):not( .oo-ui-image-destructive ) {
    filter: invert( 1 ) !important;
}

resulting in

image.png (786×2 px, 171 KB)

We've got the inverted icons for any in the icon collection already distributed.
I could see a number of (complex or maintenance risky) ways:
Either use the invert icons for all icon calls by some OOUI JS magic.
Or add a filter to non-progressive and -destructive icons (only grayscale), which would be simple code-wise, but it would only work for one mode (not sepia for example) and only in simple manner for greyscale icons. There it shines as it would let the opacities needed for interactions untouched.

Thanks @Volker_E@Catrope and I were just talking about what it would take to do this "the right way" in the OOUI icon system as it currently stands, and it seems pretty daunting. We'd probably need to add a -dark version of all existing icon variants in the OOUI Icon Pack json files, then we'd need to update a bunch of stuff in ResourceLoader's ImageModule class. We'd probably want to update that class to spit out CSS that loads the -dark variant of an icon inside a prefers-color-scheme: dark media query, but then we'd also need to pass in an arbitrary selector from the skins to support "forced" dark mode...

This would be a pretty complicated set of changes across both OOUI and MediaWiki.

I like your approach much better in comparsion – it's not a perfect solution but this would actually allow us to deliver usable OOUI dark interfaces within a week or two...

I think that my recommendation would be that we follow this approach and then we can come back and consider a more comprehensive solution if necessary (ideally with some help from the authors of the original OOUI icon system at a time which is convenient for everyone).

That's a great idea @Volker_E , let's pursue that for now since it would be much easier and faster than doing it properly (which we can always do later).

A few things I noticed while trying this out:

  • We would need additional :not()s for the warning, error and success variants (these are less common, but some icons appear to have them, at least in the OOUI icon defs)
  • This covers icons, but not indicators. That's easy to fix though, just add .oo-ui-indicatorElement-indicator to the selector (I don't think the :not()s should be needed since indicators don't seem to have variants other than invert)
  • Checkboxes use a combination of an icon class and a background color, which results in them being inverted to yellow:
    image.png (457×992 px, 75 KB)

Those all seem fixable though. The checkbox one looks annoying but I'm sure we can figure something out.

Yeah, I was too lazy before to add the -indicator and error, warning and success selectors before into that POC example. It's great to limit to -indicator only, that's handy.
The OOUI CheckboxWidget, as it mixes the widget class and the icon class onto the same element could either be handled as
:not( .oo-ui-checkboxInputWidget-checkIcon ) or as :not( .oo-ui-widget.oo-ui-icon-check )

We could also combine this rule with another selector to help Vector:

.vector-dropdown .vector-dropdown-label:not(.cdx-button--icon-only)::after {}

image.png (86×210 px, 5 KB)

Resulting in code:

.oo-ui-iconElement-icon:not( .oo-ui-image-progressive ):not( .oo-ui-image-destructive ):not( .oo-ui-checkboxInputWidget-checkIcon ), 
.oo-ui-indicatorElement-indicator,
.vector-dropdown .vector-dropdown-label:not(.cdx-button--icon-only)::after {
    filter: invert( 1 ) !important;
}

For readability it might be preferable to undo the filtering on error, warning, success, maybe also destructive and progressive.

Apart from Notifications, that looks pretty good on Special:Preferences and Special:RecentChanges. It might not even need the !important depending on where the style module would be loaded. Only a special treatment for the filter icons on RCFilters were needed.

Special:RecentChanges:

image.png (874×2 px, 229 KB)

CCiufo-WMF renamed this task from OOUI Icons: Add support for use in dark mode to [OOUI] Icons: Add support for use in dark mode.Fri, May 24, 2:12 PM
CCiufo-WMF removed a project: Epic.
CCiufo-WMF set the point value for this task to 5.Tue, May 28, 6:28 PM

I was thinking of this issue myself today, the approach that I initially thought of was to use the .skin-invert class on all OOUI icons (in both PHP and JS). That approach is similar to what @Volker_E suggests, but instead of hardcoding the invert, it uses a class instead. I created a patch for what that would look like here: https://gerrit.wikimedia.org/r/c/oojs/ui/+/1037102 . The .skin-invert class would produce slightly incorrect colors for colored icons in dark-mode, but it would at least flip black icons to white.

I was thinking of this issue myself today, the approach that I initially thought of was to use the .skin-invert class on all OOUI icons (in both PHP and JS). That approach is similar to what @Volker_E suggests, but instead of hardcoding the invert, it uses a class instead. I created a patch for what that would look like here: https://gerrit.wikimedia.org/r/c/oojs/ui/+/1037102 . The .skin-invert class would produce slightly incorrect colors for colored icons in dark-mode, but it would at least flip black icons to white.

If we can use an existing class (and apply it directly within OOUI) to apply this fix, then even better. We are okay with slightly incorrect colors as long as things are legible.

Change #1037102 had a related patch set uploaded (by Eric Gardner; author: Jdrewniak):

[oojs/ui@master] [WIP] Add `.skin-invert` class to OOUI icons

https://gerrit.wikimedia.org/r/1037102

Change #1038415 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/MinervaNeue@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038415

Change #1038418 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/Vector@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038418

Jdlrobson subscribed.

The web team will handle this ticket. This is not a blocker for switching OOUI to use CSS variables and REMs. The expectation is that some pages/experiencing using OOUI will continue to appear in light theme after the OOUI release and will need additional work on our side to get them ready (including fixing up icons)

Web team will discuss our options and decide what to do here.

Change #1038910 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] Use mask-image for all Vector icons

https://gerrit.wikimedia.org/r/1038910

Change #1038911 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/core@master] POC: Support mask-image in ResourceLoader ImageModule

https://gerrit.wikimedia.org/r/1038911

Change #1038914 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/MinervaNeue@master] Icons render consistently in night mode

https://gerrit.wikimedia.org/r/1038914

Change #1038918 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] VisualEditor toolbar should use notheme

https://gerrit.wikimedia.org/r/1038918

I took some time to think about this and write some things down and try out a few proof of concepts, but as I understand it the main thing DST team needs from the web team right now is clarity on what it needs to deliver. I've created T366709 for making that decision.

Change #1038918 merged by jenkins-bot:

[mediawiki/skins/Vector@master] VisualEditor toolbar should use notheme

https://gerrit.wikimedia.org/r/1038918

Just to provide an update:
The web team is discussing different solutions to this problem internally. Once we feel like we have agreement on our preferred approach we will reach out to the DST team to discuss this. In the mean time the DST should not concern itself with making icons work correctly in the night theme (but is welcome to explore any ideas they might have for when we have that discussion!).

[FYI] The patch merged above was a defensive patch to make sure VisualEditor toolbar uses the light theme for now, by adding the notheme class (which is what we do for other elements in the page) so that we can opt into the night theme when we are ready.

Jdlrobson updated the task description. (Show Details)
Jdlrobson removed the point value for this task.Thu, Jun 6, 6:11 PM

I think the patches reflect the acceptance criteria, and the acceptance criteria should cover all the exceptions I am aware of.

Jdlrobson set the point value for this task to 2.

Change #1037102 abandoned by VolkerE:

[oojs/ui@master] [WIP] Add `.skin-invert` class to OOUI icons

Reason:

Abandoned for Web team taking the lead here. Could be resurrected in case.

https://gerrit.wikimedia.org/r/1037102

Change #1038415 abandoned by VolkerE:

[mediawiki/skins/MinervaNeue@master] styles: Apply inversion on certain OOUI icons and indicators

Reason:

Abandoned for Web team taking the lead here. Could be resurrected in case.

https://gerrit.wikimedia.org/r/1038415

Change #1038418 abandoned by VolkerE:

[mediawiki/skins/Vector@master] styles: Apply inversion on certain OOUI icons and indicators

Reason:

Abandoned for Web team to take the lead here. Can be resurrected if needed.

https://gerrit.wikimedia.org/r/1038418

Change #1038418 restored by Jdrewniak:

[mediawiki/skins/Vector@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038418

Change #1038415 restored by Jdlrobson:

[mediawiki/skins/MinervaNeue@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038415

I'm reviewing the impact of this change, and I can see various regressions that will be caused by merging this fix. Before merging I'll double check with the team, about how to handle those tickets.
There are several significant side effects of merging these changes that need to be considered:

  • Breakages to map icons in some places
  • Breakages to Phonos in some places
  • Breakage in certain editors (non VisualEditor)

Change #1038418 merged by jenkins-bot:

[mediawiki/skins/Vector@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038418

Change #1038415 merged by jenkins-bot:

[mediawiki/skins/MinervaNeue@master] styles: Apply inversion on certain OOUI icons and indicators

https://gerrit.wikimedia.org/r/1038415

Jdlrobson added a project: Verified.

The following regressions were caused directly by this change:

There are likely more we don't know about.
I'm assuming the exploratory QA in T365383 will find some and act as QA for this task, so this task skips QA.

Jdlrobson added a subscriber: ovasileva.

The global invert does not appear to be working correctly on Special:Search so this needs more work.

Change #1043122 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] Separate out indicator and icon sizes

https://gerrit.wikimedia.org/r/1043122

Change #1043122 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Separate out indicator and icon selectors

https://gerrit.wikimedia.org/r/1043122

Change #1043818 had a related patch set uploaded (by Jdrewniak; author: Jdrewniak):

[mediawiki/skins/Vector@master] Followup to 71c532e Separate out indicator and icon selectors

https://gerrit.wikimedia.org/r/1043818

Change #1043818 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Followup to 71c532e Separate out indicator and icon selectors

https://gerrit.wikimedia.org/r/1043818

Change #1038914 abandoned by Jdlrobson:

[mediawiki/skins/MinervaNeue@master] Icons render consistently in night mode

Reason:

We will talk to the Design Systems Team about this potential solution tomorrow.

https://gerrit.wikimedia.org/r/1038914

Change #1038910 abandoned by Jdlrobson:

[mediawiki/skins/Vector@master] POC: Use mask-image for all Vector icons

Reason:

To be discussed with DST on Tuesday June 18th

https://gerrit.wikimedia.org/r/1038910

Change #1038911 abandoned by Jdlrobson:

[mediawiki/core@master] POC: Support mask-image in ResourceLoader ImageModule

Reason:

My understand is Jan spoke to DST about this. Let me know if this patch is useful and when you would have capacity to work on and I can restore it then if needed.

https://gerrit.wikimedia.org/r/1038911