Proposal: Dark Mode support in XWiki

Hey everyone,

I’d like to propose a plan for dark mode support in XWiki. The full proposal is on design.xwiki.org: it describes the plan in more details, split into seven parts. This post gives an overview of the work, so we can first discuss the overall direction. Each part would then get its own thread for its specific decisions.

Note: This is my first proposal with full on AI help. I tried to keep it concise as much as possible, but I welcome feedback on the overall output of it.

Note 2: While the topic focus on dark mode, this work would also help to have a much improved theming support in XWiki.

Context

Users ask for dark mode from time to time, on the forum and in the product survey. A few things make it hard today:

  • Most colors are fixed when the stylesheets are compiled on the server, so a page can’t switch between light and dark.
  • Our CSS variables use Bootstrap names and aren’t documented, so extensions can’t really rely on them.
  • Some colors, such as muted text and borders, can’t be set from a theme.
  • About 220 colors are hard-coded in stylesheets.
  • XWiki Standard has no maintained dark theme. Darkly and Cyborg keep their colors in custom LESS code and can’t follow a user’s preference.

Proposed solution

I see two kinds of work:

  • Dark mode support, on the architecture side: the mechanisms that would let a theme have a dark counterpart and let the page switch between them.
  • Dark themes, on the visual design side: the dark colors themselves. I’ve drafted a first one, Iceberg Dark, as a starting point.

My suggestion would be to do it in two steps:

  1. A stop-gap, marked experimental: an Iceberg Dark theme, a light and a dark theme per wiki, and a System / Light / Dark choice for each user. It could work with today’s styling. Upgraded wikis would keep a single theme until an admin turns dark mode on.
  2. Full dark mode: a documented set of CSS tokens (--xwiki-*) read by the stylesheets, so colors could switch in the browser without a reload. Cristal could use the same tokens. Here’s a good article from Penpot about design tokens: What are design tokens? A complete guide

The idea is that the second step reuses most of the first: theme pairs, the user choice and Iceberg Dark’s colors.

Draft of Iceberg Dark

*A possible way to choose the color mode in the user profile.

Draft Iceberg Dark colors next to Iceberg’s, with their contrast ratio

The Sandbox page with the Iceberg Dark draft

The seven parts of the full proposal, each to be discussed in its own thread:

Required for the stop-gap solution:
(1) gives Iceberg Dark the fields it needs for colors such as muted text and borders, and (2) is the theme itself and admin UIs for setting it.

  1. New theme fields. Some of the most used colors, such as muted text and the default border, can’t be set from a theme: they come from the old Colibri color themes or from fixed values. A dark theme gets light values for them, or has to override them in LESS code. This part suggests five new fields. Each field is one more value admins set in every theme, light and dark, so we should agree on which colors deserve a field and which can be derived from others.
  2. Stop-gap with Iceberg Dark. The Iceberg Dark theme, a light and a dark theme per wiki, a System / Light / Dark choice in the user profile, and the administration screens to manage them. It changes how themes are chosen and adds new preferences.

Required for full dark mode support:

  1. Token naming and register. Our 148 CSS variables use Bootstrap names without a prefix and aren’t documented, so nothing tells extension authors which ones they can rely on. This part suggests a naming convention, which tokens would be public API (with a deprecation policy), and one file that lists them all.
  2. Bootswatch themes to contrib. The 16 Bootswatch themes keep their colors in about 1,000 lines of custom LESS code each. That code can’t switch between light and dark, and these themes aren’t tested for accessibility. Converting them would take months of visual review, and they still wouldn’t have dark versions. The suggestion is to move them, unchanged, to a contrib extension, so existing wikis keep them. Removing themes from XWiki Standard was discussed before without a decision, so it deserves its own thread.
  3. Token renaming and migration. A new name for each current variable, with aliases so extensions and customized wikis keep working. It affects extension authors and admins who customized their wiki’s CSS.
  4. CSS color migration. For colors to switch in the browser, stylesheets have to read tokens instead of compiled values: about 380 references to LESS color variables and 220 hard-coded colors. This part suggests migrating module by module, mostly with a script, with screenshot checks to keep visual changes small. This work from @NicoletaCiausu comes to mind Proposal: Visual Regression Testing in xwiki-platform
  5. Full dark mode. Once the stop-gap is in place and the core stylesheets read tokens, colors could switch in the browser without a reload and follow the device setting as it changes. It also covers dark colors for code and diff views, and declaring the tokens a stable API. It depends on the migration.

