Skip to content

Commit 2b9283f

Browse files
authored
Cell toolbar (#254)
* 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
1 parent 6f7b031 commit 2b9283f

26 files changed

+919
-6
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
matrix:
1616
example:
1717
- clap-button-message
18+
- cell-toolbar
1819
- codemirror-extension
1920
- command-palette
2021
- commands

README.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ You may find it easier to learn how to create extensions _by examples_, instead
9696

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

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

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

141+
### [Cell toolbar](cell-toolbar)
142+
143+
Add a command button to the cell toolbar.
144+
145+
[![Cell toolbar](cell-toolbar/preview.gif)](cell-toolbar)
146+
140147
### [CodeMirror extension](codemirror-extension)
141148

142149
Add a configurable CodeMirror extension.
@@ -183,7 +190,7 @@ Create a new log console.
183190

184191
Display a Datagrid as a Lumino Widget.
185192

186-
[![Datagrid](datagrid/preview.png)](datagrid)
193+
[![Datagrid](datagrid/preview.gif)](datagrid)
187194

188195
### Dual Compatibility
189196

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

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

228235
### [Collaborative Document](documents)
229236

@@ -427,13 +434,13 @@ Then fix the conflicts.
427434

428435
The examples are automatically tested for:
429436

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

cell-toolbar/.copier-answers.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2+
_commit: v4.2.4
3+
_src_path: https://github.com/jupyterlab/extension-template
4+
author_email: ''
5+
author_name: Project Jupyter Contributors
6+
data_format: string
7+
file_extension: ''
8+
has_binder: false
9+
has_settings: true
10+
kind: frontend
11+
labextension_name: '@jupyterlab-examples/cell-toolbar'
12+
mimetype: ''
13+
mimetype_name: ''
14+
project_short_description: A JupyterLab extension to add cell toolbar buttons.
15+
python_name: jupyterlab_examples_cell_toolbar
16+
repository: https://github.com/jupyterlab/extension-examples.git
17+
test: true
18+
viewer_name: ''
19+

cell-toolbar/.gitignore

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
*.bundle.*
2+
lib/
3+
node_modules/
4+
*.log
5+
.eslintcache
6+
.stylelintcache
7+
*.egg-info/
8+
.ipynb_checkpoints
9+
*.tsbuildinfo
10+
jupyterlab_examples_cell_toolbar/labextension
11+
# Version file is handled by hatchling
12+
jupyterlab_examples_cell_toolbar/_version.py
13+
14+
# Integration tests
15+
ui-tests/test-results/
16+
ui-tests/playwright-report/
17+
18+
# Created by https://www.gitignore.io/api/python
19+
# Edit at https://www.gitignore.io/?templates=python
20+
21+
### Python ###
22+
# Byte-compiled / optimized / DLL files
23+
__pycache__/
24+
*.py[cod]
25+
*$py.class
26+
27+
# C extensions
28+
*.so
29+
30+
# Distribution / packaging
31+
.Python
32+
build/
33+
develop-eggs/
34+
dist/
35+
downloads/
36+
eggs/
37+
.eggs/
38+
lib/
39+
lib64/
40+
parts/
41+
sdist/
42+
var/
43+
wheels/
44+
pip-wheel-metadata/
45+
share/python-wheels/
46+
.installed.cfg
47+
*.egg
48+
MANIFEST
49+
50+
# PyInstaller
51+
# Usually these files are written by a python script from a template
52+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
53+
*.manifest
54+
*.spec
55+
56+
# Installer logs
57+
pip-log.txt
58+
pip-delete-this-directory.txt
59+
60+
# Unit test / coverage reports
61+
htmlcov/
62+
.tox/
63+
.nox/
64+
.coverage
65+
.coverage.*
66+
.cache
67+
nosetests.xml
68+
coverage/
69+
coverage.xml
70+
*.cover
71+
.hypothesis/
72+
.pytest_cache/
73+
74+
# Translations
75+
*.mo
76+
*.pot
77+
78+
# Scrapy stuff:
79+
.scrapy
80+
81+
# Sphinx documentation
82+
docs/_build/
83+
84+
# PyBuilder
85+
target/
86+
87+
# pyenv
88+
.python-version
89+
90+
# celery beat schedule file
91+
celerybeat-schedule
92+
93+
# SageMath parsed files
94+
*.sage.py
95+
96+
# Spyder project settings
97+
.spyderproject
98+
.spyproject
99+
100+
# Rope project settings
101+
.ropeproject
102+
103+
# Mr Developer
104+
.mr.developer.cfg
105+
.project
106+
.pydevproject
107+
108+
# mkdocs documentation
109+
/site
110+
111+
# mypy
112+
.mypy_cache/
113+
.dmypy.json
114+
dmypy.json
115+
116+
# Pyre type checker
117+
.pyre/
118+
119+
# End of https://www.gitignore.io/api/python
120+
121+
# OSX files
122+
.DS_Store
123+
124+
# Yarn cache
125+
.yarn/

cell-toolbar/.prettierignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
**/node_modules
3+
**/lib
4+
**/package.json
5+
!/package.json
6+
jupyterlab_examples_cell_toolbar

cell-toolbar/.yarnrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

cell-toolbar/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Cell Toolbar Button
2+
3+
This example shows how to add buttons to the cell toolbar.
4+
The buttons are displayed or not, depending on the cell type.
5+
6+
![Cell toolbar button](preview.gif)
7+
8+
In this particular example, the buttons will execute a code cell, or render a markdown
9+
cell.
10+
11+
The command to run is already defined (`notebook:run-cell`), but we need
12+
to create new commands to display or not the button, depending on the cell type.
13+
14+
To add a button triggering a command to the cell toolbar, you must
15+
specified the following settings:
16+
17+
```json5
18+
// schema/plugin.json#L8-L19
19+
20+
"jupyter.lab.toolbars": {
21+
"Cell": [
22+
{
23+
"name": "run-code-cell",
24+
"command": "toolbar-button:run-code-cell"
25+
},
26+
{
27+
"name": "render-markdows-cell",
28+
"command": "toolbar-button:render-markdown-cell"
29+
}
30+
]
31+
}
32+
```
33+
34+
The key `Cell` inform JupyterLab about which widget toolbar should be
35+
extended. The `name` should be an unique identifier for the widget toolbar
36+
items. The `command` is the unique command identifier.
37+
38+
The commands name are defined in the _src/index.ts_ file:
39+
40+
```ts
41+
// src/index.ts#L8-L17
42+
43+
const CommandIds = {
44+
/**
45+
* Command to render a markdown cell.
46+
*/
47+
renderMarkdownCell: 'toolbar-button:render-markdown-cell',
48+
/**
49+
* Command to run a code cell.
50+
*/
51+
runCodeCell: 'toolbar-button:run-code-cell'
52+
};
53+
```
54+
55+
And the commands are created when the extension is activated:
56+
57+
```ts
58+
// src/index.ts#L30-L48
59+
60+
/* Adds a command enabled only on code cell */
61+
commands.addCommand(CommandIds.runCodeCell, {
62+
icon: runIcon,
63+
caption: 'Run a code cell',
64+
execute: () => {
65+
commands.execute('notebook:run-cell');
66+
},
67+
isVisible: () => tracker.activeCell?.model.type === 'code'
68+
});
69+
70+
/* Adds a command enabled only on markdown cell */
71+
commands.addCommand(CommandIds.renderMarkdownCell, {
72+
icon: markdownIcon,
73+
caption: 'Render a markdown cell',
74+
execute: () => {
75+
commands.execute('notebook:run-cell');
76+
},
77+
isVisible: () => tracker.activeCell?.model.type === 'markdown'
78+
});
79+
```
80+
81+
The following line will add the class `lm-mod-hidden` to the button if the active cell
82+
is not a code cell:
83+
84+
<!-- prettier-ignore-start -->
85+
```ts
86+
// src/index.ts#L37-L37
87+
88+
isVisible: () => tracker.activeCell?.model.type === 'code'
89+
```
90+
<!-- prettier-ignore-end -->
91+
92+
To hide the button, we need to add a CSS rule on the class `lm-mod-hidden` in the file
93+
_style/base.css_:
94+
95+
<!-- prettier-ignore-start -->
96+
<!-- embedme style/base.css#L8-L10 -->
97+
98+
```css
99+
.jp-ToolbarButtonComponent.lm-mod-hidden {
100+
display: none;
101+
}
102+
```
103+
<!-- prettier-ignore-end -->
104+
105+
## Where to Go Next
106+
107+
This example uses a command to display the widget. Have a look a the
108+
[commands example](../commands/README.md) for more information about it.

cell-toolbar/install.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"packageManager": "python",
3+
"packageName": "jupyterlab_examples_cell_toolbar",
4+
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_examples_cell_toolbar"
5+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
try:
2+
from ._version import __version__
3+
except ImportError:
4+
# Fallback when using the package in dev mode without installing
5+
# in editable mode with pip. It is highly recommended to install
6+
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
7+
import warnings
8+
warnings.warn("Importing 'jupyterlab_examples_cell_toolbar' outside a proper installation.")
9+
__version__ = "dev"
10+
11+
12+
def _jupyter_labextension_paths():
13+
return [{
14+
"src": "labextension",
15+
"dest": "@jupyterlab-examples/cell-toolbar"
16+
}]

0 commit comments

Comments
 (0)