Add a simple search bar to your MyST content that filters and subsets items on the page.
Warning, this is kind of hacky!: It “breaks out of the shadow DOM” for anywidgets which is not recommended. The filter works by setting
style.displayon matched DOM elements. This works well for static MyST content (cards, lists, tables), but if React re-renders an element after the filter has hidden it, the inline style will be reset.
Usage¶
Add the plugin to your myst.yml file:
project:
plugins:
- https://github.com/jupyter-book/myst-plugins/raw/refs/heads/main/plugins/searchfilter/searchfilter.mjsThen add a {searchfilter} directive with a CSS selector argument to select the items you’d like to search and filter. For example:
```{searchfilter} .example-list li
```
:::{div}
:class: example-list
- One
- Two
- Three
:::One
Two
Three
This creates a search bar on the page. It uses the CSS selector to match elements, then hides any whose textContent doesn’t contain the search query (case-insensitive).
Search queries are automatically saved in the page URL as a ?searchfilter= query parameter, so filtered views can be shared via link.
Architecture¶
This is an anywidget plugin - it defines two kinds of things in a single file, so that we don’t have to publish two artifacts with our github releases:
Directive - defines the
{searchfilter}directive and returns ananywidgetAST node.Widget - defines the
renderfunction that creates the search UI and handles filtering (this is what :esm: points to).
The logic computes the path to itself when defining :esm: which seems to work, but is also definitely hacky.
Examples¶
Here are a few examples of how you can filter various kinds of items by providing different values for the CSS selector argument.
Cards¶
Use .myst-card to filter cards by their content.
```{searchfilter} .myst-card
```
::::{grid} 3
:::{card} Pandas
A data analysis library for Python.
:::
:::{card} NumPy
Fundamental package for scientific computing with Python.
:::
:::{card} Matplotlib
A plotting library for Python.
:::
::::A data analysis library for Python.
Fundamental package for scientific computing with Python.
A plotting library for Python.
List items¶
Use li to filter items in a list, and a div to filter multiple lists on a page.
```{searchfilter} .example-list li
```
:::{div}
:class: example-list
- **Python** - General-purpose programming language
- **Julia** - High-performance scientific computing
- **R** - Statistical computing and graphics
:::Python - General-purpose programming language
Julia - High-performance scientific computing
R - Statistical computing and graphics
Table rows¶
Use tr to filter rows of a table, and :not(first-child) to de-select the first row (e.g. title row).
```{searchfilter} .example-table tr:not(:first-child)
```
:::{div}
:class: example-table
| Package | Language | Description |
|---|---|---|
| pandas | Python | Data analysis and manipulation |
| NumPy | Python | Numerical computing |
| SciPy | Python | Scientific computing |
:::| Package | Language | Description |
|---|---|---|
| pandas | Python | Data analysis and manipulation |
| NumPy | Python | Numerical computing |
| SciPy | Python | Scientific computing |
Restrict to certain content¶
To restrict your {searchfilter} to only elements in the content area, use a parent selector and your own CSS class. For example:
This restricts the search to those within a custom div you define:
```{searchfilter} .myclass li
```
+++ {"class": "myclass"}
- One
- Two
- ThreeOne
Two
Three
This uses inline directive options to let you attach a class to the directive output:
```{searchfilter} .myclass tr
```
```{list-table .myclass}
- - One
- - Two
- - Three
```One |
Two |
Three |
Do not do this¶
If you select a generic item on the page, then the searchfilter will remove stuff you don’t want to remove! For example:
This will select all `li` items on the page (including menu items etc)
```{searchfilter} li
```
- One
- Two
- ThreeThis will select all li items on the page (including menu items etc)
One
Two
Three