npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@data-navigator/bokeh-wrapper

v2.0.0

Published

A data-navigator wrapper for Bokeh charts with smart defaults and a text-chat navigation interface.

Readme

@data-navigator/bokeh-wrapper

Accessible data navigation for Bokeh charts. One function call adds a keyboard, screen reader, and text-chat navigation interface to any Bokeh chart.

Part of the Data Navigator project.

Documentation · Getting Started · npm

Install

npm install data-navigator @data-navigator/bokeh-wrapper

Also import the text-chat stylesheet:

import 'data-navigator/text-chat.css';

Quick start

Render your Bokeh chart first, then call addDataNavigator:

import { addDataNavigator } from '@data-navigator/bokeh-wrapper';
import 'data-navigator/text-chat.css';

const wrapper = addDataNavigator({
    plotContainer: '#my-plot',
    data: myData
});

The wrapper automatically:

  1. Sets the Bokeh plot to inert so screen readers skip the inaccessible canvas output
  2. Infers the chart type from your data shape (you can also specify it)
  3. Builds a navigable graph structure (the hard part!)
  4. Appends a text-chat interface after the plot (this can be styled further using css)

Options

addDataNavigator({
    // Required
    plotContainer: '#my-plot', // CSS selector or HTMLElement
    data: myData, // Array of plain objects (same data passed to Bokeh)

    // Chart type — auto-detected if omitted
    type: 'bar',
    // 'bar' | 'hbar' | 'cartesian' | 'line' | 'multiline' | 'stacked_bar' | 'auto'

    // Field mappings — inferred from data if omitted
    xField: 'fruit', // Categorical or x-axis field
    yField: 'count', // Numerical or y-axis field
    groupField: 'year', // Series/stack layer field (multiline, stacked_bar)

    // Interface mode (default: 'text')
    mode: 'text', // 'text' | 'keyboard' | 'both'

    // Place the chat UI in a specific container (optional)
    chatContainer: '#my-chat-area',

    // Sync with the Bokeh chart
    onNavigate(node) {
        // Called on every navigation move — use to redraw focus indicators
        highlightBar(node.data);
    },
    onExit() {
        clearHighlight();
    },

    // Interaction callbacks (text mode)
    onClick(node) {
        // Triggered when user types "click" or "select"
        triggerBokehClick(node.data);
    },
    onHover(node) {
        // Triggered when user types "hover" or "inspect"
        triggerBokehHover(node.data);
    },

    // LLM integration (optional)
    llm: async messages => {
        const res = await fetch('/api/llm', { method: 'POST', body: JSON.stringify({ messages }) });
        return (await res.json()).content;
    },

    // Override auto-generated navigation command labels
    commandLabels: {
        left: 'Previous fruit',
        right: 'Next fruit'
    },

    // Advanced: pass extra options to the underlying data-navigator structure builder
    structureOptions: {}
});

Returned instance

const wrapper = addDataNavigator({ ... });

wrapper.getCurrentNode();  // Currently focused node, or null
wrapper.structure;         // Underlying data-navigator Structure (pass to Inspector, etc.)
wrapper.destroy();         // Remove all DOM additions and restore the plot

Connecting to Bokeh

Because Bokeh renders to a <canvas>, the cleanest way to show focus is to redraw the chart with an extra highlight layer on each navigation event. Bokeh also, unfortunately, makes it hard for Data Navigator to know where elements are rendered. This means that focus during navigation takes place on the whole visualization, while an indicator is added using bokeh to the specific location. This isn't ideal, but is the best approach we can take unless Bokeh adds some way to query element x, y, width, and height programmatically. We also discuss the focus indication challenge further in our core docs for Data Navigator.

const drawChart = highlight => {
    /* re-render with highlight layer */
};

const wrapper = addDataNavigator({
    plotContainer: '#my-plot',
    data,
    onNavigate(node) {
        drawChart(node.derivedNode ? null : { x: node.data.fruit });
    },
    onExit() {
        drawChart(null);
    }
});

See the Getting Started guide for the full walkthrough and examples for complete runnable code.

Using with the Inspector

Pass wrapper.structure to @data-navigator/inspector to visualize the navigation graph:

import { Inspector } from '@data-navigator/inspector';

const wrapper = addDataNavigator({ plotContainer: '#plot', data });
const inspector = Inspector({ structure: wrapper.structure, container: 'inspector-container' });

Background

Bokeh charts are visually rich but historically inaccessible — assistive technologies cannot meaningfully interact with the canvas or SVG output. This wrapper builds a parallel accessible interface using a bokeh visualization's underlying data. Our work is informed by the ongoing Bokeh Accessibility Audit, which documents accessibility issues in Bokeh. The audit and this package was supported by a CZI Essential Open Source Software (EOSS) Cycle 6 grant.

Credit

Developed at CMU's Data Interaction Group by Frank Elavsky, in collaboration with Quansight, Anaconda, and Bokeh.

Citing Data Navigator

@article{2023-data-navigator,
  title = {{Data Navigator}: An Accessibility-Centered Data Navigation Toolkit},
  publisher = {{IEEE}},
  author = {Frank Elavsky and Lucas Nadolskis and Dominik Moritz},
  journal = {{IEEE} Transactions on Visualization and Computer Graphics},
  year = {2023},
  url = {http://dig.cmu.edu/data-navigator/}
}