Custom Panel Extension in the Left JupyterLab Area

Hello there,

I am trying to build a JupyterLab extension to add a new Panel to the Left Area. I tried to take inspiration from the celltags extension but I soon realized that it is based on the INotebookTools interface that already provides by itself a Panel with some controls to manage the cell state.

I would like to start from a new blank custom left Panel, where I can add React Components from scratch and do things like setting my own custom icon beside the ones of the file browse, command palette, open tabs panel etc…

Is there any example out there that does something similar? Any advice or help would be very appreciated.

Thank you very much.

Once you have your Panel, you can add it to the left area in your plugin’s activate() method by the method app.shell.add(view, 'left');

For an in-context example, see e.g.:

Hey @vidartf thank you for the response! Are you referring to Panel as a pure React component or something else?

I think I am having a hard time understanding the snipped you linked. Would you be so kind to provide a small snippet that initializes an empty left area? I am completely new JupyterLab development, so having something to bootstrap my extension would be really helpful.

Ah, I was referring to a Phosphor Panel (I thought that’s what you meant). A minimal JS plugin could be:

/**
 * The extension manager plugin.
 */
const plugin = {
  id: '<your extension name here>:plugin',
  autoStart: true,
  activate: async (app) => {
    let view = <create a ReactWidget here>;
    view.id = '<some unique ID here>';
    view.title.iconClass = 'jp-SideBar-tabIcon';
    view.title.caption = '<your caption here>';

    shell.add(view, 'left', { rank: 1000 });
  });
};

/**
 * Export the plugin as the default.
 */
export default plugin;

The docs for creating a React widget is new for 1.0, and can be found here at the time of writing: https://jupyterlab.readthedocs.io/en/latest/developer/virtualdom.html

@vidartf Thank you very much! That was really helpful. I tried to setup a minimal implementation. It does compile successfully and loads into jupyter, but I do not see any new left panel sadly. And I don’t even see any runtime errors.
This is the code I am using, do you have any suggestion? https://pastebin.com/5mp0xT37

Thanks again for the great support!

Panel alone doesn’t do any layout, so what might be happening is that all your widgets have 0 width and height. Try using a BoxPanel instead (cf. Phosphor documentation)

As an aside, it’s perfectly fine to instantiate panels directly. If you’re not doing anything fancy, no need to subclass them!

function MyCoolReactComponent() {
  return (<div>Hello, world!</div>);
}

class MyWrapperWidget extends ReactWidget {
  render() {
    return (<MyCoolReactComponent />);
  }
}

const extension: JupyterFrontEndPlugin<void> = {
  id: 'my-launcher',
  autoStart: true,
  activate: (app) => {
    const panel = new BoxPanel();
    const widget = new MyWrapperWidget();
    panel.addWidget(widget);
    app.shell.add(view, 'left', { rank: 1000 })
  }
};
 
export default extension;

Thank you very much for the code snippet! After some tinkering I still can’t get it to show a new left panel…do you think there might something missing from this?

import * as React from 'react';
import { ReactWidget } from '@jupyterlab/apputils';
import { BoxPanel } from '@phosphor/widgets';
import { JupyterFrontEndPlugin } from '@jupyterlab/application';

function MyCoolReactComponent() {
  return (<div>Hello, world!</div>);
}

class MyWrapperWidget extends ReactWidget {
  render() {
    return (<MyCoolReactComponent />);
  }
}

const extension: JupyterFrontEndPlugin<void> = {
  id: 'my-launcher',
  autoStart: true,
  activate: (app) => {
    const panel = new BoxPanel();
    panel.id = 'my-tab';

    const widget = new MyWrapperWidget();
    panel.addWidget(widget);
    app.shell.add(panel, 'left', { rank: 1000 })
  }
};

export default extension;

Have you checked your package.json for the extension? There should be a block like this in there:

  "jupyterlab": {
    "extension": "path/to/index.js"
  }

or:

  "jupyterlab": {
    "extension": true
  }

If that’s in there, verify that the extension is actually activating with console.log.

Yes I have

"jupyterlab": {
    "extension": true
  }

in my package.json. I am pretty sure the base configuration is correct because I started out by cloning the jupyterlab-celltags repository (ended up keeping just the index.js with the code you suggested me)

I also added a couple of console.log in the activate function and I see the output in console. So I guess there is some issue with the widgets…I am pretty much stuck right now, don’t really know what to do

Hello @quigleyj-mavenomics. Unfortunately still stuck on this, I was not able to get a minimal left area extension running. Could you (or anyone else) please give me some heads up on this? Thanks!!

I’m honestly stumped by this, I’ve linked it in the JupyterLab gitter if anyone else might know what’s up.

The data explorer is an example of a react widget as a custom left panel: https://github.com/jupyterlab/jupyterlab-data-explorer/blob/37a66b977f541c3dd38f15e230e4fcb14073dc35/dataregistry-extension/src/explorer.tsx#L363-L375

1 Like

@saulshanabrook Thank you! Using that code snippet I was able to run a basic extension with custom left area, awesome!