cockpit-project / cockpit

Cockpit is a web-based graphical interface for servers.
http://www.cockpit-project.org/
GNU Lesser General Public License v2.1
11.27k stars 1.12k forks source link

dark mode #10189

Closed garrett closed 2 years ago

garrett commented 6 years ago

Dark mode should be implemented for:


As Cockpit has a lot of moving parts, it's important that we align everything toward one release so that Cockpit can be completely dark without flashes of light or pages that are bright

Proof of concept

Minimum implementation for a Cockpit release

Dark mode works:

It doesn't make sense to have a half-baked dark mode (unless we have some opt-in beta hack), so these should really land to be available to users in the same release.

Meanwhile

Once we have the start of an implementation that is working, we should reach out to other teams who work in the Cockpit ecosystem, such as 45Drives (who work on several 3rd party Cockpit plugins), SUSE, and the installer teams (at Red Hat and SUSE).

Possible follow-ups

garrett commented 6 years ago

A lot of apps are adding dark mode these days. I wondered if there would be an easy way to do this via CSS filters.

This morning, I tested a simple proof of concept by adding:

.area-ct-content {
   filter: hue-rotate(180deg) invert(150%) brightness(1.5);
}

And it's nearly perfect.

(Before using the brightness boost, I did a text-shadow: 0 0; to make the light colored fonts render better on a dark background. The brightness boost is probably better, as it also makes subtle colors like light lines and the hover color a little more noticeable.)

