Notes on the JupyterLab Notebook HTML DOM Model, Part 8: Setting CSS Variable Values from an Extension

In the previous post in this series, I looked at how we can make use of an extension’s user settings to access persistent state that we might use to modify the behaviour of an extension. In this post, I’ll look at how we can use extension settings to tune CSS properties such as a the background colour we might apply to tag classed cells based on a crib from jtpio/jupyterlab-cell-flash.

We can define a color property in our settings file in the following way (presumably we could also specifiy a colour name or use any other appropriate CSS colour formulation):

    "activity_color": {
      "type": "string",
      "title": "Color",
      "description": "The base color for the activity background",
      "default": "rgba(173, 216, 230, 1.0)"
    },

The original class CSS was defined literally:

.iou-solution-node {
    background-color: lightgreen !important;
}

However, we can parameterise the values and then set new values onto the CSS parameters based on extension settings:

:root {
    --iou-activity-bg-color: lightblue;
  }

.iou-activity-node {
    background-color: var(--iou-activity-bg-color) !important;
}

How, then, do we expose these values as a setting? The following example loads the settings in as part of our extension activation, identifies a desired class color value from the settings file, and then uses it to set the value of the CSS variable.

function activate(
   app: JupyterFrontEnd, settingRegistry: ISettingRegistry | null): void {

    // Example of how to read settings from cookiecutter
    if (settingRegistry) {
      settingRegistry
        .load(plugin.id)
        .then(settings => {
          console.log('jupyterlab-empinken settings loaded:', settings.composite);
          // Handle the background colours
          // The document object seems to be magically available?
          const root = document.documentElement;
          const updateSettings = (): void => {
            const color = settings.get('activity_color').composite as string;
            root.style.setProperty('--iou-activity-bg-color', color);
          };
          updateSettings();
          // We can auto update the color
          settings.changed.connect(updateSettings);
        })
        .catch(reason => {
          console.error('Failed to load settings for jupyterlab-empinken.', reason);
        });
    }
}

In the control panel, we then have a dialog of the form:

A couple of things to note about that; first, it would be neater if we could have a colour-picker; secondly, the extensions panel seems overly aggressive on save, saving after every keystroke if you change a string value, which means you need to type very, very, slowly, which sucks in terms of UX because it makes you think you’ve broken something.

We can now set colours for the different backgrounds via the extensions settings panel. In addition, the background colours should update immediately in the notebook if we change the setting.

In the next post in this series, I will review how the various components can all work together to give us a JupyterLab flavoured version of the classic notebook empinken extension.

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: