Loading parrot. Har Har.

JupyterLab Status Bar

Workday banner

Overview

As an intern at Project Jupyter, I worked on designing and releasing a status bar extension for JupyterLab that surfaces important changes in the system as they occur. Working closely with my team of developers, I helped ship the status bar on npm. The project has been downloaded +1 million times, and has been added to the core JupyterLab interface.

Role

UX Design Intern

Duration

March 2018 — June 2019

01. Background

Introduction to Project Jupyter and JupyterLab

Project Jupyter is a set of open-source software tools whose goal is to drive data computing and scientific exploration. JupyterLab is Project Jupyter's flagship IDE that supports multiple programming languages, dynamic and static processes, and editing of text documents. Users can write, run, and present code all within the same interface.

JupyterLab in a “console” context, using the programming language Python.
JupyterLab open in a console context and the programming language Python.

While this might seem like magic, a lot is going on behind the scenes in JupyterLab to make everything work. The status bar surfaces important changes to the back-end when they occur.

02. Problem

Monitoring various states is difficult or impossible

There is no way to monitor changes in certain states without using some third-party application, such as an activity monitor extension.

If something goes wrong in the back-end, trouble-shooting was difficult and involved intuition and guess-work to fix. Often-times, users would have to search within JupyterLab to surface problems.

After brainstorming potential design patterns as a means to surface these states, we decided to explore the status bar due to:

  1. It's minimalist design and unobtrusiveness to workflow.
  2. It can convey information quickly and effectively.
  3. It is a global component.

03. Research

Talking to our open-source community

I reached out to JupyterLab's open source community to understand pain-points and goals related to this idea of state. After 4 video calls, I audited Github issues to get an idea of the prevalence of issues raised in conversations. Key findings:

  1. Kernels (programs that run and check user code) can be dead while working, leading to lost time & overall frustration.
  2. Some actions, such as changing syntax highlighting, require many clicks to complete.
  3. If a process is taking a long time (e.g. uploading a large dataset), there's no way of knowing how long it will take.

Competitive analysis and empathy exercises

I developed empathy artifacts highlighting user motivations and frustrations after referencing other status bars from Visual Studio Code, Sublime Text, Eclipse, and Microsoft Word.

Status bars from Visual Studio Code, Sublime Text, and Microsoft Word
Status bars from Visual Studio Code, Sublime Text, and Microsoft Word

Job to be done

“I hire the status bar to streamline my workflow by allowing convenient access to important information about the software.”

User stories and job stories

“As a software engineer, I want to easily find which line and column I'm on so that I may debug my code.”
“As a data professional, I want to keep track of my memory usage without using a third party application so as to not disrupt my workflow.”
““When I am uploading a large dataset, I want to be able to see how long it will take, so that I may do other work if I have to wait.”

Auditing JupyterLab States

Working with subject matter experts, I went through JupyterLab and audited all representable states (39 total). We ranked each state based on criteria formed from user research:

  1. Pain of not knowing. How painful are the consequences of not having access to this state?
  2. Visibility. How easily can you access or find this state in JupyterLab?
  3. Frequency. How often do users need access to this state?
  4. User expectation. Do users expect to have access to this state?

We then narrowed down the list to 10 states to be represented in the default status bar. Some of these included a monitor of kernel activity, and the current line and column number.

AirTable ranking 39 representable states across JupyterLab.
AirTable ranking 39 representable states across JupyterLab. Top 10 items on the list were prioritized in design.

03. Constraints

Limitations on design

Design for the status bar was a challenge due to its unique constraints.

  • Limited real-estate. Desktop status bars typically have a width spanning the screen viewport and a small height of fewer than 30 pixels. Our solution needed to contain 10 different states in this short container.
  • Context Switching in JupyterLab. JupyterLab can open up different documents in different contexts (such as a notebook or text editor). Since some states are only relevant to certain contexts, the layout of the status bar needed to support the dropping of widgets as contexts switch.

05. Solutions

A Layout Supporting JupyterLab Context Switching

A well-defined information architecture provided a solution that handled context switching. For each of our 10 states, I assigned them organizational schemes and grouped similar items in AirTable (a spreadsheet tool for organizing qualitative and quantitative data). The schemes were: number of contexts, task, permanence, and system or document specific.

Based on the groups formed, some rules for information architecture were developed:

The left and right widgets of the status bar are global (never get dropped).
Widgets going towards the middle of the status bar get dropped more frequently. Temporary items, such as the progress bar, get placed in the middle.
Widgets with similar tasks get placed together.
System information is separate from document information.
Diagram depicting placement rules of widgets in the status bar.
Diagram depicting placement rules of widgets in the status bar.

Translating to Pixels

After sketching out states, user flows, and state changes on paper, I went into Figma and wireframed status bars in different contexts of JupyterLab. For each widget, I focused on designing the minimal amount needed to accurately represent that state. After wireframing the status bar in different contexts, I brought designs together in a prototype that simulates a typical user workflow as they change contexts within JupyterLab.

Snapshot of protoyped screens for the status bar extension
A screenshot overview of the prototype for the status bar extension in Figma.
Mockup of the status bar in the notebook context in JupyterLab
Mock-up screens of the status bar in notebook, console, text editor, terminal, and launcher contexts.

Minimizing real-estate usage

I used icons whenever possible to represent widgets due to their 1) their ability to convey summarized information at a glance and 2) small size.

Iterations of icon design for the status bar
Iterations of icon design for the status bar.

Designing interactions

Actions that were previously embedded deep within JupyterLab were made more accessible using the status bar. Users can change syntax highlighting and jump to line and column number without having to search within menus.

Hover states on widgets provide further clarity into what information the widgets represent and what actions you can do with them.

A video playing the various interactions with the status bar, including changing syntax highlighting, hover states, and reconnecting to dead kernels.
Prototyping interactions with the statusbar.

User Testing and Design Iterations

4 rounds of think-aloud user testing revealed that wording was confusing on some widgets (e.g. Tab vs. Indent), and that iconography for the kernel widget was too detailed and confusing. I iterated and did 1 more round of testing before reaching saturation on user feedback.

More detailed user testing at JupyterCon 2018 revealed that some users did not even notice the status bar. Users that did notice and use the status bar to complete their tasks, however, had a task completion rate of 96.4%.

Features of the Status Bar

  1. Kernel monitoring. Displaying information about the attached kernel given your context, as well as what language your kernel is currently using. User's can take action on disconnected kernels by clicking on this widget.
  2. Feedback on temporary states. Indicators for saving and a progress bar for uploading large files (like datasets) to give user insight on whether or not the system is working.
  3. Document contextualization. Information to situate the user as to what type of document they are dealing with. Things like document type, file path, and state of trust are displayed here.
  4. Resource monitoring. Monitor that shows capacity of system when performing memory or resource-intensive tasks.

06. Reflection

Shipping the Status Bar

By being involved in the full product cycle, I helped launch the status bar as an extension to JupyterLab via npm. Different components render based on the active context, and the status bar is customizable via external APIs to account for various workflows.

A demo video of the current status bar in the core JupyterLab interface.
The status bar in the core JupyterLab interface.

Currently, the status has over 1.1 million downloads on npm. It has been added to the core JupyterLab interface.

Takeaways from the Project

  1. Seemingly simple projects are deceptively hard to design for when they have to work across the board in a product.
  2. Planning out designs as "states" helps out a lot when you need to represent a constantly changing system.
  3. Open source is punk rock (~:
← Workday Dashboards