In order to properly implement it, we'd probably want:

  1. a user preference (most likely stored in a cookie, so it's really per-browser)
  2. handle background screens behind dialogs (invert the color to be lighter instead of darker, so it shows up darker when inverted — it's basically one more line of CSS)
  3. adjust the navigation UI (make it a little more contrasty / darker — but it's actually not bad as-is)
  4. prevent the flash of white when switching between pages (probably by splitting out the inversion & hue-rotate into something more top-level, then re-inverting the navigation UI and apply the brightness boost to the content in its own filter)
  5. have an auto setting for time & date switching?

Similarly, we can have a high contrast or low contrast accessibility mode done in a very similar manner.

The biggest drawback is that we do not have precedent to have settings stored outside the system itself. (And try to avoid that.) As this would only affect the browser, having a cookie setting would probably still make sense despite that?


I can't tease a dark mode without screenshots. So here are some screenshots. Remember, this is the only 1 line of CSS proof-of-concept.

System overview

screenshot_2018-10-01 system - sunny

Storage page

screenshot_2018-10-01 storage - sunny

Dialog on the storage page

(Here's where the fix for item 2 would be needed.) screenshot_2018-10-01 storage - sunny 1

garrett commented 6 years ago

Mobile

(I scaled this down so it wouldn't be super-huge as a preview here.)

screen shot 2018-10-01 at 10 46 25

X1Aaron commented 6 years ago

Very Nice!

rhwood commented 6 years ago

See also https://stackoverflow.com/a/51799496/176160 It is likely there will soon be some support for determining if the browser is running in dark mode.

garrett commented 5 years ago

Firefox 67 landed this week and now includes dark mode support.

OS-based dark mode in browsers (prefers-color-scheme) is only supported in Firefox and Safari. Chrome support is forthcoming (and should land some time this year).

garrett commented 5 years ago

I'm currently working on overhauling all our colors in issue https://github.com/cockpit-project/cockpit/issues/11913.

Once done, this should allow us to support dark mode in a cleaner and more performant way, by redefining all the colors. (That said, I didn't notice performance issues. But it probably would have at least a little impact to flip the colors around.)

The method used above could be useful for parts of Cockpit that might not be easy to re-theme (such as the graphs), other top-level add-ons (such as Composer) or remote machines running old versions of Cockpit. The latter two exapmples would probably need additional work — perhaps by adding a special class in an iframe to enable color-variable-based dark mode and then defaulting to the above inversion method otherwise (if the class does not exist). We'd want to make sure there isn't a jarring white background in dark mode, in other words, and would need to mix-and-match techniques to get it done.

garrett commented 5 years ago

The color reworking was absorbed in to an overall restyling of Cockpit in https://github.com/cockpit-project/cockpit/pull/11987.

Not all the colors have been ported over to variables, but most have.

Adding a proper dark mode would help spot other colors that have not been adjusted.

Meanwhile, here's a great article on the whens, whys, & hows of dark mode: https://web.dev/prefers-color-scheme/

Dorson commented 4 years ago

Coded a flexible and working solution for the Dark Mode.

Demo in here: https://dorson.github.io/CSS-Dark-Mode-and-color-switch/

Works with basic CSS variables + short JavaScript.

Can be used to define multiple color themes in one CSS file or other dynamic style setting options like text size, etc...

Have fun using my code !

garrett commented 4 years ago

More dark mode info, BTW: https://css-tricks.com/a-complete-guide-to-dark-mode-on-the-web/

garrett commented 4 years ago

@Dorson: Thanks for the link. However, Cockpit is pretty complex, being a mix of PF3, PF4, and a lot of custom code. We'd have to have our own implementation of dark mode. PF4 already has some preliminary dark widget support, but that would only get us so far. Whatever is made for Cockpit would have to handle everything. We'd probably have to use more than one technique. (Like an optimized path when possible and possibly even a fallback one that is slightly less performant for legacy code and third-party extensions that don't directly support a dark mode.)

Plus, there are various design considerations to take in mind when developing a dark mode (more than inverting + shifting hue), as mentioned in the link I just shared above.

Glad you know that you're interested in dark mode though! The higher the want for it, the more likely we can get to it sooner than later (if at all).

garrett commented 4 years ago

Copy/pasted from https://github.com/martinpitt/performance-graphs/pull/64#issuecomment-702187607:


Ideally, PatternFly would have a class for dark mode. IIRC, they would enable it at the top of the page or at a specific widget level.

So we could do something like this in SCSS:

.foo {
   color: var(--some-color);
  .dark-mode & {
     --some-color: #fff;
     background: red;
  }
}

And SASS would unwrap that as:

.foo { ... }
.dark-mode .foo { ... }

And the specificity of the dark mode overrides would win out. It would also be afterward too. :wink:

FWIW: PF would probably go with .pf-m-darkmode or something such.


Also: If dark mode is applied to the same widget, then we'd do this instead:

.foo {
   &.dark-mode {}
}

But, in most cases, we'd want dark mode at the top of the page and have everything inherit.

garrett commented 4 years ago

Ideally, we'd try to use PF4's dark mode (with it lands) and have a fallback for non-PF with the example I outlined above (in which we'd probably also drop or adjust the dropshadows so they're not "dropglows").

And we'd have a little bit of CSS like the above comment for one-off overrides where necessary.

martinpitt commented 3 years ago

Nobody else asked for this as far as I can remember, but this issue has a PoC and is clearly stated, so if anyone wants to have a go at this, it's still relevant.

garrett commented 3 years ago

Removing and updating the colors we use (#15183) was a walk in the direction of this issue. And PatternFly is working on support. Once PF lands dark mode, we can try to see what happens when enabling it.

I'm still certain we'll need a PF4 native solution and a compatibility one (based on this proof of concept) as well, as mentioned above.

garrett commented 3 years ago

Nobody else asked for this as far as I can remember

It's an accessibility feature and a user preference. Over the past few years, it's been showing up almost everywhere (with good reasons).

elementary OS (opinionated Linux-based OS that has an app store) founders have a good writeup about implementing a dark style preference... it's a nice read and makes a lot of great points (especially around accessibility) and is mostly not elementary-related: https://blog.elementary.io/the-need-for-a-freedesktop-dark-style-preference/

Meanwhile, coincidentally, I have my blinds mostly closed, sitting in a dark room, actually using dark "mode"* today as I have a bit of a headache and I want to keep working and try to not go into massive migraine mode. (It's important to me and very likely a lot of our users.)

* Technically, it's the adwaita-dark theme in gnome-tweaks. Firefox recognizes the light text and dark background, skins itself into a dark mode and then sets its own internal settings to to prefers-dark. This then causes GitHub and several other websites to flip to dark mode too.

jchristi commented 3 years ago

@garrett Have you tried the Dark Reader browser extension? I can't live without it!

garrett commented 3 years ago

@jchristi: Yeah, Dark Reader is great! I use it on my phone especially (via Firefox on Android).

It doesn't really work with Cockpit, however, as we have a bunch of CSP (Content Security Policy) protections on which (rightfully) get in the way. We'll need to have our own solution for dark mode.

garrett commented 2 years ago

Related, upstream PF dark theme proof of concept: https://github.com/patternfly/patternfly/pull/4203

septatrix commented 2 years ago

Would definitely like the modern look of Patternfly 4

garrett commented 2 years ago

@septatrix: Cockpit has had the modern look of PatternFly 4 for a few years already... If your version of Cockpit is still using PatternFly 3, then you might want to consider updating.

If you're on an older version that ships in Debian Stable or Ubuntu LTS, we have backports instructions @ https://cockpit-project.org/running.html#debian (RHEL ships newer Cockpits and we have a COPR available for those who want the absolute latest in the form of a preview.)

Cockpit is currently at version 263 as of right now.

As for the next iteration of PatternFly 4, PatternFly itself hasn't finalized that yet. But it's probably when upstream dark support will land, and then we could use it in Cockpit (although with a bit of effort on our end too, for sure).

septatrix commented 2 years ago

Oh yes please ignore me. I only check the dashboard sparingly and confused it with FreeIPA and the Ansible Galaxy homepage :D

archef2000 commented 2 years ago

I would like to know how to implement it on Cockpit @garrett from your first comment

.area-ct-content {
   filter: hue-rotate(180deg) invert(150%) brightness(1.5);
}

if not directly maybe trough Nginx

garrett commented 2 years ago

@Archef2000: That won't work, as Cockpit has changed a ton since this issue was first opened. We're using PatternFly 4 now, instead of PatternFly 3. And we're using many more PatternFly widgets instead of a lot of custom ones too.

An updated version of the proof of concept hack would be to add something like this, probably in page.scss:

.pf-c-page {
  filter: hue-rotate(180deg) invert(150%) brightness(1.5);
}

However, this is not the right way to do things:

Most of these can be worked around with additional CSS. And we'd need to do something like this anyway without PatternFly 4's native dark mode setting, for pages that don't support that.

But it's finally probably around the time where we can start looking into adding some kind of dark mode.

We'd want to have fallback dark mode first, then patch in PF4 dark mode with a way to override the fallback (most likely using :not()), as having partial dark mode support does not make sense. (It's a bad experience to get some pages and some widgets in dark mode with others not.

archef2000 commented 2 years ago

Where can i find the page.css ?

garrett commented 2 years ago

Note: a better fallback might be to redefine the PF color variables. (And I think this is what PF does for their implementation?) But we'd probably still need a hacky fallback too, as not every page in Cockpit would support it. In those cases, we might even need to attach the CSS with a more generalized selector, like body; perhaps body:not(.pf-c-page) (which would say pages that do NOT use PatternFly 4). (We'd need example pages.)

garrett commented 2 years ago

Where can i find the page.css ?

It's page.scss in the Cockpit source. You'd need to build Cockpit from source for that. But, again, it's a complete hack and would need more work done.

Otherwise, injecting the CSS in an already-compiled Cockpit somewhere would probably work... but I think you'd need to do that on every page's compiled CSS file?

There are also some browser extensions that provide a means of adding CSS to pages, such as Stylus, and others that provide a hacky dark mode, like Dark Reader... but these kinds of extensions may have issues with Cockpit's CSP (content security policy) settings.

archef2000 commented 2 years ago

And in Nginx could you injekt scss code as i cloud use it this way. @garrett

garrett commented 2 years ago

And in Nginx

I don't know about Nginx. That's completely out of scope of implementing a dark mode in Cockpit.

When I do use a proxy in the front, I use Caddy... Sorry; I can't help further with Nginx. A quick search on DuckDuckGo showed this result that might help you: https://forum.level1techs.com/t/infrastructure-series-use-nginx-to-inject-css-themes/174165

I can eventually implement dark mode directly in Cockpit. I know @jelly has also expressed interest in this. We want to try to tackle it "soon", but we're both juggling many other tasks in Cockpit (and Cockpit-Podman, Cockpit-Machines, etc.), so I can't give you an estimate aside from our wish to try to get it done sooner than later.

garrett commented 2 years ago

Meanwhile, PatternFly has an issue open about guidance for dark theme implementations for software that uses PatternFly 4, such as Cockpit (but this is a TODO item):

And they have a meta-issue ("epic") about their dark theme implementation @:

Where they say:

dark theme is not yet available for general use. We currently have an alpha version that we are testing with selected projects and don't have any firm date on when this might be fully supported


Additional notes: As the PF dark theme can be implemented at a page or a widget level, for a fallback theme to work properly, we'd want to use a way that cascades down as to not invert an already-dark mode. That is, we would want to probably use something like the CSS custom property trick to have a cascading boolean in CSS which would let us either apply or skip application of any dark mode settings, so we don't accidentally apply more than 1 dark mode change at the same time. (This would especially be true for any filter-based implementation, as inverting to dark twice (or any even number of times) means it's back to the original colors... but with degraded performance.)

https://lea.verou.me/2020/10/the-var-space-hack-to-toggle-multiple-values-with-one-custom-property/

Using this trick

So, in order of ideal implementation to less ideal, it would be something like:

  1. PatternFly 4's dark theme setting
  2. CSS variable redefining (where PF4's dark theme is not supported, which in some case, might even be some PF4 widgets that might not have their own dark mode setting yet... and in other cases, Cockpit's custom widgets)
  3. CSS filter to invert (especially on pages where PF4 does simply not exist... like in some 3rd party apps / add-ons for Cockpit)

If 1 is active, we don't want 2 or 3. If 2 is active, we don't want 3 (and 1 wouldn't be possible if 2 is active). If 3 is active, neither 1 nor 2 would be possible.

So, in other words: Fallbacks on fallbacks.

Also, this wouldn't be able to apply to remote servers, unless the remotes would also be dark mode capable (that is: on whatever version Cockpit would have a dark mode).

Cockpit is much more complicated than any other app using PatternFly 4, as we have iframes with embedded pages that might or might not be developed by us — and that might or might not even be made using PatternFly. And, we can also have remote servers with different versions of Cockpit too.

garrett commented 2 years ago

A for a CSS variable redefinition method, a good first pass to figure out which colors would need to be reassigned (when dark mode is on) would be to view the PF color page (https://www.patternfly.org/v4/guidelines/colors/) and use a simple invert on the html or body tag, such as: 'filter: invert() hue-rotate(180deg);`

It would then look like this preview:

image

And then someone (probably me) would have to redefine all the PF color variables to the color picker version of the colors shown there. Some would have to be tweaked with something like the above-mentioned filter (filter: hue-rotate(180deg) invert(150%) brightness(1.5);) — this would most notably be the the grey colors, to provide a bit more contrast.

This would provide a way to have a dark mode based on color redefinition, like I mentioned as the first fallback (# 2 in the above list), and we already have a hacky approach for a # 3 (the CSS filter with some additional CSS to correct some of the things it gets wrong).

Then, the largest task would be integrating all of this and making sure the most preferable approach is used, with fallbacks where necessary. (We'd also want to adjust the CSS variable redefinition to whatever PF winds up using in their implementation too. But the approach I mention in this comment is a good first pass for a starter implementation.)

garrett commented 2 years ago

PatternFly's implementation is at:

https://github.com/patternfly/patternfly/commit/b8f2649128d27ba1a4069a9e5047aeb16f4bf439

The main part uses color redefinition at:

https://github.com/patternfly/patternfly/blob/main/src/patternfly/themes/dark/scss-variables.scss

As long as it can apply to all of our pages, we might want to just use the PF4 implementation directly with the filter fallback and skip our own color redefinitions.

We'd still need a way to set a toggle to prefer dark, light, or auto (with auto being the default). This would be Cockpit-specific UI, probably somewhere under the session menu, with a tri-state widget. GNOME Builder is being ported to GTK4 and has a UI like this, with "Follow system", "Light", and "Dark":

image

Most desktops and operating systems just have a dark/light toggle, whereas many apps have "auto" or "follow system" (on by default) and manual light/dark overrides when they do provide overrides.

We could do what the system does by default in a first pass and then, later, add in a preference as a follow-up feature.

garrett commented 2 years ago

I've talked with some of the PF devs about enabling dark mode in PatternFly and got a response. Here's an excerpt:

The TLDR is that you import @patternfly/patternfly/patternfly-theme-dark.css directly after the base PF styles, so it can correctly override those as needed but not conflict with any additional overrides you may load after, and then apply the .pf-theme-dark class to the <html> tag to toggle the dark theme styles on.

There's also an internal WIP document with more details, including gotchas. I'm happy to share it with anyone on the team. (It's not public, so only RHers can access it for now, but some form of it will be published publicly once PF makes dark mode official for everyone. They want to iron out bugs first before officially turning it on for everyone, hence the semi-closed beta for now.)

For everyone following along: This, of course, would have to be done in the source files before compilation. There isn't a way to enable it in Cockpit builds, and it will require some work on Cockpit to properly enable it.

garrett commented 2 years ago

I took a screenshot of Cockpit Client with the login page

Screenshot from 2022-05-23 16-10-36

And made a dark mode mockup using the colors from the current PatternFly dark mode. It's not meant to be pixel perfect; it's just approximate. Colors and the general feel are the important part of this mockup.

login-dark

I've added a black screen at 75% behind the login, but above the logo, to make the background wallpaper and the OS logo darker. This also causes the login entry to still "pop" visually with a but more contrast between the login and the wallpaper. It also makes the screen overall darker, which is the point of dark mode, right? :wink:


Color guide

Not pictured:

archef2000 commented 2 years ago

I took a screenshot of Cockpit Client with the login page

Screenshot from 2022-05-23 16-10-36

And made a dark mode mockup using the colors from the current PatternFly dark mode. It's not meant to be pixel perfect; it's just approximate. Colors and the general feel are the important part of this mockup.

login-dark

I've added a black screen at 75% behind the login, but above the logo, to make the background wallpaper and the OS logo darker. This also causes the login entry to still "pop" visually with a but more contrast between the login and the wallpaper. It also makes the screen overall darker, which is the point of dark mode, right? 😉

Color guide

  • button blue: #06c
  • link blue: #8ac0f6
  • input background: #393f44
  • input underline: #6c6f72
  • divider: #34373b
  • text: #f0f0f0
  • × button: #6a6e73

Not pictured:

  • disabled button background: #444548
  • disabled button text: #d2d2d2
  • hover button (unspecified; so this is a guess): #1fa7f8

Files to recreate it on my own?

garrett commented 2 years ago

@Archef2000: No files. This is for reference.

I was going to add dark mode to the login page, but @allisonkarlitskaya wants to pick it up. She'll implement it and I'll look it over. We intend on doing this before or by Wednesday. (No promises, of course!)

Meanwhile, I looked into implementing dark mode for Cockpit itself, first as a hack (mainly for debugging purposes) and still hit some walls. It'll take some more effort for Cockpit itself.

@allisonkarlitskaya added dark mode for Cockpit Client last release and we'll likely add the login page dark mode for the upcoming release. It'll probably take longer for dark mode for Cockpit (and the various pages) itself, as that's much more complex.

archef2000 commented 2 years ago

@Archef2000: No files. This is for reference.

I was going to add dark mode to the login page, but @allisonkarlitskaya wants to pick it up. She'll implement it and I'll look it over. We intend on doing this before or by Wednesday. (No promises, of course!)

Meanwhile, I looked into implementing dark mode for Cockpit itself, first as a hack (mainly for debugging purposes) and still hit some walls. It'll take some more effort for Cockpit itself.

@allisonkarlitskaya added dark mode for Cockpit Client last release and we'll likely add the login page dark mode for the upcoming release. It'll probably take longer for dark mode for Cockpit (and the various pages) itself, as that's much more complex.

But how did you get the login page etc. dark?

garrett commented 2 years ago

But how did you get the login page etc. dark?

We didn't make it dark. Yet. This is a mockup, not a screenshot.

As I said, specifically for the login page, @allisonkarlitskaya is working on it and I'll help out and/or review. Hopefully we'll get it done for this week's release.

But that's just the log in page. Cockpit itself, once you're signed in, will take a lot more effort and time. (We're working on it, but with no ETA for most of Cockpit.)

jelly commented 2 years ago

I noticed running the following JS in your developer console on https://www.patternfly.org/v4/components/alert changes it to the dark theme:

document.documentElement.classList.toggle('pf-theme-dark');
garrett commented 2 years ago

I rebased this branch earlier today. There were some conflicts, but I think I solved them all.

After that, I've been hunting down the way dark mode should look. The best overview of all the components seems to be at https://patternfly-react-pr-7644.surge.sh/components/form — be sure to manually enable the toggle in the top-right.

I'm not sure why this isn't on PatternFly.org by default.

Anyway, this is what I'm using for reference now, to figure out which parts of Cockpit are broken in dark mode and what they should look like with a fix.

septatrix commented 2 years ago

Anyway, this is what I'm using for reference now, to figure out which parts of Cockpit are broken in dark mode and what they should look like with a fix.

First and foremost the navbar in PF4 seems to be broken in dark mode...

image

I am not sure if this might be fixed in newer versions because the main docs do not seem to have the dark mode toggle for now so I did not want to file an issue yet

garrett commented 2 years ago

latest PR branch from PF has a bunch of things fixed in dark mode

Warning buttons are legible with correct contrast again https://patternfly-pr-5137.surge.sh/components/button

Search inputs are finally styled correctly https://patternfly-pr-5137.surge.sh/components/search-input

And a bunch of other subtle things.

We need to upgrade to the latest PF to properly continue dark mode work.

jelly commented 2 years ago

https://github.com/cockpit-project/cockpit/pull/17321 now merged with dark mode.

septatrix commented 2 years ago

17321 now merged with dark mode.

That PR only implement a dark theming for the GTK wrapper but not the web interface itself. This is only a minute fraction of what this issue is encompassing and should therefore very much remain open.

jelly commented 2 years ago

See the latest release, dark mode was fully implemented https://cockpit-project.org/blog/cockpit-279.html

archef2000 commented 2 years ago

I got the new version installed but only the login and the side bar are in darkmode

jelly commented 2 years ago

@Archef2000 do you have a dark theme enabled in your environment? What browser are you using?

archef2000 commented 2 years ago

I tested Chome desktop and Firefox and https://cockpit-project.org/running.html says that my browser is compatible. I cleared my cache.

archef2000 commented 2 years ago

Screenshot 2022-11-09 145611

martinpitt commented 2 years ago

That's not dark mode, that's how cockpit has looked like for the past few years. :grin:

archef2000 commented 2 years ago

No it has not. The top where Administrative access, Help and Session are localted was white. And this is the new login screen. Screenshot 2022-11-09 162109