Skip to content

roundcube-color-mode-plugin

Generic light/dark/auto color mode preferences for Roundcube skins that advertise dark mode support.

PHP · MIT License · GitHub

Why

Roundcube skins that add dark mode tend to reinvent the same preference UI and cookie handling each time. This plugin factors that out: it is intentionally skin-agnostic, ships no theme, and does not rewrite skin CSS. It just adds a single color_mode preference (light / dark / auto) that any skin declaring dark_mode_support in its meta.json can read and act on -- roundcube-skin-classic-lightdark is one such skin.

Features

  • Light / dark / auto preference -- auto follows the browser or OS color scheme via prefers-color-scheme.
  • Skin-agnostic -- exposes the setting; the active skin's CSS and templates decide what light/dark actually look like.
  • Admin controls -- set a config default and optionally force it, hiding the preference from users entirely.
  • Elastic compatibility -- also writes the colorMode cookie that Roundcube's built-in Elastic skin already reads, so it works there too.
  • Broad localization -- ships translations for Czech, Dutch, English, French, German, Italian, Japanese, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Spanish, Swedish, Turkish, and Ukrainian.

Requirements

  • Roundcube with plugin support.
  • A skin that declares dark_mode_support in its meta.json.

Installation

Copy the repository into your Roundcube plugins/ directory as color_mode:

roundcube/
  plugins/
    color_mode/
      color_mode.php
      color_mode.js
      localization/

Enable it in your Roundcube config:

$config['plugins'][] = 'color_mode';

When the active skin has dark_mode_support: true, the plugin adds a control at:

Settings > Preferences > User Interface > Skin > Color mode

Admin configuration

Set a default for new users:

$config['color_mode'] = 'auto';

Force a value and hide the preference from users:

$config['color_mode'] = 'dark';
$config['dont_override'][] = 'color_mode';

If no preference has been saved, the plugin defaults to auto.

How skins consume it

Skins read the saved preference in templates:

<roundcube:var name="config:color_mode" />

A typical integration adds an early script, before stylesheets load, that resolves auto against prefers-color-scheme and stamps a dark-mode or light-mode class onto <html>:

<script>
try {
  (function(mode) {
    mode = mode || 'auto';
    var media = window.matchMedia
      ? window.matchMedia('(prefers-color-scheme: dark)')
      : {matches: false};
    var dark = mode == 'dark' || (mode == 'auto' && media.matches);
    document.documentElement.className += dark ? ' dark-mode' : ' light-mode';
  })('<roundcube:var name="config:color_mode" />');
} catch (e) { }
</script>

Skin CSS then scopes to those classes:

html.dark-mode body {
  color: #e6e8ea;
  background: #111417;
}

For Roundcube's built-in Elastic skin, no custom script is needed -- the plugin writes the colorMode cookie (light/dark, or clears it for auto) that Elastic already reads via rcmail.env.color_mode.

Troubleshooting

  • Setting doesn't appear -- confirm the active skin's meta.json has dark_mode_support: true and that the plugin is listed in $config['plugins'].
  • Setting appears but nothing changes -- the plugin only stores and exposes the preference; the skin still needs CSS/template support that reads config:color_mode or responds to the colorMode cookie.
  • Setting is hidden -- check whether color_mode is listed in dont_override, which is expected for admin-forced deployments.