What I’d like your opinion on:

  • Do the proposed documented --xwiki-* tokens sound like the right way for themes and stylesheets to share colors?
  • Does a stop-gap first, followed by full dark mode, make sense?
  • Is this split into seven proposals a good way to discuss it, or would you group things differently?

The details of each part are in the full proposal, and will be discussed in their own threads, provided the overall direction is decided here.

Alternatives

Some other options I looked at:

  • A new skin: most hard-coded colors are in module stylesheets that load with any skin, so I don’t think it would solve the problem.
  • Only the stop-gap: colors still couldn’t switch in the browser, and hard-coded colors would stay light.
  • Only the tokens: users would wait for the whole migration before getting any dark mode.

This post was co-written with Claude, Anthropic’s AI assistant.

Thank you all for reading, I welcome any feedback that you might have.
Thiago

Hi.

Glad to see its on your roadmap. We made our own style based on flamingo. I splitted it into a stylesheet for colors and another one for the rest (what is much bigger). In the end we use 16 colors at all (all greys for borders etc. included.) But the color stylesheet is about 750 lines of css code. And a lot of code needs !important to work. What a mess.

We use tokens for our color coding already. So I would like to work with this. And xwiki is using them on some parts too but with hardcoded colors because of compiling. You can see a lot of them on root:.

I‘m not sure about the stop-gap. I think we would try it (with 2 own color themes). It depends on the work we have to do and the timeline to the complete solution.

Regards, Simpel

I’d prefer to use light-dark() CSS function - CSS | MDN if possible. This feature is baseline 2024 so it’s supported enough for us to use. This way, we gather the changes needed to implement the dark theme at the definition of variables. Of course, this is reliant on XWIKI-22668: Migrate most of XWiki’s LESS files to native CSS, not sure how much this works with the LESS system (there might be a syntax parsing issue…). Note that I made significant progression on this topic recently, and I plan to continue migrating files one by one at the same rate so hopefully it’d be finished in a few releases.

+1, but I don’t think it’s necessary for the dark theme plan. Note that XWIKI-23029: Add a custom CSS section to the color theme editor by Sereza5 · Pull Request #6896 · xwiki/xwiki-platform · GitHub would make it easier to add CSS variables in any theme.

As explained above, I’d rather just use light-dark in default/Iceberg variable values instead. We can force the light color-scheme until it’s fully ready (overwriting this color scheme would be an easy way to test things :slight_smile: ).

[quote=“tkrieck, post:1, topic:18989”] . If we do this, it’d probably be for the best to include a new “dual color” field type and picker to avoid asking the user to write the CSS function syntax.

  1. Token naming and register. Our 148 CSS variables use Bootstrap names without a prefix and aren’t documented, so nothing tells extension authors which ones they can rely on. This part suggests a naming convention, which tokens would be public API (with a deprecation policy), and one file that lists them all.
    [/quote]
    I’m not sure to understand what your 148 list contains. Isn’t Bootstrap using LESS?

From what I understand there’s an idea crossing with Only support 3 color themes in XS that’s left open. Do we have a decision on this?

:ok_hand:

Doesn’t this collide with some old variables? For the LESS to CSS migration I might have a few @xwiki-something that became --xwiki-something. We’d also make sure to migrate any “old” variable to --legacy-something.


Thank you for tackling this topic!
Sorry for the messy answer, I’m not yet understanding how all the steps fit in with today’s XS.

Lucas.