Skip to content

Commit

Permalink
Cell toolbar (#254)
Browse files Browse the repository at this point in the history
* Add an example for custom cell toolbar button

* Add the README and the preview

* Add integration test

* Fix file diff test

* Fix embedme

* Add link in README

* Fix broken previews in README

* update setup.py

* update template
  • Loading branch information
brichet authored Dec 19, 2023
1 parent 6f7b031 commit 2b9283f
Show file tree
Hide file tree
Showing 26 changed files with 919 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
matrix:
example:
- clap-button-message
- cell-toolbar
- codemirror-extension
- command-palette
- commands
Expand Down
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ You may find it easier to learn how to create extensions _by examples_, instead

Start with the [Hello World](hello-world) and then jump to the topic you are interested in.

- [Cell toolbar](cell-toolbar)
- [CodeMirror extension](codemirror-extension)
- [Commands](commands)
- [Command Palette](command-palette)
Expand Down Expand Up @@ -137,6 +138,12 @@ We have structured the examples based on the [extension points](https://jupyterl

You are welcome to open any [issue](https://github.com/jupyterlab/extension-examples/issues) or [pull request](https://github.com/jupyterlab/extension-examples/pulls).

### [Cell toolbar](cell-toolbar)

Add a command button to the cell toolbar.

[![Cell toolbar](cell-toolbar/preview.gif)](cell-toolbar)

### [CodeMirror extension](codemirror-extension)

Add a configurable CodeMirror extension.
Expand Down Expand Up @@ -183,7 +190,7 @@ Create a new log console.

Display a Datagrid as a Lumino Widget.

[![Datagrid](datagrid/preview.png)](datagrid)
[![Datagrid](datagrid/preview.gif)](datagrid)

### Dual Compatibility

Expand Down Expand Up @@ -223,7 +230,7 @@ the top area (in JupyterLab) or the right sidebar (Jupyter Notebook). This examp
of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
Read more about this example on that page.

[![Dual Compatibility Clap Button](clap-button-message/preview.jpg)](clap-button-message)
[![Dual Compatibility Clap Button](clap-button-message/preview.png)](clap-button-message)

### [Collaborative Document](documents)

Expand Down Expand Up @@ -427,13 +434,13 @@ Then fix the conflicts.

The examples are automatically tested for:

- Homogeneous configuration:
- Homogeneous configuration:
Configuration files are compared to the reference ones of the _hello-world_ example
- TypeScript code lint
- Installation in JupyterLab:
- Installation in JupyterLab:
The installation is checked by listing the installed extension and running JupyterLab with the helper `python -m jupyterlab.browser_check`
- Integration test:
Those tests are emulating user action in JupyterLab to check the extension is behaving as expected.
- Integration test:
Those tests are emulating user action in JupyterLab to check the extension is behaving as expected.
The tests are defined in the `ui-tests` subfolder within each example.
This is possible thanks to a tool called [playwright](https://playwright.dev/).

Expand Down
19 changes: 19 additions & 0 deletions cell-toolbar/.copier-answers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
_commit: v4.2.4
_src_path: https://github.com/jupyterlab/extension-template
author_email: ''
author_name: Project Jupyter Contributors
data_format: string
file_extension: ''
has_binder: false
has_settings: true
kind: frontend
labextension_name: '@jupyterlab-examples/cell-toolbar'
mimetype: ''
mimetype_name: ''
project_short_description: A JupyterLab extension to add cell toolbar buttons.
python_name: jupyterlab_examples_cell_toolbar
repository: https://github.com/jupyterlab/extension-examples.git
test: true
viewer_name: ''

125 changes: 125 additions & 0 deletions cell-toolbar/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
*.bundle.*
lib/
node_modules/
*.log
.eslintcache
.stylelintcache
*.egg-info/
.ipynb_checkpoints
*.tsbuildinfo
jupyterlab_examples_cell_toolbar/labextension
# Version file is handled by hatchling
jupyterlab_examples_cell_toolbar/_version.py

# Integration tests
ui-tests/test-results/
ui-tests/playwright-report/

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage/
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# End of https://www.gitignore.io/api/python

# OSX files
.DS_Store

# Yarn cache
.yarn/
6 changes: 6 additions & 0 deletions cell-toolbar/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
**/node_modules
**/lib
**/package.json
!/package.json
jupyterlab_examples_cell_toolbar
1 change: 1 addition & 0 deletions cell-toolbar/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
108 changes: 108 additions & 0 deletions cell-toolbar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Cell Toolbar Button

This example shows how to add buttons to the cell toolbar.
The buttons are displayed or not, depending on the cell type.

![Cell toolbar button](preview.gif)

In this particular example, the buttons will execute a code cell, or render a markdown
cell.

The command to run is already defined (`notebook:run-cell`), but we need
to create new commands to display or not the button, depending on the cell type.

To add a button triggering a command to the cell toolbar, you must
specified the following settings:

```json5
// schema/plugin.json#L8-L19

"jupyter.lab.toolbars": {
"Cell": [
{
"name": "run-code-cell",
"command": "toolbar-button:run-code-cell"
},
{
"name": "render-markdows-cell",
"command": "toolbar-button:render-markdown-cell"
}
]
}
```

The key `Cell` inform JupyterLab about which widget toolbar should be
extended. The `name` should be an unique identifier for the widget toolbar
items. The `command` is the unique command identifier.

The commands name are defined in the _src/index.ts_ file:

```ts
// src/index.ts#L8-L17

const CommandIds = {
/**
* Command to render a markdown cell.
*/
renderMarkdownCell: 'toolbar-button:render-markdown-cell',
/**
* Command to run a code cell.
*/
runCodeCell: 'toolbar-button:run-code-cell'
};
```

And the commands are created when the extension is activated:

```ts
// src/index.ts#L30-L48

/* Adds a command enabled only on code cell */
commands.addCommand(CommandIds.runCodeCell, {
icon: runIcon,
caption: 'Run a code cell',
execute: () => {
commands.execute('notebook:run-cell');
},
isVisible: () => tracker.activeCell?.model.type === 'code'
});

/* Adds a command enabled only on markdown cell */
commands.addCommand(CommandIds.renderMarkdownCell, {
icon: markdownIcon,
caption: 'Render a markdown cell',
execute: () => {
commands.execute('notebook:run-cell');
},
isVisible: () => tracker.activeCell?.model.type === 'markdown'
});
```

The following line will add the class `lm-mod-hidden` to the button if the active cell
is not a code cell:

<!-- prettier-ignore-start -->
```ts
// src/index.ts#L37-L37

isVisible: () => tracker.activeCell?.model.type === 'code'
```
<!-- prettier-ignore-end -->

To hide the button, we need to add a CSS rule on the class `lm-mod-hidden` in the file
_style/base.css_:

<!-- prettier-ignore-start -->
<!-- embedme style/base.css#L8-L10 -->

```css
.jp-ToolbarButtonComponent.lm-mod-hidden {
display: none;
}
```
<!-- prettier-ignore-end -->

## Where to Go Next

This example uses a command to display the widget. Have a look a the
[commands example](../commands/README.md) for more information about it.
5 changes: 5 additions & 0 deletions cell-toolbar/install.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"packageManager": "python",
"packageName": "jupyterlab_examples_cell_toolbar",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_examples_cell_toolbar"
}
16 changes: 16 additions & 0 deletions cell-toolbar/jupyterlab_examples_cell_toolbar/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
try:
from ._version import __version__
except ImportError:
# Fallback when using the package in dev mode without installing
# in editable mode with pip. It is highly recommended to install
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
import warnings
warnings.warn("Importing 'jupyterlab_examples_cell_toolbar' outside a proper installation.")
__version__ = "dev"


def _jupyter_labextension_paths():
return [{
"src": "labextension",
"dest": "@jupyterlab-examples/cell-toolbar"
}]
Loading

0 comments on commit 2b9283f

Please sign in to comment.