This page demonstrates the MyST widget renderer in myst-theme.
Widgets follow the anywidget specification and are added using the {anywidget} directive.
For full documentation on using widgets, see the MyST widgets guide.
For more demos, see the example-widgets repository.
Example widget structure¶
The following local widget shows off the main API that widgets use within MyST:
/**
* An anywidget module must define and export a `render` function that uses two arguments:
- model: Widget state, initialized from the JSON body of the directive.
It has three methods (get, set, on) to update its state, demo'ed below.
- el: The DOM element that is outputted. It begins empty and authors create DOM elements inside.
*/
function render({ model, el }) {
// Inject default styles via a <style> tag so that we can over-ride them with a .css file
// This gives a user more flexibility than hard-coding styles with `style` attributes on the button element.
const style = document.createElement('style');
style.textContent = `
.counter-button {
font-size: 16px;
cursor: pointer;
border: 2px solid #333;
color: #333;
border-radius: 4px;
padding: 0.4em 0.8em;
background: #f0f0f0;
}
`;
el.appendChild(style);
// Create the button element that we'll update
let btn = document.createElement('button');
btn.classList.add('counter-button');
btn.innerHTML = `count is ${model.get('count')}`;
// Attach a click listener to our element to update its state
// Use `get` to grab the current widget count
// Use `set` to set a new widget count
btn.addEventListener('click', () => {
model.set('count', model.get('count') + 1);
});
// Attach an event listener for when the `count` changes to update our HTML
model.on('change:count', () => {
btn.innerHTML = `count is ${model.get('count')}`;
});
// By attaching it to the `el`, it will now be displayed on the page
el.appendChild(btn);
}
export default { render };
Local widget via path¶
This widget includes its own inline styles, so it looks good without any external stylesheet:
anywidget directive.You can also provide an additional CSS stylesheet via :css: to override or enhance the built-in styles:
anywidget directive.Remote widget via URL¶
The following loads a widget from the example-js-anywidget repository:
anywidget directive.Security and best practices¶
Do not modify items outside of the el element¶
Widgets have full access to the document element of a page, which means they can select, modify, or remove any element on the page.
Don’t do this! It will create confusion with React and is generally not a supported workflow, even though it is technically possible.