marimo https://docs.marimo.io marimo is a reactive Python notebook: run a cell or interact with a UI element, and marimo automatically runs dependent cells (or [marks them as stale](https://docs.marimo.io/guides/reactivity/#configuring-how-marimo-runs-cells)), keeping code and outputs consistent and preventing bugs before they happen. Every marimo notebook is stored as pure Python, executable as a script, and deployable as an app. install with pipinstall with uvinstall with conda `[](#__codelineno-0-1)pip install marimo && marimo tutorial intro` `[](#__codelineno-1-1)uv pip install marimo && marimo tutorial intro` `[](#__codelineno-2-1)conda install -c conda-forge marimo && marimo tutorial intro` Developer experience is core to marimo, with an emphasis on reproducibility, maintainability, composability, and shareability. Highlights[¶](#highlights "Permanent link") ------------------------------------------- * 🚀 **batteries-included:** replaces `jupyter`, `streamlit`, `jupytext`, `ipywidgets`, `papermill`, and more * ⚡️ **reactive**: run a cell, and marimo reactively [runs all dependent cells](https://docs.marimo.io/guides/reactivity/) or [marks them as stale](#expensive-notebooks) * 🖐️ **interactive:** [bind sliders, tables, plots, and more](https://docs.marimo.io/guides/interactivity/) to Python — no callbacks required * 🔬 **reproducible:** [no hidden state](https://docs.marimo.io/guides/reactivity/), deterministic execution, [built-in package management](https://docs.marimo.io/guides/editor_features/package_management/) * 🏃 **executable:** [execute as a Python script](https://docs.marimo.io/guides/scripts/), parameterized by CLI args * 🧪 **testable:** [run your favorite test suite](https://docs.marimo.io/guides/testing/), verify your notebook's correctness * 🛜 **shareable**: [deploy as an interactive web app](https://docs.marimo.io/guides/apps/) or [slides](https://docs.marimo.io/guides/apps/#slides-layout), [run in the browser via WASM](https://docs.marimo.io/guides/wasm/) * 🛢️ **designed for data**: query dataframes and databases [with SQL](https://docs.marimo.io/guides/working_with_data/sql/), filter and search [dataframes](https://docs.marimo.io/guides/working_with_data/dataframes/) * 🐍 **git-friendly:** notebooks are stored as `.py` files * ⌨️ **a modern editor**: [GitHub Copilot](https://docs.marimo.io/guides/editor_features/ai_completion/#github-copilot), [AI assistants](https://docs.marimo.io/guides/editor_features/ai_completion/#using-ollama), vim keybindings, variable explorer, and [more](https://docs.marimo.io/guides/editor_features/) A reactive programming environment[¶](#a-reactive-programming-environment "Permanent link") ------------------------------------------------------------------------------------------- marimo guarantees your notebook code, outputs, and program state are consistent. This [solves many problems](https://docs.marimo.io/faq/#faq-problems) associated with traditional notebooks like Jupyter. **A reactive programming environment.** Run a cell and marimo _reacts_ by automatically running the cells that reference its variables, eliminating the error-prone task of manually re-running cells. Delete a cell and marimo scrubs its variables from program memory, eliminating hidden state. **Compatible with expensive notebooks.** marimo lets you [configure the runtime to be lazy](https://docs.marimo.io/guides/configuration/runtime_configuration/), marking affected cells as stale instead of automatically running them. This gives you guarantees on program state while preventing accidental execution of expensive cells. **Synchronized UI elements.** Interact with [UI elements](https://docs.marimo.io/guides/interactivity/) like [sliders](https://docs.marimo.io/api/inputs/slider/#slider), [dropdowns](https://docs.marimo.io/api/inputs/dropdown/), [dataframe transformers](https://docs.marimo.io/api/inputs/dataframe/), and [chat interfaces](https://docs.marimo.io/api/inputs/chat/), and the cells that use them are automatically re-run with their latest values. **Interactive dataframes.** [Page through, search, filter, and sort](https://docs.marimo.io/guides/working_with_data/dataframes/) millions of rows blazingly fast, no code required. **Performant runtime.** marimo runs only those cells that need to be run by statically analyzing your code. **Dynamic markdown and SQL.** Use markdown to tell dynamic stories that depend on Python data. Or build [SQL](https://docs.marimo.io/guides/working_with_data/sql/) queries that depend on Python values and execute them against dataframes, databases, CSVs, Google Sheets, or anything else using our built-in SQL engine, which returns the result as a Python dataframe. Your notebooks are still pure Python, even if they use markdown or SQL. **Deterministic execution order.** Notebooks are executed in a deterministic order, based on variable references instead of cells' positions on the page. Organize your notebooks to best fit the stories you'd like to tell. **Built-in package management.** marimo has built-in support for all major package managers, letting you [install packages on import](https://docs.marimo.io/guides/editor_features/package_management/). marimo can even [serialize package requirements](https://docs.marimo.io/guides/package_reproducibility/) in notebook files, and auto install them in isolated venv sandboxes. **Batteries-included.** marimo comes with GitHub Copilot, AI assistants, Ruff code formatting, HTML export, fast code completion, a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=marimo-team.vscode-marimo), an interactive dataframe viewer, and [many more](https://docs.marimo.io/guides/editor_features/) quality-of-life features. Quickstart[¶](#quickstart "Permanent link") ------------------------------------------- **Installation.** In a terminal, run `[](#__codelineno-3-1)pip install marimo # or conda install -c conda-forge marimo [](#__codelineno-3-2)marimo tutorial intro` **Create notebooks.** Create or edit notebooks with **Run apps.** Run your notebook as a web app, with Python code hidden and uneditable: `[](#__codelineno-5-1)marimo run your_notebook.py` **Execute as scripts.** Execute a notebook as a script at the command line: **Automatically convert Jupyter notebooks.** Automatically convert Jupyter notebooks to marimo notebooks with the CLI `[](#__codelineno-7-1)marimo convert your_notebook.ipynb > your_notebook.py` or use our [web interface](https://marimo.io/convert). **Tutorials.** List all tutorials: Questions?[¶](#questions "Permanent link") ------------------------------------------ See our [FAQ](https://docs.marimo.io/faq/). Learn more[¶](#learn-more "Permanent link") ------------------------------------------- marimo is easy to get started with, with lots of room for power users. For example, here's an embedding visualizer made in marimo ([video](https://marimo.io/videos/landing/full.mp4)): Check out our [guides](https://docs.marimo.io/guides/), our [example gallery](https://marimo.io/gallery), and our [`examples/`](https://github.com/marimo-team/marimo/tree/main/examples) on GitHub to learn more. [](https://marimo.app/l/0ue871)
TutorialInputsPlotsLayout
Contributing[¶](#contributing "Permanent link") ----------------------------------------------- We appreciate all contributions! You don't need to be an expert to help out. Please see [CONTRIBUTING.md](https://github.com/marimo-team/marimo/blob/main/CONTRIBUTING.md) for more details on how to get started. > Questions? Reach out to us [on Discord](https://marimo.io/discord?ref=docs). We're building a community. Come hang out with us! * 🌟 [Star us on GitHub](https://github.com/marimo-team/marimo) * 💬 [Chat with us on Discord](https://marimo.io/discord?ref=docs) * 📧 [Subscribe to our Newsletter](https://marimo.io/newsletter) * ☁️ [Join our Cloud Waitlist](https://marimo.io/cloud) * ✏️ [Start a GitHub Discussion](https://github.com/marimo-team/marimo/discussions) * 💬 [Follow us on Bluesky](https://bsky.app/profile/marimo.io) * 🐦 [Follow us on Twitter](https://twitter.com/marimo_io) * 💬 [Follow us on Mastodon](https://mastodon.social/@marimo_io) * 🕴️ [Follow us on LinkedIn](https://www.linkedin.com/company/marimo-io) Inspiration ✨[¶](#inspiration "Permanent link") ----------------------------------------------- marimo is a **reinvention** of the Python notebook as a reproducible, interactive, and shareable Python program, instead of an error-prone JSON scratchpad. We believe that the tools we use shape the way we think — better tools, for better minds. With marimo, we hope to provide the Python community with a better programming environment to do research and communicate it; to experiment with code and share it; to learn computational science and teach it. Our inspiration comes from many places and projects, especially [Pluto.jl](https://github.com/fonsp/Pluto.jl), [ObservableHQ](https://observablehq.com/tutorials), and [Bret Victor's essays](http://worrydream.com/). marimo is part of a greater movement toward reactive dataflow programming. From [IPyflow](https://github.com/ipyflow/ipyflow), [streamlit](https://github.com/streamlit/streamlit), [TensorFlow](https://github.com/tensorflow/tensorflow), [PyTorch](https://github.com/pytorch/pytorch/tree/main), [JAX](https://github.com/google/jax), and [React](https://github.com/facebook/react), the ideas of functional, declarative, and reactive programming are transforming a broad range of tools for the better.
Getting Started - marimo https://docs.marimo.io/getting_started/ These tutorials will help you get started with marimo | Guide | Description | | --- | --- | | [Installation](https://docs.marimo.io/getting_started/installation/) | Installing marimo | | [Quickstart](https://docs.marimo.io/getting_started/quickstart/) | Create notebooks, run apps, and more from the marimo command-line | | [Key Concepts](https://docs.marimo.io/getting_started/key_concepts/) | A tour of key features and concepts | API Reference - marimo https://docs.marimo.io/api/ Use the marimo library in marimo notebooks (`import marimo as mo`) to * connect interactive inputs like sliders, dropdowns, and tables to Python, * express yourself with dynamically created markdown, * layout information with tabs or grids, * output media like images and audio, * and more! | | | | --- | --- | | [markdown](https://docs.marimo.io/api/markdown/) | Write markdown with `mo.md` | | [inputs](https://docs.marimo.io/api/inputs/) | Connect sliders, dropdowns, tables, and more to Python | | [layouts](https://docs.marimo.io/api/layouts/) | Customize outputs with accordions, tabs, stacks, and more | | [plotting](https://docs.marimo.io/api/plotting/) | Output interactive plots | | [media](https://docs.marimo.io/api/media/) | Output media like images, audio, PDFs, and plain text | | [diagrams](https://docs.marimo.io/api/diagrams/) | Flow charts, graphs, statistic cards, and more | | [status](https://docs.marimo.io/api/status/) | Display progress indicators | | [outputs](https://docs.marimo.io/api/outputs/) | Modify cell outputs, redirect console output | | [control\_flow](https://docs.marimo.io/api/control_flow/) | Control how cells execute | | [html](https://docs.marimo.io/api/html/) | Manipulate HTML objects | | [query\_params](https://docs.marimo.io/api/query_params/) | Access and set query parameters with `mo.query_params` | | [cli\_args](https://docs.marimo.io/api/cli_args/) | Access command-line arguments with `mo.cli_args` | | [caching](https://docs.marimo.io/api/caching/) | Cache expensive computations in memory or on disk | | [state](https://docs.marimo.io/api/state/) | Synchronize multiple UI elements with `mo.state` | | [app](https://docs.marimo.io/api/app/) | Embed notebooks in other notebooks | | [cell](https://docs.marimo.io/api/cell/) | Run cells defined in another notebook | | [miscellaneous](https://docs.marimo.io/api/miscellaneous/) | Miscellaneous utilities | User Guide - marimo https://docs.marimo.io/guides/ Guides[¶](#guides "Permanent link") ----------------------------------- These guides cover marimo's core concepts. Learn by doing! Prefer a hands-on learning experience? marimo comes packaged with interactive tutorials that you can launch with `marimo tutorial` at the command line. | Guide | Description | | --- | --- | | [Running cells](https://docs.marimo.io/guides/reactivity/) | Understanding how marimo runs cells | | [Interactive elements](https://docs.marimo.io/guides/interactivity/) | Using interactive UI elements | | [Visualizing outputs](https://docs.marimo.io/guides/outputs/) | Creating markdown, plots, and other visual outputs | | [Migrating from Jupyter](https://docs.marimo.io/guides/coming_from/jupyter/) | Tips for transitioning from Jupyter | | [Expensive notebooks](https://docs.marimo.io/guides/expensive_notebooks/) | Tips for working with expensive notebooks | | [Working with data](https://docs.marimo.io/guides/working_with_data/) | Using SQL cells, no-code dataframe, and reactive plots | | [Package reproducibility](https://docs.marimo.io/guides/package_reproducibility/) | Making notebooks reproducible down to the packages | | [Editor Features](https://docs.marimo.io/guides/editor_features/) | View variables, dataframe schemas, docstrings, and more | | [Apps](https://docs.marimo.io/guides/apps/) | Running notebooks as apps | | [Scripts](https://docs.marimo.io/guides/scripts/) | Running notebooks as scripts | | [Tests](https://docs.marimo.io/guides/testing/) | Running unit tests in notebooks | | [Export notebooks](https://docs.marimo.io/guides/exporting/) | Exporting notebooks to HTML, ipynb, flat scripts, and more | | [Publish to the web](https://docs.marimo.io/guides/publishing/) | Edit and publish notebooks on the web | | [Run notebooks with WebAssembly](https://docs.marimo.io/guides/wasm/) | Create notebooks in our online playground | | [Deploying](https://docs.marimo.io/guides/deploying/) | Deploying marimo notebooks and apps | | [Configuration](https://docs.marimo.io/guides/configuration/) | Configure various settings | | [Coming from other tools](https://docs.marimo.io/guides/coming_from/) | Transitioning from Jupyter and other tools | | [Extending marimo](https://docs.marimo.io/guides/integrating_with_marimo/) | Rich displays of objects, custom UI plugins | | [State management](https://docs.marimo.io/guides/state/) | Advanced: mutable reactive state | | [Best practices](https://docs.marimo.io/guides/best_practices/) | Best practices to help you get the most out of marimo | | [Troubleshooting](https://docs.marimo.io/guides/troubleshooting/) | Troubleshooting notebooks | Commands - marimo https://docs.marimo.io/cli/ Welcome to marimo! Getting started: * marimo tutorial intro Example usage: * marimo edit: create or edit notebooks * marimo edit notebook.py: create or edit a notebook called notebook.py * marimo run notebook.py: run a notebook as a read-only app * marimo tutorial --help: list tutorials **Usage:** `[](#__codelineno-0-1)marimo [OPTIONS] COMMAND [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--version` | boolean | Show the version and exit. | `False` | | `-l`, `--log-level` | choice (`DEBUG` | `INFO` | `WARN` | `ERROR` | `CRITICAL`) | Choose logging level. | `WARN` | | `-q`, `--quiet` | boolean | Suppress standard out. | `False` | | `-y`, `--yes` | boolean | Automatic yes to prompts, running non-interactively. | `False` | | `-d`, `--development-mode` | boolean | Run in development mode; enables debug logs and server autoreload. | `False` | | `--help` | boolean | Show this message and exit. | `False` | marimo config[¶](#marimo-config "Permanent link") ------------------------------------------------- Various commands for the marimo config. **Usage:** `[](#__codelineno-1-1)marimo config [OPTIONS] COMMAND [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | ### marimo config describe[¶](#marimo-config-describe "Permanent link") Describe the marimo config. **Usage:** `[](#__codelineno-2-1)marimo config describe [OPTIONS]` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | ### marimo config show[¶](#marimo-config-show "Permanent link") Show the marimo config. **Usage:** `[](#__codelineno-3-1)marimo config show [OPTIONS]` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | marimo convert[¶](#marimo-convert "Permanent link") --------------------------------------------------- Convert a Jupyter notebook or Markdown file to a marimo notebook. The argument may be either a path to a local .ipynb/.md file, or an .ipynb/.md file hosted on GitHub. Example usage: `marimo convert your_nb.ipynb -o your_nb.py` or `marimo convert your_nb.md -o your_nb.py` Jupyter notebook conversion will strip out all outputs. Markdown cell conversion with occur on the presence of `{python}` code fences. After conversion, you can open the notebook in the editor: Since marimo is different from traditional notebooks, once in the editor, you may need to fix errors like multiple definition errors or cycle errors. **Usage:** `[](#__codelineno-4-1)marimo convert [OPTIONS] FILENAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-o`, `--output` | path | Output file to save the converted notebook to. If not provided, the converted notebook will be printed to stdout. | None | | `--help` | boolean | Show this message and exit. | `False` | marimo edit[¶](#marimo-edit "Permanent link") --------------------------------------------- Create or edit notebooks. * marimo edit: Start the marimo notebook server * marimo edit notebook.py: Create or edit notebook.py **Usage:** `[](#__codelineno-5-1)marimo edit [OPTIONS] [NAME] [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-p`, `--port` | integer | Port to attach to. | None | | `--host` | text | Host to attach to. | `127.0.0.1` | | `--proxy` | text | Address of reverse proxy. | None | | `--headless` | boolean | Don't launch a browser. | `False` | | `--token` / `--no-token` | boolean | Use a token for authentication. This enables session-based authentication. A random token will be generated if --token-password is not set. If --no-token is set, session-based authentication will not be used. | `True` | | `--token-password` | text | Use a specific token for authentication. This enables session-based authentication. A random token will be generated if not set. | None | | `--base-url` | text | Base URL for the server. Should start with a /. | \`\` | | `--allow-origins` | text | Allowed origins for CORS. Can be repeated. Use \* for all origins. | None | | `--skip-update-check` | boolean | Don't check if a new version of marimo is available for download. | `False` | | `--sandbox` | boolean | Run the command in an isolated virtual environment using `uv run --isolated`. Requires `uv`. | `False` | | `--watch` | boolean | Watch the file for changes and reload the code when saved in another editor. | `False` | | `--help` | boolean | Show this message and exit. | `False` | marimo env[¶](#marimo-env "Permanent link") ------------------------------------------- Print out environment information for debugging purposes. **Usage:** **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | marimo export[¶](#marimo-export "Permanent link") ------------------------------------------------- Export a notebook to various formats. **Usage:** `[](#__codelineno-7-1)marimo export [OPTIONS] COMMAND [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | ### marimo export html[¶](#marimo-export-html "Permanent link") Run a notebook and export it as an HTML file. Example: `marimo export html notebook.py -o notebook.html` Optionally pass CLI args to the notebook: `marimo export html notebook.py -o notebook.html -- -arg1 foo -arg2 bar` **Usage:** `[](#__codelineno-8-1)marimo export html [OPTIONS] NAME [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--include-code` / `--no-include-code` | boolean | Include notebook code in the exported HTML file. | `True` | | `--watch` / `--no-watch` | boolean | Watch notebook for changes and regenerate the output on modification. If watchdog is installed, it will be used to watch the file. Otherwise, file watcher will poll the file every 1s. | `False` | | `-o`, `--output` | path | Output file to save the HTML to. If not provided, the HTML will be printed to stdout. | None | | `--sandbox` | boolean | Run the command in an isolated virtual environment using `uv run --isolated`. Requires `uv`. | `False` | | `--help` | boolean | Show this message and exit. | `False` | ### marimo export html-wasm[¶](#marimo-export-html-wasm "Permanent link") Export a notebook as a WASM-powered standalone HTML file. Example: `marimo export html-wasm notebook.py -o notebook.wasm.html` The exported HTML file will run the notebook using WebAssembly, making it completely self-contained and executable in the browser. This lets you share interactive notebooks on the web without setting up infrastructure to run Python code. The exported notebook runs using Pyodide, which supports most but not all Python packages. To learn more, see the Pyodide documentation. In order for this file to be able to run, it must be served over HTTP, and cannot be opened directly from the file system (e.g. file://). **Usage:** `[](#__codelineno-9-1)marimo export html-wasm [OPTIONS] NAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-o`, `--output` | path | Output directory to save the HTML to. | \_required | | `--mode` | choice (`edit` | `run`) | Whether the notebook code should be editable or readonly. | `run` | | `--watch` / `--no-watch` | boolean | Whether to watch the original file and export upon change | `False` | | `--show-code` / `--no-show-code` | boolean | Whether to show code by default in the exported HTML file; only relevant for run mode. | `False` | | `--help` | boolean | Show this message and exit. | `False` | ### marimo export ipynb[¶](#marimo-export-ipynb "Permanent link") Export a marimo notebook as a Jupyter notebook in topological order. Example: `marimo export ipynb notebook.py -o notebook.ipynb` Watch for changes and regenerate the script on modification: `marimo export ipynb notebook.py -o notebook.ipynb --watch` Requires nbformat to be installed. **Usage:** `[](#__codelineno-10-1)marimo export ipynb [OPTIONS] NAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--sort` | choice (`top-down` | `topological`) | Sort cells top-down or in topological order. | `topological` | | `--watch` / `--no-watch` | boolean | Watch notebook for changes and regenerate the output on modification. If watchdog is installed, it will be used to watch the file. Otherwise, file watcher will poll the file every 1s. | `False` | | `-o`, `--output` | path | Output file to save the ipynb file to. If not provided, the ipynb contents will be printed to stdout. | None | | `--include-outputs` / `--no-include-outputs` | boolean | Run the notebook and include outputs in the exported ipynb file. | `False` | | `--sandbox` | boolean | Run the command in an isolated virtual environment using `uv run --isolated`. Requires `uv`. | `False` | | `--help` | boolean | Show this message and exit. | `False` | ### marimo export md[¶](#marimo-export-md "Permanent link") Export a marimo notebook as a code fenced Markdown file. Example: `marimo export md notebook.py -o notebook.md` Watch for changes and regenerate the script on modification: `marimo export md notebook.py -o notebook.md --watch` **Usage:** `[](#__codelineno-11-1)marimo export md [OPTIONS] NAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--watch` / `--no-watch` | boolean | Watch notebook for changes and regenerate the output on modification. If watchdog is installed, it will be used to watch the file. Otherwise, file watcher will poll the file every 1s. | `False` | | `-o`, `--output` | path | Output file to save the markdown to. If not provided, markdown will be printed to stdout. | None | | `--help` | boolean | Show this message and exit. | `False` | ### marimo export script[¶](#marimo-export-script "Permanent link") Export a marimo notebook as a flat script, in topological order. Example: `marimo export script notebook.py -o notebook.script.py` Watch for changes and regenerate the script on modification: `marimo export script notebook.py -o notebook.script.py --watch` **Usage:** `[](#__codelineno-12-1)marimo export script [OPTIONS] NAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--watch` / `--no-watch` | boolean | Watch notebook for changes and regenerate the output on modification. If watchdog is installed, it will be used to watch the file. Otherwise, file watcher will poll the file every 1s. | `False` | | `-o`, `--output` | path | Output file to save the script to. If not provided, the script will be printed to stdout. | None | | `--help` | boolean | Show this message and exit. | `False` | marimo new[¶](#marimo-new "Permanent link") ------------------------------------------- Create a new notebook. **Usage:** **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-p`, `--port` | integer | Port to attach to. | None | | `--host` | text | Host to attach to. | `127.0.0.1` | | `--proxy` | text | Address of reverse proxy. | None | | `--headless` | boolean | Don't launch a browser. | `False` | | `--token` / `--no-token` | boolean | Use a token for authentication. This enables session-based authentication. A random token will be generated if --token-password is not set. If --no-token is set, session-based authentication will not be used. | `True` | | `--token-password` | text | Use a specific token for authentication. This enables session-based authentication. A random token will be generated if not set. | None | | `--base-url` | text | Base URL for the server. Should start with a /. | \`\` | | `--sandbox` | boolean | Run the command in an isolated virtual environment using `uv run --isolated`. Requires `uv`. | `False` | | `--help` | boolean | Show this message and exit. | `False` | marimo recover[¶](#marimo-recover "Permanent link") --------------------------------------------------- Recover a marimo notebook from JSON. **Usage:** `[](#__codelineno-14-1)marimo recover [OPTIONS] NAME` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | marimo run[¶](#marimo-run "Permanent link") ------------------------------------------- Run a notebook as an app in read-only mode. If NAME is a url, the notebook will be downloaded to a temporary file. Example: **Usage:** `[](#__codelineno-15-1)marimo run [OPTIONS] NAME [ARGS]...` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-p`, `--port` | integer | Port to attach to. | None | | `--host` | text | Host to attach to. | `127.0.0.1` | | `--proxy` | text | Address of reverse proxy. | None | | `--headless` | boolean | Don't launch a browser. | `False` | | `--token` / `--no-token` | boolean | Use a token for authentication. This enables session-based authentication. A random token will be generated if --token-password is not set. If --no-token is set, session-based authentication will not be used. | `False` | | `--token-password` | text | Use a specific token for authentication. This enables session-based authentication. A random token will be generated if not set. | None | | `--include-code` | boolean | Include notebook code in the app. | `False` | | `--session-ttl` | integer | Seconds to wait before closing a session on websocket disconnect. | `120` | | `--watch` | boolean | Watch the file for changes and reload the app. If watchdog is installed, it will be used to watch the file. Otherwise, file watcher will poll the file every 1s. | `False` | | `--base-url` | text | Base URL for the server. Should start with a /. | \`\` | | `--allow-origins` | text | Allowed origins for CORS. Can be repeated. | None | | `--redirect-console-to-browser` | boolean | Redirect console logs to the browser console. | `False` | | `--sandbox` | boolean | Run the command in an isolated virtual environment using `uv run --isolated`. Requires `uv`. | `False` | | `--help` | boolean | Show this message and exit. | `False` | marimo shell-completion[¶](#marimo-shell-completion "Permanent link") --------------------------------------------------------------------- Install shell completions for marimo. Supports bash, zsh, and fish. **Usage:** `[](#__codelineno-16-1)marimo shell-completion [OPTIONS]` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `--help` | boolean | Show this message and exit. | `False` | marimo tutorial[¶](#marimo-tutorial "Permanent link") ----------------------------------------------------- Open a tutorial. marimo is a powerful library for making reactive notebooks and apps. To get the most out of marimo, get started with a few tutorials, starting with the intro: Recommended sequence: `- intro - dataflow - ui - markdown - plots - sql - layout - fileformat - markdown-format - for-jupyter-users` **Usage:** `[](#__codelineno-17-1)marimo tutorial [OPTIONS] {intro|dataflow|ui|markdown|plots|sql|layout|filefor [](#__codelineno-17-2) mat|markdown-format|for-jupyter-users}` **Options:** | Name | Type | Description | Default | | --- | --- | --- | --- | | `-p`, `--port` | integer | Port to attach to. | None | | `--host` | text | Host to attach to. | `127.0.0.1` | | `--proxy` | text | Address of reverse proxy. | None | | `--headless` | boolean | Don't launch a browser. | `False` | | `--token` / `--no-token` | boolean | Use a token for authentication. This enables session-based authentication. A random token will be generated if --token-password is not set. If --no-token is set, session-based authentication will not be used. | `True` | | `--token-password` | text | Use a specific token for authentication. This enables session-based authentication. A random token will be generated if not set. | None | | `--help` | boolean | Show this message and exit. | `False` | Notebooks - marimo https://docs.marimo.io/examples/ Examples[¶](#examples "Permanent link") --------------------------------------- We have a large [library of examples](https://github.com/marimo-team/marimo/tree/main/examples) in our repo. Each example [encapsulates its own Python dependencies in a package sandbox](https://docs.marimo.io/guides/editor_features/package_management/), making it easy to run. We've deployed some of these examples at our [public gallery](https://marimo.io/@public). We spotlight projects from the community each week on [our Twitter](https://x.com/marimo_io); check out our [spotlights repo](https://github.com/marimo-team/spotlights) for a running archive, with links to notebooks. FAQ - marimo https://docs.marimo.io/faq/ Choosing marimo[¶](#choosing-marimo "Permanent link") ----------------------------------------------------- ### How is marimo different from Jupyter?[¶](#how-is-marimo-different-from-jupyter "Permanent link") marimo is a reinvention of the Python notebook as a reproducible, interactive, and shareable Python program that can be executed as scripts or deployed as interactive web apps. **Consistent state.** In marimo, your notebook code, outputs, and program state are guaranteed to be consistent. Run a cell and marimo reacts by automatically running the cells that reference its variables. Delete a cell and marimo scrubs its variables from program memory, eliminating hidden state. **Built-in interactivity.** marimo also comes with [UI elements](https://docs.marimo.io/guides/interactivity/) like sliders, a dataframe transformer, and interactive plots that are automatically synchronized with Python. Interact with an element and the cells that use it are automatically re-run with its latest value. **Pure Python programs.** Unlike Jupyter notebooks, marimo notebooks are stored as pure Python files that can be executed as scripts, deployed as interactive web apps, and versioned easily with Git. ### What problems does marimo solve?[¶](#what-problems-does-marimo-solve "Permanent link") marimo solves problems in reproducibility, maintainability, interactivity, reusability, and shareability of notebooks. **Reproducibility.** In Jupyter notebooks, the code you see doesn't necessarily match the outputs on the page or the program state. If you delete a cell, its variables stay in memory, which other cells may still reference; users can execute cells in arbitrary order. This leads to widespread reproducibility issues. [One study](https://blog.jetbrains.com/datalore/2020/12/17/we-downloaded-10-000-000-jupyter-notebooks-from-github-this-is-what-we-learned/#consistency-of-notebooks) analyzed 10 million Jupyter notebooks and found that 36% of them weren't reproducible. In contrast, marimo guarantees that your code, outputs, and program state are consistent, eliminating hidden state and making your notebook reproducible. marimo achieves this by intelligently analyzing your code and understanding the relationships between cells, and automatically re-running cells as needed. In addition, marimo notebooks can serialize package requirements inline; marimo runs these "sandboxed" notebooks in temporary virtual environments, making them [reproducible down to the packages](https://docs.marimo.io/guides/editor_features/package_management/). **Maintainability.** marimo notebooks are stored as pure Python programs (`.py` files). This lets you version them with Git; in contrast, Jupyter notebooks are stored as JSON and require extra steps to version. **Interactivity.** marimo notebooks come with [UI elements](https://docs.marimo.io/guides/interactivity/) that are automatically synchronized with Python (like sliders, dropdowns); _eg_, scrub a slider and all cells that reference it are automatically re-run with the new value. This is difficult to get working in Jupyter notebooks. **Reusability.** marimo notebooks can be executed as Python scripts from the command-line (since they're stored as `.py` files). In contrast, this requires extra steps to do for Jupyter, such as copying and pasting the code out or using external frameworks. In the future, we'll also let you import symbols (functions, classes) defined in a marimo notebook into other Python programs/notebooks, something you can't easily do with Jupyter. **Shareability.** Every marimo notebook can double as an interactive web app, complete with UI elements, which you can serve using the `marimo run` command. This isn't possible in Jupyter without substantial extra effort. _To learn more about problems with traditional notebooks, see these references [\[1\]](https://austinhenley.com/pubs/Chattopadhyay2020CHI_NotebookPainpoints.pdf) [\[2\]](https://www.youtube.com/watch?v=7jiPeIFXb6U&t=1s)._ ### How is `marimo.ui` different from Jupyter widgets?[¶](#how-is-marimoui-different-from-jupyter-widgets "Permanent link") Unlike Jupyter widgets, marimo's interactive elements are automatically synchronized with the Python kernel: no callbacks, no observers, no manually re-running cells. Using marimo[¶](#using-marimo "Permanent link") ----------------------------------------------- ### Is marimo a notebook or a library?[¶](#is-marimo-a-notebook-or-a-library "Permanent link") marimo is both a notebook and a library. * Create _marimo notebooks_ with the editor that opens in your browser when you run `marimo edit`. * Use the _marimo library_ (`import marimo as mo`) in marimo notebooks. Write markdown with `mo.md(...)`, create stateful interactive elements with `mo.ui` (`mo.ui.slider(...)`), and more. See the docs for an [API reference](https://docs.marimo.io/api/). ### What's the difference between a marimo notebook and a marimo app?[¶](#whats-the-difference-between-a-marimo-notebook-and-a-marimo-app "Permanent link") marimo programs are notebooks, apps, or both, depending on how you use them. There are two ways to interact with a marimo program: 1. open it as a computational _notebook_ with `marimo edit` 2. run it as an interactive _app_ with `marimo run` All marimo programs start as notebooks, since they are created with `marimo edit`. Because marimo notebooks are reactive and have built-in interactive elements, many can easily be made into useful and beautiful apps by simply hiding the notebook code: this is what `marimo run` does. Not every notebook needs to be run as an app — marimo notebooks are useful in and of themselves for rapidly exploring data and doing reproducible science. And not every app is improved by interacting with the notebook. In some settings, such as collaborative research, education, and technical presentations, going back and forth between the notebook view and app view (which you can do from `marimo edit`) can be useful! ### How does marimo know what cells to run?[¶](#how-does-marimo-know-what-cells-to-run "Permanent link") marimo reads each cell once to determine what global names it defines and what global names it reads. When a cell is run, marimo runs all other cells that read any of the global names it defines. A global name can refer to a variable, class, function, or import. In other words, marimo uses _static analysis_ to make a dataflow graph out of your cells. Each cell is a node in the graph across which global variables "flow". Whenever a cell is run, either because you changed its code or interacted with a UI element it reads, all its descendants run in turn. ### Does marimo slow my code down?[¶](#does-marimo-slow-my-code-down "Permanent link") No, marimo doesn't slow your code down. marimo determines the dependencies among cells by reading your code, not running or tracing it, so there's zero runtime overhead. ### How do I prevent automatic execution from running expensive cells?[¶](#how-do-i-prevent-automatic-execution-from-running-expensive-cells "Permanent link") Reactive (automatic) execution ensures your code and outputs are always in sync, improving reproducibility by eliminating hidden state and out-of-order execution; marimo also takes care to run only the minimal set of cells needed to keep your notebook up to date. But when some cells take a long time to run, it's understandable to be concerned that automatic execution will kick off expensive cells before you're ready to run them. _Here are some tips to avoid accidental execution of expensive cells:_ * [Disable expensive cells](https://docs.marimo.io/guides/reactivity/#disabling-cells). When a cell is disabled, it and its descendants are blocked from running. * Wrap UI elements in a [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form). * Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to conditionally stop execution of a cell and its descendants. * Decorate functions with marimo's [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) to cache expensive intermediate computations. * Use [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache) to cache variables to disk; on re-run, marimo will read values from disk instead of recalculating them as long as the cell is not stale. * Disable automatic execution in the [runtime configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/). ### How do I disable automatic execution?[¶](#how-do-i-disable-automatic-execution "Permanent link") You can disable automatic execution through the notebook runtime settings; see the [guide on runtime configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/). When automatic execution is disabled, marimo still gives you guarantees on your notebook state and automatically marks cells as stale when appropriate. ### How do I use sliders and other interactive elements?[¶](#how-do-i-use-sliders-and-other-interactive-elements "Permanent link") Interactive UI elements like sliders are available in `marimo.ui`. * Assign the UI element to a global variable (`slider = mo.ui.slider(0, 100)`) * Include it in the last expression of a cell to display it (`slider` or `mo.md(f"Choose a value: {slider}")`) * Read its current value in another cell via its `value` attribute (`slider.value`) _When a UI element bound to a global variable is interacted with, all cells referencing the global variable are run automatically_. If you have many UI elements or don't know the elements you'll create until runtime, use `marimo.ui.array` and `marimo.ui.dictionary` to create UI elements that wrap other UI elements (`sliders = mo.ui.array([slider(1, 100) for _ in range(n_sliders)])`). All this and more is explained in the UI tutorial. Run it with at the command line. ### How do I add a submit button to UI elements?[¶](#how-do-i-add-a-submit-button-to-ui-elements "Permanent link") Use the `form` method to add a submit button to a UI element. For example, `[](#__codelineno-1-1)form = marimo.ui.text_area().form()` When wrapped in a form, the text area's value will only be sent to Python when you click the submit button. Access the last submitted value of the text area with `form.value`. ### How do I write markdown?[¶](#how-do-i-write-markdown "Permanent link") Import `marimo` (as `mo`) in a notebook, and use the `mo.md` function. Learn more in the [outputs guide](https://docs.marimo.io/guides/outputs/#markdown) or by running `marimo tutorial markdown`. ### How do I display plots?[¶](#how-do-i-display-plots "Permanent link") Include plots in the last expression of a cell to display them, just like all other outputs. If you're using matplotlib, you can display the `Figure` object (get the current figure with `plt.gcf()`). For examples, run the plots tutorial: Also see the [plotting API reference](https://docs.marimo.io/api/plotting/). ### How do I prevent matplotlib plots from being cut off?[¶](#how-do-i-prevent-matplotlib-plots-from-being-cut-off "Permanent link") If your legend or axes labels are cut off, try calling `plt.tight_layout()` before outputting your plot: `[](#__codelineno-3-1)import matplotlib.pyplot as plt [](#__codelineno-3-2)[](#__codelineno-3-3)plt.plot([-8, 8]) [](#__codelineno-3-4)plt.ylabel("my variable") [](#__codelineno-3-5)plt.tight_layout() [](#__codelineno-3-6)plt.gca()` ### How do I display interactive matplotlib plots?[¶](#how-do-i-display-interactive-matplotlib-plots "Permanent link") Use [`marimo.mpl.interactive`](https://docs.marimo.io/api/plotting/#marimo.mpl.interactive). `[](#__codelineno-4-1)fig, ax = plt.subplots() [](#__codelineno-4-2)ax.plot([1, 2]) [](#__codelineno-4-3)mo.mpl.interactive(ax)` ### How do I display objects in rows and columns?[¶](#how-do-i-display-objects-in-rows-and-columns "Permanent link") Use `marimo.hstack` and `marimo.vstack`. See the layout tutorial for details: ### How do I show cell code in the app view?(#faq-show-code)[¶](#how-do-i-show-cell-code-in-the-app-viewfaq-show-code "Permanent link") Use [`mo.show_code`](https://docs.marimo.io/api/outputs/#marimo.show_code). ### How do I create an output with a dynamic number of UI elements?[¶](#how-do-i-create-an-output-with-a-dynamic-number-of-ui-elements "Permanent link") Use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary), or [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch) to create a UI element that wraps a dynamic number of other UI elements. If you need custom formatting, use [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch), otherwise use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) or [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary). For usage examples, see the [recipes for grouping UI elements together](https://docs.marimo.io/recipes/#grouping-ui-elements-together). ### How do I restart a notebook?[¶](#how-do-i-restart-a-notebook "Permanent link") To clear all program memory and restart the notebook from scratch, open the notebook menu in the top right and click "Restart kernel". ### How do I reload modules?[¶](#how-do-i-reload-modules "Permanent link") Enable automatic reloading of modules via the runtime settings in your marimo installation's user configuration. (Click the "gear" icon in the top right of a marimo notebook). When enabled, marimo will automatically hot-reload modified modules before executing a cell. ### Why aren't my `on_change`/`on_click` handlers being called?[¶](#why-arent-my-on_changeon_click-handlers-being-called "Permanent link") A UI Element's `on_change` (or for buttons, `on_click`) handlers are only called if the element is bound to a global variable. For example, this won't work `[](#__codelineno-6-1)mo.vstack([mo.ui.button(on_change=lambda _: print("I was called")) for _ in range(10)])` In such cases (when you want to output a dynamic number of UI elements), you need to use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary), or [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch). See the [recipes for grouping UI elements together](https://docs.marimo.io/recipes/#grouping-ui-elements-together) for example code. ### Why are my `on_change` handlers in an array all referencing the last element?[¶](#why-are-my-on_change-handlers-in-an-array-all-referencing-the-last-element "Permanent link") **Don't do this**: In the below snippet, every `on_change` will print `9`!. `[](#__codelineno-7-1)array = mo.ui.array( [](#__codelineno-7-2) [mo.ui.button(on_change=lambda value: print(i)) for i in range(10) [](#__codelineno-7-3)])` **Instead, do this**: Explicitly bind `i` to the current loop value: `[](#__codelineno-8-1)array = mo.ui.array( [](#__codelineno-8-2) [mo.ui.button(on_change=lambda value, i=i: print(i)) for i in range(10)] [](#__codelineno-8-3)) [](#__codelineno-8-4)array` This is necessary because [in Python, closures are late-binding](https://docs.python-guide.org/writing/gotchas/#late-binding-closures). ### Why aren't my SQL brackets working?[¶](#why-arent-my-sql-brackets-working "Permanent link") Our "SQL" cells are really just Python under the hood to keep notebooks as pure Python scripts. By default, we use `f-strings` for SQL strings, which allows for parameterized SQL like `SELECT * from table where value < {min}`. To escape real `{` / `}` that you don't want parameterized, use double `\{\{...\}\}`: `[](#__codelineno-9-1)SELECT unnest([\{\{'a': 42, 'b': 84\}\}, \{\{'a': 100, 'b': NULL\}\}]);` ### How does marimo treat type annotations?[¶](#how-does-marimo-treat-type-annotations "Permanent link") Type annotations are registered as references of a cell, unless they are explicitly written as strings. This helps ensure correctness of code that depends on type annotations at runtime (_e.g._, Pydantic), while still providing a way to omit annotations from affecting dataflow graph. For example, in `A` is treated as a reference, used in determining the dataflow graph, but in `A` isn't made a reference. For Python 3.12+, marimo additionally implements annotation scoping. ### How do I use dotenv?[¶](#how-do-i-use-dotenv "Permanent link") The package `dotenv`'s `loadenv()` function does not work out-of-the box in marimo. Instead, use `dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))`. ### What packages can I use?[¶](#what-packages-can-i-use "Permanent link") You can use any Python package. marimo cells run arbitrary Python code. ### How do I use marimo on a remote server?[¶](#how-do-i-use-marimo-on-a-remote-server "Permanent link") Use SSH port-forwarding to run marimo on a remote server and connect to it from a browser on your local machine. Make sure to pass the `--headless` flag when starting marimo on remote: You may also want to set a custom host and port: `[](#__codelineno-13-1)marimo edit --headless --host 0.0.0.0 --port 8080` ### How do I make marimo accessible on all network interfaces?[¶](#how-do-i-make-marimo-accessible-on-all-network-interfaces "Permanent link") Use `--host 0.0.0.0` with `marimo edit`, `marimo run`, or `marimo tutorial`: `[](#__codelineno-14-1)marimo edit --host 0.0.0.0` ### How do I use marimo behind JupyterHub?[¶](#how-do-i-use-marimo-behind-jupyterhub "Permanent link") JupyterHub can be configured to launch marimo using the [`jupyter-marimo-proxy` package](https://github.com/jyio/jupyter-marimo-proxy). ### How do I use marimo with JupyterBook?[¶](#how-do-i-use-marimo-with-jupyterbook "Permanent link") [JupyterBook](https://jupyterbook.org/en/stable/intro.html) makes it easy to create static websites with markdown and Jupyter notebooks. To include a marimo notebook in a JupyterBook, you can either export your notebook to an `ipynb` file, or export to `HTML`: 1. export to ipynb: `marimo export ipynb my_notebook.py -o my_notebook.ipynb --include-outputs` 2. export to HTML: `marimo export html my_notebook.py -o my_notebook.html` ### How do I deploy apps?[¶](#how-do-i-deploy-apps "Permanent link") Use the marimo CLI's `run` command to serve a notebook as an app: If you are running marimo inside a Docker container, you may want to run under a different host and port: `[](#__codelineno-16-1)marimo run notebook.py --host 0.0.0.0 --port 8080` ### Is marimo free?[¶](#is-marimo-free "Permanent link") Yes! Community - marimo https://docs.marimo.io/community/ We're building a community. Come hang out with us! * 🌟 [Star us on GitHub](https://github.com/marimo-team/marimo) * 💬 [Chat with us on Discord](https://marimo.io/discord?ref=readme) * 📧 [Subscribe to our Newsletter](https://marimo.io/newsletter) * ☁️ [Join our Cloud Waitlist](https://marimo.io/cloud) * ✏️ [Start a GitHub Discussion](https://github.com/marimo-team/marimo/discussions) * 🦋 [Follow us on Bluesky](https://bsky.app/profile/marimo.io) * 🐦 [Follow us on Twitter](https://twitter.com/marimo_io) * 🕴️ [Follow us on LinkedIn](https://www.linkedin.com/company/marimo-io) Shields[¶](#shields "Permanent link") ------------------------------------- You can use our shield for opening a marimo application: * * * **Markdown** `[](#__codelineno-0-1)[![marimo](https://marimo.io/shield.svg)](https://marimo.app/l/c7h6pz)` **HTML** `[](#__codelineno-1-1) [](#__codelineno-1-2) [](#__codelineno-1-3)` Integrations - marimo https://docs.marimo.io/integrations/ It is easy to integrate your preferred data sources or data warehouses with marimo. Since marimo is strictly Python, you can utilize any Python library to access your data. In this section, we provide some examples of how to integrate with popular data sources. | Integration | Description | | --- | --- | | [MotherDuck](https://docs.marimo.io/integrations/motherduck/) | Integrating with MotherDuck | | [Google Cloud Storage](https://docs.marimo.io/integrations/google_cloud_storage/) | Integrating with Google Cloud Storage | | [Google Cloud BigQuery](https://docs.marimo.io/integrations/google_cloud_bigquery/) | Integrating with Google Cloud BigQuery | | [Google Sheets](https://docs.marimo.io/integrations/google_sheets/) | Integrating with Google Sheets | Installation - marimo https://docs.marimo.io/getting_started/installation/ Before installing marimo, we recommend creating and activating a Python [virtual environment](https://docs.python.org/3/tutorial/venv.html#creating-virtual-environments). Setting up a virtual environment Python uses virtual environments to minimize conflicts among packages. Here's a quickstart for `pip` users. If you use `conda`, please use a [`conda` environment](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands) instead. Run the following in the terminal: * create an environment with `python -m venv marimo-env` * activate the environment: * macOS/Unix: `source marimo-env/bin/activate` * Windows: `marimo-env\Scripts\activate` _Make sure the environment is activated before installing marimo and when using marimo._ Install other packages you may need, such as numpy, pandas, matplotlib, and altair, in this environment. When you're done, deactivate the environment with `deactivate` in the terminal. Learn more from the [official Python tutorial](https://docs.python.org/3/tutorial/venv.html#creating-virtual-environments). Using uv? [uv](https://github.com/astral-sh/uv) is a next-generation Python package installer and manager that is 10-100x faster than pip, and also makes it easy to install Python and manage projects. With `uv`, creating a virtual environment is as easy as `uv venv`. To install marimo, run the following in a terminal: install with pipinstall with uvinstall with conda `[](#__codelineno-2-1)conda install -c conda-forge marimo` To check if the install worked, run A tutorial notebook should open in your browser. Quickstart - marimo https://docs.marimo.io/getting_started/quickstart/ Installing marimo gets you the `marimo` command-line interface (CLI), the entry point to all things marimo. Run tutorials[¶](#run-tutorials "Permanent link") ------------------------------------------------- `marimo tutorial intro` opens the intro tutorial. List all tutorials with Edit notebooks[¶](#edit-notebooks "Permanent link") --------------------------------------------------- Create and edit notebooks with `marimo edit`. * launch the notebook server to create new notebooks, and start or stop existing ones: * create or edit a single notebook with `[](#__codelineno-2-1)marimo edit your_notebook.py` (If `your_notebook.py` doesn't exist, marimo will create a blank notebook named `your_notebook.py`.) Deploy as apps[¶](#deploy-as-apps "Permanent link") --------------------------------------------------- Use `marimo run` to serve your notebook as an app, with Python code hidden and uneditable. `[](#__codelineno-3-1)marimo run your_notebook.py` Convert from Jupyter to marimo[¶](#convert-from-jupyter-to-marimo "Permanent link") ----------------------------------------------------------------------------------- Automatically convert Jupyter notebooks to marimo notebooks with `marimo convert`: `[](#__codelineno-4-1)marimo convert your_notebook.ipynb -o your_notebook.py` Then open the notebook with `marimo edit your_notebook.py` Disable autorun on startup marimo automatically runs notebooks when they are opened. If this is a problem for you (not all Jupyter notebooks are designed to be run on startup), you can disable autorun on startup via [user configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/). 1. Type `marimo config show` to get the location of your config file. 2. If no config file exists, create it at `~/.marimo.toml` or `$XDG_CONFIG_HOME/marimo/marimo.toml`. 3. Update your config to include the following: marimo.toml `[](#__codelineno-5-1)[runtime] [](#__codelineno-5-2)auto_instantiate = false` Export marimo notebooks to other file formats[¶](#export-marimo-notebooks-to-other-file-formats "Permanent link") ----------------------------------------------------------------------------------------------------------------- Use to convert marimo notebooks to other file formats, including HTML, IPYNB, and markdown. Install optional dependencies for more features[¶](#install-optional-dependencies-for-more-features "Permanent link") --------------------------------------------------------------------------------------------------------------------- Some features require additional dependencies, which are not installed by default. This includes: * [SQL cells](https://docs.marimo.io/guides/working_with_data/sql/) * Charts in the datasource viewer * [AI features](https://docs.marimo.io/guides/editor_features/ai_completion/) * Format on save To install the optional dependencies, run: install with pipinstall with uvinstall with conda `[](#__codelineno-7-1)pip install "marimo[recommended]"` `[](#__codelineno-8-1)uv pip install "marimo[recommended]"` `[](#__codelineno-9-1)conda install -c conda-forge marimo duckdb altair polars openai ruff` This will install: `duckdb`, `altair`, `polars`, `openai`, and `ruff`. Enable GitHub Copilot and AI Assistant[¶](#enable-github-copilot-and-ai-assistant "Permanent link") --------------------------------------------------------------------------------------------------- The marimo editor natively supports [GitHub Copilot](https://copilot.github.com/), an AI pair programmer, similar to VS Code. _Get started with Copilot_: 1. Install [Node.js](https://nodejs.org/en/download). 2. Enable Copilot via the settings menu in the marimo editor. _Note_: Copilot is not yet available in our conda distribution; please install marimo from `PyPI` if you need Copilot. marimo also comes with support for [other copilots](https://docs.marimo.io/guides/editor_features/ai_completion/#codeium-copilot), and a built-in [AI assistant](https://docs.marimo.io/guides/editor_features/ai_completion/#generate-code-with-our-ai-assistant) that helps you write code. Try our VS Code extension[¶](#try-our-vs-code-extension "Permanent link") ------------------------------------------------------------------------- The best way to use marimo is through the CLI. However, if you prefer VS Code over terminal, try our [VS Code extension](https://marketplace.visualstudio.com/items?itemName=marimo-team.vscode-marimo). Use this extension to edit and run notebooks directly from VS Code, and to list all marimo notebooks in your current directory. Key Concepts - marimo https://docs.marimo.io/getting_started/key_concepts/ This page covers marimo's key concepts: * marimo lets you rapidly experiment with data using Python, SQL, and interactive elements in a reproducible **notebook environment**. * Unlike Jupyter notebooks, marimo notebooks are reusable software artifacts. marimo notebooks can be shared as as **interactive web apps** and executed as **Python scripts**. Editing notebooks[¶](#editing-notebooks "Permanent link") --------------------------------------------------------- marimo notebooks are **reactive**: they automatically react to your code changes and UI interactions and keep your notebook up-to-date, not unlike a spreadsheet. This makes your notebooks reproducible, [eliminating hidden state](https://docs.marimo.io/faq/#faq-problems); it's also what enables marimo notebooks to double as apps and Python scripts. Working with expensive notebooks If you don't want cells to run automatically, the [runtime can be configured](https://docs.marimo.io/guides/configuration/runtime_configuration/) to be lazy, only running cells when you ask for them to be run and marking affected cells as stale. **See our guide on working with [expensive notebooks](https://docs.marimo.io/guides/expensive_notebooks/) for more tips.** **Create your first notebook.** After [installing marimo](https://docs.marimo.io/getting_started/installation/), create your first notebook with `[](#__codelineno-0-1)marimo edit my_notebook.py` at the command-line. **The marimo library**. We recommend starting each marimo notebook with a cell containing a single line of code, The marimo library lets you use interactive UI elements, layout elements, dynamic markdown, and more in your marimo notebooks. ### How marimo executes cells[¶](#how-marimo-executes-cells "Permanent link") A marimo notebook is made of small blocks of Python code called **cells**. _When you run a cell, marimo automatically runs all cells that read any global variables defined by that cell._ This is reactive execution. **Execution order.** The order of cells on the page has no bearing on the order cells are executed in: execution order is determined by the variables cells define and the variables they read. You have full freedom over how to organize your code and tell your stories: move helper functions and other "appendices" to the bottom of your notebook, or put cells with important outputs at the top. **No hidden state.** marimo notebooks have no hidden state because the program state is automatically synchronized with your code changes and UI interactions. And if you delete a cell, marimo automatically deletes that cell's variables, preventing painful bugs that arise in traditional notebooks. **No magical syntax.** There's no magical syntax or API required to opt-in to reactivity: cells are Python and _only Python_. Behind-the-scenes, marimo statically analyzes each cell's code just once, creating a directed acyclic graph based on the global names each cell defines and reads. This is how data flows in a marimo notebook. Minimize variable mutation. marimo's understanding of your code is based on variable definitions and references; marimo does not track mutations to objects at runtime. For this reason, if you need to mutate a variable (such as adding a new column to a dataframe), you should perform the mutation in the same cell as the one that defines it. Learn more in our [reactivity guide](https://docs.marimo.io/guides/reactivity/#reactivity-mutations). For more on reactive execution, open the dataflow tutorial or read the [reactivity guide](https://docs.marimo.io/guides/reactivity/). ### Visualizing outputs[¶](#visualizing-outputs "Permanent link") marimo visualizes the last expression of each cell as its **output**. Outputs can be any Python value, including markdown and interactive elements created with the marimo library, (_e.g._, [`mo.md`](https://docs.marimo.io/api/markdown/#marimo.md), [`mo.ui.slider`](https://docs.marimo.io/api/inputs/slider/#marimo.ui.slider)). You can even interpolate Python values into markdown (using `mo.md(f"...")`) and other marimo elements to build rich composite outputs: > Thanks to reactive execution, running a cell refreshes all the relevant outputs in your notebook. The marimo library also comes with elements for laying out outputs, including [`mo.hstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.hstack), [`mo.vstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.vstack), [`mo.accordion`](https://docs.marimo.io/api/layouts/accordion/#marimo.accordion), [`mo.ui.tabs`](https://docs.marimo.io/api/inputs/tabs/#marimo.ui.tabs), [`mo.sidebar`](https://docs.marimo.io/api/layouts/sidebar/#marimo.sidebar), [`mo.nav_menu`](https://docs.marimo.io/api/inputs/nav_menu/#marimo.nav_menu), [`mo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table), and [many more](https://docs.marimo.io/api/layouts/). For more on outputs, try these tutorials: `[](#__codelineno-3-1)marimo tutorial markdown [](#__codelineno-3-2)marimo tutorial plots [](#__codelineno-3-3)marimo tutorial layout` or read the [visualizing outputs guide](https://docs.marimo.io/guides/outputs/). ### Creating interactive elements[¶](#creating-interactive-elements "Permanent link") The marimo library comes with many interactive stateful elements in [`marimo.ui`](https://docs.marimo.io/api/inputs/), including simple ones like sliders, dropdowns, text fields, and file upload areas, as well as composite ones like forms, arrays, and dictionaries that can wrap other UI elements. **Using UI elements.** To use a UI element, create it with `mo.ui` and **assign it to a global variable.** When you interact with a UI element in your browser (_e.g._, sliding a slider), _marimo sends the new value back to Python and reactively runs all cells that use the element_, which you can access via its `value` attribute. > **This combination of interactivity and reactivity is very powerful**: use it to make your data tangible during exploration and to build all kinds of tools and apps. _marimo can only synchronize UI elements that are assigned to global variables._ Use composite elements like [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) and [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) if the set of UI elements is not known until runtime. Using buttons to execute cells Use [`mo.ui.run_button`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) to create a button that triggers computation when clicked; see our recipes for [an example](https://docs.marimo.io/recipes/#create-a-button-that-triggers-computation-when-clicked). For more on interactive elements, run the UI tutorial or read the [interactivity guide](https://docs.marimo.io/guides/interactivity/). ### Querying dataframes and databases with SQL[¶](#querying-dataframes-and-databases-with-sql "Permanent link") marimo has built-in support for SQL: you can query Python dataframes, databases, CSVs, Google Sheets, or anything else. After executing your query, marimo returns the result to you as a dataframe, making it seamless to go back and forth between SQL and Python. Query a dataframe using SQL! To create a SQL cell, click on the SQL button that appears at the bottom of the cell array, or right click the create cell button next to a cell. Today, SQL in marimo is executed using [duckdb](https://duckdb.org/docs/). To learn more, run the SQL tutorial or read the [SQL guide](https://docs.marimo.io/guides/working_with_data/sql/). Running notebooks as applications[¶](#running-notebooks-as-applications "Permanent link") ----------------------------------------------------------------------------------------- You can use marimo as a notebook, similar to how you might use Jupyter. But you can also do more: because marimo notebooks are reactive and can include interactive elements, hiding notebook code gives you a simple web app! You can run your notebook as a read-only web app from the command-line: `[](#__codelineno-6-1)marimo run my_notebook.py` The default renderer just hides the notebook code and concatenates outputs vertically. But marimo also supports [other layouts](https://docs.marimo.io/guides/apps/), such as slides and grid. Running notebooks as scripts[¶](#running-notebooks-as-scripts "Permanent link") ------------------------------------------------------------------------------- Because marimo notebooks are stored as pure Python files, each notebook can be executed as a script from the command-line: You can also [pass command-line arguments](https://docs.marimo.io/guides/scripts/) to scripts. Running cells - marimo https://docs.marimo.io/guides/reactivity/ marimo _reacts_ to your code changes: run a cell, and all other cells that refer to the variables it defines are automatically run with the latest data. This keeps your code and outputs consistent, and eliminates bugs before they happen. Why run cells reactively? marimo's "reactive" execution model makes your notebooks more reproducible by eliminating hidden state and providing a deterministic execution order. It also powers marimo's support for [interactive elements](https://docs.marimo.io/guides/interactivity/), for running as apps, and executing as scripts. How marimo runs cells is one of the biggest differences between marimo and traditional notebooks like Jupyter. Learn more at our [FAQ](https://docs.marimo.io/faq/#faq-jupyter). Working with expensive notebooks marimo provides tools for working with expensive notebooks, in which cells might take a long time to run or have side-effects. * The [runtime can be configured](https://docs.marimo.io/guides/configuration/runtime_configuration/) to be **lazy** instead of automatic, marking cells as stale instead of running them. * Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to conditionally stop execution at runtime. See [the expensive notebooks guide](https://docs.marimo.io/guides/expensive_notebooks/) for more tips. How marimo runs cells[¶](#how-marimo-runs-cells "Permanent link") ----------------------------------------------------------------- marimo statically analyzes each cell (i.e., without running it) to determine its * references, the global variables it reads but doesn't define; * definitions, the global variables it defines. It then forms a directed acyclic graph (DAG) on cells, with an edge from one cell to another if the latter references any of the definitions of the former. When a cell is run, its descendants are marked for execution. Runtime Rule When a cell is run, marimo automatically runs all other cells that **reference** any of the global variables it **defines**. marimo [does not track mutations](#variable-mutations-are-not-tracked) to variables, nor assignments to attributes. That means that if you assign an attribute like `foo.bar = 10`, other cells referencing `foo.bar` will _not_ be run. ### Execution order[¶](#execution-order "Permanent link") The order cells are executed in is determined by the relationships between cells and their variables, not by the order of cells on the page (similar to a spreadsheet). This lets you organize your code in whatever way makes the most sense to you. For example, you can put helper functions at the bottom of your notebook. ### Deleting a cell deletes its variables[¶](#deleting-a-cell-deletes-its-variables "Permanent link") In marimo, _deleting a cell deletes its global variables from program memory_. Cells that previously referenced these variables are automatically re-run and invalidated (or marked as stale, depending on your [runtime configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/)). In this way, marimo eliminates a common cause of bugs in traditional notebooks like Jupyter. ### Variable mutations are not tracked[¶](#variable-mutations-are-not-tracked "Permanent link") marimo does not track mutations to objects, _e.g._, mutations like `my_list.append(42)` or `my_object.value = 42` don't trigger reactive re-runs of other cells. **Avoid defining a variable in one cell and mutating it in another**. Why not track mutations? Tracking mutations reliably is impossible in Python. Reacting to mutations could result in surprising re-runs of notebook cells. If you need to mutate a variable (such as adding a new column to a dataframe), you should perform the mutation in the same cell as the one that defines it, or try creating a new variable instead. Create new variables, don't mutate existing ones Mutate variables in the cells that define them Do this ...... not this `[](#__codelineno-4-1)df = pd.DataFrame({"my_column": [1, 2]}) [](#__codelineno-4-2)df["another_column"] = [3, 4]` `[](#__codelineno-5-1)df = pd.DataFrame({"my_column": [1, 2]})` `[](#__codelineno-6-1)df["another_column"] = [3, 4]` Global variable names must be unique[¶](#global-variable-names-must-be-unique "Permanent link") ----------------------------------------------------------------------------------------------- **marimo requires that every global variable be defined by only one cell.** This lets marimo keep code and outputs consistent. Global variables A variable can refer to any Python object. Functions, classes, and imported names are all variables. This rule encourages you to keep the number of global variables in your program small, which is generally considered good practice. ### Creating temporary variables[¶](#creating-temporary-variables "Permanent link") marimo provides two ways to define temporary variables, which can help keep the number of global variables in your notebook small. #### Creating local variables[¶](#creating-local-variables "Permanent link") Variables prefixed with an underscore (_e.g._, `_x`) are "local" to a cell: they can't be read by other cells. Multiple cells can reuse the same local variables names. #### Encapsulating code in functions[¶](#encapsulating-code-in-functions "Permanent link") If you want most or all the variables in a cell to be temporary, prefixing each variable with an underscore to make it local may feel inconvenient. In these situations we recommend encapsulating the temporary variables in a function. For example, if you find yourself copy-pasting the same plotting code across multiple cells and only tweaking a few parameters, try the following pattern: `[](#__codelineno-7-1)def _(): [](#__codelineno-7-2) import matplotlib.pyplot as plt [](#__codelineno-7-3) fig, ax = plt.subplots() [](#__codelineno-7-4) ax.plot([1, 2]) [](#__codelineno-7-5) return ax [](#__codelineno-7-6)[](#__codelineno-7-7)_()` Here, the variables `plt`, `fig`, and `ax` aren't added to the globals. Configuring how marimo runs cells[¶](#configuring-how-marimo-runs-cells "Permanent link") ----------------------------------------------------------------------------------------- Through the notebook settings menu, you can configure how and when marimo runs cells. In particular, you can disable autorun on startup, disable autorun on cell execution, and enable a module autoreloader. Read our [runtime configuration guide](https://docs.marimo.io/guides/configuration/runtime_configuration/) to learn more. Disabling cells[¶](#disabling-cells "Permanent link") ----------------------------------------------------- Sometimes, you may want to edit one part of a notebook without triggering automatic execution of its dependent cells. For example, the dependent cells may take a long time to execute, and you only want to iterate on the first part of a multi-cell computation. For cases like this, marimo lets you **disable** cells: when a cell is disabled, it and its dependents are blocked from running. Disabling a cell blocks it from running. When you re-enable a cell, if any of the cell's ancestors ran while it was disabled, marimo will automatically run it. Enable a cell through the context menu. Stale cells run automatically. Interactive elements - marimo https://docs.marimo.io/guides/interactivity/ One of marimo's most powerful features is its first-class support for interactive user interface (UI) elements, or "widgets", created using [`marimo.ui`](https://docs.marimo.io/api/inputs/). **Interacting with a UI element bound to a global variable automatically runs all cells that reference it.** How interactions run cells[¶](#how-interactions-run-cells "Permanent link") --------------------------------------------------------------------------- Every UI element you make using [`marimo.ui`](https://docs.marimo.io/api/inputs/) has a value, accessible via its `value` attribute. When you interact with a UI element bound to a global variable, its value is sent back to Python. A single rule determines what happens next: Interaction rule When a UI element assigned to a global variable is interacted with, marimo automatically runs all cells that reference the variable (but don't define it). In the clip at the top of this page, interacting with the slider in the second cell re-runs the third cell (which outputs markdown) because it references the slider variable `x`. It doesn't re-run the second cell, because that cell defines `x`. **For interactions on a UI element to have any effect, the element must be assigned to a global variable.** Displaying UI elements[¶](#displaying-ui-elements "Permanent link") ------------------------------------------------------------------- Display UI elements in the output area above a cell by including them in the last expression, just like any other object. You can also embed elements in [markdown](https://docs.marimo.io/api/markdown/#marimo.md) using Python f-strings, like so: `[](#__codelineno-0-1)slider = mo.ui.slider(1, 10) [](#__codelineno-0-2)mo.md(f"Choose a value: {slider})")` Composite elements[¶](#composite-elements "Permanent link") ----------------------------------------------------------- Composite elements are advanced elements let you build UI elements out of other UI elements. The following composite elements are available: * [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) * [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) * [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch) * [`mo.ui.form`](https://docs.marimo.io/api/inputs/form/#marimo.ui.form) **Arrays and dictionaries.** Use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) and [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) to logically group together related elements. These elements are especially useful when a set of UI elements is only known at runtime (so you can't assign each to a global variable individually, but can assign them to an array or dictionary). You can access the elements contained in an array or dictionary using Pythonic syntax, and embed these elements in other outputs. See their docstrings for code examples. **Batch and form.** Use these powerful elements to group together multiple UI elements into a single element with custom formatting, and gate the sending of an element's value on form submission. Use a form to gate value updates on submission Use an array to group together elements or create a collection of elements that is determined at runtime Building custom UI elements using our plugin API[¶](#building-custom-ui-elements-using-our-plugin-api "Permanent link") ----------------------------------------------------------------------------------------------------------------------- You can build your own reactive and interactive UI elements using [anywidget](https://github.com/manzt/anywidget). See [our docs on building custom UI elements](https://docs.marimo.io/guides/integrating_with_marimo/custom_ui_plugins/) to learn more. Expensive notebooks - marimo https://docs.marimo.io/guides/expensive_notebooks/ Working with expensive notebooks[¶](#working-with-expensive-notebooks "Permanent link") --------------------------------------------------------------------------------------- marimo provides tools to control when cells run. Use these tools to prevent expensive cells, which may call APIs or take a long time to run, from accidentally running. Stop execution with `mo.stop`[¶](#stop-execution-with-mostop "Permanent link") ------------------------------------------------------------------------------ Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to stop a cell from executing if a condition is met: `[](#__codelineno-0-1)# if condition is True, the cell will stop executing after mo.stop() returns [](#__codelineno-0-2)mo.stop(condition) [](#__codelineno-0-3)# this won't be called if condition is True [](#__codelineno-0-4)expensive_function_call()` Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) with [`mo.ui.run_button()`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) to require a button press for expensive cells: Configure how marimo runs cells[¶](#configure-how-marimo-runs-cells "Permanent link") ------------------------------------------------------------------------------------- ### Disabling cell autorun[¶](#disabling-cell-autorun "Permanent link") If you habitually work with very expensive notebooks, you can [disable automatic execution](https://docs.marimo.io/guides/configuration/runtime_configuration/#on-cell-change). When automatic execution is disabled, when you run a cell, marimo marks dependent cells as stale instead of running them automatically. ### Disabling autorun on startup[¶](#disabling-autorun-on-startup "Permanent link") marimo autoruns notebooks on startup, with `marimo edit notebook.py` behaving analogously to `python notebook.py`. This can also be disabled through the [notebook settings](https://docs.marimo.io/guides/configuration/runtime_configuration/#on-startup). ### Disable individual cells[¶](#disable-individual-cells "Permanent link") marimo lets you temporarily disable cells from automatically running. This is helpful when you want to edit one part of a notebook without triggering execution of other parts. See the [reactivity guide](https://docs.marimo.io/guides/reactivity/#disabling-cells) for more info. Caching[¶](#caching "Permanent link") ------------------------------------- marimo provides two caching utilities to help you manage expensive computations: 1. In-memory caching with [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) 2. Disk caching with [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache) Both utilities can be used as decorators or context managers. ### In-memory caching[¶](#in-memory-caching "Permanent link") Use [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) to cache the return values of expensive functions, based on their arguments: decoratorcontext manager `[](#__codelineno-2-1)import marimo as mo [](#__codelineno-2-2)[](#__codelineno-2-3)@mo.cache [](#__codelineno-2-4)def compute_predictions(problem_parameters): [](#__codelineno-2-5) # do some expensive computations and return a value [](#__codelineno-2-6) ...` `[](#__codelineno-3-1)import marimo as mo [](#__codelineno-3-2)[](#__codelineno-3-3)with mo.cache("my_cache") as c: [](#__codelineno-3-4) predictions = compute_predictions(problem_parameters):` When `compute_predictions` is called with a value of `problem_parameters` it hasn't seen, it will compute the predictions and store them in an in-memory cache. The next time it is called with the same parameters, instead of recomputing the predictions, it will return the previously computed value from the cache. Comparison to `functools.cache` [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) is like `functools.cache` but smarter. `functools` will sometimes evict values from the cache when it doesn't need to. In particular, consider the case when a cell defining a `@mo.cache`\-d function re-runs due to an ancestor of it running, or a UI element value changing. `mo.cache` will analyze the dataflow graph to determine whether or not the decorated function has changed, and if it hasn't, it's cache won't be invalidated. In contrast, on re-run a `functools` cache is always invalidated, because `functools` has no knowledge about the structure of marimo's dataflow graph. Conversely, [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) knows to invalidate the cache if closed over variables change, whereas `functools.cache` doesn't, yielding incorrect cache hits. [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) is slightly slower than `functools.cache`, but in most applications the overhead is negligible. For performance critical code, where the decorated function will be called in a tight loop, prefer `functools.cache`. ### Disk caching[¶](#disk-caching "Permanent link") Use [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache) to cache variables to disk. The next time your run your notebook, the cached variables will be loaded from disk instead of being recomputed, letting you pick up where you left off. Reserve this for expensive computations that you would like to persist across notebook restarts. Cached outputs are automatically saved to `__marimo__/cache`. **Example.** decoratorcontext manager `[](#__codelineno-4-1)import marimo as mo [](#__codelineno-4-2)[](#__codelineno-4-3)@mo.persistent_cache(name="my_cache") [](#__codelineno-4-4)def compute_predictions(problem_parameters): [](#__codelineno-4-5) # do some expensive computations and return a value [](#__codelineno-4-6) ...` ```[](#__codelineno-5-1)import marimo as mo [](#__codelineno-5-2)[](#__codelineno-5-3)with mo.persistent_cache(name="my_cache"): [](#__codelineno-5-4) # This block of code and its computed variables will be cached to disk [](#__codelineno-5-5) # the first time it's run. The next time it's run, `predictions`` [](#__codelineno-5-6) # will be loaded from disk. [](#__codelineno-5-7) predictions = compute_predictions(problem_parameters) [](#__codelineno-5-8) ...``` Roughly speaking, [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache) registers a cache hit when the cell is not stale, meaning its code hasn't changed and neither have its ancestors. On cache hit the code block won't execute and instead variables will be loaded into memory. Lazy-load expensive UIs[¶](#lazy-load-expensive-uis "Permanent link") --------------------------------------------------------------------- Lazily render UI elements that are expensive to compute using `marimo.lazy`. For example, `[](#__codelineno-6-1)import marimo as mo [](#__codelineno-6-2)[](#__codelineno-6-3)data = db.query("SELECT * FROM data") [](#__codelineno-6-4)mo.lazy(mo.ui.table(data))` In this example, `mo.ui.table(data)` will not be rendered on the frontend until is it in the viewport. For example, an element can be out of the viewport due to scroll, inside a tab that is not selected, or inside an accordion that is not open. However, in this example, data is eagerly computed, while only the rendering of the table is lazy. It is possible to lazily compute the data as well: see the next example. `[](#__codelineno-7-1)import marimo as mo [](#__codelineno-7-2)[](#__codelineno-7-3)def expensive_component(): [](#__codelineno-7-4) import time [](#__codelineno-7-5) time.sleep(1) [](#__codelineno-7-6) data = db.query("SELECT * FROM data") [](#__codelineno-7-7) return mo.ui.table(data) [](#__codelineno-7-8)[](#__codelineno-7-9)accordion = mo.accordion({ [](#__codelineno-7-10) "Charts": mo.lazy(expensive_component) [](#__codelineno-7-11)})` In this example, we pass a function to `mo.lazy` instead of a component. This function will only be called when the user opens the accordion. In this way, `expensive_component` lazily computed and we only query the database when the user needs to see the data. This can be useful when the data is expensive to compute and the user may not need to see it immediately. Visualize outputs - marimo https://docs.marimo.io/guides/outputs/ Visualizing outputs[¶](#visualizing-outputs "Permanent link") ------------------------------------------------------------- The last expression of a cell is its visual output, rendered above the cell. Outputs are included in the "app" or read-only view of the notebook. marimo comes out of the box a number of elements to help you make rich outputs, documented in the [API reference](https://docs.marimo.io/api/). Markdown[¶](#markdown "Permanent link") --------------------------------------- Markdown is written with the marimo library function [`mo.md`](https://docs.marimo.io/api/markdown/#marimo.md). Writing markdown programmatically lets you make dynamic markdown: interpolate Python values into markdown strings, conditionally render your markdown, and embed markdown in other objects. Here's a simple hello world example: `[](#__codelineno-1-1)name = mo.ui.text(placeholder="Your name here") [](#__codelineno-1-2)mo.md( [](#__codelineno-1-3) f""" [](#__codelineno-1-4) Hi! What's your name? [](#__codelineno-1-5) [](#__codelineno-1-6) {name} [](#__codelineno-1-7) """ [](#__codelineno-1-8))` `[](#__codelineno-2-1)mo.md( [](#__codelineno-2-2) f""" [](#__codelineno-2-3) Hello, {name.value}! [](#__codelineno-2-4) """ [](#__codelineno-2-5))` Notice that marimo knows how to render marimo objects in markdown: you can just embed them in [`mo.md()`](https://docs.marimo.io/api/markdown/#marimo.md) using an f-string, and marimo will figure out how to display them! For other objects, like matplotlib plots, wrap them in [`mo.as_html()`](https://docs.marimo.io/api/html/#marimo.as_html) to tap into marimo's media viewer: `[](#__codelineno-3-1)mo.md( [](#__codelineno-3-2) f""" [](#__codelineno-3-3) Here's a plot! [](#__codelineno-3-4) [](#__codelineno-3-5) {mo.as_html(figure)} [](#__codelineno-3-6) """ [](#__codelineno-3-7))` ### Markdown editor[¶](#markdown-editor "Permanent link") marimo automatically renders cells that only use `mo.md("")`, without an `f`\-string, in a markdown editor that supports common hotkeys. Because the Markdown editor doesn't support f-strings, you'll need to use `mo.md` directly to interpolate Python values into your Markdown. You can switch between the Markdown and Python editors by clicking the button in the top right. marimo is pure Python, even when you're using markdown. ### Markdown extensions[¶](#markdown-extensions "Permanent link") #### Details[¶](#details "Permanent link") Create expandable details with additional context: `[](#__codelineno-4-1)/// details | Heads up [](#__codelineno-4-2)[](#__codelineno-4-3)Here's some additional context. [](#__codelineno-4-4)///` Source code for `examples/markdown/details.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you ``import marimo __generated_with = "0.10.19" app = marimo.App() @app.cell(hide_code=True) def _(mo): mo.md(r"""Create expandable markdown blocks with `details`:""") return @app.cell def _(mo): mo.md( """ /// details | Hello, details! Some additional content. /// """ ) return @app.cell(hide_code=True) def _(mo): mo.md(r"""Style details using the "type" argument:""") return @app.cell def _(mo): mo.md( """ /// details | Info details type: info Some additional content. /// """ ) return @app.cell def _(mo): mo.md( """ /// details | Warning details type: warn This highlights something to watch out for /// """ ) return @app.cell def _(mo): mo.md( """ /// details | Danger details type: danger This indicates a critical warning or dangerous situation /// """ ) return @app.cell def _(mo): mo.md( """ /// details | Success details type: success This indicates a successful outcome or positive note /// """ ) return @app.cell def _(): import marimo as mo return (mo,) if __name__ == "__main__": app.run()`` #### Admonitions[¶](#admonitions "Permanent link") Highlight text using admonitions: `[](#__codelineno-5-1)/// attention | This is important. [](#__codelineno-5-2)[](#__codelineno-5-3)Pay attention to this text! [](#__codelineno-5-4)///` Source code for `examples/markdown/admonitions.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.19" app = marimo.App() @app.cell(hide_code=True) def _(mo): mo.md(r"""Use **admonitions** in markdown to bring attention to text. Here are some examples.""") return @app.cell def _(mo): mo.md( """ /// admonition | Heads up. Here's some information. /// """ ) return @app.cell def _(mo): mo.md( """ /// attention | Attention! This is important. /// """ ) return @app.cell def _(): import marimo as mo return (mo,) if __name__ == "__main__": app.run()` #### Emoji[¶](#emoji "Permanent link") Use `:emoji:` syntax to add emojis; for example, `:rocket:` creates 🚀. ### Static files[¶](#static-files "Permanent link") marimo supports serving static files from a `public/` folder located next to your notebook. This is useful for including images or other static assets in your notebook. To use files from the public folder, create a `public` directory next to your notebook and reference files using the `public/` path prefix: `[](#__codelineno-6-1)mo.md( [](#__codelineno-6-2) ''' [](#__codelineno-6-3) [](#__codelineno-6-4) [](#__codelineno-6-5) or [](#__codelineno-6-6) [](#__codelineno-6-7) ![alt text](public/image.png) [](#__codelineno-6-8) ''' [](#__codelineno-6-9))` For security reasons: * Only files within the `public` directory can be accessed * Symlinks are not followed * Path traversal attempts (e.g., `../`) are blocked Layout[¶](#layout "Permanent link") ----------------------------------- The marimo library also comes with elements for laying out outputs, including [`mo.hstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.hstack), [`mo.vstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.vstack), [`mo.accordion`](https://docs.marimo.io/api/layouts/accordion/#marimo.accordion), [`mo.ui.tabs`](https://docs.marimo.io/api/inputs/tabs/#marimo.ui.tabs), [`mo.sidebar`](https://docs.marimo.io/api/layouts/sidebar/#marimo.sidebar), [`mo.nav_menu`](https://docs.marimo.io/api/inputs/nav_menu/#marimo.nav_menu), [`mo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table), and [many more](https://docs.marimo.io/api/layouts/). Progress bars[¶](#progress-bars "Permanent link") ------------------------------------------------- Use [`mo.status.progress_bar`](https://docs.marimo.io/api/status/#marimo.status.progress_bar) and [`mo.status.spinner`](https://docs.marimo.io/api/status/#marimo.status.spinner) to create progress indicators: `[](#__codelineno-7-1)# mo.status.progress_bar is similar to TQDM [](#__codelineno-7-2)for i in mo.status.progress_bar(range(10)): [](#__codelineno-7-3) print(i)` marimo comes with functions to display media, including images, audio, video, pdfs, and more. See the [API docs](https://docs.marimo.io/api/media/) for more info. Imperatively adding outputs[¶](#imperatively-adding-outputs "Permanent link") ----------------------------------------------------------------------------- While a cell's output is its last expression, it can at times be helpful to imperatively add to the output area while a cell is running. marimo provides utility functions like [`mo.output.append`](https://docs.marimo.io/api/outputs/#marimo.output.append) for accomplishing this; see the [API docs](https://docs.marimo.io/api/outputs/) for more information. Console Outputs[¶](#console-outputs "Permanent link") ----------------------------------------------------- Console outputs, such as print statements, show up below a cell in the console output area; they are not included in the output area or app view by default. To include console outputs in the cell output area, use [`mo.redirect_stdout`](https://docs.marimo.io/api/outputs/#marimo.redirect_stdout) or [`mo.redirect_stderr`](https://docs.marimo.io/api/outputs/#marimo.redirect_stderr): `[](#__codelineno-8-1)with mo.redirect_stdout(): [](#__codelineno-8-2) print("Hello, world!")` marimo also includes utility functions for [capturing standard out](https://docs.marimo.io/api/outputs/#marimo.capture_stdout) and [standard error](https://docs.marimo.io/api/outputs/#marimo.capture_stderr) without redirecting them. See the [API docs](https://docs.marimo.io/api/outputs/#console-outputs) for more. Threading[¶](#threading "Permanent link") ----------------------------------------- To create a thread that can reliably communicate outputs to the frontend, use [`mo.Thread`](https://docs.marimo.io/api/miscellaneous/#marimo.Thread), which has exactly the same API as as `threading.Thread`. If you need to forward outputs from threads spawned by third-party code, try patching `threading.Thread`: `[](#__codelineno-9-1)import threading [](#__codelineno-9-2)import marimo as mo [](#__codelineno-9-3)[](#__codelineno-9-4)threading.Thread = mo.Thread` SQL, dataframes, and plots - marimo https://docs.marimo.io/guides/working_with_data/ Working with data[¶](#working-with-data "Permanent link") --------------------------------------------------------- These guides introduce you to marimo's features for working with data, including SQL cells, no-code dataframe transformation tools, and plots whose selections are automatically sent back to Python. | Guide | Description | | --- | --- | | [SQL](https://docs.marimo.io/guides/working_with_data/sql/) | Use SQL to query dataframes, databases, CSVs, etc. | | [Dataframes](https://docs.marimo.io/guides/working_with_data/dataframes/) | Filter, search, and transform dataframes without code | | [Plotting](https://docs.marimo.io/guides/working_with_data/plotting/) | Send plot selections to Python | DataFrames - marimo https://docs.marimo.io/guides/working_with_data/dataframes/ Interactive dataframes[¶](#interactive-dataframes "Permanent link") ------------------------------------------------------------------- **marimo makes you more productive when working with dataframes**. * [Display dataframes](#displaying-dataframes) in a rich, interactive table and chart views * [Transform dataframes](#transforming-dataframes) with filters, groupbys, aggregations, and more, **no code required** * [Select data](#selecting-dataframes) from tables or charts and get selections back in Python as dataframes _marimo integrates with [Pandas](https://pandas.pydata.org/) and [Polars](https://pola.rs/) dataframes natively_. Displaying dataframes[¶](#displaying-dataframes "Permanent link") ----------------------------------------------------------------- marimo lets you page through, search, sort, and filter dataframes, making it extremely easy to get a feel for your data. marimo brings dataframes to life. Display dataframes by including them in the last expression of the cell, just like any other object. pandaspolars `[](#__codelineno-0-1)import pandas as pd [](#__codelineno-0-2)[](#__codelineno-0-3)df = pd.read_json( [](#__codelineno-0-4) "https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json" [](#__codelineno-0-5)) [](#__codelineno-0-6)df` `[](#__codelineno-1-1)import polars as pl [](#__codelineno-1-2)[](#__codelineno-1-3)df = pl.read_json( [](#__codelineno-1-4) "https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json" [](#__codelineno-1-5)) [](#__codelineno-1-6)df` To opt out of the rich dataframe viewer, use [`mo.plain`](https://docs.marimo.io/api/layouts/plain/#marimo.plain): pandaspolars `[](#__codelineno-2-1)df = pd.read_json( [](#__codelineno-2-2)"https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json" [](#__codelineno-2-3)) [](#__codelineno-2-4)mo.plain(df)` `[](#__codelineno-3-1)df = pl.read_json( [](#__codelineno-3-2)"https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json" [](#__codelineno-3-3)) [](#__codelineno-3-4)mo.plain(df)` Transforming dataframes[¶](#transforming-dataframes "Permanent link") --------------------------------------------------------------------- ### No-code transformations[¶](#no-code-transformations "Permanent link") Use [`mo.ui.dataframe`](https://docs.marimo.io/api/inputs/dataframe/#marimo.ui.dataframe) to interactively transform a dataframe with a GUI, no coding required. When you're done, you can copy the code that the GUI generated for you and paste it into your notebook. Build transformations using a GUI pandaspolars `[](#__codelineno-4-1)# Cell 1 [](#__codelineno-4-2)import marimo as mo [](#__codelineno-4-3)import pandas as pd [](#__codelineno-4-4)[](#__codelineno-4-5)df = pd.DataFrame({"person": ["Alice", "Bob", "Charlie"], "age": [20, 30, 40]}) [](#__codelineno-4-6)transformed_df = mo.ui.dataframe(df) [](#__codelineno-4-7)transformed_df` `[](#__codelineno-5-1)# Cell 2 [](#__codelineno-5-2)# transformed_df.value holds the transformed dataframe [](#__codelineno-5-3)transformed_df.value` `[](#__codelineno-6-1)# Cell 1 [](#__codelineno-6-2)import marimo as mo [](#__codelineno-6-3)import polars as pl [](#__codelineno-6-4)[](#__codelineno-6-5)df = pl.DataFrame({"person": ["Alice", "Bob", "Charlie"], "age": [20, 30, 40]}) [](#__codelineno-6-6)transformed_df = mo.ui.dataframe(df) [](#__codelineno-6-7)transformed_df` `[](#__codelineno-7-1)# Cell 2 [](#__codelineno-7-2)# transformed_df.value holds the transformed dataframe [](#__codelineno-7-3)transformed_df.value` Copy the code of the transformation ### Custom filters[¶](#custom-filters "Permanent link") Create custom filters with marimo UI elements, like sliders and dropdowns. pandaspolars `[](#__codelineno-8-1)# Cell 1 - create a dataframe [](#__codelineno-8-2)df = pd.DataFrame({"person": ["Alice", "Bob", "Charlie"], "age": [20, 30, 40]})` `[](#__codelineno-9-1)# Cell 2 - create a filter [](#__codelineno-9-2)age_filter = mo.ui.slider(start=0, stop=100, value=50, label="Max age") [](#__codelineno-9-3)age_filter` `[](#__codelineno-10-1)# Cell 3 - display the transformed dataframe [](#__codelineno-10-2)filtered_df = df[df["age"] < age_filter.value] [](#__codelineno-10-3)mo.ui.table(filtered_df)` `[](#__codelineno-11-1)import marimo as mo [](#__codelineno-11-2)import polars as pl [](#__codelineno-11-3)[](#__codelineno-11-4)df = pl.DataFrame({ [](#__codelineno-11-5) "name": ["Alice", "Bob", "Charlie", "David"], [](#__codelineno-11-6) "age": [25, 30, 35, 40], [](#__codelineno-11-7) "city": ["New York", "London", "Paris", "Tokyo"] [](#__codelineno-11-8)}) [](#__codelineno-11-9)[](#__codelineno-11-10)age_filter = mo.ui.slider.from_series(df["age"], label="Max age") [](#__codelineno-11-11)city_filter = mo.ui.dropdown.from_series(df["city"], label="City") [](#__codelineno-11-12)[](#__codelineno-11-13)mo.hstack([age_filter, city_filter])` `[](#__codelineno-12-1)# Cell 2 [](#__codelineno-12-2)filtered_df = df.filter((pl.col("age") <= age_filter.value) & (pl.col("city") == city_filter.value)) [](#__codelineno-12-3)mo.ui.table(filtered_df)` Select dataframe rows[¶](#selecting-dataframes "Permanent link") ---------------------------------------------------------------- Display dataframes as interactive, [selectable charts](https://docs.marimo.io/guides/working_with_data/plotting/) using [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) or [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly), or as a row-selectable table with [`mo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table). Select points in the chart, or select a table row, and your selection is _automatically sent to Python as a subset of the original dataframe_. Select rows in a table, get them back as a dataframe pandaspolars `[](#__codelineno-13-1)# Cell 1 - display a dataframe [](#__codelineno-13-2)import marimo as mo [](#__codelineno-13-3)import pandas as pd [](#__codelineno-13-4)[](#__codelineno-13-5)df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) [](#__codelineno-13-6)table = mo.ui.table(df, selection="multi") [](#__codelineno-13-7)table` `[](#__codelineno-14-1)# Cell 2 - display the selection [](#__codelineno-14-2)table.value` `[](#__codelineno-15-1)# Cell 1 - display a dataframe [](#__codelineno-15-2)import marimo as mo [](#__codelineno-15-3)import polars as pl [](#__codelineno-15-4)[](#__codelineno-15-5)df = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) [](#__codelineno-15-6)table = mo.ui.table(df, selection="multi") [](#__codelineno-15-7)table` `[](#__codelineno-16-1)# Cell 2 - display the selection [](#__codelineno-16-2)table.value` Example notebook[¶](#example-notebook "Permanent link") ------------------------------------------------------- For a comprehensive example of using Polars with marimo, check out our [Polars example notebook](https://github.com/marimo-team/marimo/blob/main/examples/third_party/polars/polars_example.py). Run it with: `[](#__codelineno-17-1)marimo edit https://raw.githubusercontent.com/marimo-team/marimo/main/examples/third_party/polars/polars_example.py` Migrate from Jupyter - marimo https://docs.marimo.io/guides/coming_from/jupyter/ Coming from Jupyter[¶](#coming-from-jupyter "Permanent link") ------------------------------------------------------------- If you're coming from Jupyter, here are a few tips to help you adapt to marimo notebooks. Adapting to marimo's execution model[¶](#adapting-to-marimos-execution-model "Permanent link") ---------------------------------------------------------------------------------------------- The biggest difference between marimo and Jupyter is the execution model. A **Jupyter** notebook is a **REPL**: you execute blocks of code one at a time, and Jupyter has no understanding of how different blocks are related to each other. As a result a Jupyter notebook can easily accumulate "hidden state" (and hidden bugs) --- you might accidentally execute cells out of order, or you might run (or delete) a cell but forget to re-run cells that depended on its variables. Because of this, Jupyter notebooks suffer from a [reproducibility crisis](https://docs.marimo.io/faq/#faq-problems), with over a third of Jupyter notebooks on GitHub failing to reproduce. Unlike Jupyter, **marimo** notebooks understand how different blocks of code are related to each other, modeling your code as a graph on cells based on variable declarations and references. This eliminates hidden state, and it's also what enables marimo notebooks to be reused as apps and scripts. **By default, if you run a cell in marimo, all other cells that read its variables run automatically.** While this ensures that your code and outputs are in sync, it can take some time getting used to. **Here are some tips and tools to help you adapt to marimo's execution model.** ### Configure marimo's runtime[¶](#configure-marimos-runtime "Permanent link") [Configure marimo's runtime](https://docs.marimo.io/guides/configuration/runtime_configuration/) to not autorun on startup or on cell execution. Even when autorun is disabled, marimo still tracks dependencies across cells, marking dependents of a cell as stale when you run it. You can click a single button to run all your stale cells and bring your notebook back up-to-date. ### Stop execution with `mo.stop`[¶](#stop-execution-with-mostop "Permanent link") Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to stop a cell from executing if a condition is met: `[](#__codelineno-0-1)# if condition is True, the cell will stop executing after mo.stop() returns [](#__codelineno-0-2)mo.stop(condition) [](#__codelineno-0-3)# this won't be called if condition is True [](#__codelineno-0-4)expensive_function_call()` Use [`mo.stop()`](https://docs.marimo.io/api/control_flow/#marimo.stop) in conjunction with [`mo.ui.run_button()`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) to require a button press for expensive cells: ### Working with expensive notebooks[¶](#working-with-expensive-notebooks "Permanent link") For more tips on adapting to marimo's execution model, see our guide on [working with expensive notebooks](https://docs.marimo.io/guides/expensive_notebooks/). Adapting to marimo's restriction on redefining variables[¶](#adapting-to-marimos-restriction-on-redefining-variables "Permanent link") -------------------------------------------------------------------------------------------------------------------------------------- marimo "compiles" your notebook cells into a directed graph on cells, linked by variable declarations and references, reusing this graph to run your notebook as a script or app. For marimo's compilation to work, the same variable cannot be defined in multiple cells; otherwise, marimo wouldn't know what order to run cells in. To adapt to the restriction, we suggest: 1. Encapsulating code into functions when possible, to minimize the number of global variables. 2. Prefixing temporary variables with an underscore (`_my_temporary`), which makes the variable **local** to a cell. 3. Mutating variables in the cell that defines them. When working with **dataframes**, you might be used to redefining the same `df` variable in multiple cells. That won't work in marimo. Instead, try merging the cells into a single cell: _Don't_ do this: `[](#__codelineno-2-1)df = pd.DataFrame({"my_column": [1, 2]})` `[](#__codelineno-3-1)df["another_column"] = [3, 4]` _Instead_, do this: `[](#__codelineno-4-1)df = pd.DataFrame({"my_column": [1, 2]}) [](#__codelineno-4-2)df["another_column"] = [3, 4]` If you do need to transform a dataframe across multiple cells, you can alias the dataframe: `[](#__codelineno-5-1)df = pd.DataFrame({"my_column": [1, 2]})` `[](#__codelineno-6-1)augmented_df = df [](#__codelineno-6-2)augmented_df["another_column"] = [3, 4]` Adapting to marimo's file format[¶](#adapting-to-marimos-file-format "Permanent link") -------------------------------------------------------------------------------------- marimo stores notebooks as Python, not JSON. This lets you version notebooks with git, [execute them as scripts](https://docs.marimo.io/guides/scripts/), and import named cells into other Python files. However, it does mean that your notebook outputs (e.g., plots) are not stored in the file. If you'd like to keep a visual record of your notebook work, [enable the "Auto-download as HTML" setting](https://docs.marimo.io/guides/configuration/), which will periodically snapshot your notebook as HTML to a `__marimo__` folder in the notebook directory. ### Converting Jupyter notebooks to marimo notebooks[¶](#converting-jupyter-notebooks-to-marimo-notebooks "Permanent link") Convert Jupyter notebooks to marimo notebooks at the command-line: `[](#__codelineno-7-1)marimo convert your_notebook.ipynb -o your_notebook.py` Adapting to the absence of magic commands[¶](#adapting-to-the-absence-of-magic-commands "Permanent link") --------------------------------------------------------------------------------------------------------- Because marimo notebooks are just Python (improving maintainability), marimo doesn't support IPython magic commands or `!`\-prefixed console commands. Here are some alternatives. ### Run console commands with subprocess.run[¶](#run-console-commands-with-subprocessrun "Permanent link") To run a console command, use Python's [subprocess.run](https://docs.python.org/3/library/subprocess.html#subprocess.run): `[](#__codelineno-8-1)import subprocess [](#__codelineno-8-2)[](#__codelineno-8-3)# run: "ls -l" [](#__codelineno-8-4)subprocess.run(["ls", "-l"])` ### Common magic commands replacements[¶](#common-magic-commands-replacements "Permanent link") | Magic Command | Replacement | | --- | --- | | %cd | `os.chdir()`, see also [`mo.notebook_dir()`](https://docs.marimo.io/api/miscellaneous/#marimo.notebook_dir) | | %clear | Right-click or toggle the cell actions | | %debug | Python's built-in debugger: `breakpoint()` | | %env | `os.environ` | | %load | N/A - use Python imports | | %load\_ext | N/A | | %autoreload | marimo's [module autoreloader](https://docs.marimo.io/guides/editor_features/module_autoreloading/) | | %matplotlib | marimo auto-displays plots | | %pwd | `os.getcwd()` | | %pip | Use marimo's [built-in package management](https://docs.marimo.io/guides/editor_features/package_management/) | | %who\_ls | `dir()`, `globals()`, [`mo.refs()`](https://docs.marimo.io/api/miscellaneous/#marimo.refs), [`mo.defs()`](https://docs.marimo.io/api/miscellaneous/#marimo.defs) | | %system | `subprocess.run()` | | %%time | `time.perf_counter()` or Python's timeit module | | %%timeit | Python's timeit module | | %%writefile | `with open("file.txt", "w") as f: f.write()` | | %%capture | [`mo.capture_stdout()`](https://docs.marimo.io/api/outputs/#marimo.capture_stdout), [`mo.capture_stderr()`](https://docs.marimo.io/api/outputs/#marimo.capture_stderr) | | %%html | [`mo.Html()`](https://docs.marimo.io/api/html/#marimo.Html) or [`mo.md()`](https://docs.marimo.io/api/markdown/#marimo.md) | | %%latex | [`mo.md(r'$$...$$')`](https://docs.marimo.io/api/markdown/#marimo.md) | ### Installing packages with marimo's package manager[¶](#installing-packages-with-marimos-package-manager "Permanent link") Use marimo's package management sidebar panel to install packages to your current environment. Learn more in our [package management guide](https://docs.marimo.io/guides/editor_features/package_management/). Interactive guide[¶](#interactive-guide "Permanent link") --------------------------------------------------------- This guide contains additional tips to help you adapt to marimo. Fun fact: the guide is itself a marimo notebook! Package reproducibility - marimo https://docs.marimo.io/guides/package_reproducibility/ marimo is the only Python notebook that is reproducible down to the packages, serializing requirements in notebook files and running notebooks in sandboxed venvs. This lets you share standalone notebooks without shipping `requirements.txt` files alongside them, and guarantees your notebooks will work weeks, months, even years into the future. To opt-in to package reproducibility, use the `sandbox` flag: editrunnew `[](#__codelineno-0-1)marimo edit --sandbox notebook.py` `[](#__codelineno-1-1)marimo run --sandbox notebook.py` When running with `--sandbox`, marimo: 1. tracks the packages and versions used by your notebook, saving them in the notebook file; 2. runs in an isolated virtual environment ("sandbox") that only contains the notebook dependencies. marimo's sandbox provides two key benefits. (1) Notebooks that carry their own dependencies are easy to share — just send the `.py` file. (2) Isolating a notebook from other installed packages prevents obscure bugs. Solving the notebook reproducibility crisis marimo's support for package sandboxing is only possible because marimo notebooks are stored as pure Python files, letting marimo take advantage of new Python standards like [PEP 723](https://peps.python.org/pep-0723/) and tools like uv. In contrast, traditional notebooks like Jupyter are stored as JSON files, and which suffer from a [reproducibility crisis](https://leomurta.github.io/papers/pimentel2019a.pdf) due to the lack of package management. When running with `--sandbox`, marimo automatically tracks package metadata in your notebook file using inline script metadata, which per [PEP 723](https://peps.python.org/pep-0723/) is essentially a pyproject.toml inlined as the script's header. This metadata is used to manage the notebook's dependencies and Python version, and looks something like this: `[](#__codelineno-3-1)# /// script [](#__codelineno-3-2)# requires-python = ">=3.11" [](#__codelineno-3-3)# dependencies = [ [](#__codelineno-3-4)# "pandas==", [](#__codelineno-3-5)# "altair==", [](#__codelineno-3-6)# ] [](#__codelineno-3-7)# ///` Example notebooks The [example notebooks](https://github.com/marimo-team/marimo/tree/main/examples) in our GitHub repo were all created using `--sandbox`. Take a look at any of them for an example of the full script metadata. ### Adding and removing packages[¶](#adding-and-removing-packages "Permanent link") When you import a module, if marimo detects that it is a third-party package, it will automatically be added to the script metadata. Removing an import does _not_ remove it from the script metadata (since library code may still use the package). Adding packages via the package manager panel will also add packages to script metadata, and removing packages from the panel will in turn remove them from the script metadata. You can also edit the script metadata manually in an editor like VS Code or neovim. ### Package locations[¶](#package-locations "Permanent link") By default, marimo will look for packages on PyPI. You can edit the script metadata to look for packages elsewhere, such as on GitHub. Consult the [Python packaging documentation](https://packaging.python.org/en/latest/specifications/dependency-specifiers/#examples) for more information. Configuration[¶](#configuration "Permanent link") ------------------------------------------------- Running marimo in a sandbox environment uses `uv` to create an isolated virtual environment. You can use any of `uv`'s [supported environment variables](https://docs.astral.sh/uv/configuration/environment/). #### Choosing the Python version[¶](#choosing-the-python-version "Permanent link") For example, you can specify the Python version using the `UV_PYTHON` environment variable: `[](#__codelineno-4-1)UV_PYTHON=3.13 marimo edit --sandbox notebook.py` #### Other common configuration[¶](#other-common-configuration "Permanent link") Another common configuration is `uv`'s link mode: `[](#__codelineno-5-1)UV_LINK_MODE="copy" marimo edit --sandbox notebook.py` Editor features - marimo https://docs.marimo.io/guides/editor_features/ The **marimo editor** is the browser-based IDE in which you write marimo notebooks. We've taken a batteries-included approach to designing the editor: it comes _packed_ with features to make you productive when working with code and data. | Guide | Description | | --- | --- | | [Overview](https://docs.marimo.io/guides/editor_features/overview/) | An overview of editor features and configuration | | [Package Management](https://docs.marimo.io/guides/editor_features/package_management/) | Using package managers in marimo | | [AI Completion](https://docs.marimo.io/guides/editor_features/ai_completion/) | Code with the help of a language model | | [Hotkeys](https://docs.marimo.io/guides/editor_features/hotkeys/) | Our hotkeys | Highlights include: * a variables panel that lets you explore variable values and see where they are defined * a data explorer that lets you inspect dataframes and tables at a glance * smart module autoreloading that tells you which cells need to be rerun * code completion * GitHub Copilot * language-model assisted coding * vim keybindings * live documentation preiews as you type and much more. SQL - marimo https://docs.marimo.io/guides/working_with_data/sql/ Using SQL[¶](#using-sql "Permanent link") ----------------------------------------- marimo lets you can mix and match **Python and SQL**: Use SQL to query Python dataframes (or databases like SQLite and Postgres), and get the query result back as a Python dataframe. To create a SQL cell, you first need to install additional dependencies, including [duckdb](https://duckdb.org/): install with pipinstall with uvinstall with conda `[](#__codelineno-0-1)pip install "marimo[sql]"` `[](#__codelineno-1-1)uv pip install "marimo[sql]"` `[](#__codelineno-2-1)conda install -c conda-forge marimo duckdb polars` Example[¶](#example "Permanent link") ------------------------------------- In this example notebook, we have a Pandas dataframe and a SQL cell that queries it. Notice that the query result is returned as a Python dataframe and usable in subsequent cells. Creating SQL cells[¶](#creating-sql-cells "Permanent link") ----------------------------------------------------------- You can create SQL cells in one of three ways: 1. **Right-click** an "add cell" button ("+" icon) next to a cell and choose "SQL cell" 2. Convert a empty cell to SQL via the cell context menu 3. Click the SQL button that appears at the bottom of the notebook Add SQL Cell This creates a "**SQL**" cell for you, which is syntactic sugar for Python code. The underlying code looks like: `[](#__codelineno-3-1)output_df = mo.sql(f"SELECT * FROM my_table LIMIT {max_rows.value}")` Notice that we have an **`output_df`** variable in the cell. This contains the query result, and is a Polars DataFrame (if you have `polars` installed) or a Pandas DataFrame (if you don't). One of them must be installed in order to interact with the query result. The SQL statement itself is an f-string, letting you interpolate Python values into the query with `{}`. In particular, this means your SQL queries can depend on the values of UI elements or other Python values, and they are fit into marimo's reactive dataflow graph. Reference a local dataframe[¶](#reference-a-local-dataframe "Permanent link") ----------------------------------------------------------------------------- You can reference a local dataframe in your SQL cell by using the name of the Python variable that holds the dataframe. If you have a database connection with a table of the same name, the database table will be used instead. Reference a dataframe Since the output dataframe variable (`_df`) has an underscore, making it private, it is not referenceable from other cells. Reference the output of a SQL cell[¶](#reference-the-output-of-a-sql-cell "Permanent link") ------------------------------------------------------------------------------------------- Defining a non-private (non-underscored) output variable in the SQL cell allows you to reference the resulting dataframe in other Python and SQL cells. Reference the SQL result Querying files, databases, and APIs[¶](#querying-files-databases-and-apis "Permanent link") ------------------------------------------------------------------------------------------- In the above example, you may have noticed we queried an HTTP endpoint instead of a local dataframe. We are not only limited to querying local dataframes; we can also query files, databases such as Postgres and SQLite, and APIs: `[](#__codelineno-4-1)-- or [](#__codelineno-4-2)SELECT * FROM 's3://my-bucket/file.parquet'; [](#__codelineno-4-3)-- or [](#__codelineno-4-4)SELECT * FROM read_csv('path/to/example.csv'); [](#__codelineno-4-5)-- or [](#__codelineno-4-6)SELECT * FROM read_parquet('path/to/example.parquet');` For a full list you can check out the [duckdb extensions](https://duckdb.org/docs/extensions/overview). You can also check out our [examples on GitHub](https://github.com/marimo-team/marimo/tree/main/examples/sql). Escaping SQL brackets[¶](#escaping-sql-brackets "Permanent link") ----------------------------------------------------------------- Our "SQL" cells are really just Python under the hood to keep notebooks as pure Python scripts. By default, we use `f-strings` for SQL strings, which allows for parameterized SQL like which allows for parameterized SQL like `SELECT * from table where value < {min}`. To escape real `{`/`}` that you don't want parameterized, use double `{{...}}`: `[](#__codelineno-5-1)SELECT unnest([{{'a': 42, 'b': 84}}, {{'a': 100, 'b': NULL}}]);` Connecting to a custom database[¶](#connecting-to-a-custom-database "Permanent link") ------------------------------------------------------------------------------------- marimo supports bringing your own database via a **connection engine** created with a library like [SQLAlchemy](https://docs.sqlalchemy.org/en/20/core/connections.html#basic-usage), [SQLModel](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/?h=create+engine#create-the-engine), or a [custom DuckDB connection](https://duckdb.org/docs/api/python/overview.html#connection-options). By default, marimo uses the [In-Memory duckdb connection](https://duckdb.org/docs/connect/overview.html#in-memory-database). First, you need to define the engine as a Python variable in a cell. marimo will auto-discover the engine and let you select it in a dropdown in the SQL cell. `[](#__codelineno-6-1)import sqlalchemy [](#__codelineno-6-2)import sqlmodel [](#__codelineno-6-3)import duckdb [](#__codelineno-6-4)[](#__codelineno-6-5)# Create an in-memory SQLite database with SQLAlchemy [](#__codelineno-6-6)sqlite_engine = sqlachemy.create_engine("sqlite:///:memory:") [](#__codelineno-6-7)# Create a Postgres database with SQLModel [](#__codelineno-6-8)postgres_engine = sqlmodel.create_engine("postgresql://username:password@server:port/database") [](#__codelineno-6-9)# Create a DuckDB connection [](#__codelineno-6-10)duckdb_conn = duckdb.connect("file.db")` Choose a custom database connection Interactive tutorial[¶](#interactive-tutorial "Permanent link") --------------------------------------------------------------- For an interactive tutorial, run at your command-line. Examples[¶](#examples "Permanent link") --------------------------------------- Check out our [examples on GitHub](https://github.com/marimo-team/marimo/tree/main/examples/sql). AI completion - marimo https://docs.marimo.io/guides/editor_features/ai_completion/ marimo comes with GitHub Copilot, a tool that helps you write code faster by suggesting in-line code suggestions based on the context of your current code. marimo also comes with the ability to use AI for refactoring a cell, finishing writing a cell, or writing a full cell from scratch. This feature is currently experimental and is not enabled by default. GitHub Copilot[¶](#github-copilot "Permanent link") --------------------------------------------------- The marimo editor natively supports [GitHub Copilot](https://copilot.github.com/), an AI pair programmer, similar to VS Code. _Get started with Copilot_: 1. Install [Node.js](https://nodejs.org/en/download). 2. Enable Copilot via the settings menu in the marimo editor. Installation Requirement Copilot is not yet available in our conda distribution; please install marimo using `pip` if you need Copilot. Codeium Copilot[¶](#codeium-copilot "Permanent link") ----------------------------------------------------- 1. Go to the Codeium website and sign up for an account: [https://codeium.com/](https://codeium.com/) 2. Install the browser extension: [https://codeium.com/chrome\_tutorial](https://codeium.com/chrome_tutorial) 3. Open the settings for the Chrome extension and click on "Get Token" 4. Right-click on the extension window and select "Inspect" to open the developer tools for the extension. Then click on "Network" 5. Copy the token and paste it into the input area, and then press "Enter Token" 6. This action will log a new API request in the **Network** tab. Click on "Preview" to get the API key. 7. Paste the API key in the marimo settings in the UI, or add it to your `marimo.toml` file as follows: marimo.toml `[](#__codelineno-0-1)[completion] [](#__codelineno-0-2)copilot = "codeium" [](#__codelineno-0-3)codeium_api_key = ""` ### Alternative: Obtain Codeium API key using VS Code[¶](#alternative-obtain-codeium-api-key-using-vs-code "Permanent link") 1. Go to the Codeium website and sign up for an account: [https://codeium.com/](https://codeium.com/) 2. Install the [Codeium Visual Studio Code extension](vscode:extension/codeium.codeium) (see [here](https://codeium.com/vscode_tutorial) for complete guide) 3. Sign in to your Codeium account in the VS Code extension 4. Select the Codeium icon on the Activity bar (left side), which opens the Codeium pane 5. Select the **Settings** button (gear icon) in the top-right corner of the Codeium pane Open Codeium settings 6. Click the **Download** link under the **Extension Diagnostics** section 7. Open the diagnostic file and search for `apiKey` Download diagnostics file with API key 8. Copy the value of the `apiKey` to `.marimo.toml` in your home directory marimo.toml `[](#__codelineno-1-1)[completion] [](#__codelineno-1-2)codeium_api_key = "a1e8..." # <-- paste your API key here [](#__codelineno-1-3)copilot = "codeium" [](#__codelineno-1-4)activate_on_typing = true` Generate code with our AI assistant[¶](#generate-code-with-our-ai-assistant "Permanent link") --------------------------------------------------------------------------------------------- marimo has built-in support for generating and refactoring code with AI, with a variety of providers. marimo works with hosted AI providers, such as OpenAI, Anthropic, and Google, as well as local models served via Ollama. ### Custom AI Rules[¶](#custom-ai-rules "Permanent link") You can customize how the AI assistant behaves by adding rules in the marimo settings. These rules help ensure consistent code generation across all AI providers. You can find more information about marimo's supported plotting libraries and data handling in the [plotting guide](https://docs.marimo.io/guides/working_with_data/plotting/#plotting) and [working with data guide](https://docs.marimo.io/guides/working_with_data/). Configure custom AI rules in settings For example, you can add rules about: * Preferred plotting libraries (matplotlib, plotly, altair) * Data handling practices * Code style conventions * Error handling preferences Example custom rules: `[](#__codelineno-2-1)Use plotly for interactive visualizations and matplotlib for static plots [](#__codelineno-2-2)Prefer polars over pandas for data manipulation due to better performance [](#__codelineno-2-3)Include docstrings for all functions using NumPy style [](#__codelineno-2-4)Use Type hints for all function parameters and return values [](#__codelineno-2-5)Handle errors with try/except blocks and provide informative error messages [](#__codelineno-2-6)Follow PEP 8 style guidelines [](#__codelineno-2-7)When working with data: [](#__codelineno-2-8)- Use altair, plotly for declarative visualizations [](#__codelineno-2-9)- Prefer polars over pandas [](#__codelineno-2-10)- Ensure proper error handling for data operations [](#__codelineno-2-11)For plotting: [](#__codelineno-2-12)- Use px.scatter for scatter plots [](#__codelineno-2-13)- Use px.line for time series [](#__codelineno-2-14)- Include proper axis labels and titles [](#__codelineno-2-15)- Set appropriate color schemes` To locate your configuration file, run: At the top, the path to your `marimo.toml` file will be shown. You can Ctrl/Cmd+click the path to open it in your editor. For more information about configuration, see the [Configuration Guide](https://docs.marimo.io/guides/configuration/). Below we describe how to connect marimo to your AI provider. Once enabled, you can generate entirely new cells by clicking the "Generate with AI" button at the bottom of your notebook. You can also refactor existing cells by inputting `Ctrl/Cmd-Shift-e` in a cell, opening an input to modify the cell using AI. Use AI to modify a cell by pressing \`Ctrl/Cmd-Shift-e\`. ### Using OpenAI[¶](#using-openai "Permanent link") 1. Install openai: `pip install openai` 2. Add the following to your `marimo.toml`: marimo.toml `[](#__codelineno-4-1)[ai.open_ai] [](#__codelineno-4-2)# Get your API key from https://platform.openai.com/account/api-keys [](#__codelineno-4-3)api_key = "sk-proj-..." [](#__codelineno-4-4)# Choose a model, we recommend "gpt-4-turbo" [](#__codelineno-4-5)model = "gpt-4-turbo" [](#__codelineno-4-6)# Available models: gpt-4-turbo-preview, gpt-4, gpt-3.5-turbo [](#__codelineno-4-7)# See https://platform.openai.com/docs/models for all available models [](#__codelineno-4-8)[](#__codelineno-4-9)# Change the base_url if you are using a different OpenAI-compatible API [](#__codelineno-4-10)base_url = "https://api.openai.com/v1"` ### Using Anthropic[¶](#using-anthropic "Permanent link") To use Anthropic with marimo: 1. Sign up for an account at [Anthropic](https://console.anthropic.com/) and grab your [Anthropic Key](https://console.anthropic.com/settings/keys). 2. Add the following to your `marimo.toml`: marimo.toml `[](#__codelineno-5-1)[ai.open_ai] [](#__codelineno-5-2)model = "claude-3-5-sonnet-20240620" [](#__codelineno-5-3)# or any model from https://docs.anthropic.com/en/docs/about-claude/models [](#__codelineno-5-4)[](#__codelineno-5-5)[ai.anthropic] [](#__codelineno-5-6)api_key = "sk-ant-..."` ### Using Google AI[¶](#using-google-ai "Permanent link") To use Google AI with marimo: 1. Sign up for an account at [Google AI Studio](https://aistudio.google.com/app/apikey) and obtain your API key. 2. Install the Google AI Python client: `pip install google-generativeai` 3. Add the following to your `marimo.toml`: marimo.toml `[](#__codelineno-6-1)[ai.open_ai] [](#__codelineno-6-2)model = "gemini-1.5-flash" [](#__codelineno-6-3)# or any model from https://ai.google.dev/gemini-api/docs/models/gemini [](#__codelineno-6-4)[](#__codelineno-6-5)[ai.google] [](#__codelineno-6-6)api_key = "AI..."` ### Using local models with Ollama[¶](#using-ollama "Permanent link") Ollama allows you to run open-source LLMs on your local machine. To integrate Ollama with marimo: 1. Download and install [Ollama](https://ollama.com/). 2. Download the model you want to use: `[](#__codelineno-7-1)# View available models at https://ollama.com/library [](#__codelineno-7-2)ollama pull llama3.1 [](#__codelineno-7-3)ollama pull codellama # recommended for code generation [](#__codelineno-7-4)[](#__codelineno-7-5)# View your installed models [](#__codelineno-7-6)ollama ls` 3. Start the Ollama server in a terminal: `[](#__codelineno-8-1)ollama serve [](#__codelineno-8-2)# In a new terminal [](#__codelineno-8-3)ollama run codellama # or any model from ollama ls` 4. Visit [http://127.0.0.1:11434](http://127.0.0.1:11434/) to confirm that the server is running. Port already in use If you get a "port already in use" error, you may need to close an existing Ollama instance. On Windows, click the up arrow in the taskbar, find the Ollama icon, and select "Quit". This is a known issue (see [Ollama Issue #3575](https://github.com/ollama/ollama/issues/3575)). Once you've closed the existing Ollama instance, you should be able to run `ollama serve` successfully. 5. Open a new terminal and start marimo: 6. Add the following to your `marimo.toml`: marimo.toml ``[](#__codelineno-10-1)[ai.open_ai] [](#__codelineno-10-2)api_key = "ollama" # This is not used, but required [](#__codelineno-10-3)model = "codellama" # or another model from `ollama ls` [](#__codelineno-10-4)base_url = "http://127.0.0.1:11434/v1"`` ### Using other AI providers[¶](#using-other-ai-providers "Permanent link") marimo supports OpenAI's API by default. Many providers offer OpenAI API-compatible endpoints, which can be used by simply changing the `base_url` in your configuration. For example, providers like [GROQ](https://console.groq.com/docs/openai) and [DeepSeek](https://platform.deepseek.com/) follow this pattern. Using OpenAI-compatible providers (e.g., DeepSeek) Via marimo.tomlVia UI Settings Add the following configuration to your `marimo.toml` file: `[](#__codelineno-11-1)[ai.open_ai] [](#__codelineno-11-2)api_key = "dsk-..." # Your provider's API key [](#__codelineno-11-3)model = "deepseek-chat" # or "deepseek-reasoner" [](#__codelineno-11-4)base_url = "https://api.deepseek.com/"` 1. Open marimo's Settings panel 2. Navigate to the AI section 3. Enter your provider's API key in the "OpenAI API Key" field 4. Under AI Assist settings: - Set Base URL to your provider's endpoint (e.g., `https://api.deepseek.com`) - Set Model to your chosen model (e.g., `deepseek-chat` or `deepseek-reasoner`) For a comprehensive list of compatible providers and their configurations, please refer to the [liteLLM Providers documentation](https://litellm.vercel.app/docs/providers). For providers not compatible with OpenAI's API, please submit a [feature request](https://github.com/marimo-team/marimo/issues/new?template=feature_request.yaml) or "thumbs up" an existing one. Editor overview - marimo https://docs.marimo.io/guides/editor_features/overview/ This guide introduces some of marimo editor's features, including a variables panel, dependency graph viewer, table of contents, HTML export, GitHub copilot, code formatting, a feedback form, and more. Configuration[¶](#configuration "Permanent link") ------------------------------------------------- The editor exposes of a number of settings for the current notebook, as well as user-wide configuration that will apply to all your notebooks. These settings include the option to display the current notebook in full width, to use vim keybindings, to enable GitHub copilot, and more. To access these settings, click the gear icon in the top-right of the editor: A non-exhaustive list of settings: * Outputs above or below code cells * [Disable/enable autorun](https://docs.marimo.io/guides/reactivity/#configuring-how-marimo-runs-cells) * Package installation * Vim keybindings * Dark mode * Auto-save * Auto-complete * Editor font-size * Code formatting with ruff/black * [GitHub Copilot](https://docs.marimo.io/guides/editor_features/ai_completion/) * [LLM coding assistant](https://docs.marimo.io/guides/editor_features/ai_completion/) * [Module autoreloading](https://docs.marimo.io/guides/configuration/runtime_configuration/#on-module-change) ### Vim keybindings[¶](#vim-keybindings "Permanent link") marimo supports vim keybindings. **Additional bindings/features:** * `gd` - go to definition * `dd` - when a cell is empty, delete it Overview panels[¶](#overview-panels "Permanent link") ----------------------------------------------------- marimo ships with the IDE panels that provide an overview of your notebook * **file explorer**: view the file tree, open other notebooks * **variables**: explore variable values, see where they are defined and used, with go-to-definition * **data explorer**: see dataframe and table schemas at a glance * **dependency graph**: view dependencies between cells, drill-down on nodes and edges * **package manager**: add and remove packages, and view your current environment * **table of contents**: corresponding to your markdown * **documentation** - move your text cursor over a symbol to see its documentation * **logs**: a continuous stream of stdout and stderr * **scratchpad**: a scratchpad cell where you can execute throwaway code * **snippets** - searchable snippets to copy directly into your notebook * **feedback** - share feedback! These panels can be toggled via the buttons in the left of the editor. Cell actions[¶](#cell-actions "Permanent link") ----------------------------------------------- Click the three dots in the top right of a cell to pull up a context menu, letting you format code, hide code, send a cell to the top or bottom of the notebook, give the cell a name, and more. Drag a cell using the vertical dots to the right of the cell. marimo supports context-sensitive right-click menus in various locations of the editor. Right-click on a cell to open a context-sensitive menu; right click on the create-cell button (the plus icon) to get options for the cell type to create. Go-to-definition[¶](#go-to-definition "Permanent link") ------------------------------------------------------- * Click on a variable in the editor to see where it's defined and used * `Cmd/Ctrl-Click` on a variable to jump to its definition * Right-click on a variable to see a context menu with options to jump to its definition Keyboard shortcuts[¶](#keyboard-shortcuts "Permanent link") ----------------------------------------------------------- We've kept some well-known [keyboard shortcuts](https://docs.marimo.io/guides/editor_features/hotkeys/) for notebooks (`Ctrl-Enter`, `Shift-Enter`), dropped others, and added a few of our own. Hit `Ctrl/Cmd-Shift-H` to pull up the shortcuts. We know keyboard shortcuts are very personal; you can remap them in the configuration. _Missing a shortcut? File a [GitHub issue](https://github.com/marimo-team/marimo/issues)._ Command palette[¶](#command-palette "Permanent link") ----------------------------------------------------- Hit `Cmd/Ctrl+K` to open the command palette. Quickly access common commands with the command palette. _Missing a command? File a [GitHub issue](https://github.com/marimo-team/marimo/issues)._ Editor widths[¶](#editor-widths "Permanent link") ------------------------------------------------- You can set the width of the editor in the notebook settings: * **Compact**: A narrow width with generous margins, ideal for reading * **Wide**: A wider layout that gives more space for content * **Full**: Uses the full width of your browser window, ideal for dashboard-style notebooks * **Multi-column**: Splits your notebook into multiple columns, letting you view and edit cells side-by-side. This is only possible because marimo models your notebook as a directed acyclic graph (DAG) and the [execution order](https://docs.marimo.io/guides/reactivity/#execution-order) is determined by the relationships between cells and their variables, not by the order of cells on the page. Multi-column notebook Get a link to share your notebook via our [online playground](https://docs.marimo.io/guides/wasm/): _Our online playground uses WebAssembly. Most but not all packages on PyPI are supported. Local files are not synchronized to our playground._ Export to static HTML[¶](#export-to-static-html "Permanent link") ----------------------------------------------------------------- Export the current view your notebook to static HTML via the notebook menu: Download as static HTML. You can also export to HTML at the command-line: `[](#__codelineno-0-1)marimo export html notebook.py -o notebook.html` Send feedback[¶](#send-feedback "Permanent link") ------------------------------------------------- The question mark icon in the panel tray opens a dialog to send anonymous feedback. We welcome any and all feedback, from the tiniest quibbles to the biggest blue-sky dreams. Send anonymous feedback with our feedback form. If you'd like your feedback to start a conversation (we'd love to talk with you!), please consider posting in our [GitHub issues](https://github.com/marimo-team/marimo/issues) or [Discord](https://marimo.io/discord?ref=docs). But if you're in a flow state and can't context switch out, the feedback form has your back. Package management - marimo https://docs.marimo.io/guides/editor_features/package_management/ marimo supports package management for `pip, rye, uv, poetry, pixi`. When marimo comes across a module that is not installed, you will be prompted to install it using your preferred package manager. Once the module is installed, all cells that depend on the module will be rerun. Package Installation We use some heuristic for guessing the package name in your registry (e.g. PyPI) from the module name. It is possible that the package name is different from the module name. If you encounter an error, please file an issue or help us by adding your mapping [directly to the codebase](https://github.com/marimo-team/marimo/blob/main/marimo/_runtime/packages/module_name_to_pypi_name.py). Package reproducibility[¶](#package-reproducibility "Permanent link") --------------------------------------------------------------------- marimo is the only Python notebook that is reproducible down to the packages they use. This makes it possible to share standalone notebooks without shipping `requirements.txt` files alongside them, and guarantees your notebooks will work weeks, months, even years into the future. To learn more, see the [Package Reproducibility Guide](https://docs.marimo.io/guides/package_reproducibility/). Module autoreloading - marimo https://docs.marimo.io/guides/editor_features/module_autoreloading/ marimo has an advanced module autoreloader built-in, which you can enable in the [notebook settings](https://docs.marimo.io/guides/configuration/runtime_configuration/). When you make edits to Python modules that your notebook has imported, the module autoreloader will automatically mark cells that use them as stale and, optionally, automatically run them. Why autoreload? Autoreloading enables a workflow that many developers find productive: develop complex logic in Python modules, and use the marimo notebook as a DAG or main script that orchestrates your logic. Based on static analysis, the reloader only runs cells affected by your edits. The reloader is recursive, meaning that marimo tracks modifications for modules imported by your notebook's imported modules too. These two featuers make marimo's module autoreloader far more advanced than IPython's. Autoreloading comes in two types: 1. **autorun**: automatically re-runs cells affected by module modification. When set to autorun, marimo's reloader automatically run cells when you edit Python files. 2. **lazy**: marks cells affected by module modifications as stale, letting you know which cells need to be re-run. When set to lazy, marimo's reloader marks cells as stale when you edit Python files. Using your own editor - marimo https://docs.marimo.io/guides/editor_features/watching/ While we recommend using the [marimo editor](https://docs.marimo.io/guides/editor_features/), we understand that you may prefer to use your own. marimo provides a `--watch` flag that watches your notebook file for changes, syncing them to the marimo editor or running application. This lets you edit your notebook using an editor of your choice, like neovim, VSCode, Cursor, or PyCharm, and have the changes automatically reflected in your browser. Install watchdog for better file watching For better performance, install [watchdog](https://pypi.org/project/watchdog/). Without watchdog, marimo resorts to polling. `marimo edit --watch`[¶](#marimo-edit-watch "Permanent link") ------------------------------------------------------------- When you run `marimo edit` with the `--watch` flag, the marimo server will open your notebook in the browser and watch the underlying notebook file for changes. When you make changes to the notebook file, they will be streamed to the marimo editor in the browser. Synced code will not be executed automatically, with cells marked as stale instead. Run all stale cells with the marimo editor's "Run" button, or the [`runStale` hotkey](https://docs.marimo.io/guides/editor_features/hotkeys/), to see the new outputs. Cell signature and returns Don't worry about maintaining the signatures of cells and their return values; marimo will handle this for you. `marimo run --watch`[¶](#marimo-run-watch "Permanent link") ----------------------------------------------------------- When you run a notebook with the `--watch` flag, whenever the file watcher detects a change to the notebook file, the application will be refreshed. The browser will trigger a page refresh to ensure your notebook starts from a fresh state. Watching for changes to other modules[¶](#watching-for-changes-to-other-modules "Permanent link") ------------------------------------------------------------------------------------------------- marimo can also watch for changes to Python modules that your notebook imports, letting you edit auxiliary Python files in your own editor as well. Learn how to enable this feature in our [Module Autoreloading Guide](https://docs.marimo.io/guides/editor_features/module_autoreloading/) Watching for data changes[¶](#watching-for-data-changes "Permanent link") ------------------------------------------------------------------------- Hot-reloading WebAssembly notebooks[¶](#hot-reloading-webassembly-notebooks "Permanent link") --------------------------------------------------------------------------------------------- Follow these steps to develop a notebook using your own editor while previewing it as a [WebAssembly notebook](https://docs.marimo.io/guides/wasm/) in the browser. This lets you take advantage of local development tools while seeing the notebook as it appears when deployed as a WebAssembly notebook. `[](#__codelineno-0-1)# in one terminal, start a watched edit (or run) session [](#__codelineno-0-2)marimo edit notebook.py --watch [](#__codelineno-0-3)[](#__codelineno-0-4)# in another terminal [](#__codelineno-0-5)marimo export html-wasm notebook.py -o output_dir --watch [](#__codelineno-0-6)[](#__codelineno-0-7)# in a third terminal, serve the WASM application [](#__codelineno-0-8)cd path/to/output_dir [](#__codelineno-0-9)python -m http.server # or a server that watches for changes` Hotkeys - marimo https://docs.marimo.io/guides/editor_features/hotkeys/ If you'd like to override the default hotkeys, you can do so in the hotkeys menu (`Mod-Shift-h`), or modifying your `marimo.toml`. You can find a list of available hotkeys below: | Hotkey | | --- | | `cell.aiCompletion` | | `cell.cellActions` | | `cell.complete` | | `cell.createAbove` | | `cell.createBelow` | | `cell.delete` | | `cell.findAndReplace` | | `cell.focusDown` | | `cell.focusUp` | | `cell.fold` | | `cell.foldAll` | | `cell.format` | | `cell.goToDefinition` | | `cell.hideCode` | | `cell.moveUp` | | `cell.moveDown` | | `cell.moveLeft` | | `cell.moveRight` | | `cell.redo` | | `cell.run` | | `cell.runAndNewAbove` | | `cell.runAndNewBelow` | | `cell.selectNextOccurrence` | | `cell.sendToBottom` | | `cell.sendToTop` | | `cell.splitCell` | | `cell.undo` | | `cell.unfold` | | `cell.unfoldAll` | | `cell.viewAsMarkdown` | | `completion.moveDown` | | `completion.moveUp` | | `global.commandPalette` | | `global.focusBottom` | | `global.focusTop` | | `global.foldCode` | | `global.formatAll` | | `global.hideCode` | | `global.interrupt` | | `global.runStale` | | `global.save` | | `global.showHelp` | | `global.toggleLanguage` | | `global.toggleTerminal` | | `global.toggleSidebar` | | `global.unfoldCode` | | `markdown.blockquote` | | `markdown.bold` | | `markdown.code` | | `markdown.italic` | | `markdown.link` | | `markdown.orderedList` | | `markdown.unorderedList` | Run notebooks as apps - marimo https://docs.marimo.io/guides/apps/ Run as an app[¶](#run-as-an-app "Permanent link") ------------------------------------------------- The marimo CLI lets you run any notebook as an app: `marimo run` lays out the notebook as an app and starts a web server that hosts the resulting app. By default, apps are laid out as a concatenation of their outputs, with code hidden. You can customize the layout using marimo's built-in drag-and-drop grid editor; you can also choose to include code in the app view. CLI[¶](#cli "Permanent link") ----------------------------- Run marimo notebooks as apps with View the [CLI documentation](https://docs.marimo.io/cli/#marimo-run) for more details. Layout[¶](#layout "Permanent link") ----------------------------------- While editing a notebook with `marimo edit`, you can preview the notebook as an app by clicking the preview button in the bottom-right of the editor. (You can also use the command palette.) ### Vertical layout[¶](#vertical-layout "Permanent link") The default layout is the vertical layout: cell outputs are concatenated vertically and code is hidden. When combined with marimo's [built-in functions for laying out outputs](https://docs.marimo.io/api/layouts/), as well as its configurable app widths (configure via the notebook settings menu), the vertical layout can successfully support a wide breadth of application user interfaces. ### Grid layout[¶](#grid-layout "Permanent link") If you prefer a drag-and-drop experience over [programmatic layout](https://docs.marimo.io/api/layouts/), consider using marimo's grid editor for making your apps: with this editor, you simply drag outputs onto a grid to arrange them on the page. Enable the grid editor in the app preview, via a dropdown: marimo saves metadata about your constructed layout in a `layouts` folder; make sure to include this folder when sharing your notebook so that others can reconstruct your layout. ### Slides layout[¶](#slides-layout "Permanent link") If you prefer a slideshow-like experience, you can use the slides layout. Enable the slides layout in the app preview, via the same dropdown as above. Unlike the grid layout, the slides are much less customizable: * The order of the slides is determined by the order of the cells in the notebook. * The slides do not support drag-and-drop rearrangement or resizing. * All outputs are shown and all code is hidden. If you need more control over the layout, please file an issue on [GitHub](https://github.com/marimo-team/marimo/issues), so we can properly prioritize this feature. Run notebooks as scripts - marimo https://docs.marimo.io/guides/scripts/ Run as a script[¶](#run-as-a-script "Permanent link") ----------------------------------------------------- You can run marimo notebooks as scripts at the command line, just like any other Python script. For example, `[](#__codelineno-0-1)python my_marimo_notebook.py` Running a notebook as a script is useful when your notebook has side-effects, like writing to disk. Print statements and other console outputs will show up in your terminal. You can pass arguments to your notebook at the command-line: see the [docs page on CLI args](https://docs.marimo.io/api/cli_args/) to learn more. Producing notebook outputs To run as a script while also producing HTML of the notebook outputs, use `[](#__codelineno-1-1)marimo export html notebook.py -o notebook.html` Testing notebooks - marimo https://docs.marimo.io/guides/testing/ Because marimo notebooks are stored as Python, test them like any other Python program. | Guide | Description | | --- | --- | | [pytest](https://docs.marimo.io/guides/testing/pytest/) | Include unit tests in notebooks, or implement entire tests as notebooks | | [doctest](https://docs.marimo.io/guides/testing/doctest/) | Test code snippets in docstrings using doctest | Plotting - marimo https://docs.marimo.io/guides/working_with_data/plotting/ marimo supports most major plotting libraries, including Matplotlib, Seaborn, Plotly, Altair, and HoloViews. Just import your plotting library of choice and use it as you normally would. For Altair and Plotly plots, marimo does something special: use [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) or [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) to connect frontend selections to Python! Reactive plots! marimo supports reactive plots via [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) and [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly)! Select and filter with your mouse, and marimo _automatically makes the selected data available in Python as a Pandas dataframe_! Reactive plots! ⚡[¶](#reactive-plots "Permanent link") ------------------------------------------------------ Requirements Reactive plots currently require Altair or Plotly. Install with `pip install altair` or `pip install plotly`, depending on which library you are using. Selections in plotly are limited to scatter plots, treemaps charts, and sunbursts charts, while Altair supports a larger class of plots for selections. ### Altair[¶](#altair "Permanent link") Use [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) to easily create interactive, selectable plots: _selections you make on the frontend are automatically made available as Pandas dataframes in Python._ Wrap an Altair chart in [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) to make it **reactive**: select data on the frontend, access it via the chart's `value` attribute (`chart.value`). #### Disabling automatic selection[¶](#disabling-automatic-selection "Permanent link") marimo automatically adds a default selection based on the mark type, however, you may want to customize the selection behavior of your Altair chart. You can do this by setting `chart_selection` and `legend_selection` to `False`, and using `.add_params` directly on your Altair chart. `[](#__codelineno-1-1)# Create an interval selection [](#__codelineno-1-2)brush = alt.selection_interval(encodings=["x"]) [](#__codelineno-1-3)[](#__codelineno-1-4)_chart = ( [](#__codelineno-1-5) alt.Chart(traces, height=150) [](#__codelineno-1-6) .mark_line() [](#__codelineno-1-7) .encode(x="index:Q", y="value:Q", color="traces:N") [](#__codelineno-1-8) .add_params(brush) # add the selection to the chart [](#__codelineno-1-9)) [](#__codelineno-1-10)[](#__codelineno-1-11)chart = mo.ui.altair_chart( [](#__codelineno-1-12) _chart, [](#__codelineno-1-13) # disable automatic selection [](#__codelineno-1-14) chart_selection=False, [](#__codelineno-1-15) legend_selection=False [](#__codelineno-1-16)) [](#__codelineno-1-17)chart # You can now access chart.value to get the selected data` _Reactive plots are just one way that marimo **makes your data tangible**._ #### Example[¶](#example "Permanent link") `[](#__codelineno-2-1)import marimo as mo [](#__codelineno-2-2)import altair as alt [](#__codelineno-2-3)import vega_datasets [](#__codelineno-2-4)[](#__codelineno-2-5)# Load some data [](#__codelineno-2-6)cars = vega_datasets.data.cars() [](#__codelineno-2-7)[](#__codelineno-2-8)# Create an Altair chart [](#__codelineno-2-9)chart = alt.Chart(cars).mark_point().encode( [](#__codelineno-2-10) x='Horsepower', # Encoding along the x-axis [](#__codelineno-2-11) y='Miles_per_Gallon', # Encoding along the y-axis [](#__codelineno-2-12) color='Origin', # Category encoding by color [](#__codelineno-2-13)) [](#__codelineno-2-14)[](#__codelineno-2-15)# Make it reactive ⚡ [](#__codelineno-2-16)chart = mo.ui.altair_chart(chart)` `[](#__codelineno-3-1)# In a new cell, display the chart and its data filtered by the selection [](#__codelineno-3-2)mo.vstack([chart, chart.value.head()])` #### Learning Altair[¶](#learning-altair "Permanent link") If you're new to **Altair**, we highly recommend exploring the [Altair documentation](https://altair-viz.github.io/). Altair provides a declarative, concise, and simple way to create highly interactive and sophisticated plots. Altair is based on [Vega-Lite](https://vega.github.io/vega-lite/), an exceptional tool for creating interactive charts that serves as the backbone for marimo's reactive charting capabilities. ##### Concepts[¶](#concepts "Permanent link") Learn by doing? Skip this section! This section summarizes the main concepts used by Altair (and Vega-Lite). Feel free to skip this section and return later. Our choice to use the Vega-Lite specification was driven by its robust data model, which is well-suited for data analysis. Some key concepts are summarized below. (For a more detailed explanation, with examples, we recommend the [Basic Statistical Visualization](https://altair-viz.github.io/getting_started/starting.html) tutorial from Altair.) * **Data Source**: This is the information that will be visualized in the chart. It can be provided in various formats such as a dataframe, a list of dictionaries, or a URL pointing to the data source. * **Mark Type**: This refers to the visual representation used for each data point on the chart. The options include 'bar', 'dot', 'circle', 'area', and 'line'. Each mark type offers a different way to visualize and interpret the data. * **Encoding**: This is the process of mapping various aspects or dimensions of the data to visual characteristics of the marks. Encodings can be of different types: * **Positional Encodings**: These are encodings like 'x' and 'y' that determine the position of the marks in the chart. * **Categorical Encodings**: These are encodings like 'color' and 'shape' that categorize data points. They are typically represented in a legend for easy reference. * **Transformations**: These are operations that can be applied to the data before it is visualized, for example, filtering and aggregation. These transformations allow for more complex and nuanced visualizations. **Automatically interactive.** marimo adds interactivity automatically, based on the mark used and the encodings. For example, if you use a `mark_point` and an `x` encoding, marimo will automatically add a brush selection to the chart. If you add a `color` encoding, marimo will add a legend and a click selection. #### Automatic Selections[¶](#automatic-selections "Permanent link") By default [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) will make the chart and legend selectable. Depending on the mark type, the chart will either have a `point` or `interval` ("brush") selection. When using non-positional encodings (color, size, etc), [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) will also make the legend selectable. Selection configurable through `*_selection` params in [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart). See the [API docs](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) for details. Note You may still add your own selection parameters via Altair or Vega-Lite. marimo will not override your selections. #### Altair transformations[¶](#altair-transformations "Permanent link") Altair supports a variety of transformations, such as filtering, aggregation, and sorting. These transformations can be used to create more complex and nuanced visualizations. For example, you can use a filter to show only the points that meet a certain condition, or use an aggregation to show the average value of a variable. In order for marimo's reactive plots to work with transformations, you must install `vegafusion`, as this feature uses `chart.transformed_data` (which requires version 1.4.0 or greater of the `vegafusion` packages). `[](#__codelineno-4-1)# These can be installed with pip using: [](#__codelineno-4-2)pip install "vegafusion[embed]>=1.4.0" [](#__codelineno-4-3)# Or with conda using: [](#__codelineno-4-4)conda install -c conda-forge "vegafusion-python-embed>=1.4.0" "vegafusion>=1.4.0"` ### Plotly[¶](#plotly "Permanent link") mo.ui.plotly only supports scatter plots, treemaps charts, and sunbursts charts marimo can render any Plotly plot, but [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) only supports reactive selections for scatter plots, treemaps charts, and sunbursts charts. If you require other kinds of selection, consider using [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart). Use [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) to create selectable Plotly plots whose values are sent back to Python on selection. matplotlib[¶](#matplotlib "Permanent link") ------------------------------------------- To output a matplotlib plot in a cell's output area, include its `Axes` or `Figure` object as the last expression in your notebook. For example: ``[](#__codelineno-6-1)plt.plot([1, 2]) [](#__codelineno-6-2)# plt.gca() gets the current `Axes` [](#__codelineno-6-3)plt.gca()`` or `[](#__codelineno-7-1)fig, ax = plt.subplots() [](#__codelineno-7-2)[](#__codelineno-7-3)ax.plot([1, 2]) [](#__codelineno-7-4)ax` If you want to output the plot in the console area, use `plt.show()` or `fig.show()`. ### Interactive plots[¶](#interactive-plots "Permanent link") To make matplotlib plots interactive, use [mo.mpl.interactive](https://docs.marimo.io/api/plotting/#marimo.mpl.interactive). (Matplotlib plots are not yet reactive.) pytest - marimo https://docs.marimo.io/guides/testing/pytest/ Running unit tests with pytest[¶](#running-unit-tests-with-pytest "Permanent link") ----------------------------------------------------------------------------------- Since marimo notebooks are Python programs, you can test them using [`pytest`](https://docs.pytest.org/en/stable/), a popular testing framework for Python. For example, runs and tests all notebook cells whose names start with `test_`. Naming cells Name a cell by giving its function a name in the notebook file, or using the cell action menu in the notebook editor. Use marimo notebooks just like normal pytest tests Include test notebooks (notebooks whose names start with `test_`) in your standard test suite, and `pytest` will discover them automatically. In addition, you can write self-contained notebooks that contain their own unit tests, and run `pytest` on them directly (`pytest my_notebook.py`). Example[¶](#example "Permanent link") ------------------------------------- Running `pytest` on `[](#__codelineno-1-1)# content of test_notebook.py [](#__codelineno-1-2)import marimo [](#__codelineno-1-3)[](#__codelineno-1-4)__generated_with = "0.10.6" [](#__codelineno-1-5)app = marimo.App() [](#__codelineno-1-6) [](#__codelineno-1-7)[](#__codelineno-1-8)@app.cell [](#__codelineno-1-9)def _(): [](#__codelineno-1-10) def inc(x): [](#__codelineno-1-11) return x + 1 [](#__codelineno-1-12) return inc [](#__codelineno-1-13) [](#__codelineno-1-14)[](#__codelineno-1-15)@app.cell [](#__codelineno-1-16)def test_answer(inc): [](#__codelineno-1-17) assert inc(3) == 5, "This test fails" [](#__codelineno-1-18) [](#__codelineno-1-19)[](#__codelineno-1-20)@app.cell [](#__codelineno-1-21)def test_sanity(inc): [](#__codelineno-1-22) assert inc(3) == 4, "This test passes"` prints `[](#__codelineno-2-1)============================= test session starts ============================== [](#__codelineno-2-2)platform linux -- Python 3.11.10, pytest-8.3.3, pluggy-1.5.0 [](#__codelineno-2-3)rootdir: /notebooks [](#__codelineno-2-4)configfile: pyproject.toml [](#__codelineno-2-5)collected 2 items [](#__codelineno-2-6)[](#__codelineno-2-7)test_notebook.py F. [100%] [](#__codelineno-2-8)[](#__codelineno-2-9)=================================== FAILURES =================================== [](#__codelineno-2-10)__________________________________ test_fails __________________________________ [](#__codelineno-2-11) [](#__codelineno-2-12) import marimo [](#__codelineno-2-13) [](#__codelineno-2-14) __generated_with = "0.10.6" [](#__codelineno-2-15) app = marimo.App(width="medium") [](#__codelineno-2-16) [](#__codelineno-2-17) [](#__codelineno-2-18) @app.cell [](#__codelineno-2-19) def _(): [](#__codelineno-2-20) def inc(x): [](#__codelineno-2-21) return x + 1 [](#__codelineno-2-22) return (inc,) [](#__codelineno-2-23) [](#__codelineno-2-24) [](#__codelineno-2-25) @app.cell [](#__codelineno-2-26) def test_answser(inc): [](#__codelineno-2-27)> assert inc(3) == 5, "This test fails" [](#__codelineno-2-28)E AssertionError: This test fails [](#__codelineno-2-29)[](#__codelineno-2-30)test_notebook.py:16: AssertionError [](#__codelineno-2-31)=========================== short test summary info ============================ [](#__codelineno-2-32)FAILED test_notebook.py::test_fails - AssertionError: This test fails [](#__codelineno-2-33)========================= 1 failed, 1 passed in 0.20s ===========================` Export to other formats - marimo https://docs.marimo.io/guides/exporting/ Exporting to HTML and other formats[¶](#exporting-to-html-and-other-formats "Permanent link") --------------------------------------------------------------------------------------------- Export marimo notebooks to other file formats at the command line using Export to static HTML[¶](#export-to-static-html "Permanent link") ----------------------------------------------------------------- ### Export from a running notebook[¶](#export-from-a-running-notebook "Permanent link") Export the current view your notebook to static HTML via the notebook menu: Download as static HTML. Additionally, you can configure individual notebooks to automatically save as HTML through the notebook menu. These automatic snapshots are saved to a folder called `__marimo__` in the notebook directory. ### Export from the command line[¶](#export-from-the-command-line "Permanent link") Export to HTML at the command line: `[](#__codelineno-1-1)marimo export html notebook.py -o notebook.html` or watch the notebook for changes and automatically export to HTML: `[](#__codelineno-2-1)marimo export html notebook.py -o notebook.html --watch` When you export from the command line, marimo runs your notebook to produce its visual outputs before saving as HTML. Note If any cells error during the export process, the status code will be non-zero. However, the export result may still be generated, with the error included in the output. Errors can be ignored by appending `|| true` to the command, e.g. `marimo export html notebook.py || true`. Export to a Python script[¶](#export-to-a-python-script "Permanent link") ------------------------------------------------------------------------- Export to a flat Python script in topological order, so the cells adhere to their dependency graph. `[](#__codelineno-3-1)marimo export script notebook.py -o notebook.script.py` Top-level await not supported Exporting to a flat Python script does not support top-level await. If you have top-level await in your notebook, you can still execute the notebook as a script with `python notebook.py`. Export to markdown[¶](#export-to-markdown "Permanent link") ----------------------------------------------------------- Export to markdown notebook in top to bottom order, so the cells are in the order as they appear in the notebook. `[](#__codelineno-4-1)marimo export md notebook.py -o notebook.md` This can be useful to plug into other tools that read markdown, such as [Quarto](https://quarto.org/) or [MyST](https://myst-parser.readthedocs.io/). You can also convert the markdown back to a marimo notebook: `[](#__codelineno-5-1)marimo convert notebook.md > notebook.py` Export to Jupyter notebook[¶](#export-to-jupyter-notebook "Permanent link") --------------------------------------------------------------------------- Export to Jupyter notebook in topological order, so the cells adhere to their dependency graph. `[](#__codelineno-6-1)marimo export ipynb notebook.py -o notebook.ipynb` Exporting to PDF, slides, or rst[¶](#exporting-to-pdf-slides-or-rst "Permanent link") ------------------------------------------------------------------------------------- If you export to a Jupyter notebook, you can leverage various Jupyter ecosystem tools. For PDFs, you will need to have [Pandoc](https://nbconvert.readthedocs.io/en/latest/install.html#installing-pandoc) and [Tex](https://nbconvert.readthedocs.io/en/latest/install.html#installing-tex) installed. The examples below use `uvx`, which you can obtain by [installing `uv`](https://docs.astral.sh/uv/getting-started/installation/). `[](#__codelineno-7-1)NOTEBOOK=notebook.ipynb [](#__codelineno-7-2)[](#__codelineno-7-3)# Convert to PDF using nbconvert [](#__codelineno-7-4)uvx --with nbconvert --from jupyter-core jupyter nbconvert --to pdf $NOTEBOOK [](#__codelineno-7-5)[](#__codelineno-7-6)# Convert to web PDF [](#__codelineno-7-7)uvx --with "nbconvert[webpdf]" --from jupyter-core jupyter nbconvert --to webpdf $NOTEBOOK --allow-chromium-download [](#__codelineno-7-8)[](#__codelineno-7-9)# Convert to slides [](#__codelineno-7-10)uvx --with nbconvert --from jupyter-core jupyter nbconvert --to slides $NOTEBOOK [](#__codelineno-7-11)[](#__codelineno-7-12)# Convert to rst with nbconvert [](#__codelineno-7-13)uvx --with nbconvert --from jupyter-core jupyter nbconvert --to rst $NOTEBOOK [](#__codelineno-7-14)[](#__codelineno-7-15)# Generate PNG/PDF of specific cells using nbconvert [](#__codelineno-7-16)uvx --with nbconvert --with jupyter --from jupyter-core jupyter nbconvert --to pdf --execute --stdout $NOTEBOOK \ [](#__codelineno-7-17) --TemplateExporter.exclude_input=True [](#__codelineno-7-18)[](#__codelineno-7-19)# Use nbconvert programmatically for more control [](#__codelineno-7-20)uv run --with nbconvert python -c " [](#__codelineno-7-21)from nbconvert import PDFExporter [](#__codelineno-7-22)import nbformat [](#__codelineno-7-23)nb = nbformat.read('$NOTEBOOK', as_version=4) [](#__codelineno-7-24)pdf_exporter = PDFExporter() [](#__codelineno-7-25)pdf_data, resources = pdf_exporter.from_notebook_node(nb) [](#__codelineno-7-26)with open('notebook.pdf', 'wb') as f: [](#__codelineno-7-27) f.write(pdf_data) [](#__codelineno-7-28)"` You can also use other tools that work with Jupyter notebooks: * [Quarto](https://quarto.org/) - Create beautiful documents, websites, presentations * [nbgrader](https://nbgrader.readthedocs.io/) - Grade notebook assignments Export to WASM-powered HTML[¶](#export-to-wasm-powered-html "Permanent link") ----------------------------------------------------------------------------- Export your notebook to a self-contained HTML file that runs using WebAssembly: `[](#__codelineno-8-1)# export as readonly, with code locked [](#__codelineno-8-2)marimo export html-wasm notebook.py -o output_dir --mode run [](#__codelineno-8-3)# export as an editable notebook [](#__codelineno-8-4)marimo export html-wasm notebook.py -o output_dir --mode edit` The exported HTML file will run your notebook using WebAssembly, making it completely self-contained and executable in the browser. This means users can interact with your notebook without needing Python or marimo installed. Options: * `--mode`: Choose between `run` (read-only) or `edit` (allows editing) * `--output`: Directory to save the HTML and required assets * `--show-code/--no-show-code`: Whether to initially show or hide the code in the notebook * `--watch/--no-watch`: Watch the notebook for changes and automatically export Note The exported file must be served over HTTP to function correctly - it cannot be opened directly from the filesystem (`file://`). Your server must also serve the assets in the `assets` directory, next to the HTML file. For a simpler publishing experience, publish to [GitHub Pages](https://docs.marimo.io/guides/publishing/github_pages/) or use the [online playground](https://docs.marimo.io/guides/publishing/playground/). ### Testing the export[¶](#testing-the-export "Permanent link") You can test the export by running the following command in the directory containing your notebook: `[](#__codelineno-9-1)cd path/to/output_dir [](#__codelineno-9-2)python -m http.server` ### Including data files[¶](#including-data-files "Permanent link") See the docs for [mo.notebook\_location](https://docs.marimo.io/api/miscellaneous/#marimo.notebook_location) to learn how to include data files in exported WASM HTML notebooks. ### Publishing to GitHub Pages[¶](#publishing-to-github-pages "Permanent link") After exporting your notebook to WASM HTML, you can publish it to [GitHub Pages](https://pages.github.com/) for free. See our [guide on GitHub Pages](https://docs.marimo.io/guides/publishing/github_pages/) to learn more. ### Exporting multiple notebooks[¶](#exporting-multiple-notebooks "Permanent link") In order to export multiple notebooks under the same folder, you can use the following snippet: `[](#__codelineno-10-1)files=("batch_and_form.py" "data_explorer.py") [](#__codelineno-10-2)[](#__codelineno-10-3)for file in "${files[@]}"; do [](#__codelineno-10-4) without_extension="${file%.*}" [](#__codelineno-10-5) marimo export html-wasm "$file" -o public/"$without_extension".html --mode run [](#__codelineno-10-6)done` Optionally, you can create an `index.html` file in the public directory: `[](#__codelineno-11-1)echo "" >> public/index.html` 🏝️ Embed marimo outputs in HTML using Islands[¶](#embed-marimo-outputs-in-html-using-islands "Permanent link") --------------------------------------------------------------------------------------------------------------- Preview Islands are an early feature. While the API likely won't change, there are some improvements we'd like to make before we consider them stable. Please let us know on [GitHub](https://github.com/marimo-team/marimo/issues) if you run into any issues or have any feedback! marimo islands are a way to embed marimo outputs and/or python code in your HTML that will become interactive when the page is loaded. This is useful for creating interactive blog posts, tutorials, and educational materials, all powered by marimo's reactive runtime. Check out an [example island-powered document](https://docs.marimo.io/guides/island_example/). ### Generating islands[¶](#generating-islands "Permanent link") Use `MarimoIslandGenerator` to generate HTML for islands Example From code blocksFrom notebook files `[](#__codelineno-12-1)import asyncio [](#__codelineno-12-2)import sys [](#__codelineno-12-3)from marimo import MarimoIslandGenerator [](#__codelineno-12-4)[](#__codelineno-12-5)if sys.platform == 'win32': [](#__codelineno-12-6) asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) [](#__codelineno-12-7)[](#__codelineno-12-8)async def main(): [](#__codelineno-12-9) generator = MarimoIslandGenerator() [](#__codelineno-12-10) block1 = generator.add_code("import marimo as mo") [](#__codelineno-12-11) block2 = generator.add_code("mo.md('Hello, islands!')") [](#__codelineno-12-12) [](#__codelineno-12-13) # Build the app [](#__codelineno-12-14) app = await generator.build() [](#__codelineno-12-15) [](#__codelineno-12-16) # Render the app [](#__codelineno-12-17) output = f""" [](#__codelineno-12-18) [](#__codelineno-12-19) [](#__codelineno-12-20) {generator.render_head()} [](#__codelineno-12-21) [](#__codelineno-12-22) [](#__codelineno-12-23) {block1.render(display_output=False)} [](#__codelineno-12-24) {block2.render()} [](#__codelineno-12-25) [](#__codelineno-12-26) [](#__codelineno-12-27) """ [](#__codelineno-12-28) print(output) [](#__codelineno-12-29) # Save the HTML to a file [](#__codelineno-12-30) output_file = "output.html" [](#__codelineno-12-31) with open(output_file, "w", encoding="utf-8") as f: [](#__codelineno-12-32) f.write(output) [](#__codelineno-12-33)[](#__codelineno-12-34)if __name__ == '__main__': [](#__codelineno-12-35) asyncio.run(main())` `[](#__codelineno-13-1)from marimo import MarimoIslandGenerator [](#__codelineno-13-2)[](#__codelineno-13-3)# Create the generator from file [](#__codelineno-13-4)generator = MarimoIslandGenerator.from_file("./.py", display_code=False) [](#__codelineno-13-5)[](#__codelineno-13-6)# Generate and print the HTML without building [](#__codelineno-13-7)# This will still work for basic rendering, though without running the cells [](#__codelineno-13-8)html = generator.render_html(include_init_island=False) [](#__codelineno-13-9)print(html) [](#__codelineno-13-10)# Save the HTML to a file [](#__codelineno-13-11)output_file = "output.html" [](#__codelineno-13-12)with open(output_file, "w", encoding="utf-8") as f: [](#__codelineno-13-13) f.write(html)` Any relevant `.html` that gets generated can be run through the [`development.md`](https://github.com/marimo-team/marimo/blob/main/frontend/islands/development.md) file instructions. ### Islands in action[¶](#islands-in-action "Permanent link") Advanced topic! Islands are an advanced concept that is meant to be a building block for creating integrations with existing tools such as static site generators or documentation tools. In order to use marimo islands, you need to import the necessary JS/CSS headers in your HTML file, and use our custom HTML tags to define the islands. `[](#__codelineno-14-1) [](#__codelineno-14-2) [](#__codelineno-14-10) [](#__codelineno-14-11) [](#__codelineno-14-12) [](#__codelineno-14-16) [](#__codelineno-14-22) [](#__codelineno-14-23)[](#__codelineno-14-24) [](#__codelineno-14-25) [](#__codelineno-14-26) [](#__codelineno-14-27) [](#__codelineno-14-28) Hello, islands! [](#__codelineno-14-29) [](#__codelineno-14-30) [](#__codelineno-14-31) [](#__codelineno-14-32) [](#__codelineno-14-33)` marimo.MarimoIslandGenerator [¶](#marimo.MarimoIslandGenerator "Permanent link") -------------------------------------------------------------------------------- `[](#__codelineno-0-1)MarimoIslandGenerator(app_id: [str](https://docs.python.org/3/library/stdtypes.html#str) = 'main')` Generates Marimo islands for embedding in other pages. This is a great way to use another SSG framework that converts Python code to HTML using marimo-islands. Generally you will want to: 1. Find all the code snippets and add them to the generator. 2. Build the app. 3. Replace all code snippets with the rendered HTML. 4. Include the header in the tag. ### Example[¶](#marimo.MarimoIslandGenerator--example "Permanent link") Using the MarimoIslandGenerator class: `[](#__codelineno-0-1)import asyncio [](#__codelineno-0-2)import sys [](#__codelineno-0-3)from marimo import MarimoIslandGenerator [](#__codelineno-0-4)[](#__codelineno-0-5)async def main(): [](#__codelineno-0-6) generator = MarimoIslandGenerator() [](#__codelineno-0-7) block1 = generator.add_code("import marimo as mo") [](#__codelineno-0-8) block2 = generator.add_code("mo.md('Hello, islands!')") [](#__codelineno-0-9) [](#__codelineno-0-10) # Build the app [](#__codelineno-0-11) app = await generator.build() [](#__codelineno-0-12) [](#__codelineno-0-13) # Render the app [](#__codelineno-0-14) output = f""" [](#__codelineno-0-15) [](#__codelineno-0-16) [](#__codelineno-0-17) {generator.render_head()} [](#__codelineno-0-18) [](#__codelineno-0-19) [](#__codelineno-0-20) {block1.render(display_output=False)} [](#__codelineno-0-21) {block2.render()} [](#__codelineno-0-22) [](#__codelineno-0-23) [](#__codelineno-0-24) """ [](#__codelineno-0-25) print(output) [](#__codelineno-0-26) # Save the HTML to a file [](#__codelineno-0-27) output_file = "output.html" [](#__codelineno-0-28) with open(output_file, "w", encoding="utf-8") as f: [](#__codelineno-0-29) f.write(output) [](#__codelineno-0-30)[](#__codelineno-0-31)if __name__ == '__main__': [](#__codelineno-0-32) asyncio.run(main())` You can also create the generator from a file: `[](#__codelineno-1-1)from marimo import MarimoIslandGenerator [](#__codelineno-1-2)[](#__codelineno-1-3)# Create the generator from file [](#__codelineno-1-4)generator = MarimoIslandGenerator.from_file( [](#__codelineno-1-5) "./.py", display_code=False [](#__codelineno-1-6)) [](#__codelineno-1-7)[](#__codelineno-1-8)# Generate and print the HTML without building [](#__codelineno-1-9)# This will still work for basic rendering, though without running the cells [](#__codelineno-1-10)html = generator.render_html(include_init_island=False) [](#__codelineno-1-11)print(html) [](#__codelineno-1-12)# Save the HTML to a file [](#__codelineno-1-13)output_file = "output.html" [](#__codelineno-1-14)with open(output_file, "w", encoding="utf-8") as f: [](#__codelineno-1-15) f.write(html)` ### has\_run `instance-attribute` [¶](#marimo.MarimoIslandGenerator.has_run "Permanent link") ### add\_code [¶](#marimo.MarimoIslandGenerator.add_code "Permanent link") `[](#__codelineno-0-1)add_code( [](#__codelineno-0-2) code: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) display_code: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-4) display_output: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) is_reactive: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-6) is_raw: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7)) -> MarimoIslandStub` Add a code cell to the app. _Args:_ * code (str): The code to add to the app. * display\_code (bool): Whether to display the code in the HTML. * display\_output (bool): Whether to display the output in the HTML. * is\_raw (bool): Whether to handled the code without formatting. * is\_reactive (bool): Whether this code block will run with pyodide. ### build `async` [¶](#marimo.MarimoIslandGenerator.build "Permanent link") Build the app. This should be called after adding all the code cells. _Returns:_ * App: The built app. ### from\_file `staticmethod` [¶](#marimo.MarimoIslandGenerator.from_file "Permanent link") `[](#__codelineno-0-1)from_file( [](#__codelineno-0-2) filename: [str](https://docs.python.org/3/library/stdtypes.html#str), display_code: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-3)) -> [MarimoIslandGenerator](#marimo.MarimoIslandGenerator "marimo._islands.island_generator.MarimoIslandGenerator")` Create a MarimoIslandGenerator and populate MarimoIslandStubs using code cells from a marimo \*.py file. _Args:_ * filename (str): Marimo .py filename to convert to reactive HTML. * display\_code (bool): Whether to display the code in HTML snippets. ### render\_body [¶](#marimo.MarimoIslandGenerator.render_body "Permanent link") Render the body for the app. This should be included in the tag of the page. _Args:_ - include\_init\_island (bool): If True, adds initialization loader. - max\_width (str): CSS style max\_width property. - margin (str): CSS style margin property. - style (str): CSS style. Overrides max\_width and margin. ### render\_head [¶](#marimo.MarimoIslandGenerator.render_head "Permanent link") `[](#__codelineno-0-1)render_head( [](#__codelineno-0-2) *, [](#__codelineno-0-3) version_override: [str](https://docs.python.org/3/library/stdtypes.html#str) = __version__, [](#__codelineno-0-4) _development_url: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [bool](https://docs.python.org/3/library/functions.html#bool)] = False [](#__codelineno-0-5)) -> [str](https://docs.python.org/3/library/stdtypes.html#str)` Render the header for the app. This should be included in the tag of the page. _Args:_ * version\_override (str): Marimo version to use for loaded js/css. * \_development\_url (str): If True, uses local marimo islands js. ### render\_html [¶](#marimo.MarimoIslandGenerator.render_html "Permanent link") Render reactive html for the app. _Args:_ * version\_override (str): Marimo version to use for loaded js/css. * \_development\_url (str): If True, uses local marimo islands js. * include\_init\_island (bool): If True, adds initialization loader. * max\_width (str): CSS style max\_width property. * margin (str): CSS style margin property. * style (str): CSS style. Overrides max\_width and margin. ### render\_init\_island [¶](#marimo.MarimoIslandGenerator.render_init_island "Permanent link") `[](#__codelineno-0-1)render_init_island() -> [str](https://docs.python.org/3/library/stdtypes.html#str)` Renders a static html MarimoIsland str which displays a spinning initialization loader while Pyodide loads and disappears once the kernel is ready to use. Publish to the web - marimo https://docs.marimo.io/guides/publishing/ Publishing notebooks to the web[¶](#publishing-notebooks-to-the-web "Permanent link") ------------------------------------------------------------------------------------- You can publish marimo notebooks to the web as interactive editable notebooks, readonly web apps, or [static documents](https://docs.marimo.io/guides/exporting/). Thanks to [WebAssembly](https://docs.marimo.io/guides/wasm/), you can even share executable notebooks on GitHub Pages or other static sites without paying for backend infrastrcture. This makes it easy to share your work with colleagues, embed executable notebooks in web documentation or educational websites, and more. This guide provides an overview of the various ways to publish marimo notebooks. | Guide | Description | | --- | --- | | [Embedding](https://docs.marimo.io/guides/publishing/embedding/) | An overview of embedding notebooks in other sites | | [From GitHub](https://docs.marimo.io/guides/publishing/from_github/) | How to share links to executable notebooks hosted on GitHUb | | [GitHub Pages](https://docs.marimo.io/guides/publishing/github_pages/) | Publishing interactive notebooks on GitHub Pages | | [Online playground](https://docs.marimo.io/guides/publishing/playground/) | Sharing notebook links using our online playground | | [Community Cloud](https://docs.marimo.io/guides/publishing/community_cloud/) | Save notebooks to our free Community Cloud | | [Self-host WebAssembly notebooks](https://docs.marimo.io/guides/publishing/self_host_wasm/) | Self-hosting interactive WebAssembly (HTML export) notebooks | | [View notebooks on GitHub](https://docs.marimo.io/guides/publishing/view_outputs_on_github/) | Viewing notebook outputs on GitHub | | [Deploy on a backend](https://docs.marimo.io/guides/publishing/deploy/) | Deploying notebooks on backends | doctest - marimo https://docs.marimo.io/guides/testing/doctest/ Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.6" app = marimo.App(width="medium") @app.cell def _(): import marimo as mo return (mo,) @app.cell def _(): def euclid_mcd(a: int, b: int) -> int: """Return the MCD between positive a, b. >>> euclid_mcd(42, 24) 6 >>> euclid_mcd(24, 42) 6 >>> euclid_mcd(42, 42) 42 """ assert a > 0 assert b > 0 if a < b: a, b = b, a if (a != b): r = a - b return euclid_mcd(b, r) return a return (euclid_mcd,) @app.cell def _(euclid_mcd, mo): # Include a reference to each function to test euclid_mcd import doctest failures, success = doctest.testmod(verbose=True) mo.md(f"Success: {success}, Failures: {failures}") return doctest, failures, success if __name__ == "__main__": app.run()` Embedding - marimo https://docs.marimo.io/guides/publishing/embedding/ There are various ways to embed marimo notebooks in other web pages, such as web documentation, educational platforms, or static sites in general. Here are two ways: * Host on [GitHub Pages](https://docs.marimo.io/guides/publishing/github_pages/) or [self-host WASM HTML](https://docs.marimo.io/guides/publishing/self_host_wasm/), and `` ### Embedding an existing notebook[¶](#embedding-an-existing-notebook "Permanent link") To embed existing marimo notebooks into a webpage, first, [obtain a URL to your notebook](#creating-and-sharing-playground-notebooks), then put it in an iframe. `[](#__codelineno-3-1)` ### Embedding an existing notebook in read-only mode[¶](#embedding-an-existing-notebook-in-read-only-mode "Permanent link") You can optionally render embedded notebooks in read-only mode by appending `&mode=read` to your URL. `[](#__codelineno-4-1)` Authentication - marimo https://docs.marimo.io/guides/deploying/authentication/ marimo provides a simple way to add token/password protection to your marimo server. Given that authentication is a complex topic, marimo does not provide a built-in authentication/authorization system, but instead makes it easy to add your own through ASGI middleware. Enabling Basic Authentication[¶](#enabling-basic-authentication "Permanent link") --------------------------------------------------------------------------------- Authentication is enabled by default when running `marimo edit/tutorial/new`. To disable authentication, you may pass `--no-token` to your `marimo edit/run/new` command from the Terminal. The auth token will be randomly generated when in `Edit mode` and deterministically generated in `Run mode` (based on the code of the notebook). However, you can also pass your own token/password using the `--token-password` flag. `[](#__codelineno-0-1)marimo run my_notebook.py --token --token-password="sup3rs3cr3t"` ### Ways to Authenticate[¶](#ways-to-authenticate "Permanent link") In order to authenticate, you must either pass the token as a password in the `Authorization` header, or as a query parameter under `access_token` in the URL. 1. Enter the token in the login page: If you try to access marimo from a browser, you will be redirected to a login page where you can enter the token. 2. Query parameter: To authenticate using a query parameter, you must pass the token as a query parameter under `access_token` in the URL. For example, to authenticate with the token `sup3rs3cr3t`, you would pass the query parameter `http://localhost:2718?access_token=sup3rs3cr3t`. For convenience, when running locally, marimo will automatically open the URL with the query parameter in your default browser. 3. Basic Authorization header: To authenticate using the `Authorization` header, you must pass the token as a password in the `Authorization` header using the [Basic authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). For example, to authenticate with the token `sup3rs3cr3t`, you would pass the header `Authorization Basic base64("any_username:sup3rs3cr3t")`. This is not necessary when using a browser, as the marimo server will redirect you to a minimal login page where you can enter the token. Custom Authentication[¶](#custom-authentication "Permanent link") ----------------------------------------------------------------- If you choose to make your marimo application public, you may want to add your own authentication system, along with authorization, rate limiting, etc. You can do this by creating a marimo application programmatically and adding your own middleware to the ASGI application. Here's an example of how you can add authentication to a marimo application using FastAPI: `[](#__codelineno-1-1)from typing import Annotated, Callable, Coroutine [](#__codelineno-1-2)from fastapi.responses import HTMLResponse, RedirectResponse [](#__codelineno-1-3)import marimo [](#__codelineno-1-4)from fastapi import FastAPI, Form, Request, Response [](#__codelineno-1-5)# Custom auth middleware and login page [](#__codelineno-1-6)from my_auth_module import auth_middleware, my_login_route [](#__codelineno-1-7) [](#__codelineno-1-8)[](#__codelineno-1-9)# Create a marimo asgi app [](#__codelineno-1-10)server = ( [](#__codelineno-1-11) marimo.create_asgi_app() [](#__codelineno-1-12) .with_app(path="", root="./pages/index.py") [](#__codelineno-1-13) .with_app(path="/dashboard", root="./pages/dashboard.py") [](#__codelineno-1-14) .with_app(path="/sales", root="./pages/sales.py") [](#__codelineno-1-15)) [](#__codelineno-1-16)[](#__codelineno-1-17)# Create a FastAPI app [](#__codelineno-1-18)app = FastAPI() [](#__codelineno-1-19)[](#__codelineno-1-20)app.add_middleware(auth_middleware) [](#__codelineno-1-21)app.add_route("/login", my_login_route, methods=["POST"]) [](#__codelineno-1-22)[](#__codelineno-1-23)app.mount("/", server.build()) [](#__codelineno-1-24)[](#__codelineno-1-25)# Run the server [](#__codelineno-1-26)if __name__ == "__main__": [](#__codelineno-1-27) import uvicorn [](#__codelineno-1-28) [](#__codelineno-1-29) uvicorn.run(app, host="localhost", port=8000)` or for a full example on implementing OAuth2 with FastAPI, see the [FastAPI OAuth2 example](https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/). Docker - marimo https://docs.marimo.io/guides/deploying/deploying_docker/ Deploy with Docker[¶](#deploy-with-docker "Permanent link") ----------------------------------------------------------- Prerequisites[¶](#prerequisites "Permanent link") ------------------------------------------------- * A marimo notebook or app: `app.py` that you want to deploy * A `requirements.txt` file that contains the dependencies needed for your application to run Create a Dockerfile[¶](#create-a-dockerfile "Permanent link") ------------------------------------------------------------- `Dockerfile` is a text file that contains instructions for building a Docker image. Here's an example `Dockerfile` for a marimo notebook: `[](#__codelineno-0-1)# syntax=docker/dockerfile:1.4 [](#__codelineno-0-2)[](#__codelineno-0-3)# Choose a python version that you know works with your application [](#__codelineno-0-4)FROM python:3.11-slim [](#__codelineno-0-5)[](#__codelineno-0-6)# Install uv for fast package management [](#__codelineno-0-7)COPY --from=ghcr.io/astral-sh/uv:0.4.20 /uv /bin/uv [](#__codelineno-0-8)ENV UV_SYSTEM_PYTHON=1 [](#__codelineno-0-9)[](#__codelineno-0-10)WORKDIR /app [](#__codelineno-0-11)[](#__codelineno-0-12)# Copy requirements file [](#__codelineno-0-13)COPY --link requirements.txt . [](#__codelineno-0-14)[](#__codelineno-0-15)# Install the requirements using uv [](#__codelineno-0-16)RUN uv pip install -r requirements.txt [](#__codelineno-0-17)[](#__codelineno-0-18)# Copy application files [](#__codelineno-0-19)COPY --link app.py . [](#__codelineno-0-20)# Uncomment the following line if you need to copy additional files [](#__codelineno-0-21)# COPY --link . . [](#__codelineno-0-22)[](#__codelineno-0-23)EXPOSE 8080 [](#__codelineno-0-24)[](#__codelineno-0-25)# Create a non-root user and switch to it [](#__codelineno-0-26)RUN useradd -m app_user [](#__codelineno-0-27)USER app_user [](#__codelineno-0-28)[](#__codelineno-0-29)CMD [ "marimo", "run", "app.py", "--host", "0.0.0.0", "-p", "8080" ]` Breaking it down[¶](#breaking-it-down "Permanent link") ------------------------------------------------------- `FROM` instructs what base image to choose. In our case, we chose Python 3.11 with the “slim” variant. This removes a lot of extra dependencies. You can always add them back as needed. A slimmer Dockerfile (by bytes) means quick to build, deploy, and start up. The `WORKDIR` sets the current working directory. In most cases, this does not need to be changed. The `COPY` steps will copy all the necessary files into your docker. By adding `--link`, we end up creating a new layer that does not get invalidated by previous changes. This can be especially important for expensive install steps that do not depend on each other. `RUN` lets us run shell commands. We can use this to install dependencies via apt-get, pip, or package managers. In our case, we use it to install our requirements.txt with pip. Our `EXPOSE` step tells us which port is exposed to be accessed from outside the Docker container. This will need to match the port at which we run our marimo application on. We then create a new user and switch to it with the `USER` instruction, in order to limit the permissions of the marimo application. This is not required, but recommended. The final step `CMD` instructions what command to run when we run our docker container. Here we run our marimo application at the port 8080. Running your application locally[¶](#running-your-application-locally "Permanent link") --------------------------------------------------------------------------------------- Once you have your Dockerfile and your application files, you can test it out locally: `[](#__codelineno-1-1)# Build your image, and tag it as my_app [](#__codelineno-1-2)docker build -t my_app . [](#__codelineno-1-3)[](#__codelineno-1-4)# Start your container, mapping port 8080 [](#__codelineno-1-5)docker run -p 8080:8080 -it my_app [](#__codelineno-1-6)[](#__codelineno-1-7)# Visit http://localhost:8080` After verifying that your application runs without errors, you can use these files to deploy your application on your preferred cloud provider that supports dockerized applications. Health checks[¶](#health-checks "Permanent link") ------------------------------------------------- You can add a health check to your Dockerfile to ensure that your application is running as expected. This is especially useful when deploying to a cloud provider. `[](#__codelineno-2-1)HEALTHCHECK --interval=30s --timeout=3s \ [](#__codelineno-2-2) CMD curl -f http://localhost:8080/health || exit 1` The following endpoints may be useful when deploying your application: * `/health` or `/healthz` - A health check endpoint that returns a 200 status code if the application is running as expected * `/api/status` - A status endpoint that returns a JSON object with the status of the server HuggingFace - marimo https://docs.marimo.io/guides/deploying/deploying_hugging_face/ Deploy to Hugging Face[¶](#deploy-to-hugging-face "Permanent link") ------------------------------------------------------------------- Hugging Face is a platform that allows you to deploy machine learning models and applications easily. You can deploy a marimo notebook as an interactive web app on Hugging Face Spaces with just a few steps. Deploy[¶](#deploy "Permanent link") ----------------------------------- To deploy your marimo notebook to Hugging Face Spaces: 1. Create a new Space on Hugging Face by forking or copying the following template: [https://huggingface.co/spaces/marimo-team/marimo-app-template/tree/main](https://huggingface.co/spaces/marimo-team/marimo-app-template/tree/main) 2. Replace the contents of the `app.py` file with your marimo notebook. 3. Update the `requirements.txt` file to include any other dependencies your notebook requires. 4. Commit these files to your Space, and Hugging Face will automatically deploy your marimo notebook as an interactive web app. For more detailed instructions and advanced configurations, please refer to the [Hugging Face Spaces documentation](https://huggingface.co/docs/hub/spaces-overview). Ploomber - marimo https://docs.marimo.io/guides/deploying/deploying_ploomber/ Deploy to Ploomber Cloud[¶](#deploy-to-ploomber-cloud "Permanent link") ----------------------------------------------------------------------- For production deployments, you can use Ploomber Cloud. It allows you to deploy marimo in a secure and scalable way. See [deployment instructions here](https://docs.cloud.ploomber.io/en/latest/apps/marimo.html) Railway - marimo https://docs.marimo.io/guides/deploying/deploying_railway/ Deploy to Railway[¶](#deploy-to-railway "Permanent link") --------------------------------------------------------- Railway is a platform that allows you to deploy Dockerize containers easily. Using this pre-built template, Railway will deploy a single-instance marimo edit server with persistent storage in a few clicks. Deploy[¶](#deploy "Permanent link") ----------------------------------- Public gallery - marimo https://docs.marimo.io/guides/deploying/deploying_public_gallery/ Deploy to our public gallery[¶](#deploy-to-our-public-gallery "Permanent link") ------------------------------------------------------------------------------- If you would like to deploy your application to our [public gallery](https://marimo.io/gallery), please reach out on [Discord](https://marimo.io/discord?ref=docs). You can also easily share your notebooks on the public web using [WASM notebooks](https://docs.marimo.io/guides/wasm/), which run entirely in the browser, no backend required. nginx - marimo https://docs.marimo.io/guides/deploying/deploying_nginx/ Deploy with nginx[¶](#deploy-with-nginx "Permanent link") --------------------------------------------------------- nginx is a popular web server that can be used as a reverse proxy for web applications. This guide will show you how to deploy marimo behind an nginx reverse proxy. Prerequisites[¶](#prerequisites "Permanent link") ------------------------------------------------- * A marimo notebook or app that you want to deploy * nginx installed on your server * Basic understanding of nginx configuration Configuration[¶](#configuration "Permanent link") ------------------------------------------------- Create a new configuration file in `/etc/nginx/conf.d/` (e.g., `marimo.conf`): `[](#__codelineno-0-1)server { [](#__codelineno-0-2) server_name your-domain.com; [](#__codelineno-0-3) [](#__codelineno-0-4) location / { [](#__codelineno-0-5) proxy_set_header Host $host; [](#__codelineno-0-6) proxy_set_header X-Real-IP $remote_addr; [](#__codelineno-0-7) proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; [](#__codelineno-0-8) proxy_set_header X-Forwarded-Proto $scheme; [](#__codelineno-0-9) proxy_pass http://127.0.0.1:2718; [](#__codelineno-0-10) [](#__codelineno-0-11) # Required for WebSocket support [](#__codelineno-0-12) proxy_http_version 1.1; [](#__codelineno-0-13) proxy_set_header Upgrade $http_upgrade; [](#__codelineno-0-14) proxy_set_header Connection "upgrade"; [](#__codelineno-0-15) proxy_read_timeout 600; [](#__codelineno-0-16) } [](#__codelineno-0-17) [](#__codelineno-0-18) # Optional: Serve static files [](#__codelineno-0-19) location /static/ { [](#__codelineno-0-20) alias /path/to/your/static/files/; [](#__codelineno-0-21) } [](#__codelineno-0-22)}` Breaking it down[¶](#breaking-it-down "Permanent link") ------------------------------------------------------- * `server_name`: Replace with your domain name * `proxy_pass`: Points to your marimo application (default port is 2718) * WebSocket support: The following lines are required for marimo to function properly: `[](#__codelineno-1-1)proxy_http_version 1.1; [](#__codelineno-1-2)proxy_set_header Upgrade $http_upgrade; [](#__codelineno-1-3)proxy_set_header Connection "upgrade";` * `proxy_read_timeout`: Increased to 600 seconds to handle long-running operations Running your application[¶](#running-your-application "Permanent link") ----------------------------------------------------------------------- 1. Start your marimo application: `[](#__codelineno-2-1)marimo run app.py --host 127.0.0.1 --port 2718` 2. Test your nginx configuration: 3. Reload nginx to apply changes: Your marimo application should now be accessible at your domain. SSL/HTTPS[¶](#sslhttps "Permanent link") ---------------------------------------- For production deployments, it's recommended to use HTTPS. You can use [Certbot](https://certbot.eff.org/) to automatically configure SSL with Let's Encrypt certificates. Common Issues[¶](#common-issues "Permanent link") ------------------------------------------------- ### Kernel Not Found[¶](#kernel-not-found "Permanent link") If you see a "kernel not found" error, ensure that: 1. WebSocket support is properly configured in your nginx configuration 2. The proxy headers are correctly set 3. Your marimo application is running and accessible at the specified proxy\_pass address Prebuilt containers - marimo https://docs.marimo.io/guides/deploying/prebuilt_containers/ marimo provides prebuilt containers for running a marimo server. You can find the containers and tags on [marimo's GitHub packages page](https://github.com/marimo-team/marimo/pkgs/container/marimo). We provide the following variants: * `marimo:latest` - The latest version of marimo * `marimo:latest-data` - The latest version of marimo with `altair`, `pandas`, and `numpy` preinstalled. * `marimo:latest-sql` - The latest version of marimo with `marimo[sql]` and `duckdb` preinstalled. or any particular version of marimo; for example, `marimo:0.8.3`, `marimo:0.8.3-data`, `marimo:0.8.3-sql`. Each container is built on `3.12-slim`, but if you'd like to see different configurations, please file an issue or submit a PR! Running locally[¶](#running-locally "Permanent link") ----------------------------------------------------- To run the container locally, you can use the following command: `[](#__codelineno-0-1)docker run -p 8080:8080 -it ghcr.io/marimo-team/marimo:latest-sql` Use in a Dockerfile[¶](#use-in-a-dockerfile "Permanent link") ------------------------------------------------------------- To use a prebuilt container in a Dockerfile, you can use the following command: `[](#__codelineno-1-1)FROM ghcr.io/marimo-team/marimo:latest-sql [](#__codelineno-1-2)[](#__codelineno-1-3)# Install any additional dependencies here [](#__codelineno-1-4)[](#__codelineno-1-5)CMD ["marimo", "edit", "--no-token", "-p", "8080", "--host", "0.0.0.0"]` Programmatic - marimo https://docs.marimo.io/guides/deploying/programmatically/ Running the marimo backend programmatically[¶](#running-the-marimo-backend-programmatically "Permanent link") ------------------------------------------------------------------------------------------------------------- marimo can be run programmatically using the `marimo` module. This is useful when you want to run marimo as part of a larger application or when you need to customize the behavior of marimo (e.g. middleware, custom error handling, authentication, routing, etc). FastAPI Example[¶](#fastapi-example "Permanent link") ----------------------------------------------------- Here's an example of how you can run a marimo application programmatically using FastAPI: `[](#__codelineno-0-1)from typing import Annotated, Callable, Coroutine [](#__codelineno-0-2)from fastapi.responses import HTMLResponse, RedirectResponse [](#__codelineno-0-3)import marimo [](#__codelineno-0-4)from fastapi import FastAPI, Form, Request, Response [](#__codelineno-0-5) [](#__codelineno-0-6)[](#__codelineno-0-7)# Create a marimo asgi app [](#__codelineno-0-8)server = ( [](#__codelineno-0-9) marimo.create_asgi_app() [](#__codelineno-0-10) .with_app(path="", root="./pages/index.py") [](#__codelineno-0-11) .with_app(path="/dashboard", root="./pages/dashboard.py") [](#__codelineno-0-12) .with_app(path="/sales", root="./pages/sales.py") [](#__codelineno-0-13)) [](#__codelineno-0-14)[](#__codelineno-0-15)# Create a FastAPI app [](#__codelineno-0-16)app = FastAPI() [](#__codelineno-0-17)[](#__codelineno-0-18)app.add_middleware(auth_middleware) [](#__codelineno-0-19)app.add_route("/login", my_login_route, methods=["POST"]) [](#__codelineno-0-20)[](#__codelineno-0-21)app.mount("/", server.build()) [](#__codelineno-0-22)[](#__codelineno-0-23)# Run the server [](#__codelineno-0-24)if __name__ == "__main__": [](#__codelineno-0-25) import uvicorn [](#__codelineno-0-26) [](#__codelineno-0-27) uvicorn.run(app, host="localhost", port=8000)` For a more complete example, see the [FastAPI example](https://github.com/marimo-team/marimo/tree/main/examples/frameworks/fastapi). Dynamic directory[¶](#dynamic-directory "Permanent link") --------------------------------------------------------- If you'd like to create a server to dynamically load marimo notebooks from a directory, you can use the `with_dynamic_directory` method. This is useful if the contents of the directory change often, such as a directory of notebooks for a dashboard, without restarting the server. `[](#__codelineno-1-1)server = ( [](#__codelineno-1-2) marimo.create_asgi_app() [](#__codelineno-1-3) .with_dynamic_directory(path="/dashboard", directory="./notebooks") [](#__codelineno-1-4))` If the notebooks in the directory are expected to be static, it is better to use the `with_app` method and loop through the directory contents. `[](#__codelineno-2-1)from pathlib import Path [](#__codelineno-2-2)server = marimo.create_asgi_app() [](#__codelineno-2-3)app_names: list[str] = [] [](#__codelineno-2-4)[](#__codelineno-2-5)notebooks_dir = Path(__file__).parent / "notebooks" [](#__codelineno-2-6)[](#__codelineno-2-7)for filename in sorted(notebooks_dir.iterdir()): [](#__codelineno-2-8) if filename.suffix == ".py": [](#__codelineno-2-9) app_name = filename.stem [](#__codelineno-2-10) server = server.with_app(path=f"/{app_name}", root=filename) [](#__codelineno-2-11) app_names.append(app_name)` Accessing Request Data[¶](#accessing-request-data "Permanent link") ------------------------------------------------------------------- Inside your marimo notebooks, you can access the current request data using `mo.app_meta().request`. This is particularly useful when implementing authentication or accessing user data. `[](#__codelineno-3-1)import marimo as mo [](#__codelineno-3-2)[](#__codelineno-3-3)# Access request data in your notebook [](#__codelineno-3-4)request = mo.app_meta().request [](#__codelineno-3-5)if request and request.user and request.user["is_authenticated"]: [](#__codelineno-3-6) content = f"Welcome {request.user['username']}!" [](#__codelineno-3-7)else: [](#__codelineno-3-8) content = "Please log in" [](#__codelineno-3-9)[](#__codelineno-3-10)mo.md(content)` ### Authentication Middleware Example[¶](#authentication-middleware-example "Permanent link") Here's an example of how to implement authentication middleware that populates `request.user`: `[](#__codelineno-4-1)from starlette.middleware.base import BaseHTTPMiddleware [](#__codelineno-4-2)from starlette.requests import Request [](#__codelineno-4-3)[](#__codelineno-4-4)class AuthMiddleware(BaseHTTPMiddleware): [](#__codelineno-4-5) async def dispatch(self, request: Request, call_next): [](#__codelineno-4-6) # Add user data to the request scope [](#__codelineno-4-7) # This will be accessible via mo.app_meta().request.user [](#__codelineno-4-8) request.scope["user"] = { [](#__codelineno-4-9) "is_authenticated": True, [](#__codelineno-4-10) "username": "example_user", [](#__codelineno-4-11) # Add any other user data [](#__codelineno-4-12) } [](#__codelineno-4-13) response = await call_next(request) [](#__codelineno-4-14) return response [](#__codelineno-4-15)[](#__codelineno-4-16)# Add the middleware to your FastAPI app [](#__codelineno-4-17)app.add_middleware(AuthMiddleware)` The `request` object provides access to: * `request.headers`: Request headers * `request.cookies`: Request cookies * `request.query_params`: Query parameters * `request.path_params`: Path parameters * `request.user`: User data added by authentication middleware * `request.url`: URL information including path, query parameters Configuration - marimo https://docs.marimo.io/guides/configuration/ marimo offers two types of configuration: User Configuration and App Configuration. Both can be easily managed through the Settings menu in the marimo editor. App Configuration[¶](#app-configuration "Permanent link") --------------------------------------------------------- App Configuration is specific to each notebook and is stored in the `notebook.py` file. This allows you to customize various aspects of your notebook, including: * Notebook width * Notebook title * [Custom CSS](https://docs.marimo.io/guides/configuration/theming/) * [Custom HTML Head](https://docs.marimo.io/guides/configuration/html_head/) * Automatically download HTML snapshots Configure these settings through the notebook menu (⚙️) in the top-right corner. User Configuration[¶](#user-configuration "Permanent link") ----------------------------------------------------------- User Configuration applies globally across all marimo notebooks and is stored in a `.marimo.toml` file. While you can edit the `.marimo.toml` file directly, we recommend using the marimo UI for a more user-friendly experience. You can customize the following settings: * [Runtime](https://docs.marimo.io/guides/configuration/runtime_configuration/), including whether notebooks autorun * [Hotkeys](https://docs.marimo.io/guides/editor_features/hotkeys/) * Completion (auto-completion, AI copilot, etc.) * Display (theme, font size, output placement, etc.) * Autosave * [Package management](https://docs.marimo.io/guides/editor_features/package_management/#package-management) * Server settings * [VIM keybindings](https://docs.marimo.io/guides/editor_features/overview/#vim-keybindings) * Formatting settings * [AI assistance](https://docs.marimo.io/guides/editor_features/ai_completion/) * Experimental features ### User configuration file[¶](#user-configuration-file "Permanent link") marimo searches for the `.marimo.toml` file in the following order: 1. Current directory 2. Parent directories (moving up the tree) 3. Home directory (`~/.marimo.toml`) 4. [XDG](https://xdgbasedirectoryspecification.com/) directory (`~/.config/marimo/marimo.toml` or `$XDG_CONFIG_HOME/marimo/marimo.toml`) If no `.marimo.toml` file is found, marimo creates one for you in an XDG config compliant way. To view your current configuration and locate the config file, run: To describe the user configuration options, run: ### Overriding settings with pyproject.toml[¶](#overriding-settings-with-pyprojecttoml "Permanent link") You can override user configuration settings with a `pyproject.toml` file. This is useful for sharing configurations across teams or ensuring consistency across notebooks. You must edit the `pyproject.toml` file directly to override settings. For example, the following `pyproject.toml` file overrides the `autosave` setting in the user configuration: pyproject.toml `[](#__codelineno-2-1)[tool.marimo.format] [](#__codelineno-2-2)line_length = 120 [](#__codelineno-2-3)[](#__codelineno-2-4)[tool.marimo.display] [](#__codelineno-2-5)default_width = "full"` You can override any user configuration setting in this way. To find these settings run `marimo config show`. Environment Variables[¶](#environment-variables "Permanent link") ----------------------------------------------------------------- marimo supports the following environment variables for advanced configuration: | Environment Variable | Description | Default Value | | --- | --- | --- | | `MARIMO_OUTPUT_MAX_BYTES` | Maximum size of output that marimo will display. Outputs larger than this will be truncated. | 5,000,000 (5MB) | | `MARIMO_STD_STREAM_MAX_BYTES` | Maximum size of standard stream (stdout/stderr) output that marimo will display. Outputs larger than this will be truncated. | 1,000,000 (1MB) | | `MARIMO_SKIP_UPDATE_CHECK` | If set to "1", marimo will skip checking for updates when starting. | Not set | | `MARIMO_SQL_DEFAULT_LIMIT` | Default limit for SQL query results. If not set, no limit is applied. | Not set | ### Tips[¶](#tips "Permanent link") * The `.marimo.toml` file can be version controlled to share configurations across teams * App configurations can be committed with notebooks to ensure consistent appearance Runtime configuration - marimo https://docs.marimo.io/guides/configuration/runtime_configuration/ Through the notebook settings menu, you can configure how and when marimo runs cells. On startup[¶](#on-startup "Permanent link") ------------------------------------------- By default, marimo notebooks run automatically on startup; just how the command executes a script, executes the notebook. Disable this behavior by unchecking "Autorun on startup". _When sharing a notebook as an app with `marimo run`, this setting has no effect._ On cell change[¶](#on-cell-change "Permanent link") --------------------------------------------------- By default, when a cell is run or a UI element is interacted with, marimo automatically runs cells that reference any of its variables. **You can disable automatic execution of cell's descendants in the notebook settings menu by setting `"On cell change"` to `"lazy"`.** When the runtime is lazy, running a cell marks affected cells as stale but doesn't automatically run them. Lazy evaluation means cells are only run when their outputs are needed. If you run a cell that has stale ancestors, those ancestors will also run to make sure your cell doesn't use stale inputs. You can always click the notebook run button or use the keyboard shortcut to run all stale cells. **When should I use lazy evaluation?** Choosing the lazy runtime can be helpful when working on notebooks with expensive cells. Tip: speed up expensive notebooks with marimo's smart caching In addition to runtime configuration, marimo also provides [opt-in caching](https://docs.marimo.io/api/caching/) to help you work with expensive or side-effectful notebooks. marimo's can cache expensive functions in memory and expensive blocks of code to disk, letting you skip entire sections of your code and automatically loading variables in memory on notebook startup. Read our [caching guide](https://docs.marimo.io/api/caching/) to learn more. _When sharing a notebook as an app with `marimo run`, this setting has no effect._ On module change[¶](#on-module-change "Permanent link") ------------------------------------------------------- When module autoreloading is enabled, marimo automatically runs cells when you edit Python files. Based on static analysis, the reloader only runs cells affected by your edits. The reloader is recursive, meaning that marimo tracks modifications for modules imported by your notebook's imported modules too. Why autoreload? Autoreloading enables a workflow that many developers find productive: develop complex logic in Python modules, and use the marimo notebook as a DAG or main script that orchestrates your logic. Autoreloading comes in two types: 1. **autorun**: automatically re-runs cells affected by module modification. When set to autorun, marimo's reloader automatically run cells when you edit Python files. 2. **lazy**: marks cells affected by module modifications as stale, letting you know which cells need to be re-run. When set to lazy, marimo's reloader marks cells as stale when you edit Python files. HTML head - marimo https://docs.marimo.io/guides/configuration/html_head/ Custom HTML Head[¶](#custom-html-head "Permanent link") ------------------------------------------------------- You can include a custom HTML head file to add additional functionality to your notebook, such as analytics, custom fonts, meta tags, or external scripts. The contents of this file will be injected into the `` section of your notebook. To include a custom HTML head file, specify the relative file path in your app configuration. This can be done through the marimo editor UI in the notebook settings (top-right corner). This will be reflected in your notebook file: `[](#__codelineno-0-1)app = marimo.App(html_head_file="head.html")` Example Use Cases[¶](#example-use-cases "Permanent link") --------------------------------------------------------- Here are some common use cases for custom HTML head content: 1. **Google Analytics** `[](#__codelineno-1-1) [](#__codelineno-1-2) [](#__codelineno-1-3) [](#__codelineno-1-4)` 2. **Custom Fonts** `[](#__codelineno-2-1) [](#__codelineno-2-2) [](#__codelineno-2-3) [](#__codelineno-2-4)` 3. **Meta Tags** `[](#__codelineno-3-1) [](#__codelineno-3-2) [](#__codelineno-3-3) [](#__codelineno-3-4) [](#__codelineno-3-5) [](#__codelineno-3-6) [](#__codelineno-3-7)` 4. **External Scripts and Libraries** `[](#__codelineno-4-1) [](#__codelineno-4-2) [](#__codelineno-4-3) [](#__codelineno-4-4) [](#__codelineno-4-5)[](#__codelineno-4-6) [](#__codelineno-4-7)` WebAssembly notebooks - marimo https://docs.marimo.io/guides/wasm/ marimo lets you execute notebooks _entirely in the browser_, without a backend executing Python. marimo notebooks that run entirely in the browser are called WebAssembly notebooks, or WASM notebooks for short. Try our online playground To create your first WASM notebook, try our online playground at [marimo.new](https://marimo.new/). Read the [playground docs](https://docs.marimo.io/guides/publishing/playground/) to learn more. WASM notebooks have three benefits compared to notebooks hosted using a traditional client-server model. WASM notebooks: 1. eliminate the need to install Python, making scientific computing accessible; 2. eliminate the cost and complexity of deploying backend infrastructure, making it easy to share notebooks; 3. eliminate network requests to a remote Python runner, making development feel snappy. When should I use WASM notebooks? WASM notebooks are excellent for sharing your work, quickly experimenting with code and models, doing lightweight data exploration, authoring blog posts, tutorials, and educational materials, and even building tools. For notebooks that do heavy computation, [use marimo locally](https://docs.marimo.io/getting_started/) or on a backend. **Try it!** Try editing the below notebook (your browser, not a backend server, is executing it!) _This feature is powered by [Pyodide](https://pyodide.org/), a port of Python to WebAssembly that enables browsers to run Python code._ Creating WASM notebooks[¶](#creating-wasm-notebooks "Permanent link") --------------------------------------------------------------------- marimo provides three ways to create and share WASM notebooks: 1. [Export to WASM HTML](https://docs.marimo.io/guides/exporting/#export-to-wasm-powered-html), which you can host on GitHub Pages or self-host. This is great for publishing companion notebooks for research papers that are automatically updated on Git push, or for embedding interactive notebooks as part of other websites. 2. The [online playground](https://docs.marimo.io/guides/publishing/playground/), which lets you create one-off notebooks and share via links, no login required. The playground is also great for embedding editable notebooks in documentation. 3. The [Community Cloud](https://docs.marimo.io/guides/publishing/community_cloud/), which lets you save a collection of notebook to a workspace (for free!) and share publicly or privately with sensible URLs. ### From GitHub[¶](#from-github "Permanent link") marimo provides three ways to share notebooks stored on GitHub as WASM notebooks: 1. Automatically publish to GitHub Pages on git push with [our GitHub action](https://docs.marimo.io/guides/publishing/github_pages/). 2. Load a notebook by URL into the online playground (New > Open from URL ...) 3. Load a notebook from GitHub in the [Community Cloud](https://docs.marimo.io/guides/publishing/community_cloud/). Packages[¶](#packages "Permanent link") --------------------------------------- Rendering performance To make sure markdown and other elements render quickly: make sure to put `import marimo as mo` in its own cell, with no other lines of code. WASM notebooks come with many packages pre-installed, including NumPy, SciPy, scikit-learn, pandas, and matplotlib; see [Pyodide's documentation](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) for a full list. If you attempt to import a package that is not installed, marimo will attempt to automatically install it for you. To manually install packages, use [`micropip`](https://micropip.pyodide.org/en/stable/project/usage.html): In one cell, import micropip: In the next cell, install packages: `[](#__codelineno-1-1)await micropip.install("plotly") [](#__codelineno-1-2)import plotly` ### Supported packages[¶](#supported-packages "Permanent link") All packages with pure Python wheels on PyPI are supported, as well as additional packages like NumPy, SciPy, scikit-learn, duckdb, polars, and more. For a full list of supported packages, see [Pyodide's documentation on supported packages.](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) If you want a package to be supported, consider [filing an issue](https://github.com/pyodide/pyodide/issues/new?assignees=&labels=new+package+request&projects=&template=package_request.md&title=). Including data[¶](#including-data "Permanent link") --------------------------------------------------- **For notebooks exported to WASM HTML.** To include data files in notebooks [exported to WASM HTML](https://docs.marimo.io/guides/exporting/#export-to-wasm-powered-html), place them in a `public/` folder in the same directory as your notebook. When you export to WASM HTML, the public folder will be copied to the export directory. In order to access data both locally and when an exported notebook runs via WebAssembly (e.g., hosted on GitHub Pages), use [`mo.notebook_location()`](https://docs.marimo.io/api/miscellaneous/#marimo.notebook_location) to construct the path to your data: `[](#__codelineno-2-1)import polars as pl [](#__codelineno-2-2)[](#__codelineno-2-3)path_to_csv = mo.notebook_location() / "public" / "data.csv" [](#__codelineno-2-4)df = pl.read_csv(str(path_to_csv)) [](#__codelineno-2-5)df.head()` **Fetching data files from the web.** Instead of bundling data files with your notebook, you can host data files on the web and fetch them in your notebook. Depending on where your files are hosted, you may need to use a CORS Proxy; see the [Pyodide documentation](https://pyodide.org/en/stable/usage/loading-packages.html#installing-wheels-from-arbitrary-urls) for more details. **Playground notebooks.** When opening a playground notebook from GitHub, all the files in the GitHub repo are made available to your notebook. See the [Playground Guide](https://docs.marimo.io/guides/publishing/playground/#including-data-files) for more info. **Community Cloud notebooks.** Our free [Community Cloud](https://docs.marimo.io/guides/publishing/community_cloud/) lets you upload a limited amount of data, and also lets you sync notebooks (and their data) from GitHub. Limitations[¶](#limitations "Permanent link") --------------------------------------------- While WASM notebooks let you share marimo notebooks seamlessly, they have some limitations. **PDB.** PDB is not currently supported. **Threading and multi-processing.** WASM notebooks do not support multithreading and multiprocessing. [This may be fixed in the future](https://github.com/pyodide/pyodide/issues/237). **Memory.** WASM notebooks have a memory limit of 2GB; this may be increased in the future. If memory consumption is an issue, try offloading memory-intensive computations to hosted APIs or precomputing expensive operations. Browser support[¶](#browser-support "Permanent link") ----------------------------------------------------- WASM notebooks are supported in the latest versions of Chrome, Firefox, Edge, and Safari. Chrome is the recommended browser for WASM notebooks as it seems to have the best performance and compatibility. Theming - marimo https://docs.marimo.io/guides/configuration/theming/ marimo provides basic support for theming. You can include a custom CSS file in your notebook that will be applied to the entire notebook. This allows you to customize the appearance of your notebook to your liking. To include a custom CSS file, in the configuration dropdown, add the relative file path to your CSS file in the `Custom CSS` field. Once saved, you should see the changes applied to your notebook: `[](#__codelineno-0-1)app = marimo.App(css_file="custom.css")` CSS Variables[¶](#css-variables "Permanent link") ------------------------------------------------- We support only a few CSS variables as part of the "public API" for theming. These are: `[](#__codelineno-1-1)--marimo-monospace-font [](#__codelineno-1-2)--marimo-text-font [](#__codelineno-1-3)--marimo-heading-font` Other CSS Variables We cannot guarantee that other CSS variables or classnames will be stable across versions. Example[¶](#example "Permanent link") ------------------------------------- Here is an example of a custom CSS file that changes the font of the notebook: `[](#__codelineno-2-1)/* Load Inter from Google Fonts */ [](#__codelineno-2-2)@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); [](#__codelineno-2-3)[](#__codelineno-2-4):root { [](#__codelineno-2-5) --marimo-heading-font: 'Inter', sans-serif; [](#__codelineno-2-6)} [](#__codelineno-2-7)[](#__codelineno-2-8)/* Increase paragraph font size and change color */ [](#__codelineno-2-9).paragraph { [](#__codelineno-2-10) font-size: 1.2rem; [](#__codelineno-2-11) color: light-dark(navy, pink); [](#__codelineno-2-12)}` Custom HTML Head[¶](#custom-html-head "Permanent link") ------------------------------------------------------- You can further customize your notebook by adding custom HTML in the `` section of your notebook. This allows you to add additional functionality to your notebook, such as analytics, custom fonts, meta tags, or external scripts. See the [Custom HTML Head](https://docs.marimo.io/guides/configuration/html_head/) guide for more details. Targeting cells[¶](#targeting-cells "Permanent link") ----------------------------------------------------- You can target a cell's styles from the `data-cell-name` attribute. You can also target a cell's output with the `data-cell-role="output"` attribute. `[](#__codelineno-3-1)/* Target the cell named "My Cell" */ [](#__codelineno-3-2)[data-cell-name="my_cell"] { [](#__codelineno-3-3) background-color: light-dark(navy, pink); [](#__codelineno-3-4)} [](#__codelineno-3-5)[](#__codelineno-3-6)/* Target the output of the cell named "My Cell" */ [](#__codelineno-3-7)[data-cell-name="my_cell"] [data-cell-role="output"] { [](#__codelineno-3-8) background-color: light-dark(navy, pink); [](#__codelineno-3-9)}` The marimo community maintains a [library of custom themes](https://github.com/metaboulie/marimo-themes) that you can use in your notebooks. The library includes various themes like "coldme", "nord", "mininini", and "wigwam", each supporting both light and dark modes. You can: * Browse and download existing themes * Use them in your own notebooks * Contribute your own themes to share with the community Visit the [marimo-themes repository](https://github.com/metaboulie/marimo-themes) to explore available themes and learn how to contribute your own. More customizations[¶](#more-customizations "Permanent link") ------------------------------------------------------------- We want to hear from you! If you have any suggestions for more customization options, please let us know on [GitHub](https://github.com/marimo-team/marimo/discussions) Coming from other tools - marimo https://docs.marimo.io/guides/coming_from/ marimo is a **single tool** that replaces `jupyter`, `streamlit`, `jupytext`, `ipywidgets`, `papermill`, and more. | Guide | Description | | --- | --- | | [Streamlit](https://docs.marimo.io/guides/coming_from/streamlit/) | Transitioning from Streamlit | | [Jupytext](https://docs.marimo.io/guides/coming_from/jupytext/) | Transitioning from Jupytext | | [Papermill](https://docs.marimo.io/guides/coming_from/papermill/) | Transitioning from Papermill | Coming from Jupyter? See our [coming from Jupyter guide](https://docs.marimo.io/guides/coming_from/jupyter/). Jupytext - marimo https://docs.marimo.io/guides/coming_from/jupytext/ Coming from Jupytext[¶](#coming-from-jupytext "Permanent link") --------------------------------------------------------------- If you're familiar with Jupytext, you'll find that marimo offers similar functionality for working with notebooks as Python files, but without the need for additional setup or synchronization issues because marimo notebooks are stored as `.py` files by default. However, Jupytext works with IPython notebooks, whereas marimo works with marimo notebooks, which are not based on IPython/Jupyter. Here's a comparison to help you transition smoothly. Notebook Format[¶](#notebook-format "Permanent link") ----------------------------------------------------- | Jupytext | marimo | | --- | --- | | Jupytext uses comments or special markers to define cell types in notebooks. | Notebooks are pure Python (`.py`) files by default, using standard Python syntax, such as decorators and functions, to define cells. | Converting Jupyter notebooks[¶](#converting-jupyter-notebooks "Permanent link") ------------------------------------------------------------------------------- ### From `.ipynb`[¶](#from-ipynb "Permanent link") | Jupytext | marimo | | --- | --- | | `jupytext --to py notebook.ipynb` | `marimo convert notebook.ipynb > notebook.py` | From py:percent notebooks to marimo notebooks If you have a Python file encoded in the [py:percent](https://jupytext.readthedocs.io/en/latest/#text-notebooks) format, you can convert it to a marimo notebook in two steps: `[](#__codelineno-0-1)jupytext --to notebook.ipynb percent_notebook.py [](#__codelineno-0-2)marimo convert notebook.ipynb > marimo_notebook.py` ### To `.ipynb`[¶](#to-ipynb "Permanent link") | Jupytext | marimo | | --- | --- | | `jupytext --to notebook.ipynb notebook.py` | `marimo export ipynb notebook.py > notebook.ipynb` | Editing Notebooks[¶](#editing-notebooks "Permanent link") --------------------------------------------------------- | Jupytext | marimo | | --- | --- | | Requires synchronization between `.ipynb` and `.py` files. | Edit marimo notebooks files directly in the marimo editor (`marimo edit notebook.py`), and changes are read from and written to the same file. | Executing Notebooks[¶](#executing-notebooks "Permanent link") ------------------------------------------------------------- | Jupytext | marimo | | --- | --- | | Use Jupyter to edit notebooks interactively, or Papermill to execute notebooks from the command line. | In addition to running notebooks interactively (`marimo notebook.py`), you can run notebooks as scripts (`python notebook.py`) or as apps (`marimo run notebook.py`), passing values to them with marimo's built-in support for [CLI args](https://docs.marimo.io/api/cli_args/). | Version Control[¶](#version-control "Permanent link") ----------------------------------------------------- | Jupytext | marimo | | --- | --- | | Jupyter notebooks are stored as JSON by default, making them difficult to meaningfully version with git. Use Jupytext to pair and synchronize jupyter notebooks with text representations for smaller git diffs. | Notebooks are already in `.py` format, making them git-friendly by default. Small changes to the notebook are guaranteed to yield small diffs. | Markdown and Code Cells[¶](#markdown-and-code-cells "Permanent link") --------------------------------------------------------------------- | Jupytext | marimo | | --- | --- | | Uses special markers or formats to distinguish cell types. Magical syntax is required. | Uses `mo.md("...")` for Markdown content, and interpolate Python values with `mo.md(f"...")`; no magical syntax. | Deployment[¶](#deployment "Permanent link") ------------------------------------------- | Jupytext | marimo | | --- | --- | | Requires migrating to other libraries like Voila or Streamlit for deployment. | Can be deployed as interactive web apps with `marimo run`. | Papermill - marimo https://docs.marimo.io/guides/coming_from/papermill/ Coming from Papermill[¶](#coming-from-papermill "Permanent link") ----------------------------------------------------------------- marimo provides built-in support for parametrizing and executing marimo notebooks. If you're familiar with Papermill, this guide will help you understand how to achieve similar functionality using marimo's features. Parameterizing Notebooks[¶](#parameterizing-notebooks "Permanent link") ----------------------------------------------------------------------- **Papermill** Papermill allows you to parameterize Jupyter notebooks by defining a "parameters" cell and injecting values at runtime. **marimo** marimo offers two main ways to parameterize notebooks: 1. **Command Line Arguments**: Use [`mo.cli_args`](https://docs.marimo.io/api/cli_args/) to access command-line arguments passed to your notebook. `[](#__codelineno-0-1)import marimo as mo [](#__codelineno-0-2)[](#__codelineno-0-3)# Access CLI args [](#__codelineno-0-4)args = mo.cli_args() [](#__codelineno-0-5)param1 = args.get("param1", "default_value")` Run your notebook as a script with: `[](#__codelineno-1-1)python notebook.py -- --param1 value1` Run your notebook as an app with: `[](#__codelineno-2-1)marimo run notebook.py -- --param1 value1` 2. **Query Parameters**: For web apps, use `mo.query_params` to access URL query parameters. `[](#__codelineno-3-1)import marimo as mo [](#__codelineno-3-2)[](#__codelineno-3-3)# Access query params [](#__codelineno-3-4)params = mo.query_params() [](#__codelineno-3-5)param1 = params.get("param1", "default_value")` Access your app with: Then visit: `[](#__codelineno-5-1)http://your-app-url/?param1=value1` Executing Notebooks[¶](#executing-notebooks "Permanent link") ------------------------------------------------------------- **Papermill** Papermill allows you to execute notebooks programmatically and pass parameters. **marimo** marimo notebooks are pure Python files, making them easy to execute programmatically. 1. **Running a named cell**: After naming a cell in your file, you can run it using the [cell execution API](https://docs.marimo.io/api/cell/#marimo.Cell.run). `[](#__codelineno-6-1)from my_notebook import my_cell [](#__codelineno-6-2)[](#__codelineno-6-3)# last_expression is the visual output of the cell [](#__codelineno-6-4)# definitions is a dictionary of the variables defined by the cell [](#__codelineno-6-5)last_expression, definitions = my_cell.run()` This API also allows for parametrizing the inputs to the cell; to learn more, make sure to checkout [the example](https://docs.marimo.io/api/cell/#marimo.Cell.run) in our API reference. 2. **Using subprocess**: `[](#__codelineno-7-1)import subprocess [](#__codelineno-7-2)[](#__codelineno-7-3)subprocess.run(["python", "notebook.py", "--", "--param1", "value1"])` Storing or Sharing Artifacts[¶](#storing-or-sharing-artifacts "Permanent link") ------------------------------------------------------------------------------- **Papermill** Papermill can store executed notebooks with output. **marimo** marimo offers several options for storing and sharing outputs: 1. **Export to HTML**: `[](#__codelineno-8-1)marimo export html notebook.py -o notebook.html -- -arg1 foo --arg2 bar` 2. **Deploy as Web App**: 3. **Auto-export HTML**: You can configure marimo to automatically export to HTML during the editing process. This is configured in the marimo application settings directly in the editor. This way, after changes are made to your notebook, an HTML snapshot is generated, and placed in a `.marimo/` directory in the same location as your notebook. Workflow Integration[¶](#workflow-integration "Permanent link") --------------------------------------------------------------- **Papermill** Papermill is often used in data pipelines and workflow systems. **marimo** marimo notebooks can be easily integrated into workflows: 1. **As Python Scripts**: marimo notebooks are Python files, so they can be executed directly in most workflow systems. See [our examples](https://github.com/marimo-team/marimo/tree/main/examples) for integrating with popular tools. 2. **Programmatic Execution**: Importing notebook as Python modules or executing via subprocess allows for chaining together multiple notebooks in a workflow. Extending marimo - marimo https://docs.marimo.io/guides/integrating_with_marimo/ Integrating with marimo[¶](#integrating-with-marimo "Permanent link") --------------------------------------------------------------------- These guides will help you integrate your objects with marimo and hook into marimo's reactive execution engine for UI plugins. Still need help? Reach out to us on [Discord](https://marimo.io/discord?ref=docs) or [GitHub issues](https://github.com/marimo-team/marimo/issues). Checking if running in a marimo notebook You can check if Python is running in a marimo notebook with [`mo.running_in_notebook`](https://docs.marimo.io/api/miscellaneous/#marimo.running_in_notebook). This can be helpful when developing library code that integrates with marimo. | Guide | Description | | --- | --- | | [Displaying Objects](https://docs.marimo.io/guides/integrating_with_marimo/displaying_objects/) | Richly display objects by hooking into marimo's media viewer | | [Custom UI Plugins](https://docs.marimo.io/guides/integrating_with_marimo/custom_ui_plugins/) | Build custom UI plugins that hook into marimo's reactive execution engine | Streamlit - marimo https://docs.marimo.io/guides/coming_from/streamlit/ Coming from Streamlit[¶](#coming-from-streamlit "Permanent link") ----------------------------------------------------------------- If you're familiar with Streamlit and looking to transition to marimo, read on. The biggest difference between Streamlit and marimo is that Streamlit can only be used for data apps, whereas marimo is a notebook-first programming environment that makes it effortless to run notebooks as apps. In addition, marimo is much more performant than streamlit. Key Differences[¶](#key-differences "Permanent link") ----------------------------------------------------- 1. **Notebook vs. App Framework**: - marimo is primarily a reactive notebook environment, while Streamlit is an app framework. - marimo notebooks can be run as apps -- often with better performance than streamlit apps -- but they're designed with a notebook-first approach. - When creating streamlit apps, it is common to first prototype them as Jupyter notebooks, then migrate and refactor them into streamlit apps. With marimo, every notebook is automatically an app; there's no migration step needed. 2. **Performance.** - marimo uses a reactive execution model that, on interaction or code change, runs the minimal subset of notebook code needed to keep your notebook up-to-date. - Streamlit reruns the entire script on each interaction, which frequently causes performance issues. 3. **File Format**: * marimo notebooks and Streamlit apps are pure Python files (.py). * marimo's structure allows for more fine-grained reactivity. * Unlike streamlit files, marimo files can be executed as Python scripts from the command-line, and can be imported and used as a module by other Python programs. For example, other programs can [reuse cells](https://docs.marimo.io/api/cell/#marimo.Cell.run) from a marimo notebook. 4. **UI Elements**: * Both offer UI elements like sliders, text fields, and tables. * In streamlit, creating a UI element automatically outputs it to the display. -In marimo, the creation of a UI element is separated from its display, meaning that you can easily create custom layouts and higher-order elements, and even emit the same UI element twice. * marimo support the [anywidget](https://anywidget.dev/) spec for custom UI components, letting you reuse widgets that were originally developed for the Jupyter ecosystem, * streamlit has its own system for creating custom components. 5. **Built-in Editor**: * marimo includes a [built-in editor](https://docs.marimo.io/guides/editor_features/) for notebooks, designed specifically for working with data. * Streamlit relies on external editors. * Both approaches have their pros and cons. 6. **Working with data.**: * marimo's notebook environment allows for iterative and interactive development and exploration, letting it serve as your daily driver for working with data. marimo even has native support for [SQL](https://docs.marimo.io/guides/working_with_data/sql/). * Streamlit is exclusively used for building standalone data apps. Common Streamlit Features in marimo[¶](#common-streamlit-features-in-marimo "Permanent link") --------------------------------------------------------------------------------------------- ### 1\. Displaying text[¶](#1-displaying-text "Permanent link") Streamlit: `[](#__codelineno-0-1)import streamlit as st [](#__codelineno-0-2)st.markdown( [](#__codelineno-0-3) """ [](#__codelineno-0-4) # Greetings [](#__codelineno-0-5) Hello world [](#__codelineno-0-6) """ [](#__codelineno-0-7))` marimo: `[](#__codelineno-1-1)import marimo as mo [](#__codelineno-1-2)mo.md( [](#__codelineno-1-3) """ [](#__codelineno-1-4) # Greetings [](#__codelineno-1-5) Hello world [](#__codelineno-1-6) """ [](#__codelineno-1-7))` ### 2\. Displaying Data[¶](#2-displaying-data "Permanent link") Streamlit: marimo: `[](#__codelineno-3-1)df # Last expression in a cell is automatically displayed` ### 3\. Input Widgets[¶](#3-input-widgets "Permanent link") Streamlit: `[](#__codelineno-4-1)age = st.slider("How old are you?", 0, 130, 25)` marimo: `[](#__codelineno-5-1)age = mo.ui.slider(label="How old are you?", start=0, stop=130, value=25) [](#__codelineno-5-2)mo.md(f"One more question: {age}") # marimo can achieve more advanced composition` ### 4\. Buttons[¶](#4-buttons "Permanent link") Streamlit: `[](#__codelineno-6-1)if st.button("Click me"): [](#__codelineno-6-2) st.write("Button clicked!")` marimo: `[](#__codelineno-7-1)button = mo.ui.run_button("Click me")` `[](#__codelineno-8-1)# In another cell [](#__codelineno-8-2)if button.value: [](#__codelineno-8-3) mo.output.replace(mo.md("Button clicked!"))` `[](#__codelineno-9-1)# Or [](#__codelineno-9-2)mo.md("Button clicked!") if button.value else None` ### 5\. Layouts[¶](#5-layouts "Permanent link") Streamlit: `[](#__codelineno-10-1)col1, col2 = st.columns(2) [](#__codelineno-10-2)with col1: [](#__codelineno-10-3) st.write("Column 1") [](#__codelineno-10-4)with col2: [](#__codelineno-10-5) st.write("Column 2")` marimo: `[](#__codelineno-11-1)mo.hstack([ [](#__codelineno-11-2) mo.md("Column 1"), [](#__codelineno-11-3) mo.md("Column 2") [](#__codelineno-11-4)])` ### 6\. Advanced Layouts (tabs, accordions)[¶](#6-advanced-layouts-tabs-accordions "Permanent link") Streamlit: `[](#__codelineno-12-1)with st.expander("Expand me"): [](#__codelineno-12-2) st.write("Hello from the expander!")` marimo: `[](#__codelineno-13-1)mo.accordion({"Expand me": "Hello from the expander!"})` marimo's unique approach to composition allows for more flexible layouts with unlimited nesting. ### 6\. Plotting[¶](#6-plotting "Permanent link") Streamlit: `[](#__codelineno-14-1)import matplotlib.pyplot as plt [](#__codelineno-14-2)[](#__codelineno-14-3)fig, ax = plt.subplots() [](#__codelineno-14-4)ax.plot([1, 2, 3, 4]) [](#__codelineno-14-5)st.pyplot(fig)` marimo: `[](#__codelineno-15-1)import matplotlib.pyplot as plt [](#__codelineno-15-2)[](#__codelineno-15-3)plt.plot([1, 2, 3, 4]) [](#__codelineno-15-4)plt.gca() # Last expression is displayed` ### 7\. Caching[¶](#7-caching "Permanent link") Streamlit: `[](#__codelineno-16-1)@st.cache_data [](#__codelineno-16-2)def expensive_computation(args): [](#__codelineno-16-3) # ...` marimo: `[](#__codelineno-17-1)@functools.cache [](#__codelineno-17-2)def expensive_computation(args): [](#__codelineno-17-3) # ...` ### 8\. Session State[¶](#8-session-state "Permanent link") Streamlit uses `st.session_state` for persisting data. In marimo, you can use regular Python variables, as the notebook maintains consistent state for cells that are not re-executed. ### 9\. Running as an App[¶](#9-running-as-an-app "Permanent link") Streamlit: `[](#__codelineno-18-1)streamlit run your_app.py` marimo: `[](#__codelineno-19-1)marimo run your_notebook.py` Key Concepts to Remember[¶](#key-concepts-to-remember "Permanent link") ----------------------------------------------------------------------- 1. In marimo, cells are automatically re-executed when their dependencies change. But only the affected cells are re-executed, making it far more efficient than a naively written streamlit program. 2. UI elements in marimo are typically assigned to variables and their values accessed via the `value` attribute. 3. marimo's `mo.md()` function is versatile and can include both text and UI elements with f-strings. 4. marimo's notebook-first approach allows it to be used for all kinds of data work, including exploratory data analysis, data engineering, machine learning experimentation and model training, library documentation and examples, and more. Custom UI plugins - marimo https://docs.marimo.io/guides/integrating_with_marimo/custom_ui_plugins/ Build custom UI plugins that hook into marimo’s reactive execution engine by using [anywidget](https://anywidget.dev/). [See our AnyWidget API docs](https://docs.marimo.io/api/inputs/anywidget/) for more information. Best practices - marimo https://docs.marimo.io/guides/best_practices/ Here are best practices for writing marimo notebooks. **Use global variables sparingly.** Keep the number of global variables in your program small to avoid name collisions. If you have intermediate variables, encapsulate them in functions or prefix them with an underscore (`_tmp = ...`) to make them local to a cell. **Use descriptive names.** Use descriptive variable names, especially for global variables. This will help you minimize name clashes, and will also result in better code. **Use functions.** Encapsulate logic into functions to avoid polluting the global namespace with temporary or intermediate variables, and to avoid code duplication. **Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to stop execution.** Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to stop a cell from running when a condition is true; this is helpful when working with expensive notebooks. For example, prevent a cell from running until a button is clicked using [`mo.ui.run_button`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) and [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop). Expensive notebooks For more tips on working with expensive notebooks, see the associated [guide](https://docs.marimo.io/guides/expensive_notebooks/). **Use Python modules.** If your notebook gets too long, split complex logic into helper Python modules and import them into your notebook. Use marimo's built-in [module reloading](https://docs.marimo.io/guides/configuration/runtime_configuration/#on-module-change) to automatically bring changes from your modules into your notebook. **Minimize mutations.** marimo does not track mutations to objects. Try to only mutate an object in the cell that creates it, or create new objects instead of mutating existing ones. Example _Don't_ split up declarations and mutations over multiple cells. For example, _don't do this:_ Instead, _do_ **declare and mutate in the same cell**: `[](#__codelineno-2-1)l = [1, 2, 3] [](#__codelineno-2-2)... [](#__codelineno-2-3)l.append(new_item())` or, if working in multiple cells, **declare a new variable based on the old one**: `[](#__codelineno-4-1)extended_list = l + [new_item()]` **Don't use state and `on_change` handlers.** Don't use `on_change` handlers to react to UI interactions. Instead, use marimo's built-in [reactive execution for interactive elements](https://docs.marimo.io/guides/interactivity/). **Write idempotent cells.** Write cells whose outputs and behavior are the same when given the same inputs (references); such cells are called idempotent. This will help you avoid bugs and cache expensive intermediate computations. Troubleshooting - marimo https://docs.marimo.io/guides/troubleshooting/ This guide covers common issues and unexpected behaviors you might encounter when using marimo notebooks, along with ways to debug and resolve them. If your issue isn't covered here, try checking our [FAQ](https://docs.marimo.io/faq/). Why aren't my cells running?[¶](#why-arent-my-cells-running "Permanent link") ----------------------------------------------------------------------------- If you're expecting cells to run in response to changes in other cells, but they're not, consider the following: ### Check for mutations[¶](#check-for-mutations "Permanent link") marimo doesn't track mutations to objects. If you're modifying an object in one cell and expecting another cell to react, this won't work as expected. Instead of mutating objects across cells, try creating new objects or performing all mutations within the same cell. [Read more about reactivity](https://docs.marimo.io/guides/reactivity/). ### Verify cell connections[¶](#verify-cell-connections "Permanent link") Use the Dependency Panel or Variable Panel to check if your cells are actually connected as you expect. 1. Open the Dependency Panel (graph icon) or Variable Panel (variable icon) in the left sidebar. 2. Look for arrows connecting your cells or check which cells are listed as using each variable. 3. If connections are missing, review your variable usage to ensure cells are properly referencing each other. Dependency graph showing cell connections. Why is my cell running unexpectedly?[¶](#why-is-my-cell-running-unexpectedly "Permanent link") ---------------------------------------------------------------------------------------------- If a cell is running more often than you anticipate: ### Check cell dependencies[¶](#check-cell-dependencies "Permanent link") Use the Dependency Panel or Variable Panel to see what's triggering your cell: 1. Open the Dependency Panel or Variable Panel. 2. Locate your cell and examine its incoming connections. 3. You might find unexpected dependencies that are causing the cell to run. ### Understand global vs local variables vs functions args[¶](#understand-global-vs-local-variables-vs-functions-args "Permanent link") Ensure you're not inadvertently using a global variables when intending to use a local variable or function argument: 1. Check for any variables used in your cell that aren't defined within it. 2. Consider using local variables (prefixed with `_`) for values that shouldn't be consumed by other cells. Why is my UI element's value being reset?[¶](#why-is-my-ui-elements-value-being-reset "Permanent link") ------------------------------------------------------------------------------------------------------- If a UI element's value keeps resetting: ### Check that cell defining the UI element isn't rerunning[¶](#check-that-cell-defining-the-ui-element-isnt-rerunning "Permanent link") If the cell defining the UI element reruns, it will reset the element's value to its initial `value` argument. You may be able to avoid this by splitting the UI element definition into a separate cell. ### Use state for persistence[¶](#use-state-for-persistence "Permanent link") If you need to maintain UI element values across cell runs, consider using `mo.state`: `[](#__codelineno-0-1)# Declare state in a separate cell [](#__codelineno-0-2)get_value, set_value = mo.state(initial_value)` `[](#__codelineno-1-1)element = mo.ui.slider(0, 10, value=get_value(), on_change=set_value)` This way, the value persists even if the cell defining the element reruns. How can I force one cell to run after another?[¶](#how-can-i-force-one-cell-to-run-after-another "Permanent link") ------------------------------------------------------------------------------------------------------------------ If you need to ensure a specific execution order: ### Use explicit dependencies[¶](#use-explicit-dependencies "Permanent link") Create an explicit dependency by using a variable from the first cell in the second: `[](#__codelineno-2-1)# Cell 1 [](#__codelineno-2-2)result = some_computation()` `[](#__codelineno-3-1)# Cell 2 [](#__codelineno-3-2)_ = result # This creates a dependency on Cell 1 [](#__codelineno-3-3)further_computation()` ### Consider refactoring[¶](#consider-refactoring "Permanent link") If you find yourself needing to force execution order often, it might be a sign that your notebook structure could be improved: 1. Try to organize your cells so that natural data flow creates the desired order. 2. Consider combining related operations into single cells where appropriate. General debugging tips[¶](#general-debugging-tips "Permanent link") ------------------------------------------------------------------- * Use the Variables Panel to inspect variable values and see where they're defined and used. * Add print statements or use `mo.md()` to output debug information in cell outputs. * Temporarily disable cells to isolate issues. * Use the "Lazy" runtime configuration to see which cells are being marked as stale without automatically running them. Remember, marimo's reactivity is based on global variable definitions and references, and mutations to objects aren't tracked. Keeping this in mind can help you understand and debug unexpected behaviors in your notebooks. Why is the notebook returning 404s on the web assets?[¶](#why-is-the-notebook-returning-404s-on-the-web-assets "Permanent link") -------------------------------------------------------------------------------------------------------------------------------- If you're seeing 404 errors for web assets like JS or CSS files, it may be due to symlink settings or proxy settings. ### Check symlink settings[¶](#check-symlink-settings "Permanent link") If you are using `bazel` or `uv`'s [**link-mode: symlink**](https://docs.astral.sh/uv/reference/settings/#link-mode), you may need to adjust your symlink settings to ensure that web assets are correctly found. By default marimo does not follow symlinks, so you may need to turn this setting on. Locate your `marimo.toml` configuration file with `marimo config show`, and edit the `follow_symlink` flag: marimo.toml `[](#__codelineno-4-1)[server] [](#__codelineno-4-2)follow_symlink = true` ### Check proxy settings[¶](#check-proxy-settings "Permanent link") If you are using a proxy server, you need to include the `--proxy` flag when running marimo. The proxy will default to port 80 if no port is specified. For example, if your proxy is `example.com` and it uses port 8080, you would run: `[](#__codelineno-5-1)marimo edit --proxy example.com:8080 [](#__codelineno-5-2)# or [](#__codelineno-5-3)marimo run --proxy example.com:8080` Dangerously set state - marimo https://docs.marimo.io/guides/state/ Reactive state[¶](#reactive-state "Permanent link") --------------------------------------------------- Advanced topic! This guide covers reactive state (`mo.state`), an advanced topic. **You likely don't need `mo.state`**. UI elements already have built-in state, their associated value, which you can access with their `value` attribute. For example, `mo.ui.slider()` has a value that is its current position on an interval, while `mo.ui.button()` has a value that can be configured to count the number of times it has been clicked, or to toggle between `True` and `False`. Additionally, interacting with UI elements bound to global variables [automatically executes cells](https://docs.marimo.io/guides/interactivity/) that reference those variables, letting you react to changes by just reading their `value` attributes. **This functional paradigm is the preferred way of reacting to UI interactions in marimo.** **Chances are, the reactive execution built into UI elements will suffice.** (For example, [you don't need reactive state to handle a button click](https://docs.marimo.io/recipes/#working-with-buttons).) That said, here are some signs you might need `mo.state`: * you need to maintain historical state related to a UI element that can't be computed from its built-in `value` (_e.g._, all values the user has ever input into a form) * you need to synchronize two different UI elements (_e.g._, so that interacting with either one controls the other) * you need to introduce cycles across cells **In over 99% of cases, you don't need and shouldn't use `mo.state`.** This feature can introduce hard-to-find bugs. You can build powerful, interactive notebooks and apps using just `mo.ui` and reactivity. But sometimes, you might want interactions to mutate state: * You're building a checklist, and you want to maintain a list of action items, even as you add and remove some items. A proof-of-concept TODO list made using state. * You want to tie two different UI elements so that updating **either** one updates the other. Use state to tie two elements together in a cycle. Use reactive execution for uni-directional flow If you just want the value of a single element to update another element, then **you shouldn't use `mo.state`**. Instead, use marimo's built-in reactive execution --- see the [interactivity guide](https://docs.marimo.io/guides/interactivity/). For cases like these, marimo provides the function [`mo.state()`](https://docs.marimo.io/api/state/), which creates a state object and returns a getter and setter function. When you call the setter function in one cell, all other cells that reference the getter function **via a global variable** are automatically run (similar to UI elements). State and UI elements are similar State is analogous to UI elements. When you interact with a UI element, all cells that reference that element via a global variable run automatically with the new value. In the same way, when you update state via the setter, all other cells that reference the getter via a global variable run automatically with the new value. [`mo.state()`](https://docs.marimo.io/api/state/) takes an initial state value as its argument, creates a state object, and returns * a getter function for reading the state * a setter function for updating the state For exaxmple, `[](#__codelineno-0-1)get_counter, set_counter = mo.state(0)` Assign state to global variables! When using `mo.state()`, **you must assign the state getter to a global variable**. This is similar to UI elements work. Reading state[¶](#reading-state "Permanent link") ------------------------------------------------- Access the state's latest value via the getter: Updating state[¶](#updating-state "Permanent link") --------------------------------------------------- You can update a state's value by calling its setter function with a new value. For example, To update the state based on its current value, pass a function that takes the current state value as an argument and returns a new value `[](#__codelineno-3-1)set_counter(lambda count: count + 1)` A single rule determines what happens next: State reactivity rule When a state setter function is called in one cell, marimo automatically runs all _other_ cells that reference any **global** variables assigned to the state getter. This rule has some important aspects: 1. Only cells that read the state getter via a global variable will be run. 2. The cell that called the setter won't be re-run, even if it references the getter. This restriction helps prevent against bugs that could otherwise arise. To lift this restriction, and allow the caller cell to be re-run, create your state with `mo.state(value, allow_self_loops=True)`. Notice how similar this rule is to the reactivity rule for UI element interactions. Using state with UI elements[¶](#using-state-with-ui-elements "Permanent link") ------------------------------------------------------------------------------- Every UI element takes an optional `on_change` callback, a function that takes the new value of the element and does anything with it. You can use the setter function in an `on_change` callback to mutate state. Use state sparingly You can get far using just `mo.ui`, without state, because marimo automatically runs cells that reference UI elements on interaction (see the [interactivity guide](https://docs.marimo.io/guides/interactivity/)). Only use `on_change` callbacks as a last resort! ### Example: counter[¶](#example-counter "Permanent link") The next few cells implement a counter controlled by two buttons. This particular example could be implemented without state (try it!), but the implementation using state is simpler. `[](#__codelineno-5-1)get_counter, set_counter = mo.state(0) [](#__codelineno-5-2)[](#__codelineno-5-3)increment = mo.ui.button( [](#__codelineno-5-4) label="increment", [](#__codelineno-5-5) on_change=lambda _: set_counter(lambda v: v + 1), [](#__codelineno-5-6)) [](#__codelineno-5-7)[](#__codelineno-5-8)decrement = mo.ui.button( [](#__codelineno-5-9) label="decrement", [](#__codelineno-5-10) on_change=lambda _: set_counter(lambda v: v - 1), [](#__codelineno-5-11)) [](#__codelineno-5-12)[](#__codelineno-5-13)mo.hstack([increment, decrement], justify="center")` `[](#__codelineno-6-1)mo.md( [](#__codelineno-6-2) f""" [](#__codelineno-6-3) The counter's current value is **{get_counter()}**! [](#__codelineno-6-4) [](#__codelineno-6-5) This cell runs automatically on button click, even though it [](#__codelineno-6-6) doesn't reference either button. [](#__codelineno-6-7) """ [](#__codelineno-6-8))` ### Example: tied elements[¶](#example-tied-elements "Permanent link") This example shows how to tie two different UI elements so that each one's value depends on the other. This is impossible to do without `mo.state`. `[](#__codelineno-8-1)get_x, set_x = mo.state(0)` `[](#__codelineno-9-1)x = mo.ui.slider( [](#__codelineno-9-2) 0, 10, value=get_x(), on_change=set_x, label="$x$:" [](#__codelineno-9-3))` `[](#__codelineno-10-1)x_plus_one = mo.ui.number( [](#__codelineno-10-2) 1, [](#__codelineno-10-3) 11, [](#__codelineno-10-4) value=get_x() + 1, [](#__codelineno-10-5) on_change=lambda v: set_x_state(v - 1), [](#__codelineno-10-6) label="$x + 1$:", [](#__codelineno-10-7))` Create tied UI elements in separate cells Notice that we created the slider and number elements in different cells. When tying elements, this is necessary, because calling a setter in a cell queues all _other_ cells reading the state to run, not including the one that just called the setter. Cycles at runtime You can use state to introduce cycles across cells at runtime. This lets you tie multiple UI elements together, for example. Just be careful not to introduce an infinite loop! marimo programs are statically parsed into directed acyclic graphs (DAGs) involving cells, and state doesn't change that. Think of state setters as hooking into the DAG: at runtime, when they're invoked (and only when they're invoked), they trigger additional computation. ### Example: todo list[¶](#example-todo-list "Permanent link") The next few cells use state to create a todo list. `[](#__codelineno-12-1)import marimo as mo [](#__codelineno-12-2)from dataclasses import dataclass` `[](#__codelineno-13-1)@dataclass [](#__codelineno-13-2)class Task: [](#__codelineno-13-3) name: str [](#__codelineno-13-4) done: bool = False [](#__codelineno-13-5) [](#__codelineno-13-6)[](#__codelineno-13-7)get_tasks, set_tasks = mo.state([]) [](#__codelineno-13-8)task_added, set_task_added = mo.state(False)` `[](#__codelineno-14-1)# Refresh the text box whenever a task is added [](#__codelineno-14-2)task_added [](#__codelineno-14-3)[](#__codelineno-14-4)task_entry_box = mo.ui.text(placeholder="a task ...")` `[](#__codelineno-15-1)def add_task(): [](#__codelineno-15-2) if task_entry_box.value: [](#__codelineno-15-3) set_tasks(lambda v: v + [Task(task_entry_box.value)]) [](#__codelineno-15-4) set_task_added(True) [](#__codelineno-15-5)[](#__codelineno-15-6)def clear_tasks(): [](#__codelineno-15-7) set_tasks(lambda v: [task for task in v if not task.done]) [](#__codelineno-15-8)[](#__codelineno-15-9)add_task_button = mo.ui.button( [](#__codelineno-15-10) label="add task", [](#__codelineno-15-11) on_change=lambda _: add_task(), [](#__codelineno-15-12)) [](#__codelineno-15-13)[](#__codelineno-15-14)clear_tasks_button = mo.ui.button( [](#__codelineno-15-15) label="clear completed tasks", [](#__codelineno-15-16) on_change=lambda _: clear_tasks() [](#__codelineno-15-17))` `[](#__codelineno-16-1)task_list = mo.ui.array( [](#__codelineno-16-2) [mo.ui.checkbox(value=task.done, label=task.name) for task in get_tasks()], [](#__codelineno-16-3) label="tasks", [](#__codelineno-16-4) on_change=lambda v: set_tasks( [](#__codelineno-16-5) lambda tasks: [Task(task.name, done=v[i]) for i, task in enumerate(tasks)] [](#__codelineno-16-6) ), [](#__codelineno-16-7))` `[](#__codelineno-17-1)mo.hstack( [](#__codelineno-17-2) [task_entry_box, add_task_button, clear_tasks_button], justify="start" [](#__codelineno-17-3))` Displaying objects - marimo https://docs.marimo.io/guides/integrating_with_marimo/displaying_objects/ Richly display objects[¶](#richly-display-objects "Permanent link") ------------------------------------------------------------------- marimo has built-in rich representations of many objects, including native Python objects like lists and dicts as well as marimo objects like [UI elements](https://docs.marimo.io/guides/interactivity/) and libraries, including matplotlib, seaborn, Plotly, altair pandas, and more. These rich representations are displayed for the last expression of a cell, or when using [`mo.output.append`](https://docs.marimo.io/api/outputs/#marimo.output.append). You can register rich displays with marimo for your own objects. You have three options: 1. Implement a `_display_()` method 2. Implement a `_mime_()` method 3. Implement an IPython-style `_repr_*_()` method If you can't modify the object, you can also add a formatter to the marimo library (option 4). The return value of these methods determines what is shown. `_display_` has the highest precedence, then built-in formatters, then `_mime_`, then `IPython` style `_repr_*_` methods. Option 1: Implement a `_display_()` method[¶](#option-1-implement-a-_display_-method "Permanent link") ------------------------------------------------------------------------------------------------------ If an object implements a `_display_()`, marimo will use its return value to visualize the object as an output. For example: `[](#__codelineno-0-1)class Dice: [](#__codelineno-0-2) def _display_(self): [](#__codelineno-0-3) import random [](#__codelineno-0-4) [](#__codelineno-0-5) return f"You rolled {random.randint(0, 7)}"` The return value of `_display_` can be any Python object, for example a a matplotlib plot, a dataframe, a list, `mo.Html`, or a `mo.ui` element, and marimo will attempt to display it. In addition to being the most convenient way do define a custom display in marimo (in terms of syntax), it is also helpful for library developers: this option lets you make an object showable in marimo without adding marimo as a dependency to your project. However, if you need to display an object that marimo does not know how to render (for example, maybe you are building a new plotting library), then you need to consider of the other options below. Option 2: Implement an IPython `_repr_*_()` method[¶](#option-2-implement-an-ipython-_repr__-method "Permanent link") --------------------------------------------------------------------------------------------------------------------- marimo can render objects that implement [IPython's `_repr_*_()` protocol](https://ipython.readthedocs.io/en/stable/config/integrating.html#custom-methods) for rich display. Here is an example of implementing `_repr_html_`, borrowed from IPython's documentation: `[](#__codelineno-1-1)class Shout: [](#__codelineno-1-2) def __init__(self, text): [](#__codelineno-1-3) self.text = text [](#__codelineno-1-4) [](#__codelineno-1-5) def _repr_html_(self): [](#__codelineno-1-6) return "

" + self.text + "

"` We support the following methods: * `_repr_html_` * `_repr_mimebundle_` * `_repr_svg_` * `_repr_json_` * `_repr_png_` * `_repr_jpeg_` * `_repr_markdown_` * `_repr_latex_` * `_repr_text_` Option 3: Implement a `_mime_` method[¶](#option-3-implement-a-_mime_-method "Permanent link") ---------------------------------------------------------------------------------------------- When displaying an object, marimo's media viewer checks for the presence of a method called `_mime_`. This method should take no arguments and return a tuple of two strings, the [mime type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) and data to be displayed as a string. **Examples.** Option 4: Add a formatter to the marimo repo[¶](#option-4-add-a-formatter-to-the-marimo-repo "Permanent link") -------------------------------------------------------------------------------------------------------------- The recommended way to render rich displays of objects in marimo is to implement `_display_` if possible, otherwise either the IPython `_repr_*_()_` protocol or marimo's `_mime_()` protocol. If you are a a user of a library that does not render properly in marimo, consider asking the library maintainers to implement one of these protocols. If it is not possible to implement a renderer protocol on the type you want displayed, we will consider contributions to add formatters to the marimo codebase. [Look at our codebase for examples](https://github.com/marimo-team/marimo/tree/main/marimo/_output/formatters), then open a pull request.
Markdown - marimo https://docs.marimo.io/api/markdown/ Write markdown with `mo.md`; make your markdown **interactive**, **dynamic**, and **visually rich** by interpolating arbitrary Python values and marimo elements. marimo.md [¶](#marimo.md "Permanent link") ------------------------------------------ Write markdown This function takes a string of markdown as input and returns an Html object. Output the object as the last expression of a cell to render the markdown in your app. **Interpolation.** You can interpolate Python values into your markdown strings, for example using f-strings. Html objects and UI elements can be directly interpolated. For example: `[](#__codelineno-0-1)text_input = mo.ui.text() [](#__codelineno-0-2)md(f"Enter some text: {text_input}")` For other objects, like plots, use marimo's `as_html` method to embed them in markdown: `[](#__codelineno-1-1)import matplotlib.pyplot as plt [](#__codelineno-1-2)[](#__codelineno-1-3)plt.plot([1, 2]) [](#__codelineno-1-4)axis = plt.gca() [](#__codelineno-1-5)md(f"Here's a plot: {mo.as_html(axis)}")` **LaTeX.** Enclose LaTeX in single '$' signs for inline math, and double '$$' for display math or square brackets for display math. (Use raw strings, prefixed with an "r", to use single backslashes.) For example: `[](#__codelineno-2-1)mo.md( [](#__codelineno-2-2) r''' [](#__codelineno-2-3) The exponential function $f(x) = e^x$ can be represented as [](#__codelineno-2-4) [](#__codelineno-2-5) \[ [](#__codelineno-2-6) f(x) = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \ldots. [](#__codelineno-2-7) \] [](#__codelineno-2-8) ''' [](#__codelineno-2-9))` renders: The exponential function \\(f(x) = e^x\\) can be represented as \\\[ f(x) = 1 + x + \\frac{x^2}{2!} + \\frac{x^3}{3!} + \\ldots. \\\] **Args**: * `text`: a string of markdown **Returns**: * An `Html` object. Icons[¶](#icons "Permanent link") --------------------------------- We support rendering icons from [Iconify](https://icon-sets.iconify.design/). When is inside markdown, you can render an icon with the syntax `::iconset:icon-name::` for example `::lucide:rocket::` or `::mdi:home::`. This is useful for quickly adding an icon, however, it does not support advanced configuration such as size, color, and rotation. For other advanced features, use `mo.icon()` such as `mo.icon("lucide:rocket", size=20)` or `mo.icon("mdi:home", color="blue")`. marimo.icon [¶](#marimo.icon "Permanent link") ---------------------------------------------- `[](#__codelineno-0-1)icon( [](#__codelineno-0-2) icon_name: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) *, [](#__codelineno-0-4) size: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-5) color: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-6) inline: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-7) flip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-8) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-9) "horizontal", "vertical", "horizontal,vertical" [](#__codelineno-0-10) ] [](#__codelineno-0-11) ] = None, [](#__codelineno-0-12) rotate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-13) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["90deg", "180deg", "270deg"] [](#__codelineno-0-14) ] = None, [](#__codelineno-0-15) style: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-16) [dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), None]] [](#__codelineno-0-17) ] = None [](#__codelineno-0-18)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Displays an icon. These icons are referenced by name from the [Iconify](https://iconify.design/) library. They are named in the format `icon-set:icon-name`, e.g. `lucide:leaf`. Icons are lazily loaded from a CDN, so they will not be loaded when not connected to the internet. These can be used in buttons, tabs, and other UI elements. Examples: `[](#__codelineno-0-1)mo.md(f"# {mo.icon('lucide:leaf')} Leaf") [](#__codelineno-0-2)[](#__codelineno-0-3)mo.ui.button( [](#__codelineno-0-4) label=f"{mo.icon('lucide:rocket')} Submit", [](#__codelineno-0-5))` | PARAMETER | DESCRIPTION | | --- | --- | | `icon_name` | the name of the icon to display **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | `size` | the size of the icon in pixels **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)]` **DEFAULT:** `None` | | `color` | the color of the icon **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `inline` | whether to display the icon inline or as a block element **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `flip` | whether to flip the icon horizontally, vertically, or both **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['horizontal', 'vertical', 'horizontal,vertical']]` **DEFAULT:** `None` | | `rotate` | whether to rotate the icon 90, 180, or 270 degrees **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['90deg', '180deg', '270deg']]` **DEFAULT:** `None` | | `style` | a dictionary of CSS styles to apply to the icon **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), None]]]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An `Html` object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | You can render a tooltip by adding the `data-tooltip` attribute to an element. `[](#__codelineno-0-1)mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3)
Hover over me
[](#__codelineno-0-4) ''' [](#__codelineno-0-5)) [](#__codelineno-0-6)mo.ui.button( [](#__codelineno-0-7) label='
Hover over me
' [](#__codelineno-0-8))` Rendering images[¶](#rendering-images "Permanent link") ------------------------------------------------------- You can render images from a local `public/` folder: `[](#__codelineno-1-1)mo.md( [](#__codelineno-1-2) ''' [](#__codelineno-1-3) [](#__codelineno-1-4) ''' [](#__codelineno-1-5))` See [Static files](https://docs.marimo.io/guides/outputs/#static-files) for information about serving images and other static assets.
Inputs - marimo https://docs.marimo.io/api/inputs/ marimo comes packaged with interactive UI elements that you can use to build powerful notebooks and apps. These elements are available in `marimo.ui`. | Element | Description | | --- | --- | | [`marimo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) | Create array inputs | | [`marimo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch) | Batch operations | | [`marimo.ui.button`](https://docs.marimo.io/api/inputs/button/#marimo.ui.button) | Create buttons | | [`marimo.ui.chat`](https://docs.marimo.io/api/inputs/chat/#marimo.ui.chat) | Create chat interfaces | | [`marimo.ui.checkbox`](https://docs.marimo.io/api/inputs/checkbox/#marimo.ui.checkbox) | Create checkboxes | | [`marimo.ui.code_editor`](https://docs.marimo.io/api/inputs/code_editor/#marimo.ui.code_editor) | Create code editors | | [`marimo.ui.dataframe`](https://docs.marimo.io/api/inputs/dataframe/#marimo.ui.dataframe) | Interactive dataframes | | [`marimo.ui.data_explorer`](https://docs.marimo.io/api/inputs/data_explorer/#marimo.ui.data_explorer) | Explore data | | [`marimo.ui.date`](https://docs.marimo.io/api/inputs/dates/#marimo.ui.date) | Date picker | | [`marimo.ui.datetime`](https://docs.marimo.io/api/inputs/dates/#marimo.ui.datetime) | Date and time picker | | [`marimo.ui.date_range`](https://docs.marimo.io/api/inputs/dates/#marimo.ui.date_range) | Date range picker | | [`marimo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) | Dictionary inputs | | [`marimo.ui.dropdown`](https://docs.marimo.io/api/inputs/dropdown/#marimo.ui.dropdown) | Create dropdowns | | [`marimo.ui.file`](https://docs.marimo.io/api/inputs/file/#marimo.ui.file) | File uploads | | [`marimo.ui.file_browser`](https://docs.marimo.io/api/inputs/file_browser/#marimo.ui.file_browser) | Browse files | | [`marimo.ui.form`](https://docs.marimo.io/api/inputs/form/#marimo.ui.form) | Create forms | | [`marimo.ui.microphone`](https://docs.marimo.io/api/inputs/microphone/#marimo.ui.microphone) | Record audio | | [`marimo.ui.multiselect`](https://docs.marimo.io/api/inputs/multiselect/#marimo.ui.multiselect) | Multiple selection | | [`marimo.ui.number`](https://docs.marimo.io/api/inputs/number/#marimo.ui.number) | Number inputs | | [`marimo.ui.radio`](https://docs.marimo.io/api/inputs/radio/#marimo.ui.radio) | Radio buttons | | [`marimo.ui.range_slider`](https://docs.marimo.io/api/inputs/range_slider/#marimo.ui.range_slider) | Range sliders | | [`marimo.ui.refresh`](https://docs.marimo.io/api/inputs/refresh/#marimo.ui.refresh) | Refresh buttons | | [`marimo.ui.run_button`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) | Run buttons | | [`marimo.ui.slider`](https://docs.marimo.io/api/inputs/slider/#marimo.ui.slider) | Create sliders | | [`marimo.ui.switch`](https://docs.marimo.io/api/inputs/switch/#marimo.ui.switch) | Toggle switches | | [`marimo.ui.tabs`](https://docs.marimo.io/api/inputs/tabs/#marimo.ui.tabs) | Tabbed interfaces | | [`marimo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table) | Interactive tables | | [`marimo.ui.text`](https://docs.marimo.io/api/inputs/text/#marimo.ui.text) | Text inputs | | [`marimo.ui.text_area`](https://docs.marimo.io/api/inputs/text_area/#marimo.ui.text_area) | Multiline text inputs | To use a UI element, assign it to a global variable and output it in a cell. When you interact with the frontend element, the Python object's `value` attribute is automatically updated, and all cells referencing that object automatically run with the element's latest value. Integrations[¶](#integrations "Permanent link") ----------------------------------------------- | Integration | Description | | --- | --- | | [`marimo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) | Interactive Altair charts | | [`marimo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) | Interactive Plotly charts | | [`marimo.mpl.interactive`](https://docs.marimo.io/api/plotting/#marimo.mpl.interactive) | Interactive Matplotlib plots | | [`marimo.ui.anywidget`](https://docs.marimo.io/api/inputs/anywidget/#marimo.ui.anywidget) | Custom widgets | AnyWidget - marimo https://docs.marimo.io/api/inputs/anywidget/ Building custom UI elements[¶](#building-custom-ui-elements "Permanent link") ----------------------------------------------------------------------------- Build custom UI plugins that hook into marimo's reactive execution engine by using [anywidget](https://anywidget.dev/). [anywidget](https://anywidget.dev/) is a Python library and specification for creating custom Jupyter-compatible widgets. marimo supports anywidget, allowing you to import anywidget widgets or create your own custom widgets and use them in your notebooks and apps. You can use anywidgets that others have built, such as [quak](https://github.com/manzt/quak) or [drawdata](https://github.com/koaning/drawdata), directly in marimo. Here is an example using `drawdata`: `[](#__codelineno-0-1)# pip install drawdata [](#__codelineno-0-2)from drawdata import ScatterWidget [](#__codelineno-0-3)[](#__codelineno-0-4)widget = mo.ui.anywidget(ScatterWidget()) [](#__codelineno-0-5)[](#__codelineno-0-6)# In another cell, you can access the widget's value [](#__codelineno-0-7)widget.value [](#__codelineno-0-8)[](#__codelineno-0-9)# You can also access the widget's specific properties [](#__codelineno-0-10)widget.data [](#__codelineno-0-11)widget.data_as_polars` For additional examples, see [our repo](https://github.com/marimo-team/marimo/tree/main/examples/third_party/anywidget). ``[](#__codelineno-1-1)import anywidget [](#__codelineno-1-2)import traitlets [](#__codelineno-1-3)import marimo as mo [](#__codelineno-1-4)[](#__codelineno-1-5)class CounterWidget(anywidget.AnyWidget): [](#__codelineno-1-6) # Widget front-end JavaScript code [](#__codelineno-1-7) _esm = """ [](#__codelineno-1-8) function render({ model, el }) { [](#__codelineno-1-9) let getCount = () => model.get("count"); [](#__codelineno-1-10) let button = document.createElement("button"); [](#__codelineno-1-11) button.innerHTML = `count is ${getCount()}`; [](#__codelineno-1-12) button.addEventListener("click", () => { [](#__codelineno-1-13) model.set("count", getCount() + 1); [](#__codelineno-1-14) model.save_changes(); [](#__codelineno-1-15) }); [](#__codelineno-1-16) model.on("change:count", () => { [](#__codelineno-1-17) button.innerHTML = `count is ${getCount()}`; [](#__codelineno-1-18) }); [](#__codelineno-1-19) el.appendChild(button); [](#__codelineno-1-20) } [](#__codelineno-1-21) export default { render }; [](#__codelineno-1-22) """ [](#__codelineno-1-23) _css = """ [](#__codelineno-1-24) button { [](#__codelineno-1-25) padding: 5px !important; [](#__codelineno-1-26) border-radius: 5px !important; [](#__codelineno-1-27) background-color: #f0f0f0 !important; [](#__codelineno-1-28) [](#__codelineno-1-29) &:hover { [](#__codelineno-1-30) background-color: lightblue !important; [](#__codelineno-1-31) color: white !important; [](#__codelineno-1-32) } [](#__codelineno-1-33) } [](#__codelineno-1-34) """ [](#__codelineno-1-35) [](#__codelineno-1-36) # Stateful property that can be accessed by JavaScript & Python [](#__codelineno-1-37) count = traitlets.Int(0).tag(sync=True) [](#__codelineno-1-38)[](#__codelineno-1-39)widget = mo.ui.anywidget(CounterWidget()) [](#__codelineno-1-40) [](#__codelineno-1-41)[](#__codelineno-1-42)# In another cell, you can access the widget's value [](#__codelineno-1-43)widget.value [](#__codelineno-1-44)[](#__codelineno-1-45)# You can also access the widget's specific properties [](#__codelineno-1-46)widget.count`` * * * `[](#__codelineno-0-1)anywidget(widget: 'AnyWidget')` Bases: `UIElement[T, T]` Create a UIElement from an AnyWidget. This proxies all the widget's attributes and methods, allowing seamless integration of AnyWidget instances with Marimo's UI system. Examples: `[](#__codelineno-0-1)from drawdata import ScatterWidget [](#__codelineno-0-2)import marimo as mo [](#__codelineno-0-3)[](#__codelineno-0-4)scatter = ScatterWidget() [](#__codelineno-0-5)scatter = mo.ui.anywidget(scatter) [](#__codelineno-0-6)[](#__codelineno-0-7)# In another cell, access its value [](#__codelineno-0-8)# This works for all widgets [](#__codelineno-0-9)scatter.value [](#__codelineno-0-10)[](#__codelineno-0-11)# Or attributes specifically on the ScatterWidget [](#__codelineno-0-12)scatter.data_as_pandas [](#__codelineno-0-13)scatter.data_as_polars` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.anywidget.value "marimo.ui.anywidget.value")` | The value of the widget's traits as a dictionary. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `[widget](#marimo.ui.anywidget.widget "marimo.ui.anywidget.widget")` | The widget being wrapped. **TYPE:** `AnyWidget` | | PARAMETER | DESCRIPTION | | --- | --- | | `widget` | The widget to wrap. **TYPE:** `AnyWidget` | ### text `property` [¶](#marimo.ui.anywidget.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.anywidget.value "Permanent link") The element's current value. ### widget `instance-attribute` [¶](#marimo.ui.anywidget.widget "Permanent link") ### batch [¶](#marimo.ui.anywidget.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.anywidget.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.anywidget.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.anywidget.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.anywidget.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.anywidget.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.anywidget.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.anywidget.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Array - marimo https://docs.marimo.io/api/inputs/array/ marimo.ui.array [¶](#marimo.ui.array "Permanent link") ------------------------------------------------------ Bases: `UIElement[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), JSONType], [Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)]]` An array of UI elements. Use an array to: - create a dynamic number of UI elements at runtime - group together logically related UI elements - keep the number of global variables in your program small Access the values of the elements using the `value` attribute of the array (`array.value`). The elements in the array can be accessed using square brackets (`array[index]`) and embedded in other marimo outputs. You can also iterate over the UI elements using the `in` operator (`for element in array`). Note: The UI elements in the array are clones of the original elements: interacting with the array will _not_ update the original elements, and vice versa. Examples: A heterogeneous collection of UI elements: `[](#__codelineno-0-1)array = mo.ui.array([mo.ui.slider(1, 10), mo.ui.text(), mo.ui.date()])` Get the values of the `slider`, `text`, and `date` elements via `array.value`: `[](#__codelineno-1-1)# array.value returns a list with the values of the elements [](#__codelineno-1-2)array.value` Access and output a UI element in the array: `[](#__codelineno-2-1)mo.md(f"This is a slider: array[0]")` Some number of UI elements, determined at runtime: `[](#__codelineno-3-1)mo.ui.array([mo.ui.slider(1, 10) for _ in range random.randint(4, 8)])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.array.value "marimo.ui.array.value")` | A list containing the values of the array's entries. **TYPE:** `[list](https://docs.python.org/3/glossary.html#term-list)` | | `[elements](#marimo.ui.array.elements "marimo.ui.array.elements")` | A list of the wrapped elements (clones of the originals). **TYPE:** `[list](https://docs.python.org/3/glossary.html#term-list)` | | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | The UI elements to include. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[UIElement]` | | `label` | A descriptive name for the array. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)]], None]]` **DEFAULT:** `None` | ### elements `property` [¶](#marimo.ui.array.elements "Permanent link") ### text `property` [¶](#marimo.ui.array.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.array.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.array.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.array.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.array.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.array.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### hstack [¶](#marimo.ui.array.hstack "Permanent link") Stack the elements horizontally. | PARAMETER | DESCRIPTION | | --- | --- | | `**kwargs` | Additional arguments passed to `marimo.hstack`. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | HTML representation of horizontally stacked elements. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | ### left [¶](#marimo.ui.array.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.array.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.array.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.array.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | ### vstack [¶](#marimo.ui.array.vstack "Permanent link") Stack the elements vertically. | PARAMETER | DESCRIPTION | | --- | --- | | `**kwargs` | Additional arguments passed to `marimo.vstack`. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | HTML representation of vertically stacked elements. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | Batch - marimo https://docs.marimo.io/api/inputs/batch/ marimo.ui.batch [¶](#marimo.ui.batch "Permanent link") ------------------------------------------------------ Bases: `_batch_base` Convert an HTML object with templated text into a UI element. A `batch` is a UI element that wraps other UI elements, and is represented by custom HTML or markdown. You can create a `batch` by calling the `batch()` method on `Html` objects. Get the value of the wrapped UI elements using the `value` attribute of the batch. Examples: In the below example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and `'birthday'` (and values equal to the values of their corresponding elements). `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` To get the value of `name` and `birthday`, use: You can also instantiate this class directly: `[](#__codelineno-2-1)markdown = mo.md( [](#__codelineno-2-2) ''' [](#__codelineno-2-3) - What's your name?: {name} [](#__codelineno-2-4) - When were you born?: {birthday} [](#__codelineno-2-5) ''' [](#__codelineno-2-6)) [](#__codelineno-2-7)batch = mo.ui.batch( [](#__codelineno-2-8) markdown, {"name": mo.ui.text(), "birthday": mo.ui.date()} [](#__codelineno-2-9))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.batch.value "marimo.ui.batch.value")` | A dict of the batched elements' values. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | `[elements](#marimo.ui.batch.elements "marimo.ui.batch.elements")` | A dict of the batched elements (clones of the originals). **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")]` | | PARAMETER | DESCRIPTION | | --- | --- | | `html` | A templated Html object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | | `elements` | The UI elements to interpolate into the HTML template. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), UIElement]` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [object](https://docs.python.org/3/glossary.html#term-object)]], None]]` **DEFAULT:** `None` | ### elements `property` [¶](#marimo.ui.batch.elements "Permanent link") ### text `property` [¶](#marimo.ui.batch.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.batch.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.batch.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.batch.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.batch.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.batch.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### get [¶](#marimo.ui.batch.get "Permanent link") `[](#__codelineno-0-1)get(key: [str](https://docs.python.org/3/library/stdtypes.html#str), default: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") | None = None) -> [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` Get a UI element by key with an optional default value. | PARAMETER | DESCRIPTION | | --- | --- | | `key` | The key to look up in the batch. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | `default` | Value to return if key is not found. Defaults to None. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") | None` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Any` | The UI element if found, otherwise the default value. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | ### items [¶](#marimo.ui.batch.items "Permanent link") Return a view of the batch's items (key-value pairs). | RETURNS | DESCRIPTION | | --- | --- | | `[ItemsView](https://docs.python.org/3/library/collections.abc.html#collections.abc.ItemsView "collections.abc.ItemsView")[[str](https://docs.python.org/3/library/stdtypes.html#str), UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]]` | ItemsView\[str, UIElement\]: A view of the batch's (key, element) pairs. | ### left [¶](#marimo.ui.batch.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.batch.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.batch.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.batch.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | ### values [¶](#marimo.ui.batch.values "Permanent link") Return a view of the batch's values (UI elements). | RETURNS | DESCRIPTION | | --- | --- | | `[ValuesView](https://docs.python.org/3/library/collections.abc.html#collections.abc.ValuesView "collections.abc.ValuesView")[UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]]` | ValuesView\[UIElement\]: A view of the batch's UI elements. | Checkbox - marimo https://docs.marimo.io/api/inputs/checkbox/ marimo.ui.checkbox [¶](#marimo.ui.checkbox "Permanent link") ------------------------------------------------------------ Bases: `UIElement[[bool](https://docs.python.org/3/library/functions.html#bool), [bool](https://docs.python.org/3/library/functions.html#bool)]` A boolean checkbox. Examples: `[](#__codelineno-0-1)checkbox = mo.ui.checkbox()` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.checkbox.value "marimo.ui.checkbox.value")` | A boolean, True if checked. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` | | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Default value, True or False. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[bool](https://docs.python.org/3/library/functions.html#bool)], None]` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.checkbox.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.checkbox.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.checkbox.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.checkbox.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.checkbox.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.checkbox.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.checkbox.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.checkbox.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.checkbox.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.checkbox.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Chat - marimo https://docs.marimo.io/api/inputs/chat/ The chat UI element provides an interactive chatbot interface for conversations. It can be customized with different models, including built-in AI models from popular providers or custom functions. marimo.ui.chat [¶](#marimo.ui.chat "Permanent link") ---------------------------------------------------- `[](#__codelineno-0-1)chat( [](#__codelineno-0-2) model: [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[ [](#__codelineno-0-3) [[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")], [ChatModelConfig](#marimo.ai.ChatModelConfig "marimo._ai.types.ChatModelConfig")], [object](https://docs.python.org/3/glossary.html#term-object) [](#__codelineno-0-4) ], [](#__codelineno-0-5) *, [](#__codelineno-0-6) prompts: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-7) on_message: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-8) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")]], None] [](#__codelineno-0-9) ] = None, [](#__codelineno-0-10) show_configuration_controls: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) config: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ChatModelConfigDict] = None, [](#__codelineno-0-12) allow_attachments: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[bool](https://docs.python.org/3/library/functions.html#bool), [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] = False, [](#__codelineno-0-13) max_height: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None [](#__codelineno-0-14))` Bases: `UIElement[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")]]` A chatbot UI element for interactive conversations. Define a chatbot by implementing a function that takes a list of ChatMessages and optionally a config object as input, and returns the chat response. The response can be any object, including text, plots, or marimo UI elements. Examples: Using a custom model: ``[](#__codelineno-0-1)def my_rag_model(messages, config): [](#__codelineno-0-2) # Each message has a `content` attribute, as well as a `role` [](#__codelineno-0-3) # attribute ("user", "system", "assistant"); [](#__codelineno-0-4) question = messages[-1].content [](#__codelineno-0-5) docs = find_docs(question) [](#__codelineno-0-6) prompt = template(question, docs, messages) [](#__codelineno-0-7) response = query(prompt) [](#__codelineno-0-8) if is_dataset(response): [](#__codelineno-0-9) return dataset_to_chart(response) [](#__codelineno-0-10) return response [](#__codelineno-0-11) [](#__codelineno-0-12)[](#__codelineno-0-13)chat = mo.ui.chat(my_rag_model)`` Async functions and async generators are also supported: `[](#__codelineno-1-1)async def my_rag_model(messages): [](#__codelineno-1-2) return await my_async_function(messages)` `[](#__codelineno-2-1)async def my_rag_model(messages): [](#__codelineno-2-2) for response in my_async_iterator(messages): [](#__codelineno-2-3) yield response` The last value yielded by the async generator is treated as the model response. ui.chat does not yet support streaming responses to the frontend. Please file a GitHub issue if this is important to you: [https://github.com/marimo-team/marimo/issues](https://github.com/marimo-team/marimo/issues) Using a built-in model: `[](#__codelineno-3-1)chat = mo.ui.chat( [](#__codelineno-3-2) mo.ai.llm.openai( [](#__codelineno-3-3) "gpt-4o", [](#__codelineno-3-4) system_message="You are a helpful assistant.", [](#__codelineno-3-5) ), [](#__codelineno-3-6))` Using attachments: `[](#__codelineno-4-1)chat = mo.ui.chat( [](#__codelineno-4-2) mo.ai.llm.openai( [](#__codelineno-4-3) "gpt-4o", [](#__codelineno-4-4) ), [](#__codelineno-4-5) allow_attachments=["image/png", "image/jpeg"], [](#__codelineno-4-6))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.chat.value "marimo.ui.chat.value")` | The current chat history, a list of ChatMessage objects. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")]` | | PARAMETER | DESCRIPTION | | --- | --- | | `model` | A callable that takes in the chat history and returns a response. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")], [ChatModelConfig](#marimo.ai.ChatModelConfig "marimo._ai.types.ChatModelConfig")], [object](https://docs.python.org/3/glossary.html#term-object)]` | | `prompts` | Optional list of initial prompts to present to the user. Defaults to None. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `on_message` | Optional callback function to handle new messages. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[ChatMessage](#marimo.ai.ChatMessage "marimo._ai.types.ChatMessage")]], None]` **DEFAULT:** `None` | | `show_configuration_controls` | Whether to show the configuration controls. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `config` | Optional configuration to override the default configuration. Keys include: - max\_tokens - temperature - top\_p - top\_k - frequency\_penalty - presence\_penalty Defaults to None. **TYPE:** `ChatModelConfigDict` **DEFAULT:** `None` | | `allow_attachments` | Allow attachments. True for any attachments types, or pass a list of mime types. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool) | [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `False` | | `max_height` | Optional maximum height for the chat element. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.chat.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.chat.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.chat.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.chat.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.chat.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.chat.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.chat.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.chat.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.chat.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.chat.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Basic Usage[¶](#basic-usage "Permanent link") --------------------------------------------- Here's a simple example using a custom echo model: `[](#__codelineno-1-1)import marimo as mo [](#__codelineno-1-2)[](#__codelineno-1-3)def echo_model(messages, config): [](#__codelineno-1-4) return f"Echo: {messages[-1].content}" [](#__codelineno-1-5)[](#__codelineno-1-6)chat = mo.ui.chat(echo_model, prompts=["Hello", "How are you?"]) [](#__codelineno-1-7)chat` Here, `messages` is a list of [`ChatMessage`](#marimo.ai.ChatMessage) objects, which has `role` (`"user"`, `"assistant"`, or `"system"`) and `content` (the message string) attributes; `config` is a [`ChatModelConfig`](#marimo.ai.ChatModelConfig) object with various configuration parameters, which you are free to ignore. Using a Built-in AI Model[¶](#using-a-built-in-ai-model "Permanent link") ------------------------------------------------------------------------- You can use marimo's built-in AI models, such as OpenAI's GPT: `[](#__codelineno-2-1)import marimo as mo [](#__codelineno-2-2)[](#__codelineno-2-3)chat = mo.ui.chat( [](#__codelineno-2-4) mo.ai.llm.openai( [](#__codelineno-2-5) "gpt-4", [](#__codelineno-2-6) system_message="You are a helpful assistant.", [](#__codelineno-2-7) ), [](#__codelineno-2-8) show_configuration_controls=True [](#__codelineno-2-9)) [](#__codelineno-2-10)chat` Accessing Chat History[¶](#accessing-chat-history "Permanent link") ------------------------------------------------------------------- You can access the chat history using the `value` attribute: This returns a list of [`ChatMessage`](#marimo.ai.ChatMessage) objects, each containing `role`, `content`, and optional `attachments` attributes. marimo.ai.ChatMessage `dataclass` [¶](#marimo.ai.ChatMessage "Permanent link") ------------------------------------------------------------------------------ A message in a chat. ### attachments `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatMessage.attachments "Permanent link") ### content `instance-attribute` [¶](#marimo.ai.ChatMessage.content "Permanent link") ### role `instance-attribute` [¶](#marimo.ai.ChatMessage.role "Permanent link") `[](#__codelineno-0-1)role: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['user', 'assistant', 'system']` Custom Model with Additional Context[¶](#custom-model-with-additional-context "Permanent link") ----------------------------------------------------------------------------------------------- Here's an example of a custom model that uses additional context: `[](#__codelineno-4-1)import marimo as mo [](#__codelineno-4-2)[](#__codelineno-4-3)def rag_model(messages, config): [](#__codelineno-4-4) question = messages[-1].content [](#__codelineno-4-5) docs = find_relevant_docs(question) [](#__codelineno-4-6) context = "\n".join(docs) [](#__codelineno-4-7) prompt = f"Context: {context}\n\nQuestion: {question}\n\nAnswer:" [](#__codelineno-4-8) response = query_llm(prompt, config) [](#__codelineno-4-9) return response [](#__codelineno-4-10)[](#__codelineno-4-11)mo.ui.chat(rag_model)` This example demonstrates how you can implement a Retrieval-Augmented Generation (RAG) model within the chat interface. Templated Prompts[¶](#templated-prompts "Permanent link") --------------------------------------------------------- You can pass sample prompts to `mo.ui.chat` to allow users to select from a list of predefined prompts. By including a `{{var}}` in the prompt, you can dynamically insert values into the prompt; a form will be generated to allow users to fill in the variables. `[](#__codelineno-5-1)mo.ui.chat( [](#__codelineno-5-2) mo.ai.llm.openai("gpt-4o"), [](#__codelineno-5-3) prompts=[ [](#__codelineno-5-4) "What is the capital of France?", [](#__codelineno-5-5) "What is the capital of Germany?", [](#__codelineno-5-6) "What is the capital of {{country}}?", [](#__codelineno-5-7) ], [](#__codelineno-5-8))` Including Attachments[¶](#including-attachments "Permanent link") ----------------------------------------------------------------- You can allow users to upload attachments to their messages by passing an `allow_attachments` parameter to `mo.ui.chat`. `[](#__codelineno-6-1)mo.ui.chat( [](#__codelineno-6-2) rag_model, [](#__codelineno-6-3) allow_attachments=["image/png", "image/jpeg"], [](#__codelineno-6-4) # or True for any attachment type [](#__codelineno-6-5) # allow_attachments=True, [](#__codelineno-6-6))` Built-in Models[¶](#built-in-models "Permanent link") ----------------------------------------------------- marimo provides several built-in AI models that you can use with the chat UI element. ### OpenAI[¶](#openai "Permanent link") `[](#__codelineno-7-1)import marimo as mo [](#__codelineno-7-2)[](#__codelineno-7-3)mo.ui.chat( [](#__codelineno-7-4) mo.ai.llm.openai( [](#__codelineno-7-5) "gpt-4o", [](#__codelineno-7-6) system_message="You are a helpful assistant.", [](#__codelineno-7-7) api_key="sk-proj-...", [](#__codelineno-7-8) ), [](#__codelineno-7-9) show_configuration_controls=True [](#__codelineno-7-10))` marimo.ai.llm.openai [¶](#marimo.ai.llm.openai "Permanent link") ---------------------------------------------------------------- Bases: `ChatModel` OpenAI ChatModel **Args:** * model: The model to use. Can be found on the [OpenAI models page](https://platform.openai.com/docs/models) * system\_message: The system message to use * api\_key: The API key to use. If not provided, the API key will be retrieved from the OPENAI\_API\_KEY environment variable or the user's config. * base\_url: The base URL to use ### api\_key `instance-attribute` [¶](#marimo.ai.llm.openai.api_key "Permanent link") ### base\_url `instance-attribute` [¶](#marimo.ai.llm.openai.base_url "Permanent link") ### model `instance-attribute` [¶](#marimo.ai.llm.openai.model "Permanent link") ### system\_message `instance-attribute` [¶](#marimo.ai.llm.openai.system_message "Permanent link") `[](#__codelineno-0-1)system_message = [system_message](#marimo.ai.llm.openai.system_message "marimo._ai.llm.openai.system_message")` ### Anthropic[¶](#anthropic "Permanent link") `[](#__codelineno-8-1)import marimo as mo [](#__codelineno-8-2)[](#__codelineno-8-3)mo.ui.chat( [](#__codelineno-8-4) mo.ai.llm.anthropic( [](#__codelineno-8-5) "claude-3-5-sonnet-20240620", [](#__codelineno-8-6) system_message="You are a helpful assistant.", [](#__codelineno-8-7) api_key="sk-ant-...", [](#__codelineno-8-8) ), [](#__codelineno-8-9) show_configuration_controls=True [](#__codelineno-8-10))` marimo.ai.llm.anthropic [¶](#marimo.ai.llm.anthropic "Permanent link") ---------------------------------------------------------------------- Bases: `ChatModel` Anthropic ChatModel **Args:** * model: The model to use. Can be found on the [Anthropic models page](https://docs.anthropic.com/en/docs/about-claude/models) * system\_message: The system message to use * api\_key: The API key to use. If not provided, the API key will be retrieved from the ANTHROPIC\_API\_KEY environment variable or the user's config. * base\_url: The base URL to use ### api\_key `instance-attribute` [¶](#marimo.ai.llm.anthropic.api_key "Permanent link") ### base\_url `instance-attribute` [¶](#marimo.ai.llm.anthropic.base_url "Permanent link") ### model `instance-attribute` [¶](#marimo.ai.llm.anthropic.model "Permanent link") ### system\_message `instance-attribute` [¶](#marimo.ai.llm.anthropic.system_message "Permanent link") `[](#__codelineno-0-1)system_message = [system_message](#marimo.ai.llm.anthropic.system_message "marimo._ai.llm.anthropic.system_message")` ### Google AI[¶](#google-ai "Permanent link") `[](#__codelineno-9-1)import marimo as mo [](#__codelineno-9-2)[](#__codelineno-9-3)mo.ui.chat( [](#__codelineno-9-4) mo.ai.llm.google( [](#__codelineno-9-5) "gemini-1.5-pro-latest", [](#__codelineno-9-6) system_message="You are a helpful assistant.", [](#__codelineno-9-7) api_key="AI..", [](#__codelineno-9-8) ), [](#__codelineno-9-9) show_configuration_controls=True [](#__codelineno-9-10))` marimo.ai.llm.google [¶](#marimo.ai.llm.google "Permanent link") ---------------------------------------------------------------- `[](#__codelineno-0-1)google( [](#__codelineno-0-2) model: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) *, [](#__codelineno-0-4) system_message: [str](https://docs.python.org/3/library/stdtypes.html#str) = DEFAULT_SYSTEM_MESSAGE, [](#__codelineno-0-5) api_key: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None [](#__codelineno-0-6))` Bases: `ChatModel` Google AI ChatModel **Args:** * model: The model to use. Can be found on the [Gemini models page](https://ai.google.dev/gemini-api/docs/models/gemini) * system\_message: The system message to use * api\_key: The API key to use. If not provided, the API key will be retrieved from the GOOGLE\_AI\_API\_KEY environment variable or the user's config. ### api\_key `instance-attribute` [¶](#marimo.ai.llm.google.api_key "Permanent link") ### model `instance-attribute` [¶](#marimo.ai.llm.google.model "Permanent link") ### system\_message `instance-attribute` [¶](#marimo.ai.llm.google.system_message "Permanent link") `[](#__codelineno-0-1)system_message = [system_message](#marimo.ai.llm.google.system_message "marimo._ai.llm.google.system_message")` ### Groq[¶](#groq "Permanent link") `[](#__codelineno-10-1)import marimo as mo [](#__codelineno-10-2)[](#__codelineno-10-3)mo.ui.chat( [](#__codelineno-10-4) mo.ai.llm.groq( [](#__codelineno-10-5) "llama-3.1-70b-versatile", [](#__codelineno-10-6) system_message="You are a helpful assistant.", [](#__codelineno-10-7) api_key="gsk-...", [](#__codelineno-10-8) ), [](#__codelineno-10-9) show_configuration_controls=True [](#__codelineno-10-10))` marimo.ai.llm.groq [¶](#marimo.ai.llm.groq "Permanent link") ------------------------------------------------------------ Bases: `ChatModel` Groq ChatModel **Args:** * model: The model to use. Can be found on the [Groq models page](https://console.groq.com/docs/models) * system\_message: The system message to use * api\_key: The API key to use. If not provided, the API key will be retrieved from the GROQ\_API\_KEY environment variable or the user's config. * base\_url: The base URL to use ### api\_key `instance-attribute` [¶](#marimo.ai.llm.groq.api_key "Permanent link") ### base\_url `instance-attribute` [¶](#marimo.ai.llm.groq.base_url "Permanent link") ### model `instance-attribute` [¶](#marimo.ai.llm.groq.model "Permanent link") ### system\_message `instance-attribute` [¶](#marimo.ai.llm.groq.system_message "Permanent link") `[](#__codelineno-0-1)system_message = [system_message](#marimo.ai.llm.groq.system_message "marimo._ai.llm.groq.system_message")` Types[¶](#types "Permanent link") --------------------------------- Chatbots can be implemented with a function that receives a list of [`ChatMessage`](#marimo.ai.ChatMessage) objects and a [`ChatModelConfig`](#marimo.ai.ChatModelConfig). marimo.ai.ChatMessage `dataclass` [¶](#marimo.ai.ChatMessage "Permanent link") ------------------------------------------------------------------------------ A message in a chat. ### attachments `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatMessage.attachments "Permanent link") ### content `instance-attribute` [¶](#marimo.ai.ChatMessage.content "Permanent link") ### role `instance-attribute` [¶](#marimo.ai.ChatMessage.role "Permanent link") `[](#__codelineno-0-1)role: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['user', 'assistant', 'system']` marimo.ai.ChatModelConfig `dataclass` [¶](#marimo.ai.ChatModelConfig "Permanent link") -------------------------------------------------------------------------------------- ### frequency\_penalty `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.frequency_penalty "Permanent link") ### max\_tokens `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.max_tokens "Permanent link") ### presence\_penalty `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.presence_penalty "Permanent link") ### temperature `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.temperature "Permanent link") ### top\_k `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.top_k "Permanent link") ### top\_p `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatModelConfig.top_p "Permanent link") [`mo.ui.chat`](#marimo.ui.chat) can be instantiated with an initial configuration with a dictionary conforming to the config. `ChatMessage`s can also include attachments. marimo.ai.ChatAttachment `dataclass` [¶](#marimo.ai.ChatAttachment "Permanent link") ------------------------------------------------------------------------------------ `[](#__codelineno-0-1)ChatAttachment( [](#__codelineno-0-2) url: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) name: [str](https://docs.python.org/3/library/stdtypes.html#str) = "attachment", [](#__codelineno-0-4) content_type: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-5))` ### content\_type `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatAttachment.content_type "Permanent link") ### name `class-attribute` `instance-attribute` [¶](#marimo.ai.ChatAttachment.name "Permanent link") ### url `instance-attribute` [¶](#marimo.ai.ChatAttachment.url "Permanent link") Supported Model Providers[¶](#supported-model-providers "Permanent link") ------------------------------------------------------------------------- We support any OpenAI-compatible endpoint. If you want any specific provider added explicitly (ones that don't abide by the standard OpenAI API format), you can file a [feature request](https://github.com/marimo-team/marimo/issues/new?template=feature_request.yaml). Normally, overriding the `base_url` parameter should work. Here are some examples: CerebrasGroqxAI `[](#__codelineno-11-1)chatbot = mo.ui.chat( [](#__codelineno-11-2) mo.ai.llm.openai( [](#__codelineno-11-3) model="llama3.1-8b", [](#__codelineno-11-4) api_key="csk-...", # insert your key here [](#__codelineno-11-5) base_url="https://api.cerebras.ai/v1/", [](#__codelineno-11-6) ), [](#__codelineno-11-7)) [](#__codelineno-11-8)chatbot` `[](#__codelineno-12-1)chatbot = mo.ui.chat( [](#__codelineno-12-2) mo.ai.llm.openai( [](#__codelineno-12-3) model="llama-3.1-70b-versatile", [](#__codelineno-12-4) api_key="gsk_...", # insert your key here [](#__codelineno-12-5) base_url="https://api.groq.com/openai/v1/", [](#__codelineno-12-6) ), [](#__codelineno-12-7)) [](#__codelineno-12-8)chatbot` `[](#__codelineno-13-1)chatbot = mo.ui.chat( [](#__codelineno-13-2) mo.ai.llm.openai( [](#__codelineno-13-3) model="grok-beta", [](#__codelineno-13-4) api_key=key, # insert your key here [](#__codelineno-13-5) base_url="https://api.x.ai/v1", [](#__codelineno-13-6) ), [](#__codelineno-13-7)) [](#__codelineno-13-8)chatbot` Note We have added examples for GROQ and Cerebras. These providers offer free API keys and are great for trying out Llama models (from Meta). You can sign up on their platforms and integrate with various AI integrations in marimo easily. For more information, refer to the [AI completion documentation in marimo](https://docs.marimo.io/guides/editor_features/ai_completion/). Button - marimo https://docs.marimo.io/api/inputs/button/ Looking for a submit/run button? If you're looking for a button to trigger computation on click, consider using [`mo.ui.run_button`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button). Source code for `examples/ui/button.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.6" app = marimo.App() @app.cell def _(): import marimo as mo return (mo,) @app.cell def _(mo): button = mo.ui.button( value=0, on_click=lambda value: value + 1, label="increment", kind="warn" ) button return (button,) @app.cell def _(button): button.value return if __name__ == "__main__": app.run()` marimo.ui.button [¶](#marimo.ui.button "Permanent link") -------------------------------------------------------- `[](#__codelineno-0-1)button( [](#__codelineno-0-2) on_click: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]] = None, [](#__codelineno-0-3) value: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")] = None, [](#__codelineno-0-4) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-5) "neutral", "success", "warn", "danger" [](#__codelineno-0-6) ] = "neutral", [](#__codelineno-0-7) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-8) tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-9) *, [](#__codelineno-0-10) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "click here", [](#__codelineno-0-11) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]] = None, [](#__codelineno-0-12) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-13) keyboard_shortcut: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None [](#__codelineno-0-14))` Bases: `UIElement[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` A button with an optional callback and optional value. Examples: `[](#__codelineno-0-1)# a button that when clicked will execute [](#__codelineno-0-2)# any cells referencing that button [](#__codelineno-0-3)button = mo.ui.button()` `[](#__codelineno-1-1)# a counter implementation [](#__codelineno-1-2)counter_button = mo.ui.button( [](#__codelineno-1-3) value=0, on_click=lambda value: value + 1, label="increment" [](#__codelineno-1-4)) [](#__codelineno-1-5)[](#__codelineno-1-6)# adding intent [](#__codelineno-1-7)delete_button = mo.ui.button( [](#__codelineno-1-8) label="Do not click", [](#__codelineno-1-9) kind="danger", [](#__codelineno-1-10))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.button.value "marimo.ui.button.value")` | The value of the button. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | | PARAMETER | DESCRIPTION | | --- | --- | | `on_click` | A callable called on click that takes the current value of the button and returns a new value. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` **DEFAULT:** `None` | | `value` | An initial value for the button. Defaults to None. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `None` | | `kind` | Button style. Defaults to "neutral". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['neutral', 'success', 'warn', 'danger']` **DEFAULT:** `'neutral'` | | `disabled` | Whether the button is disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `tooltip` | Tooltip text for the button. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "click here". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'click here'` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `keyboard_shortcut` | Keyboard shortcut to trigger the button (e.g. 'Ctrl-L'). Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.button.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.button.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.button.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.button.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.button.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.button.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.button.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.button.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.button.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.button.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Data Explorer - marimo https://docs.marimo.io/api/inputs/data_explorer/ The data explorer UI element outputs a visual editor explore your data via plotting and intelligent recommendations. You can incrementally build your "main" plot by adding different encodings: x-axis, y-axis, color, size, and shape. As you build your plot, the UI element will suggest further plots by intelligently "exploding" an additional encoding derived from your base plot. Pandas Required In order to use the dataframe UI element, you must have the `pandas` package installed. You can install it with `pip install pandas`. marimo.ui.data\_explorer [¶](#marimo.ui.data_explorer "Permanent link") ----------------------------------------------------------------------- Bases: `UIElement[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` Quickly explore a DataFrame with automatically suggested visualizations. Examples: `[](#__codelineno-0-1)mo.ui.data_explorer(data)` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.data_explorer.value "marimo.ui.data_explorer.value")` | The resulting DataFrame chart spec. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | PARAMETER | DESCRIPTION | | --- | --- | | `df` | The DataFrame to visualize. **TYPE:** `IntoDataFrame` | ### text `property` [¶](#marimo.ui.data_explorer.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.data_explorer.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.data_explorer.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.data_explorer.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.data_explorer.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.data_explorer.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.data_explorer.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.data_explorer.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.data_explorer.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.data_explorer.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | DataFrame - marimo https://docs.marimo.io/api/inputs/dataframe/ The dataframe UI element outputs a visual editor to apply "transforms" to a dataframe, such as filtering rows, applying group-bys and aggregations, and more. The transformed dataframe is shown below the transform editor. The UI output also includes the generated Python used to generate the resulting dataframe, which you can copy paste into a cell. You can programmatically access the resulting dataframe by accessing the element's `.value` attribute. Pandas or Polars Required In order to use the dataframe UI element, you must have the `pandas` or `polars` package installed. You can install it with `pip install pandas` or `pip install polars`. Supported transforms are: * Filter Rows * Rename Column * Column Conversion * Sort Column * Group By * Aggregate marimo.ui.dataframe [¶](#marimo.ui.dataframe "Permanent link") -------------------------------------------------------------- Bases: `UIElement[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], DataFrameType]` Run transformations on a DataFrame or series. Currently only Pandas or Polars DataFrames are supported. Examples: `[](#__codelineno-0-1)dataframe = mo.ui.dataframe(data)` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.dataframe.value "marimo.ui.dataframe.value")` | The transformed DataFrame or series. **TYPE:** `DataFrameType` | | PARAMETER | DESCRIPTION | | --- | --- | | `df` | The DataFrame or series to transform. **TYPE:** `DataFrameType` | | `page_size` | The number of rows to show in the table. Defaults to 5. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)]` **DEFAULT:** `5` | | `limit` | The number of items to load into memory, in case the data is remote and lazily fetched. This is likely true for SQL-backed dataframes via Ibis. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)]` **DEFAULT:** `None` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[DataFrameType], None]]` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.dataframe.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.dataframe.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.dataframe.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.dataframe.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.dataframe.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.dataframe.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.dataframe.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.dataframe.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.dataframe.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.dataframe.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Code Editor - marimo https://docs.marimo.io/api/inputs/code_editor/ Source code for `examples/ui/code_editor.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.6" app = marimo.App(width="medium") @app.cell def _(): import marimo as mo return (mo,) @app.cell def _(mo): initial_code = """# implement foo below def foo(): ... """ editor = mo.ui.code_editor( value=initial_code, language="python" ) editor return editor, initial_code @app.cell def _(editor): editor.value return if __name__ == "__main__": app.run()` marimo.ui.code\_editor [¶](#marimo.ui.code_editor "Permanent link") ------------------------------------------------------------------- `[](#__codelineno-0-1)code_editor( [](#__codelineno-0-2) value: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) language: [str](https://docs.python.org/3/library/stdtypes.html#str) = "python", [](#__codelineno-0-4) placeholder: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-5) theme: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["light", "dark"]] = None, [](#__codelineno-0-6) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7) min_height: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-8) max_height: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-9) *, [](#__codelineno-0-10) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-11) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]] = None [](#__codelineno-0-12))` Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]` A code editor. Examples: `[](#__codelineno-0-1)code_editor = mo.ui.code_editor()` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.code_editor.value "marimo.ui.code_editor.value")` | A string of the code editor contents. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Initial value of the code editor. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `language` | Language of the code editor. Most major languages are supported, including "sql", "javascript", "typescript", "html", "css", "c", "cpp", "rust", and more. Defaults to "python". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'python'` | | `placeholder` | Placeholder text to display when the code editor is empty. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `theme` | Theme of the code editor. Defaults to the editor's default. **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['light', 'dark']` **DEFAULT:** `None` | | `disabled` | Whether the input is disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `min_height` | Minimum height of the code editor in pixels. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `max_height` | Maximum height of the code editor in pixels. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.code_editor.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.code_editor.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.code_editor.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.code_editor.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.code_editor.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.code_editor.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.code_editor.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.code_editor.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.code_editor.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.code_editor.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Dictionary - marimo https://docs.marimo.io/api/inputs/dictionary/ marimo.ui.dictionary [¶](#marimo.ui.dictionary "Permanent link") ---------------------------------------------------------------- Bases: `_batch_base` A dictionary of UI elements. Use a dictionary to: - create a set of UI elements at runtime - group together logically related UI elements - keep the number of global variables in your program small Access the values of the elements using the `value` attribute of the dictionary. The elements in the dictionary can be accessed using square brackets (`dictionary[key]`) and embedded in other marimo outputs. You can also iterate over the UI elements using the same syntax used for Python dicts. Note The UI elements in the dictionary are clones of the original elements: interacting with the dictionary will _not_ update the original elements, and vice versa. The main reason to use `mo.ui.dictionary` is for reactive execution — when you interact with an element in a `mo.ui.dictionary`, all cells that reference the `mo.ui.dictionary` run automatically, just like all other ui elements. When you use a regular dictionary, you don't get this reactivity. Examples: A heterogeneous collection of UI elements: `[](#__codelineno-0-1)d = mo.ui.dictionary( [](#__codelineno-0-2) { [](#__codelineno-0-3) "slider": mo.ui.slider(1, 10), [](#__codelineno-0-4) "text": mo.ui.text(), [](#__codelineno-0-5) "date": mo.ui.date(), [](#__codelineno-0-6) } [](#__codelineno-0-7))` Get the values of the `slider`, `text`, and `date` elements via `d.value`: `[](#__codelineno-1-1)# d.value returns a dict with keys "slider", "text", "date" [](#__codelineno-1-2)d.value` Access and output a UI element in the array: `[](#__codelineno-2-1)mo.md(f"This is a slider: {d['slider']}")` Some number of UI elements, determined at runtime: `[](#__codelineno-3-1)mo.ui.dictionary( [](#__codelineno-3-2) { [](#__codelineno-3-3) f"option {i}": mo.ui.slider(1, 10) [](#__codelineno-3-4) for i in range(random.randint(4, 8)) [](#__codelineno-3-5) } [](#__codelineno-3-6))` Quick layouts of UI elements: ``[](#__codelineno-4-1)mo.ui.dictionary( [](#__codelineno-4-2) { [](#__codelineno-4-3) f"option {i}": mo.ui.slider(1, 10) [](#__codelineno-4-4) for i in range(random.randint(4, 8)) [](#__codelineno-4-5) } [](#__codelineno-4-6)).vstack() # Can also use `hstack`, `callout`, `center`, etc.`` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.dictionary.value "marimo.ui.dictionary.value")` | A dict holding the values of the UI elements, keyed by their names. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | `[elements](#marimo.ui.dictionary.elements "marimo.ui.dictionary.elements")` | A dict of the wrapped elements (clones of the originals). **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [object](https://docs.python.org/3/glossary.html#term-object)]], None]]` | | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | A dict mapping names to UI elements to include. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), UIElement[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` | | `label` | A descriptive name for the dictionary. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | ### elements `property` [¶](#marimo.ui.dictionary.elements "Permanent link") ### text `property` [¶](#marimo.ui.dictionary.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.dictionary.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.dictionary.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.dictionary.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.dictionary.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.dictionary.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### get [¶](#marimo.ui.dictionary.get "Permanent link") `[](#__codelineno-0-1)get(key: [str](https://docs.python.org/3/library/stdtypes.html#str), default: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") | None = None) -> [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` Get a UI element by key with an optional default value. | PARAMETER | DESCRIPTION | | --- | --- | | `key` | The key to look up in the batch. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | `default` | Value to return if key is not found. Defaults to None. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") | None` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Any` | The UI element if found, otherwise the default value. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | ### hstack [¶](#marimo.ui.dictionary.hstack "Permanent link") Stack the elements horizontally. For kwargs, see `marimo.hstack`. ### items [¶](#marimo.ui.dictionary.items "Permanent link") Return a view of the batch's items (key-value pairs). | RETURNS | DESCRIPTION | | --- | --- | | `[ItemsView](https://docs.python.org/3/library/collections.abc.html#collections.abc.ItemsView "collections.abc.ItemsView")[[str](https://docs.python.org/3/library/stdtypes.html#str), UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]]` | ItemsView\[str, UIElement\]: A view of the batch's (key, element) pairs. | ### left [¶](#marimo.ui.dictionary.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.dictionary.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.dictionary.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.dictionary.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | ### values [¶](#marimo.ui.dictionary.values "Permanent link") Return a view of the batch's values (UI elements). | RETURNS | DESCRIPTION | | --- | --- | | `[ValuesView](https://docs.python.org/3/library/collections.abc.html#collections.abc.ValuesView "collections.abc.ValuesView")[UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]]` | ValuesView\[UIElement\]: A view of the batch's UI elements. | ### vstack [¶](#marimo.ui.dictionary.vstack "Permanent link") Stack the elements vertically. For kwargs, see `marimo.vstack`. Dates - marimo https://docs.marimo.io/api/inputs/dates/ Single date[¶](#single-date "Permanent link") --------------------------------------------- marimo.ui.date [¶](#marimo.ui.date "Permanent link") ---------------------------------------------------- Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")]` A date picker with an optional start and stop date. Examples: `[](#__codelineno-0-1)# initialize the date picker at a given date [](#__codelineno-0-2)date = mo.ui.date(value="2022-01-01")` `[](#__codelineno-1-1)# when value is omitted, date picker initializes with today's date [](#__codelineno-1-2)date = mo.ui.date()` `[](#__codelineno-2-1)# create a date picker with bounds [](#__codelineno-2-2)date = mo.ui.date( [](#__codelineno-2-3) value="2022-06-01", [](#__codelineno-2-4) start="2022-01-01", [](#__codelineno-2-5) stop="2022-12-31", [](#__codelineno-2-6))` Or from a dataframe series: `[](#__codelineno-3-1)date = mo.ui.date.from_series(df["column_name"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.date.value "marimo.ui.date.value")` | A str (YYYY-MM-DD) or `datetime.date` object of the chosen date. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str) | date` | | `[start](#marimo.ui.date.start "marimo.ui.date.start")` | The start date. **TYPE:** `date` | | `[stop](#marimo.ui.date.stop "marimo.ui.date.stop")` | The stop date. **TYPE:** `date` | | PARAMETER | DESCRIPTION | | --- | --- | | `start` | Minimum date selectable. If None, defaults to 01-01-0001. **TYPE:** `date | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `stop` | Maximum date selectable. If None, defaults to 12-31-9999. **TYPE:** `date | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `value` | Default date. If None and start and stop are None, defaults to the current day. If None and start is not None, defaults to start. If None and stop is not None, defaults to stop. **TYPE:** `date | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `label` | Markdown label for the element. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[date], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### DATE\_FORMAT `class-attribute` `instance-attribute` [¶](#marimo.ui.date.DATE_FORMAT "Permanent link") ### start `property` [¶](#marimo.ui.date.start "Permanent link") Get the minimum selectable date. | RETURNS | DESCRIPTION | | --- | --- | | `[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")` | datetime.date: The start date, which is either the user-specified minimum date or 01-01-0001 if no start date was specified. | ### stop `property` [¶](#marimo.ui.date.stop "Permanent link") Get the maximum selectable date. | RETURNS | DESCRIPTION | | --- | --- | | `[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")` | datetime.date: The stop date, which is either the user-specified maximum date or 12-31-9999 if no stop date was specified. | ### text `property` [¶](#marimo.ui.date.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.date.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.date.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.date.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.date.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.date.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.date.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "date"` Create a date picker from a dataframe series. | PARAMETER | DESCRIPTION | | --- | --- | | `series` | A pandas Series containing datetime values. **TYPE:** `DataFrameSeries` | | `**kwargs` | Additional keyword arguments passed to the date picker constructor. Supported arguments: start, stop, label, and any other date picker parameters. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `date` | A date picker initialized with the series' min and max dates as bounds. **TYPE:** `'date'` | ### left [¶](#marimo.ui.date.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.date.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.date.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.date.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | :members: Date and time[¶](#date-and-time "Permanent link") ------------------------------------------------- `[](#__codelineno-1-1) @app.cell [](#__codelineno-1-2) def __(): [](#__codelineno-1-3) datetime = mo.ui.datetime(label="Start Date") [](#__codelineno-1-4) return [](#__codelineno-1-5) [](#__codelineno-1-6) @app.cell [](#__codelineno-1-7) def __(): [](#__codelineno-1-8) mo.hstack([datetime, mo.md(f"Has value: {datetime.value}")]) [](#__codelineno-1-9) return` marimo.ui.datetime [¶](#marimo.ui.datetime "Permanent link") ------------------------------------------------------------ Bases: `UIElement[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[datetime](https://docs.python.org/3/library/datetime.html#datetime.datetime "datetime.datetime")]]` A datetime picker over an interval. Examples: `[](#__codelineno-0-1)datetime_picker = mo.ui.datetime( [](#__codelineno-0-2) start=dt.datetime(2023, 1, 1), [](#__codelineno-0-3) stop=dt.datetime(2023, 12, 31, 23, 59, 59), [](#__codelineno-0-4))` Or from a dataframe series: `[](#__codelineno-1-1)datetime_picker = mo.ui.datetime.from_series(df["datetime_column"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.datetime.value "marimo.ui.datetime.value")` | The selected datetime, possibly None. **TYPE:** `datetime` | | `[start](#marimo.ui.datetime.start "marimo.ui.datetime.start")` | The minimum selectable datetime. **TYPE:** `datetime` | | `[stop](#marimo.ui.datetime.stop "marimo.ui.datetime.stop")` | The maximum selectable datetime. **TYPE:** `datetime` | | PARAMETER | DESCRIPTION | | --- | --- | | `start` | The minimum selectable datetime. Defaults to minimum datetime. **TYPE:** `datetime | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `stop` | The maximum selectable datetime. Defaults to maximum datetime. **TYPE:** `datetime | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `value` | Default value. **TYPE:** `datetime | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `label` | Markdown label for the element. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[datetime]], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### DATETIME\_FORMAT `class-attribute` `instance-attribute` [¶](#marimo.ui.datetime.DATETIME_FORMAT "Permanent link") `[](#__codelineno-0-1)DATETIME_FORMAT: [Final](https://docs.python.org/3/library/typing.html#typing.Final "typing.Final")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = '%Y-%m-%dT%H:%M:%S'` ### start `property` [¶](#marimo.ui.datetime.start "Permanent link") Get the minimum selectable datetime. | RETURNS | DESCRIPTION | | --- | --- | | `[datetime](https://docs.python.org/3/library/datetime.html#datetime.datetime "datetime.datetime")` | datetime.datetime: The start datetime, which is either the user-specified minimum datetime or datetime.min if no start datetime was specified. | ### stop `property` [¶](#marimo.ui.datetime.stop "Permanent link") Get the maximum selectable datetime. | RETURNS | DESCRIPTION | | --- | --- | | `[datetime](https://docs.python.org/3/library/datetime.html#datetime.datetime "datetime.datetime")` | datetime.datetime: The stop datetime, which is either the user-specified maximum datetime or datetime.max if no stop datetime was specified. | ### text `property` [¶](#marimo.ui.datetime.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.datetime.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.datetime.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.datetime.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.datetime.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.datetime.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.datetime.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "datetime"` Create a datetime picker from a dataframe series. | PARAMETER | DESCRIPTION | | --- | --- | | `series` | A pandas Series containing datetime values. **TYPE:** `DataFrameSeries` | | `**kwargs` | Additional keyword arguments passed to the datetime picker constructor. Supported arguments: start, stop, label, and any other datetime picker parameters. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `datetime` | A datetime picker initialized with the series' min and max datetimes as bounds. **TYPE:** `'datetime'` | ### left [¶](#marimo.ui.datetime.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.datetime.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.datetime.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.datetime.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | :members: Date range[¶](#date-range "Permanent link") ------------------------------------------- marimo.ui.date\_range [¶](#marimo.ui.date_range "Permanent link") ----------------------------------------------------------------- `[](#__codelineno-0-1)date_range( [](#__codelineno-0-2) start: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date") | [str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-3) stop: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date") | [str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-4) value: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-5) [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date"), [date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")] | [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)] [](#__codelineno-0-6) ] = None, [](#__codelineno-0-7) *, [](#__codelineno-0-8) label: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-9) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-10) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date"), [date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")]], None] [](#__codelineno-0-11) ] = None, [](#__codelineno-0-12) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-13))` Bases: `UIElement[[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)], [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date"), [date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")]]` A date range picker over an interval. Examples: `[](#__codelineno-0-1)date_range = mo.ui.date_range( [](#__codelineno-0-2) start=dt.date(2023, 1, 1), stop=dt.date(2023, 12, 31) [](#__codelineno-0-3))` Or from a dataframe series: `[](#__codelineno-1-1)date_range = mo.ui.date_range.from_series(df["date_column"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.date_range.value "marimo.ui.date_range.value")` | A tuple of (start\_date, end\_date) representing the selected range. **TYPE:** `[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[date, date]` | | `[start](#marimo.ui.date_range.start "marimo.ui.date_range.start")` | The minimum selectable date. **TYPE:** `date` | | `[stop](#marimo.ui.date_range.stop "marimo.ui.date_range.stop")` | The maximum selectable date. **TYPE:** `date` | | PARAMETER | DESCRIPTION | | --- | --- | | `start` | Minimum date selectable. If None, defaults to 01-01-0001. **TYPE:** `date | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `stop` | Maximum date selectable. If None, defaults to 12-31-9999. **TYPE:** `date | [str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `value` | Default value as (start\_date, end\_date). If None, defaults to (start, stop) if provided, otherwise today's date for both. **TYPE:** `[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[date | [str](https://docs.python.org/3/library/stdtypes.html#str), date | [str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `label` | Markdown label for the element. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[date, date]], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### DATEFORMAT `class-attribute` `instance-attribute` [¶](#marimo.ui.date_range.DATEFORMAT "Permanent link") ### start `property` [¶](#marimo.ui.date_range.start "Permanent link") Get the minimum selectable date. | RETURNS | DESCRIPTION | | --- | --- | | `[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")` | datetime.date: The start date, which is either the user-specified minimum date or 01-01-0001 if no start date was specified. | ### stop `property` [¶](#marimo.ui.date_range.stop "Permanent link") Get the maximum selectable date. | RETURNS | DESCRIPTION | | --- | --- | | `[date](https://docs.python.org/3/library/datetime.html#datetime.date "datetime.date")` | datetime.date: The stop date, which is either the user-specified maximum date or 12-31-9999 if no stop date was specified. | ### text `property` [¶](#marimo.ui.date_range.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.date_range.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.date_range.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.date_range.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.date_range.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.date_range.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.date_range.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "date_range"` Create a date range picker from a dataframe series. | PARAMETER | DESCRIPTION | | --- | --- | | `series` | A pandas Series containing datetime values. **TYPE:** `DataFrameSeries` | | `**kwargs` | Additional keyword arguments passed to the date range picker constructor. Supported arguments: start, stop, label, and any other date range picker parameters. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `date_range` | A date range picker initialized with the series' min and max dates as bounds. **TYPE:** `'date_range'` | ### left [¶](#marimo.ui.date_range.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.date_range.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.date_range.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.date_range.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | :members: File - marimo https://docs.marimo.io/api/inputs/file/ marimo.ui.file [¶](#marimo.ui.file "Permanent link") ---------------------------------------------------- Bases: `UIElement[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple "typing.Tuple")[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]], [Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileUploadResults]]` A button or drag-and-drop area to upload a file. Once a file is uploaded, the UI element's value is a list of namedtuples (name, contents), where name is the filename and contents is the contents of the file. Alternatively, use the methods name(index: int = 0) and contents(index: int = 0) to retrieve the name or contents of the file at a specified index. Use the kind argument to switch between a button and a drag-and-drop area. The maximum file size is 100MB. Examples: Uploading a single file: `[](#__codelineno-0-1)f = mo.ui.file() [](#__codelineno-0-2)[](#__codelineno-0-3)# access the uploaded file's name [](#__codelineno-0-4)f.value[0].name [](#__codelineno-0-5)# or [](#__codelineno-0-6)f.name() [](#__codelineno-0-7)[](#__codelineno-0-8)# access the uploaded file's contents [](#__codelineno-0-9)f.value[0].contents [](#__codelineno-0-10)# or [](#__codelineno-0-11)f.contents()` Uploading multiple files, accepting only .png and .jpg extensions: `[](#__codelineno-1-1)f = mo.ui.file(filetypes=[".png", ".jpg"], multiple=True) [](#__codelineno-1-2)[](#__codelineno-1-3)# access an uploaded file's name [](#__codelineno-1-4)f.value[index].name [](#__codelineno-1-5)# or [](#__codelineno-1-6)f.name(index) [](#__codelineno-1-7)[](#__codelineno-1-8)# access the uploaded file's contents [](#__codelineno-1-9)f.value[index].contents [](#__codelineno-1-10)# or [](#__codelineno-1-11)f.contents(index)` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.file.value "marimo.ui.file.value")` | A sequence of FileUploadResults, which have string name and bytes contents fields. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileUploadResults]` | | METHOD | DESCRIPTION | | --- | --- | | `[name](#marimo.ui.file.name "marimo.ui.file.name")` | int = 0) -> Optional\[str\]: Get the name of the uploaded file at index. | | `[contents](#marimo.ui.file.contents "marimo.ui.file.contents")` | int = 0) -> Optional\[bytes\]: Get the contents of the uploaded file at index. | | PARAMETER | DESCRIPTION | | --- | --- | | `filetypes` | The file types accepted; for example, filetypes=\[".png", ".jpg"\]. If None, all files are accepted. In addition to extensions, you may provide "audio/_", "video/_", or "image/\*" to accept any audio, video, or image file. Defaults to None. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `multiple` | If True, allow the user to upload multiple files. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `kind` | Type of upload interface. Defaults to "button". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['button', 'area']` **DEFAULT:** `'button'` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileUploadResults]], None]` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.file.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.file.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.file.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.file.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.file.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### contents [¶](#marimo.ui.file.contents "Permanent link") Get file contents at index. | PARAMETER | DESCRIPTION | | --- | --- | | `index` | Index of the file to get the contents from. Defaults to 0. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `0` | | RETURNS | DESCRIPTION | | --- | --- | | `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[bytes](https://docs.python.org/3/library/stdtypes.html#bytes)]` | Optional\[bytes\]: The contents of the file at the specified index, or None if index is out of range. | ### form [¶](#marimo.ui.file.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.file.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### name [¶](#marimo.ui.file.name "Permanent link") Get file name at index. | PARAMETER | DESCRIPTION | | --- | --- | | `index` | Index of the file to get the name from. Defaults to 0. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `0` | | RETURNS | DESCRIPTION | | --- | --- | | `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` | Optional\[str\]: The name of the file at the specified index, or None if index is out of range. | ### right [¶](#marimo.ui.file.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.file.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.file.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | File Browser - marimo https://docs.marimo.io/api/inputs/file_browser/ marimo.ui.file\_browser [¶](#marimo.ui.file_browser "Permanent link") --------------------------------------------------------------------- Bases: `UIElement[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]], [Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileInfo]]` File browser for browsing and selecting server-side files. Examples: Selecting multiple files: `[](#__codelineno-0-1)file_browser = mo.ui.file_browser( [](#__codelineno-0-2) initial_path="path/to/dir", multiple=True [](#__codelineno-0-3)) [](#__codelineno-0-4)[](#__codelineno-0-5)# Access the selected file path(s): [](#__codelineno-0-6)file_browser.path(index) [](#__codelineno-0-7)[](#__codelineno-0-8)# Get name of selected file(s) [](#__codelineno-0-9)file_browser.name(index)` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.file_browser.value "marimo.ui.file_browser.value")` | A sequence of file paths representing selected files. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileInfo]` | | PARAMETER | DESCRIPTION | | --- | --- | | `initial_path` | Starting directory. Defaults to current working directory. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `filetypes` | The file types to display in each directory; for example, filetypes=\[".txt", ".csv"\]. If None, all files are displayed. Defaults to None. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `selection_mode` | Either "file" or "directory". Defaults to "file". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'file'` | | `multiple` | If True, allow the user to select multiple files. Defaults to True. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `restrict_navigation` | If True, prevent the user from navigating any level above the given path. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[FileInfo]], None]` **DEFAULT:** `None` | ### filetypes `instance-attribute` [¶](#marimo.ui.file_browser.filetypes "Permanent link") ### initial\_path `instance-attribute` [¶](#marimo.ui.file_browser.initial_path "Permanent link") `[](#__codelineno-0-1)initial_path = [initial_path](#marimo.ui.file_browser.initial_path "marimo._plugins.ui._impl.input.file_browser.initial_path")` ### restrict\_navigation `instance-attribute` [¶](#marimo.ui.file_browser.restrict_navigation "Permanent link") `[](#__codelineno-0-1)restrict_navigation = [restrict_navigation](#marimo.ui.file_browser.restrict_navigation "marimo._plugins.ui._impl.input.file_browser.restrict_navigation")` ### selection\_mode `instance-attribute` [¶](#marimo.ui.file_browser.selection_mode "Permanent link") `[](#__codelineno-0-1)selection_mode = [selection_mode](#marimo.ui.file_browser.selection_mode "marimo._plugins.ui._impl.input.file_browser.selection_mode")` ### text `property` [¶](#marimo.ui.file_browser.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.file_browser.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.file_browser.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.file_browser.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.file_browser.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.file_browser.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.file_browser.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### name [¶](#marimo.ui.file_browser.name "Permanent link") Get file name at index. | PARAMETER | DESCRIPTION | | --- | --- | | `index` | Index of the file to get the name from. Defaults to 0. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `0` | | RETURNS | DESCRIPTION | | --- | --- | | `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` | Optional\[str\]: The name of the file at the specified index, or None if index is out of range. | ### path [¶](#marimo.ui.file_browser.path "Permanent link") Get file path at index. | PARAMETER | DESCRIPTION | | --- | --- | | `index` | Index of the file to get the path from. Defaults to 0. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `0` | | RETURNS | DESCRIPTION | | --- | --- | | `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` | Optional\[str\]: The path of the file at the specified index, or None if index is out of range. | ### right [¶](#marimo.ui.file_browser.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.file_browser.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.file_browser.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Dropdown - marimo https://docs.marimo.io/api/inputs/dropdown/ marimo.ui.dropdown [¶](#marimo.ui.dropdown "Permanent link") ------------------------------------------------------------ Bases: `UIElement[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)], [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` A dropdown selector. Examples: `[](#__codelineno-0-1)dropdown = mo.ui.dropdown( [](#__codelineno-0-2) options=["a", "b", "c"], value="a", label="choose one" [](#__codelineno-0-3))` `[](#__codelineno-1-1)dropdown = mo.ui.dropdown( [](#__codelineno-1-2) options={"one": 1, "two": 2, "three": 3}, [](#__codelineno-1-3) value="one", [](#__codelineno-1-4) label="pick a number", [](#__codelineno-1-5))` Or from a dataframe series: `[](#__codelineno-2-1)dropdown = mo.ui.dropdown.from_series(df["column_name"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.dropdown.value "marimo.ui.dropdown.value")` | The selected value, or None if no selection. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | | `[options](#marimo.ui.dropdown.options "marimo.ui.dropdown.options")` | A dict mapping option name to option value. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | `[selected_key](#marimo.ui.dropdown.selected_key "marimo.ui.dropdown.selected_key")` | The selected option's key, or None if no selection. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `options` | Sequence of text options, or dict mapping option name to option value. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)] | [dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `value` | Default option name. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `allow_select_none` | Whether to include special option ("--") for a None value; when None, defaults to True when value is None. Defaults to None. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### options `instance-attribute` [¶](#marimo.ui.dropdown.options "Permanent link") ### selected\_key `property` [¶](#marimo.ui.dropdown.selected_key "Permanent link") The selected option's key, or `None` if no selection. ### text `property` [¶](#marimo.ui.dropdown.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.dropdown.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.dropdown.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.dropdown.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.dropdown.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.dropdown.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.dropdown.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "dropdown"` Create a dropdown from a dataframe series. ### left [¶](#marimo.ui.dropdown.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.dropdown.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.dropdown.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.dropdown.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Multiselect - marimo https://docs.marimo.io/api/inputs/multiselect/ marimo.ui.multiselect [¶](#marimo.ui.multiselect "Permanent link") ------------------------------------------------------------------ Bases: `UIElement[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)], [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[object](https://docs.python.org/3/glossary.html#term-object)]]` A multiselect input. Examples: `[](#__codelineno-0-1)multiselect = mo.ui.multiselect( [](#__codelineno-0-2) options=["a", "b", "c"], label="choose some options" [](#__codelineno-0-3))` Or from a dataframe series: `[](#__codelineno-1-1)multiselect = mo.ui.multiselect.from_series(df["column_name"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.multiselect.value "marimo.ui.multiselect.value")` | The selected values, or None if no selection. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[object](https://docs.python.org/3/glossary.html#term-object)]` | | `[options](#marimo.ui.multiselect.options "marimo.ui.multiselect.options")` | A dict mapping option name to option value. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | PARAMETER | DESCRIPTION | | --- | --- | | `options` | Sequence of text options, or dict mapping option name to option value. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)] | [dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `value` | A list of initially selected options. Defaults to None. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[object](https://docs.python.org/3/glossary.html#term-object)]], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `max_selections` | Maximum number of items that can be selected. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | ### options `instance-attribute` [¶](#marimo.ui.multiselect.options "Permanent link") ### text `property` [¶](#marimo.ui.multiselect.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.multiselect.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.multiselect.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.multiselect.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.multiselect.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.multiselect.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.multiselect.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "multiselect"` Create a multiselect from a dataframe series. ### left [¶](#marimo.ui.multiselect.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.multiselect.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.multiselect.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.multiselect.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Form - marimo https://docs.marimo.io/api/inputs/form/ marimo.ui.form [¶](#marimo.ui.form "Permanent link") ---------------------------------------------------- `[](#__codelineno-0-1)form( [](#__codelineno-0-2) element: UIElement[S, T], [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-17) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-18) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-19) ] = None [](#__codelineno-0-20))` Bases: `UIElement[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[S], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]]` A submittable form linked to a UIElement. Use a `form` to prevent sending UI element values to Python until a button is clicked. The value of a `form` is the value of the underlying element the last time the form was submitted. Examples: Create a form with chaining: `[](#__codelineno-0-1)# Create a form with chaining [](#__codelineno-0-2)form = mo.ui.slider(1, 100).form()` Create a form with multiple elements: `[](#__codelineno-1-1)# Create a form with multiple elements [](#__codelineno-1-2)form = ( [](#__codelineno-1-3) mo.md(''' [](#__codelineno-1-4) **Your form.** [](#__codelineno-1-5) [](#__codelineno-1-6) {name} [](#__codelineno-1-7) [](#__codelineno-1-8) {date} [](#__codelineno-1-9)''') [](#__codelineno-1-10) .batch( [](#__codelineno-1-11) name=mo.ui.text(label="name"), [](#__codelineno-1-12) date=mo.ui.date(label="date"), [](#__codelineno-1-13) ) [](#__codelineno-1-14) .form(show_clear_button=True, bordered=False) [](#__codelineno-1-15))` Instantiate a form directly: `[](#__codelineno-2-1)# Instantiate a form directly [](#__codelineno-2-2)form = mo.ui.form(element=mo.ui.slider(1, 100))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.form.value "marimo.ui.form.value")` | The value of the wrapped element when the form's submit button was last clicked. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | | `[element](#marimo.ui.form.element "marimo.ui.form.element")` | A copy of the wrapped element. **TYPE:** `UIElement` | | PARAMETER | DESCRIPTION | | --- | --- | | `element` | The element to wrap. **TYPE:** `UIElement[S, T]` | | `bordered` | Whether the form should have a border. Defaults to True. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. Defaults to "Submit". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. Defaults to "Clear". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if the value is invalid, or None if the value is valid. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `label` | Markdown label for the form. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]` **DEFAULT:** `None` | ### element `instance-attribute` [¶](#marimo.ui.form.element "Permanent link") ### text `property` [¶](#marimo.ui.form.text "Permanent link") A string of HTML representing this element. ### validate `instance-attribute` [¶](#marimo.ui.form.validate "Permanent link") ### value `property` `writable` [¶](#marimo.ui.form.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.form.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.form.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.form.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.form.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.form.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.form.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.form.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.form.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Microphone - marimo https://docs.marimo.io/api/inputs/microphone/ marimo.ui.microphone [¶](#marimo.ui.microphone "Permanent link") ---------------------------------------------------------------- Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO")]` An audio recorder element. Use `mo.ui.microphone` to record audio via the user's browser. The user must grant permission to use the microphone. Examples: `[](#__codelineno-0-1)mic = mo.ui.microphone() [](#__codelineno-0-2)mic` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.microphone.value "marimo.ui.microphone.value")` | The blob of the recorded audio, as an `io.BytesIO` object. **TYPE:** `[BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO")` | | PARAMETER | DESCRIPTION | | --- | --- | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO")], None]]` **DEFAULT:** `None` | ### name `class-attribute` `instance-attribute` [¶](#marimo.ui.microphone.name "Permanent link") ### text `property` [¶](#marimo.ui.microphone.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.microphone.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.microphone.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.microphone.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.microphone.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.microphone.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.microphone.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.microphone.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.microphone.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.microphone.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Navigation Menu - marimo https://docs.marimo.io/api/inputs/nav_menu/ `[](#__codelineno-0-1)nav_menu( [](#__codelineno-0-2) menu: [dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), JSONType], [](#__codelineno-0-3) *, [](#__codelineno-0-4) orientation: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-5) "horizontal", "vertical" [](#__codelineno-0-6) ] = "horizontal" [](#__codelineno-0-7)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Navigation menu component. This is useful for creating a navigation menu with hyperlinks, most used when creating multi-page applications, with `marimo.create_asgi_app` ([docs](https://docs.marimo.io/guides/deploying/programmatically.html)). | PARAMETER | DESCRIPTION | | --- | --- | | `menu` | a dictionary of tab names to tab content; the content can also be nested dictionaries (one level deep) strings are interpreted as markdown **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), JSONType]` | | `orientation` | The orientation of the menu. **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['horizontal', 'vertical']` **DEFAULT:** `'horizontal'` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | Example `[](#__codelineno-0-1)nav_menu = mo.nav_menu( [](#__codelineno-0-2) { [](#__codelineno-0-3) "/overview": "Overview", [](#__codelineno-0-4) "/sales": f"{mo.icon('lucide:shopping-cart')} Sales", [](#__codelineno-0-5) "/products": f"{mo.icon('lucide:package')} Products", [](#__codelineno-0-6) } [](#__codelineno-0-7))` `[](#__codelineno-1-1)nav_menu = mo.nav_menu( [](#__codelineno-1-2) { [](#__codelineno-1-3) "/overview": "Overview", [](#__codelineno-1-4) "Sales": { [](#__codelineno-1-5) "/sales": "Overview", [](#__codelineno-1-6) "/sales/invoices": { [](#__codelineno-1-7) "label": "Invoices", [](#__codelineno-1-8) "description": "View invoices", [](#__codelineno-1-9) }, [](#__codelineno-1-10) "/sales/customers": { [](#__codelineno-1-11) "label": "Customers", [](#__codelineno-1-12) "description": "View customers", [](#__codelineno-1-13) }, [](#__codelineno-1-14) }, [](#__codelineno-1-15) } [](#__codelineno-1-16))` Number - marimo https://docs.marimo.io/api/inputs/number/ marimo.ui.number [¶](#marimo.ui.number "Permanent link") -------------------------------------------------------- Bases: `UIElement[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric]]` A number picker over an interval. **Example.** `[](#__codelineno-0-1)number = mo.ui.number(start=1, stop=10, step=2)` Or for integer-only values: `[](#__codelineno-1-1)number = mo.ui.number(step=1)` Or from a dataframe series: `[](#__codelineno-2-1)number = mo.ui.number.from_series(df["column_name"])` **Attributes.** * `value`: the value of the number, possibly `None` * `start`: the minimum value of the interval * `stop`: the maximum value of the interval * `step`: the number increment **Initialization Args.** * `start`: optional, the minimum value of the interval * `stop`: optional, the maximum value of the interval * `step`: the number increment * `value`: default value * `debounce`: whether to debounce (rate-limit) value updates from the frontend * `label`: markdown label for the element * `on_change`: optional callback to run when this element's value changes * `full_width`: whether the input should take up the full width of its container ### start `instance-attribute` [¶](#marimo.ui.number.start "Permanent link") ### step `instance-attribute` [¶](#marimo.ui.number.step "Permanent link") ### stop `instance-attribute` [¶](#marimo.ui.number.stop "Permanent link") ### text `property` [¶](#marimo.ui.number.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.number.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.number.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.number.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.number.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.number.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.number.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "number"` Create a number picker from a dataframe series. ### left [¶](#marimo.ui.number.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.number.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.number.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.number.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Radio - marimo https://docs.marimo.io/api/inputs/radio/ marimo.ui.radio [¶](#marimo.ui.radio "Permanent link") ------------------------------------------------------ Bases: `UIElement[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)], [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` A radio group. Examples: `[](#__codelineno-0-1)radiogroup = mo.ui.radio( [](#__codelineno-0-2) options=["a", "b", "c"], value="a", label="choose one" [](#__codelineno-0-3))` `[](#__codelineno-1-1)radiogroup = mo.ui.radio( [](#__codelineno-1-2) options={"one": 1, "two": 2, "three": 3}, [](#__codelineno-1-3) value="one", [](#__codelineno-1-4) label="pick a number", [](#__codelineno-1-5))` Or from a dataframe series: `[](#__codelineno-2-1)radiogroup = mo.ui.radio.from_series(df["column_name"])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.radio.value "marimo.ui.radio.value")` | The value of the selected radio option. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | | `[options](#marimo.ui.radio.options "marimo.ui.radio.options")` | A dict mapping option name to option value. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)` | | PARAMETER | DESCRIPTION | | --- | --- | | `options` | Sequence of text options, or dict mapping option name to option value. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)] | [dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `value` | Default option name, if None, starts with nothing checked. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `inline` | Whether to display options inline. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `label` | Optional markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]` **DEFAULT:** `None` | ### options `instance-attribute` [¶](#marimo.ui.radio.options "Permanent link") ### text `property` [¶](#marimo.ui.radio.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.radio.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.radio.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.radio.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.radio.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.radio.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.radio.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "radio"` Create a radio group from a dataframe series. ### left [¶](#marimo.ui.radio.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.radio.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.radio.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.radio.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Range Slider - marimo https://docs.marimo.io/api/inputs/range_slider/ marimo.ui.range\_slider [¶](#marimo.ui.range_slider "Permanent link") --------------------------------------------------------------------- `[](#__codelineno-0-1)range_slider( [](#__codelineno-0-2) start: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-3) stop: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-4) step: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-5) value: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[Numeric]] = None, [](#__codelineno-0-6) debounce: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7) orientation: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-8) "horizontal", "vertical" [](#__codelineno-0-9) ] = "horizontal", [](#__codelineno-0-10) show_value: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) steps: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[Numeric]] = None, [](#__codelineno-0-12) *, [](#__codelineno-0-13) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-14) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-15) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[Numeric]], None] [](#__codelineno-0-16) ] = None, [](#__codelineno-0-17) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-18))` Bases: `UIElement[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[Numeric], [Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[Numeric]]` A numeric slider for specifying a range over an interval. **Example.** `[](#__codelineno-0-1)range_slider = mo.ui.range_slider(start=1, stop=10, step=2, value=[2, 6])` Or from a dataframe series: `[](#__codelineno-1-1)range_slider = mo.ui.range_slider.from_series(df["column_name"])` Or using numpy arrays: `[](#__codelineno-2-1)import numpy as np [](#__codelineno-2-2)[](#__codelineno-2-3)steps = np.array([1, 2, 3, 4, 5]) [](#__codelineno-2-4)# linear steps [](#__codelineno-2-5)range_slider = mo.ui.range_slider(steps=steps) [](#__codelineno-2-6)# log steps [](#__codelineno-2-7)log_range_slider = mo.ui.range_slider(steps=np.logspace(0, 3, 4)) [](#__codelineno-2-8)# power steps [](#__codelineno-2-9)power_range_slider = mo.ui.range_slider(steps=np.power([1, 2, 3], 2))` **Attributes.** * `value`: the current range value of the slider * `start`: the minimum value of the interval * `stop`: the maximum value of the interval * `step`: the slider increment * `steps`: list of steps **Initialization Args.** * `start`: the minimum value of the interval * `stop`: the maximum value of the interval * `step`: the slider increment * `value`: default value * `debounce`: whether to debounce the slider to only send the value on mouse-up or drag-end * `orientation`: the orientation of the slider, either "horizontal" or "vertical" * `show_value`: whether to display the current value of the slider * `steps`: list of steps to customize the slider, mutually exclusive with `start`, `stop`, and `step` * `label`: markdown label for the element * `on_change`: optional callback to run when this element's value changes * `full_width`: whether the input should take up the full width of its container ### start `instance-attribute` [¶](#marimo.ui.range_slider.start "Permanent link") ### step `instance-attribute` [¶](#marimo.ui.range_slider.step "Permanent link") ### steps `instance-attribute` [¶](#marimo.ui.range_slider.steps "Permanent link") ### stop `instance-attribute` [¶](#marimo.ui.range_slider.stop "Permanent link") ### text `property` [¶](#marimo.ui.range_slider.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.range_slider.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.range_slider.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.range_slider.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.range_slider.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.range_slider.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.range_slider.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "range_slider"` Create a range slider from a dataframe series. ### left [¶](#marimo.ui.range_slider.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.range_slider.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.range_slider.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.range_slider.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Refresh - marimo https://docs.marimo.io/api/inputs/refresh/ marimo.ui.refresh [¶](#marimo.ui.refresh "Permanent link") ---------------------------------------------------------- Bases: `UIElement[[int](https://docs.python.org/3/library/functions.html#int), [int](https://docs.python.org/3/library/functions.html#int)]` A refresh button that will auto-refresh its descendants for a given interval. Each option value can either be a number (int or float) in seconds or a human-readable string (e.g. "1s", "10s", "1m"). You can also combine multiple time units (e.g. "1m 30s"). Note The refresh interval may not be exact, as it depends on the time it takes to render the content and the time it takes to send the content to the client. Also, due to the buffering of UI element changes, if the downstream cells take a long time to render, the refresh interval may be longer than expected. Examples: `[](#__codelineno-0-1)refresh_button = mo.ui.refresh( [](#__codelineno-0-2) options=["1m", "5m 30s", "10m"], [](#__codelineno-0-3) default_interval="10m", [](#__codelineno-0-4)) [](#__codelineno-0-5)refresh_button` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.refresh.value "marimo.ui.refresh.value")` | The time in seconds since the refresh has been activated. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` | | PARAMETER | DESCRIPTION | | --- | --- | | `options` | The options for the refresh interval, as a list of human-readable strings or numbers (int or float) in seconds. If no options are provided and default\_interval is provided, the options will be generated automatically. If no options are provided and default\_interval is not provided, the refresh button will not be displayed with a dropdown for auto-refresh. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[list](https://docs.python.org/3/glossary.html#term-list)[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), [str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `default_interval` | The default value of the refresh interval. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[int](https://docs.python.org/3/library/functions.html#int)], None]]` **DEFAULT:** `None` | ### name `class-attribute` `instance-attribute` [¶](#marimo.ui.refresh.name "Permanent link") ### text `property` [¶](#marimo.ui.refresh.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.refresh.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.refresh.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.refresh.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.refresh.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.refresh.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.refresh.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.refresh.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.refresh.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.refresh.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Run Button - marimo https://docs.marimo.io/api/inputs/run_button/ Source code for `examples/ui/run_button.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.6" app = marimo.App() @app.cell def _(): import marimo as mo return (mo,) @app.cell def _(mo): first_button = mo.ui.run_button(label="Option 1") second_button = mo.ui.run_button(label="Option 2") first_button, second_button return first_button, second_button @app.cell def _(first_button, second_button): if first_button.value: print("You chose option 1!") elif second_button.value: print("You chose option 2!") else: print("Click a button!") return if __name__ == "__main__": app.run()` marimo.ui.run\_button [¶](#marimo.ui.run_button "Permanent link") ----------------------------------------------------------------- `[](#__codelineno-0-1)run_button( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "success", "warn", "danger" [](#__codelineno-0-4) ] = "neutral", [](#__codelineno-0-5) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-7) *, [](#__codelineno-0-8) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "click to run", [](#__codelineno-0-9) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]] = None, [](#__codelineno-0-10) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) keyboard_shortcut: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None [](#__codelineno-0-12))` Bases: `UIElement[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` A button that can be used to trigger computation. When clicked, run\_button's value is set to True, and any cells referencing it are run. After those cells are run, run\_button's value will automatically be set back to False as long as automatic execution is enabled. Examples: `[](#__codelineno-0-1)# a button that when clicked will have its value set to True; [](#__codelineno-0-2)# any cells referencing that button will automatically run. [](#__codelineno-0-3)button = mo.ui.run_button() [](#__codelineno-0-4)button` `[](#__codelineno-1-1)slider = mo.ui.slider(1, 10) [](#__codelineno-1-2)slider` `[](#__codelineno-2-1)# if the button hasn't been clicked, don't run. [](#__codelineno-2-2)mo.stop(not button.value) [](#__codelineno-2-3)[](#__codelineno-2-4)slider.value` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.run_button.value "marimo.ui.run_button.value")` | The value of the button; True when clicked, and reset to False after cells referencing the button finish running (when automatic execution is enabled). **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` | | PARAMETER | DESCRIPTION | | --- | --- | | `kind` | Button style. Defaults to "neutral". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['neutral', 'success', 'warn', 'danger']` **DEFAULT:** `'neutral'` | | `disabled` | Whether the button is disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `tooltip` | A tooltip to display for the button. Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "click to run". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'click to run'` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `keyboard_shortcut` | Keyboard shortcut to trigger the button (e.g. 'Ctrl-L'). Defaults to None. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.run_button.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.run_button.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.run_button.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.run_button.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.run_button.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.run_button.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.run_button.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.run_button.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.run_button.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.run_button.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Slider - marimo https://docs.marimo.io/api/inputs/slider/ marimo.ui.slider [¶](#marimo.ui.slider "Permanent link") -------------------------------------------------------- `[](#__codelineno-0-1)slider( [](#__codelineno-0-2) start: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-3) stop: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-4) step: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-5) value: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric] = None, [](#__codelineno-0-6) debounce: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7) orientation: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-8) "horizontal", "vertical" [](#__codelineno-0-9) ] = "horizontal", [](#__codelineno-0-10) show_value: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) steps: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[Numeric]] = None, [](#__codelineno-0-12) *, [](#__codelineno-0-13) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-14) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-15) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[Numeric]], None] [](#__codelineno-0-16) ] = None, [](#__codelineno-0-17) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-18))` Bases: `UIElement[Numeric, Numeric]` A numeric slider over an interval. **Example.** `[](#__codelineno-0-1)slider = mo.ui.slider(start=1, stop=10, step=2)` Or from a dataframe series: `[](#__codelineno-1-1)slider = mo.ui.slider.from_series(df["column_name"])` Or using numpy arrays: `[](#__codelineno-2-1)import numpy as np [](#__codelineno-2-2)[](#__codelineno-2-3)# linear steps [](#__codelineno-2-4)steps = np.array([1, 2, 3, 4, 5]) [](#__codelineno-2-5)slider = mo.ui.slider(steps=steps) [](#__codelineno-2-6)# log steps [](#__codelineno-2-7)log_slider = mo.ui.slider(steps=np.logspace(0, 3, 4)) [](#__codelineno-2-8)# power steps [](#__codelineno-2-9)power_slider = mo.ui.slider(steps=np.power([1, 2, 3], 2))` **Attributes.** * `value`: the current numeric value of the slider * `start`: the minimum value of the interval * `stop`: the maximum value of the interval * `step`: the slider increment * `steps`: list of steps **Initialization Args.** * `start`: the minimum value of the interval * `stop`: the maximum value of the interval * `step`: the slider increment * `value`: default value * `debounce`: whether to debounce the slider to only send the value on mouse-up or drag-end * `orientation`: the orientation of the slider, either "horizontal" or "vertical" * `show_value`: whether to display the current value of the slider * `steps`: list of steps to customize the slider, mutually exclusive with `start`, `stop`, and `step` * `label`: markdown label for the element * `on_change`: optional callback to run when this element's value changes * `full_width`: whether the input should take up the full width of its container ### start `instance-attribute` [¶](#marimo.ui.slider.start "Permanent link") ### step `instance-attribute` [¶](#marimo.ui.slider.step "Permanent link") ### steps `instance-attribute` [¶](#marimo.ui.slider.steps "Permanent link") ### stop `instance-attribute` [¶](#marimo.ui.slider.stop "Permanent link") ### text `property` [¶](#marimo.ui.slider.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.slider.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.slider.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.slider.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.slider.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.slider.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### from\_series `staticmethod` [¶](#marimo.ui.slider.from_series "Permanent link") `[](#__codelineno-0-1)from_series( [](#__codelineno-0-2) series: DataFrameSeries, **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-3)) -> "slider"` Create a slider from a dataframe series. ### left [¶](#marimo.ui.slider.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.slider.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.slider.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.slider.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Switch - marimo https://docs.marimo.io/api/inputs/switch/ marimo.ui.switch [¶](#marimo.ui.switch "Permanent link") -------------------------------------------------------- Bases: `UIElement[[bool](https://docs.python.org/3/library/functions.html#bool), [bool](https://docs.python.org/3/library/functions.html#bool)]` A boolean switch. Examples: | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.switch.value "marimo.ui.switch.value")` | A boolean, `True` if checked. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` | | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Default value, True or False. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[bool](https://docs.python.org/3/library/functions.html#bool)], None]]` **DEFAULT:** `None` | ### text `property` [¶](#marimo.ui.switch.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.switch.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.switch.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.switch.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.switch.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.switch.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.switch.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.switch.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.switch.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.switch.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Tabs - marimo https://docs.marimo.io/api/inputs/tabs/ marimo.ui.tabs [¶](#marimo.ui.tabs "Permanent link") ---------------------------------------------------- Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]` Display objects in a tabbed view. Examples: Show content in tabs: `[](#__codelineno-0-1)tab1 = mo.vstack([ [](#__codelineno-0-2) "slider": mo.ui.slider(1, 10), [](#__codelineno-0-3) "text": mo.ui.text(), [](#__codelineno-0-4) "date": mo.ui.date() [](#__codelineno-0-5)]) [](#__codelineno-0-6)[](#__codelineno-0-7)tab2 = mo.md("You can show arbitrary content in a tab.") [](#__codelineno-0-8)[](#__codelineno-0-9)tabs = mo.ui.tabs({ [](#__codelineno-0-10) "Heading 1": tab1, [](#__codelineno-0-11) "Heading 2": tab2 [](#__codelineno-0-12)})` Control which tab is selected: `[](#__codelineno-1-1)tabs = mo.ui.tabs( [](#__codelineno-1-2) {"Heading 1": tab1, "Heading 2": tab2}, value="Heading 2" [](#__codelineno-1-3))` Tab content can be lazily loaded: `[](#__codelineno-2-1)tabs = mo.ui.tabs( [](#__codelineno-2-2) {"Heading 1": tab1, "Heading 2": expensive_component}, lazy=True [](#__codelineno-2-3))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.tabs.value "marimo.ui.tabs.value")` | The name of the selected tab. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `tabs` | A dictionary of tab names to tab content; strings are interpreted as markdown. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [object](https://docs.python.org/3/glossary.html#term-object)]` | | `value` | The name of the tab to open. Defaults to the first tab. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `lazy` | Whether to lazily load the tab content. This is a convenience that wraps each tab in a `mo.lazy` component. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### text `property` [¶](#marimo.ui.tabs.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.tabs.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.tabs.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.tabs.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.tabs.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.tabs.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.tabs.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.tabs.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.tabs.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.tabs.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Table - marimo https://docs.marimo.io/api/inputs/table/ `[](#__codelineno-0-1)table( [](#__codelineno-0-2) data: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[ [](#__codelineno-0-3) ListOrTuple[ [](#__codelineno-0-4) [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), [bool](https://docs.python.org/3/library/functions.html#bool), MIME, None] [](#__codelineno-0-5) ], [](#__codelineno-0-6) ListOrTuple[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), JSONType]], [](#__codelineno-0-7) [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), ListOrTuple[JSONType]], [](#__codelineno-0-8) "IntoDataFrame", [](#__codelineno-0-9) ], [](#__codelineno-0-10) pagination: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[bool](https://docs.python.org/3/library/functions.html#bool)] = None, [](#__codelineno-0-11) selection: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-12) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["single", "multi"] [](#__codelineno-0-13) ] = "multi", [](#__codelineno-0-14) initial_selection: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[int](https://docs.python.org/3/library/functions.html#int)]] = None, [](#__codelineno-0-15) page_size: [int](https://docs.python.org/3/library/functions.html#int) = 10, [](#__codelineno-0-16) show_column_summaries: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[bool](https://docs.python.org/3/library/functions.html#bool), [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["stats", "chart"]] [](#__codelineno-0-18) ] = None, [](#__codelineno-0-19) format_mapping: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-20) [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]] [](#__codelineno-0-21) ] = None, [](#__codelineno-0-22) freeze_columns_left: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-23) freeze_columns_right: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-24) text_justify_columns: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-25) [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["left", "center", "right"]] [](#__codelineno-0-26) ] = None, [](#__codelineno-0-27) wrapped_columns: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-28) show_download: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-29) max_columns: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = 50, [](#__codelineno-0-30) *, [](#__codelineno-0-31) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-32) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-33) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[ [](#__codelineno-0-34) [ [](#__codelineno-0-35) [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[ [](#__codelineno-0-36) [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType], [](#__codelineno-0-37) [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), ListOrTuple[JSONType]], [](#__codelineno-0-38) "IntoDataFrame", [](#__codelineno-0-39) ] [](#__codelineno-0-40) ], [](#__codelineno-0-41) None, [](#__codelineno-0-42) ] [](#__codelineno-0-43) ] = None, [](#__codelineno-0-44) _internal_column_charts_row_limit: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-45) _internal_summary_row_limit: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-46) _internal_total_rows: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-47) [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["too_many"]] [](#__codelineno-0-48) ] = None [](#__codelineno-0-49))` Bases: `UIElement[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)], [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[int](https://docs.python.org/3/library/functions.html#int)]], [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType], IntoDataFrame]]` A table component with selectable rows. Get the selected rows with `table.value`. The table data can be supplied as: 1. a list of dicts, with one dict for each row, keyed by column names; 2. a list of values, representing a table with a single column; 3. a Pandas dataframe; or 4. a Polars dataframe; or 5. an Ibis dataframe; or 6. a PyArrow table. Examples: Create a table from a list of dicts, one for each row: `[](#__codelineno-0-1)table = mo.ui.table( [](#__codelineno-0-2) data=[ [](#__codelineno-0-3) {"first_name": "Michael", "last_name": "Scott"}, [](#__codelineno-0-4) {"first_name": "Dwight", "last_name": "Schrute"}, [](#__codelineno-0-5) ], [](#__codelineno-0-6) label="Users", [](#__codelineno-0-7))` Create a table from a single column of data: `[](#__codelineno-1-1)table = mo.ui.table( [](#__codelineno-1-2) data=[ [](#__codelineno-1-3) {"first_name": "Michael", "last_name": "Scott"}, [](#__codelineno-1-4) {"first_name": "Dwight", "last_name": "Schrute"}, [](#__codelineno-1-5) ], [](#__codelineno-1-6) label="Users", [](#__codelineno-1-7))` Create a table from a dataframe: `[](#__codelineno-2-1)# df is a Pandas or Polars dataframe [](#__codelineno-2-2)table = mo.ui.table( [](#__codelineno-2-3) data=df, [](#__codelineno-2-4) # use pagination when your table has many rows [](#__codelineno-2-5) pagination=True, [](#__codelineno-2-6) label="Dataframe", [](#__codelineno-2-7))` Create a table with format mapping: `[](#__codelineno-3-1)# format_mapping is a dict keyed by column names, [](#__codelineno-3-2)# with values as formatting functions or strings [](#__codelineno-3-3)def format_name(name): [](#__codelineno-3-4) return name.upper() [](#__codelineno-3-5) [](#__codelineno-3-6)[](#__codelineno-3-7)table = mo.ui.table( [](#__codelineno-3-8) data=[ [](#__codelineno-3-9) {"first_name": "Michael", "last_name": "Scott", "age": 45}, [](#__codelineno-3-10) {"first_name": "Dwight", "last_name": "Schrute", "age": 40}, [](#__codelineno-3-11) ], [](#__codelineno-3-12) format_mapping={ [](#__codelineno-3-13) "first_name": format_name, # Use callable to format first names [](#__codelineno-3-14) "age": "{:.1f}".format, # Use string format for age [](#__codelineno-3-15) }, [](#__codelineno-3-16) label="Format Mapping", [](#__codelineno-3-17))` In each case, access the table data with `table.value`. | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.table.value "marimo.ui.table.value")` | The selected rows, in the same format as the original data, or None if no selection. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType], IntoDataFrame]` | | `[data](#marimo.ui.table.data "marimo.ui.table.data")` | The original table data. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType], IntoDataFrame]` | | PARAMETER | DESCRIPTION | | --- | --- | | `data` | Values can be primitives (`str`, `int`, `float`, `bool`, or `None`) or marimo elements: e.g. `mo.ui.button(...)`, `mo.md(...)`, `mo.as_html(...)`, etc. Data can be passed in many ways: - as dataframes: a pandas dataframe, a polars dataframe - as rows: a list of dicts, where each dict represents a row in the table - as columns: a dict keyed by column names, where the value of each entry is a list representing a column - as a single column: a list of values **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [int](https://docs.python.org/3/library/functions.html#int), [float](https://docs.python.org/3/library/functions.html#float), [bool](https://docs.python.org/3/library/functions.html#bool), MIME, None]], [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), JSONType]], [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType]], IntoDataFrame]` | | `pagination` | Whether to paginate; if False, all rows will be shown. Defaults to True when above 10 rows, False otherwise. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `None` | | `selection` | 'single' or 'multi' to enable row selection, or None to disable. Defaults to "multi". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['single', 'multi']` **DEFAULT:** `'multi'` | | `initial_selection` | Indices of the rows you want selected by default. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[int](https://docs.python.org/3/library/functions.html#int)]` **DEFAULT:** `None` | | `page_size` | The number of rows to show per page. Defaults to 10. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `10` | | `show_column_summaries` | Whether to show column summaries. Defaults to True when the table has less than 40 columns, False otherwise. If "stats", only show stats. If "chart", only show charts. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[bool](https://docs.python.org/3/library/functions.html#bool), [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['stats', 'chart']]` **DEFAULT:** `None` | | `show_download` | Whether to show the download button. Defaults to True for dataframes, False otherwise. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `format_mapping` | A mapping from column names to formatting strings or functions. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]]` **DEFAULT:** `None` | | `freeze_columns_left` | List of column names to freeze on the left. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `freeze_columns_right` | List of column names to freeze on the right. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `text_justify_columns` | Dictionary of column names to text justification options: left, center, right. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['left', 'center', 'right']]` **DEFAULT:** `None` | | `wrapped_columns` | List of column names to wrap. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType], [Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[JSONType]], IntoDataFrame]], None]` **DEFAULT:** `None` | | `max_columns` | Maximum number of columns to display. Defaults to 50. Set to None to show all columns. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `50` | ### data `property` [¶](#marimo.ui.table.data "Permanent link") Get the original table data. | RETURNS | DESCRIPTION | | --- | --- | | `TableData` | The original data passed to the table constructor, in its original format (list, dict, dataframe, etc.). **TYPE:** `TableData` | ### text `property` [¶](#marimo.ui.table.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.table.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.table.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.table.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.table.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.table.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.table.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.table.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.table.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.table.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Control Flow - marimo https://docs.marimo.io/api/control_flow/ Use `mo.stop` to halt execution of a cell, and optionally output an object. This function is useful for validating user input. marimo.stop [¶](#marimo.stop "Permanent link") ---------------------------------------------- Stops execution of a cell when `predicate` is `True` When `predicate` is `True`, this function raises a `MarimoStopError`. If uncaught, this exception stops execution of the current cell and makes `output` its output. Any descendants of this cell that were previously scheduled to run will not be run, and their defs will be removed from program memory. **Example:** `[](#__codelineno-0-1)mo.stop(form.value is None, mo.md("**Submit the form to continue.**"))` **Raises:** When `predicate` is `True`, raises a `MarimoStopError`. Use [`mo.ui.refresh`](https://docs.marimo.io/api/inputs/refresh/#marimo.ui.refresh) to trigger other cells to run periodically, on a configurable interval (or on click). Text - marimo https://docs.marimo.io/api/inputs/text/ marimo.ui.text [¶](#marimo.ui.text "Permanent link") ---------------------------------------------------- `[](#__codelineno-0-1)text( [](#__codelineno-0-2) value: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) placeholder: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-4) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-5) "text", "password", "email", "url" [](#__codelineno-0-6) ] = "text", [](#__codelineno-0-7) max_length: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-8) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) debounce: [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) = True, [](#__codelineno-0-10) *, [](#__codelineno-0-11) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-12) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]] = None, [](#__codelineno-0-13) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-14))` Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]` A text input. Examples: `[](#__codelineno-0-1)text = mo.ui.text(value="Hello, World!")` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.text.value "marimo.ui.text.value")` | A string of the input's contents. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Default value of text box. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `placeholder` | Placeholder text to display when the text area is empty. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `kind` | Input kind. Defaults to "text". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['text', 'password', 'email', 'url']` **DEFAULT:** `'text'` | | `max_length` | Maximum length of input. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `disabled` | Whether the input is disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `debounce` | Whether the input is debounced. If number, debounce by that many milliseconds. If True, then value is only emitted on Enter or when the input loses focus. Defaults to True. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `True` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### text `property` [¶](#marimo.ui.text.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.text.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.text.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.text.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.text.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.text.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.text.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.text.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.text.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.text.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Text Area - marimo https://docs.marimo.io/api/inputs/text_area/ Source code for `examples/ui/text_area.py` Tip: paste this code into an empty cell, and the marimo editor will create cells for you `import marimo __generated_with = "0.10.9" app = marimo.App() @app.cell def _(): import marimo as mo return (mo,) @app.cell def _(mo): text_area = mo.ui.text_area(placeholder="type some text ...") text_area return (text_area,) @app.cell def _(text_area): text_area.value return if __name__ == "__main__": app.run()` marimo.ui.text\_area [¶](#marimo.ui.text_area "Permanent link") --------------------------------------------------------------- `[](#__codelineno-0-1)text_area( [](#__codelineno-0-2) value: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) placeholder: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-4) max_length: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-5) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) debounce: [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) = True, [](#__codelineno-0-7) rows: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-8) *, [](#__codelineno-0-9) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-10) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]] = None, [](#__codelineno-0-11) full_width: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-12))` Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]` A text area that is larger than `ui.text`. Examples: `[](#__codelineno-0-1)text_area = mo.ui.text_area()` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.text_area.value "marimo.ui.text_area.value")` | A string of the text area contents. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Initial value of the text area. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `placeholder` | Placeholder text to display when the text area is empty. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `max_length` | Maximum length of input. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `disabled` | Whether the input is disabled. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `debounce` | Whether the input is debounced. If number, debounce by that many milliseconds. If True, then value is only emitted on Ctrl+Enter or when the input loses focus. Defaults to True. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `True` | | `rows` | Number of rows of text to display. Defaults to None. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[str](https://docs.python.org/3/library/stdtypes.html#str)], None]` **DEFAULT:** `None` | | `full_width` | Whether the input should take up the full width of its container. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### text `property` [¶](#marimo.ui.text_area.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.text_area.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.text_area.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.text_area.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.text_area.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.text_area.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.text_area.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.text_area.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.text_area.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.text_area.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Layouts - marimo https://docs.marimo.io/api/layouts/ marimo has higher-order layout functions that you can use to arrange outputs in rows, columns, tables, tabs, and more. Stateless[¶](#stateless "Permanent link") ----------------------------------------- Unlike elements in `marimo.ui`, these don't have any values associated with them but just render their children in a certain way. | Function | Description | | --- | --- | | [`marimo.accordion`](https://docs.marimo.io/api/layouts/accordion/#marimo.accordion) | Create collapsible sections | | [`marimo.carousel`](https://docs.marimo.io/api/layouts/carousel/#marimo.carousel) | Create a slideshow | | [`marimo.callout`](https://docs.marimo.io/api/layouts/callout/#marimo.callout) | Create highlighted sections | | [`marimo.center`](https://docs.marimo.io/api/layouts/justify/#marimo.center) | Center content | | [`marimo.hstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.hstack) | Stack elements horizontally | | [`marimo.lazy`](https://docs.marimo.io/api/layouts/lazy/#marimo.lazy) | Lazy load content | | [`marimo.left`](https://docs.marimo.io/api/layouts/justify/#marimo.left) | Left-align content | | [`marimo.nav_menu`](https://docs.marimo.io/api/inputs/nav_menu/#marimo.nav_menu) | Create navigation menus | | [`marimo.plain`](https://docs.marimo.io/api/layouts/plain/#marimo.plain) | Display content without styling | | [`marimo.right`](https://docs.marimo.io/api/layouts/justify/#marimo.right) | Right-align content | | [`marimo.routes`](https://docs.marimo.io/api/layouts/routes/#marimo.routes) | Create page routing | | [`marimo.sidebar`](https://docs.marimo.io/api/layouts/sidebar/#marimo.sidebar) | Create sidebars | | [`marimo.tree`](https://docs.marimo.io/api/layouts/tree/#marimo.tree) | Create tree structures | | [`marimo.vstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.vstack) | Stack elements vertically | Stateful[¶](#stateful "Permanent link") --------------------------------------- Some elements in `marimo.ui` are also helpful for layout. These elements do have values associated with them: for example, `tabs` tracks the selected tab name, and `table` tracks the selected rows. | Function | Description | | --- | --- | | [`marimo.ui.tabs`](https://docs.marimo.io/api/inputs/tabs/#marimo.ui.tabs) | Create tabbed interfaces | | [`marimo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table) | Create interactive tables | Accordion - marimo https://docs.marimo.io/api/layouts/accordion/ Accordion of one or more items. | PARAMETER | DESCRIPTION | | --- | --- | | `items` | a dictionary of item names to item content; strings are interpreted as markdown **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [object](https://docs.python.org/3/glossary.html#term-object)]` | | `multiple` | whether to allow multiple items to be open simultaneously **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `lazy` | a boolean, whether to lazily load the accordion content. This is a convenience that wraps each accordion in a `mo.lazy` component. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | Example `[](#__codelineno-0-1)mo.accordion( [](#__codelineno-0-2) {"Tip": "Use accordions to let users reveal and hide content."} [](#__codelineno-0-3))` Accordion content can be lazily loaded: `[](#__codelineno-1-1)mo.accordion({"View total": expensive_item}, lazy=True)` where `expensive_item` is the item to render, or a callable that returns the item to render. Callout - marimo https://docs.marimo.io/api/layouts/callout/ marimo.callout [¶](#marimo.callout "Permanent link") ---------------------------------------------------- `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) value: [object](https://docs.python.org/3/glossary.html#term-object), [](#__codelineno-0-3) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-4) "neutral", "warn", "success", "info", "danger" [](#__codelineno-0-5) ] = "neutral", [](#__codelineno-0-6)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Build a callout output. | PARAMETER | DESCRIPTION | | --- | --- | | `value` | A value to render in the callout **TYPE:** `[object](https://docs.python.org/3/glossary.html#term-object)` | | `kind` | The kind of callout (affects styling). **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['neutral', 'warn', 'success', 'info', 'danger']` **DEFAULT:** `'neutral'` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An HTML object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo.Html")` | Justify - marimo https://docs.marimo.io/api/layouts/justify/ marimo.center [¶](#marimo.center "Permanent link") -------------------------------------------------- `[](#__codelineno-0-1)center(item: [object](https://docs.python.org/3/glossary.html#term-object)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Center an item. | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | A centered `Html` object. | marimo.left [¶](#marimo.left "Permanent link") ---------------------------------------------- `[](#__codelineno-0-1)left(item: [object](https://docs.python.org/3/glossary.html#term-object)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Left-justify an item. | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | A left-justified `Html` object. | marimo.right [¶](#marimo.right "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)right(item: [object](https://docs.python.org/3/glossary.html#term-object)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Right-justify an item. | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | A right-justified `Html` object. | Carousel - marimo https://docs.marimo.io/api/layouts/carousel/ Create a carousel of items. | PARAMETER | DESCRIPTION | | --- | --- | | `items` | A list of items. **TYPE:** `[Sequence](https://docs.python.org/3/library/typing.html#typing.Sequence "typing.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)]` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | Example `[](#__codelineno-0-1)mo.carousel([mo.md("..."), mo.ui.text_area()])` Plain - marimo https://docs.marimo.io/api/layouts/plain/ marimo.plain [¶](#marimo.plain "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)plain(value: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")) -> Plain` Wrap a value to indicate that it should be displayed without any opinionated formatting. This is the best way to opt out of marimo's default dataframe rendering. Example `[](#__codelineno-0-1)df = data.cars() [](#__codelineno-0-2)mo.plain(df)` | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Any value **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` | Lazy - marimo https://docs.marimo.io/api/layouts/lazy/ marimo.lazy [¶](#marimo.lazy "Permanent link") ---------------------------------------------- Bases: `UIElement[[bool](https://docs.python.org/3/library/functions.html#bool), [bool](https://docs.python.org/3/library/functions.html#bool)]` Lazy load a component until it is visible. Use `mo.lazy` to defer rendering of an item until it's visible. This is useful for loading expensive components only when they are needed, e.g., only when an accordion or tab is opened. The argument to `mo.lazy` can be an object to render lazily, or a function that returns the object to render (that is, functions are lazily evaluated). The function can be synchronous or asynchronous. Using a function is useful when the item to render is the result of a database query or some other expensive operation. Examples: Create a lazy-loaded tab: `[](#__codelineno-0-1)tabs = mo.ui.tabs( [](#__codelineno-0-2) {"Overview": tab1, "Charts": mo.lazy(expensive_component)} [](#__codelineno-0-3))` Create a lazy-loaded accordion: `[](#__codelineno-1-1)accordion = mo.accordion({"Charts": mo.lazy(expensive_component)})` Usage with async functions: `[](#__codelineno-2-1)async def expensive_component(): ... [](#__codelineno-2-2) [](#__codelineno-2-3)[](#__codelineno-2-4)mo.lazy(expensive_component)` | PARAMETER | DESCRIPTION | | --- | --- | | `element` | Object or callable that returns content to be lazily loaded. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[], [object](https://docs.python.org/3/glossary.html#term-object)], [object](https://docs.python.org/3/glossary.html#term-object), [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[], [Coroutine](https://docs.python.org/3/library/typing.html#typing.Coroutine "typing.Coroutine")[None, None, [object](https://docs.python.org/3/glossary.html#term-object)]]]` | | `show_loading_indicator` | Whether to show a loading indicator while the content is being loaded. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### text `property` [¶](#marimo.lazy.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.lazy.value "Permanent link") The element's current value. ### batch [¶](#marimo.lazy.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.lazy.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.lazy.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.lazy.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.lazy.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.lazy.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.lazy.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.lazy.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Routes - marimo https://docs.marimo.io/api/layouts/routes/ marimo.routes [¶](#marimo.routes "Permanent link") -------------------------------------------------- Bases: `UIElement[[str](https://docs.python.org/3/library/stdtypes.html#str), [str](https://docs.python.org/3/library/stdtypes.html#str)]` Renders a list of routes that are switched based on the URL path. Routes currently don't support nested routes, or dynamic routes (e.g. `#/user/:id`). If you'd like to see these features, please let us know on GitHub: [https://github.com/marimo-team/marimo/issues](https://github.com/marimo-team/marimo/issues) For a simple-page-application (SPA) experience, you should use hash-based routing. For example, prefix your routes with `#/`. If you are using a multi-page-application (MPA) with `marimo.create_asgi_app`, you should use path-based routing. For example, prefix your routes with `/`. Examples: `[](#__codelineno-0-1)mo.routes( [](#__codelineno-0-2) { [](#__codelineno-0-3) "#/": render_home, [](#__codelineno-0-4) "#/about": render_about, [](#__codelineno-0-5) "#/contact": render_contact, [](#__codelineno-0-6) mo.routes.CATCH_ALL: render_home, [](#__codelineno-0-7) } [](#__codelineno-0-8))` | PARAMETER | DESCRIPTION | | --- | --- | | `routes` | A dictionary of routes, where the key is the URL path and the value is a function that returns the content to display. **TYPE:** `[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[], [object](https://docs.python.org/3/glossary.html#term-object)], [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[], [Coroutine](https://docs.python.org/3/library/typing.html#typing.Coroutine "typing.Coroutine")[None, None, [object](https://docs.python.org/3/glossary.html#term-object)]], [object](https://docs.python.org/3/glossary.html#term-object)]]` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An Html object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo.Html")` | ### CATCH\_ALL `class-attribute` `instance-attribute` [¶](#marimo.routes.CATCH_ALL "Permanent link") ### DEFAULT `class-attribute` `instance-attribute` [¶](#marimo.routes.DEFAULT "Permanent link") ### text `property` [¶](#marimo.routes.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.routes.value "Permanent link") The element's current value. ### batch [¶](#marimo.routes.batch "Permanent link") ### callout [¶](#marimo.routes.callout "Permanent link") ### center [¶](#marimo.routes.center "Permanent link") ### form [¶](#marimo.routes.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.routes.left "Permanent link") ### right [¶](#marimo.routes.right "Permanent link") ### send\_message [¶](#marimo.routes.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.routes.style "Permanent link") python import marimo app = marimo.App() @app.cell def \_\_(): import marimo as mo return @app.cell def \_\_(): mo.sidebar( \[ mo.md("# marimo"), mo.nav\_menu( { "#/": f"{mo.icon('lucide:home')} Home", "#/about": f"{mo.icon('lucide:user')} About", "#/contact": f"{mo.icon('lucide:phone')} Contact", "Links": { "[https://twitter.com/marimo\_io](https://twitter.com/marimo_io)": "Twitter", "[https://github.com/marimo-team/marimo](https://github.com/marimo-team/marimo)": "GitHub", }, }, orientation="vertical", ), \] ) return @app.cell def \_\_(): mo.routes({ "#/": mo.md("# Home"), "#/about": mo.md("# About"), "#/contact": mo.md("# Contact"), mo.routes.CATCH\_ALL: mo.md("# Home"), }) return Sidebar - marimo https://docs.marimo.io/api/layouts/sidebar/ Bases: `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Displays content in a sidebar. This is a special layout component that will display the content in a sidebar layout, rather than below/above the cell. This component still needs to be the last expression in the cell, in order to display correctly. You may use more than one `mo.sidebar` - they will be displayed in the order they are called. Examples: `[](#__codelineno-0-1)mo.sidebar( [](#__codelineno-0-2) [ [](#__codelineno-0-3) mo.md("# marimo"), [](#__codelineno-0-4) mo.nav_menu( [](#__codelineno-0-5) { [](#__codelineno-0-6) "#home": f"{mo.icon('lucide:home')} Home", [](#__codelineno-0-7) "#about": f"{mo.icon('lucide:user')} About", [](#__codelineno-0-8) "#contact": f"{mo.icon('lucide:phone')} Contact", [](#__codelineno-0-9) "Links": { [](#__codelineno-0-10) "https://twitter.com/marimo_io": "Twitter", [](#__codelineno-0-11) "https://github.com/marimo-team/marimo": "GitHub", [](#__codelineno-0-12) }, [](#__codelineno-0-13) }, [](#__codelineno-0-14) orientation="vertical", [](#__codelineno-0-15) ), [](#__codelineno-0-16) ] [](#__codelineno-0-17))` | PARAMETER | DESCRIPTION | | --- | --- | | `item` | The content to display in the sidebar. **TYPE:** `[object](https://docs.python.org/3/glossary.html#term-object)` | | `footer` | The content to display at the bottom of the sidebar. **TYPE:** `[object](https://docs.python.org/3/glossary.html#term-object)` **DEFAULT:** `None` | | `width` | The width of the sidebar when open. Can be any valid CSS width value (e.g. "300px", "20rem"). If not provided, defaults to the standard width. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An Html object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo.Html")` | A string of HTML representing this element. Tree - marimo https://docs.marimo.io/api/layouts/tree/ Render a nested structure of lists, tuples, or dicts as a tree. Example `[](#__codelineno-0-1)mo.tree( [](#__codelineno-0-2) ["entry", "another entry", {"key": [0, 1, 2]}], label="A tree." [](#__codelineno-0-3))` | PARAMETER | DESCRIPTION | | --- | --- | | `items` | nested structure of lists, tuples, or dicts **TYPE:** `[list](https://docs.python.org/3/glossary.html#term-list)[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")] | [tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")] | [dict](https://docs.python.org/3/reference/expressions.html#dict)[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `label` | optional text label for the tree **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | `Html` object **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | Stacks - marimo https://docs.marimo.io/api/layouts/stacks/ marimo.hstack [¶](#marimo.hstack "Permanent link") -------------------------------------------------- `[](#__codelineno-0-1)hstack( [](#__codelineno-0-2) items: [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)], [](#__codelineno-0-3) *, [](#__codelineno-0-4) justify: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-5) "start", [](#__codelineno-0-6) "center", [](#__codelineno-0-7) "end", [](#__codelineno-0-8) "space-between", [](#__codelineno-0-9) "space-around", [](#__codelineno-0-10) ] = "space-between", [](#__codelineno-0-11) align: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-12) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["start", "end", "center", "stretch"] [](#__codelineno-0-13) ] = None, [](#__codelineno-0-14) wrap: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-15) gap: [float](https://docs.python.org/3/library/functions.html#float) = 0.5, [](#__codelineno-0-16) widths: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["equal"] | [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[float](https://docs.python.org/3/library/functions.html#float)] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Stack items horizontally, in a row. Combine with `vstack` to build a grid. Examples: Build a row of items: `[](#__codelineno-0-1)# Build a row of items [](#__codelineno-0-2)mo.hstack([mo.md("..."), mo.ui.text_area()])` Build a grid: `[](#__codelineno-1-1)# Build a grid. [](#__codelineno-1-2)mo.hstack( [](#__codelineno-1-3) [ [](#__codelineno-1-4) mo.vstack([mo.md("..."), mo.ui.text_area()]), [](#__codelineno-1-5) mo.vstack([mo.ui.checkbox(), mo.ui.text(), mo.ui.date()]), [](#__codelineno-1-6) ] [](#__codelineno-1-7))` | PARAMETER | DESCRIPTION | | --- | --- | | `items` | A list of items. **TYPE:** `[Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)]` | | `justify` | Justify items horizontally: start, center, end, space-between, or space-around. Defaults to "space-between". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['start', 'center', 'end', 'space-between', 'space-around']` **DEFAULT:** `'space-between'` | | `align` | Align items vertically: start, end, center, or stretch. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['start', 'end', 'center', 'stretch']]` **DEFAULT:** `None` | | `wrap` | Wrap items or not. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `gap` | Gap between items as a float in rem. 1rem is 16px by default. Defaults to 0.5. **TYPE:** `[float](https://docs.python.org/3/library/functions.html#float)` **DEFAULT:** `0.5` | | `widths` | "equal" to give items equal width; or a list of relative widths with same length as `items`, eg, \[1, 2\] means the second item is twice as wide as the first; or None for a sensible default. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['equal'] | [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[float](https://docs.python.org/3/library/functions.html#float)]]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An Html object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | marimo.vstack [¶](#marimo.vstack "Permanent link") -------------------------------------------------- `[](#__codelineno-0-1)vstack( [](#__codelineno-0-2) items: [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)], [](#__codelineno-0-3) *, [](#__codelineno-0-4) align: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-5) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["start", "end", "center", "stretch"] [](#__codelineno-0-6) ] = None, [](#__codelineno-0-7) justify: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-8) "start", [](#__codelineno-0-9) "center", [](#__codelineno-0-10) "end", [](#__codelineno-0-11) "space-between", [](#__codelineno-0-12) "space-around", [](#__codelineno-0-13) ] = "start", [](#__codelineno-0-14) gap: [float](https://docs.python.org/3/library/functions.html#float) = 0.5, [](#__codelineno-0-15) heights: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-16) [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")["equal"] | [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[float](https://docs.python.org/3/library/functions.html#float)] [](#__codelineno-0-17) ] = None [](#__codelineno-0-18)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Stack items vertically, in a column. Combine with `hstack` to build a grid of items. Examples: Build a column of items: `[](#__codelineno-0-1)# Build a column of items [](#__codelineno-0-2)mo.vstack([mo.md("..."), mo.ui.text_area()])` Build a grid: `[](#__codelineno-1-1)# Build a grid. [](#__codelineno-1-2)mo.vstack( [](#__codelineno-1-3) [ [](#__codelineno-1-4) mo.hstack([mo.md("..."), mo.ui.text_area()]), [](#__codelineno-1-5) mo.hstack([mo.ui.checkbox(), mo.ui.text(), mo.ui.date()]), [](#__codelineno-1-6) ] [](#__codelineno-1-7))` | PARAMETER | DESCRIPTION | | --- | --- | | `items` | A list of items. **TYPE:** `[Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[object](https://docs.python.org/3/glossary.html#term-object)]` | | `align` | Align items horizontally: start, end, center, or stretch. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['start', 'end', 'center', 'stretch']]` **DEFAULT:** `None` | | `justify` | Justify items vertically: start, center, end, space-between, or space-around. Defaults to "start". **TYPE:** `[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['start', 'center', 'end', 'space-between', 'space-around']` **DEFAULT:** `'start'` | | `gap` | Gap between items as a float in rem. 1rem is 16px by default. Defaults to 0.5. **TYPE:** `[float](https://docs.python.org/3/library/functions.html#float)` **DEFAULT:** `0.5` | | `heights` | "equal" to give items equal height; or a list of relative heights with same length as `items`, eg, \[1, 2\] means the second item is twice as tall as the first; or None for a sensible default. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['equal'] | [Sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "collections.abc.Sequence")[[float](https://docs.python.org/3/library/functions.html#float)]]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An Html object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | Media - marimo https://docs.marimo.io/api/media/ Use these functions to embed media in your outputs. | Function | Description | | --- | --- | | [`marimo.image`](https://docs.marimo.io/api/media/image/) | Display images | | [`marimo.audio`](https://docs.marimo.io/api/media/audio/) | Play audio files | | [`marimo.video`](https://docs.marimo.io/api/media/video/) | Play videos | | [`marimo.pdf`](https://docs.marimo.io/api/media/pdf/) | Display PDFs | | [`marimo.download`](https://docs.marimo.io/api/media/download/) | Create download links | | [`marimo.plain_text`](https://docs.marimo.io/api/media/plain_text/) | Display plain text | Most of these methods accept URLs (including data URLs), paths to local files, or file-like objects. Plotting - marimo https://docs.marimo.io/api/plotting/ marimo supports most major plotting libraries, including Matplotlib, Seaborn, Plotly, and Altair. Just import your plotting library of choice and use it as you normally would. For more information about plotting, see the [plotting guide](https://docs.marimo.io/guides/working_with_data/plotting/). Reactive charts with Altair[¶](#reactive-charts-with-altair "Permanent link") ----------------------------------------------------------------------------- ### Disabling automatic selection[¶](#disabling-automatic-selection "Permanent link") marimo automatically adds a default selection based on the mark type, however, you may want to customize the selection behavior of your Altair chart. You can do this by setting `chart_selection` and `legend_selection` to `False`, and using `.add_params` directly on your Altair chart. `[](#__codelineno-1-1)# Create an interval selection [](#__codelineno-1-2)brush = alt.selection_interval(encodings=["x"]) [](#__codelineno-1-3)[](#__codelineno-1-4)_chart = ( [](#__codelineno-1-5) alt.Chart(traces, height=150) [](#__codelineno-1-6) .mark_line() [](#__codelineno-1-7) .encode(x="index:Q", y="value:Q", color="traces:N") [](#__codelineno-1-8) .add_params(brush) # add the selection to the chart [](#__codelineno-1-9)) [](#__codelineno-1-10)[](#__codelineno-1-11)chart = mo.ui.altair_chart( [](#__codelineno-1-12) _chart, [](#__codelineno-1-13) # disable automatic selection [](#__codelineno-1-14) chart_selection=False, [](#__codelineno-1-15) legend_selection=False [](#__codelineno-1-16)) [](#__codelineno-1-17)chart # You can now access chart.value to get the selected data` marimo.ui.altair\_chart [¶](#marimo.ui.altair_chart "Permanent link") --------------------------------------------------------------------- Bases: `UIElement[ChartSelection, ChartDataType]` Make reactive charts with Altair. Use `mo.ui.altair_chart` to make Altair charts reactive: select chart data with your cursor on the frontend, get them as a dataframe in Python! Supports polars, pandas, and arrow DataFrames. Examples: `[](#__codelineno-0-1)import altair as alt [](#__codelineno-0-2)import marimo as mo [](#__codelineno-0-3)from vega_datasets import data [](#__codelineno-0-4)[](#__codelineno-0-5)chart = ( [](#__codelineno-0-6) alt.Chart(data.cars()) [](#__codelineno-0-7) .mark_point() [](#__codelineno-0-8) .encode( [](#__codelineno-0-9) x="Horsepower", [](#__codelineno-0-10) y="Miles_per_Gallon", [](#__codelineno-0-11) color="Origin", [](#__codelineno-0-12) ) [](#__codelineno-0-13)) [](#__codelineno-0-14)[](#__codelineno-0-15)chart = mo.ui.altair_chart(chart)` `[](#__codelineno-1-1)# View the chart and selected data as a dataframe [](#__codelineno-1-2)mo.hstack([chart, chart.value])` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.altair_chart.value "marimo.ui.altair_chart.value")` | A dataframe of the plot data filtered by the selections. **TYPE:** `ChartDataType` | | `[dataframe](#marimo.ui.altair_chart.dataframe "marimo.ui.altair_chart.dataframe")` | A dataframe of the unfiltered chart data. **TYPE:** `ChartDataType` | | `[selections](#marimo.ui.altair_chart.selections "marimo.ui.altair_chart.selections")` | The selection of the chart; this may be an interval along the name of an axis or a selection of points. **TYPE:** `ChartSelection` | | PARAMETER | DESCRIPTION | | --- | --- | | `chart` | An Altair Chart object. **TYPE:** `Chart` | | `chart_selection` | Selection type, "point", "interval", or a bool. Defaults to True which will automatically detect the best selection type. This is ignored if the chart already has a point/interval selection param. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['point'], [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")['interval'], [bool](https://docs.python.org/3/library/functions.html#bool)]` **DEFAULT:** `True` | | `legend_selection` | List of legend fields (columns) for which to enable selection, True to enable selection for all fields, or False to disable selection entirely. This is ignored if the chart already has a legend selection param. Defaults to True. **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[list](https://docs.python.org/3/glossary.html#term-list)[[str](https://docs.python.org/3/library/stdtypes.html#str)], [bool](https://docs.python.org/3/library/functions.html#bool)]` **DEFAULT:** `True` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Optional callback to run when this element's value changes. Defaults to None. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[ChartDataType], None]]` **DEFAULT:** `None` | ### dataframe `instance-attribute` [¶](#marimo.ui.altair_chart.dataframe "Permanent link") `[](#__codelineno-0-1)dataframe: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-2) ChartDataType [](#__codelineno-0-3)] = _get_dataframe_from_chart(chart)` ### name `class-attribute` `instance-attribute` [¶](#marimo.ui.altair_chart.name "Permanent link") ### selections `property` [¶](#marimo.ui.altair_chart.selections "Permanent link") `[](#__codelineno-0-1)selections: ChartSelection` ### text `property` [¶](#marimo.ui.altair_chart.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.altair_chart.value "Permanent link") ### apply\_selection [¶](#marimo.ui.altair_chart.apply_selection "Permanent link") `[](#__codelineno-0-1)apply_selection(df: ChartDataType) -> ChartDataType` Apply the selection to a DataFrame. This method is useful when you have a layered chart and you want to apply the selection to a DataFrame. | PARAMETER | DESCRIPTION | | --- | --- | | `df` | A DataFrame to apply the selection to. **TYPE:** `ChartDataType` | | RETURNS | DESCRIPTION | | --- | --- | | `ChartDataType` | A DataFrame of the plot data filtered by the selections. **TYPE:** `ChartDataType` | Examples: `[](#__codelineno-0-1)import altair as alt [](#__codelineno-0-2)import marimo as mo [](#__codelineno-0-3)from vega_datasets import data [](#__codelineno-0-4)[](#__codelineno-0-5)cars = data.cars() [](#__codelineno-0-6)[](#__codelineno-0-7)_chart = ( [](#__codelineno-0-8) alt.Chart(cars) [](#__codelineno-0-9) .mark_point() [](#__codelineno-0-10) .encode( [](#__codelineno-0-11) x="Horsepower", [](#__codelineno-0-12) y="Miles_per_Gallon", [](#__codelineno-0-13) color="Origin", [](#__codelineno-0-14) ) [](#__codelineno-0-15)) [](#__codelineno-0-16)[](#__codelineno-0-17)chart = mo.ui.altair_chart(_chart) [](#__codelineno-0-18)chart [](#__codelineno-0-19)[](#__codelineno-0-20)# In another cell [](#__codelineno-0-21)selected_df = chart.apply_selection(cars)` ### batch [¶](#marimo.ui.altair_chart.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.altair_chart.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.altair_chart.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.altair_chart.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.altair_chart.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.altair_chart.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.altair_chart.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.altair_chart.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | ### Performance and Data Transformers[¶](#performance-and-data-transformers "Permanent link") Altair has a concept of [data](https://altair-viz.github.io/user_guide/data_transformers.html) transformers, which can be used to improve performance. Such examples are: * pandas Dataframe has to be sanitized and serialized to JSON. * The rows of a Dataframe might need to be sampled or limited to a maximum number. * The Dataframe might be written to a `.csv` or `.json` file for performance reasons. By default, Altair uses the `default` data transformer, which is the slowest in marimo. It is limited to 5000 rows (although we increase this to `20_000` rows as marimo can handle this). This includes the data inside the HTML that is being sent over the network, which can also be limited by marimo's maximum message size. It is recommended to use the `marimo_csv` data transformer, which is the most performant and can handle the largest datasets: it converts the data to a CSV file which is smaller and can be sent over the network. This can handle up to +400,000 rows with no issues. When using `mo.ui.altair_chart`, we automatically set the data transformer to `marimo_csv` for you. If you are using Altair directly, you can set the data transformer using the following code: `[](#__codelineno-2-1)import altair as alt [](#__codelineno-2-2)alt.data_transformers.enable('marimo_csv')` Reactive plots with Plotly[¶](#reactive-plots-with-plotly "Permanent link") --------------------------------------------------------------------------- mo.ui.plotly only supports scatter plots, treemaps charts, and sunbursts charts. marimo can render any Plotly plot, but [`mo.ui.plotly`](#marimo.ui.plotly) only supports reactive selections for scatter plots, treemaps charts, and sunbursts charts. If you require other kinds of selection, consider using [`mo.ui.altair_chart`](#marimo.ui.altair_chart). marimo.ui.plotly [¶](#marimo.ui.plotly "Permanent link") -------------------------------------------------------- Bases: `UIElement[PlotlySelection, [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]]` Make reactive plots with Plotly. Use `mo.ui.plotly` to make plotly plots reactive: select data with your cursor on the frontend, get them as a list of dicts in Python! This function currently only supports scatter plots, treemaps charts, and sunbursts charts. Examples: `[](#__codelineno-0-1)import plotly.express as px [](#__codelineno-0-2)import marimo as mo [](#__codelineno-0-3)from vega_datasets import data [](#__codelineno-0-4)[](#__codelineno-0-5)_plot = px.scatter( [](#__codelineno-0-6) data.cars(), x="Horsepower", y="Miles_per_Gallon", color="Origin" [](#__codelineno-0-7)) [](#__codelineno-0-8)[](#__codelineno-0-9)plot = mo.ui.plotly(_plot)` `[](#__codelineno-1-1)# View the plot and selected data [](#__codelineno-1-2)mo.hstack([plot, plot.value])` Or with custom configuration: `[](#__codelineno-2-1)plot = mo.ui.plotly( [](#__codelineno-2-2) _plot, [](#__codelineno-2-3) config={"staticPlot": True}, [](#__codelineno-2-4))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[value](#marimo.ui.plotly.value "marimo.ui.plotly.value")` | A dict of the plot data. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]` | | `[ranges](#marimo.ui.plotly.ranges "marimo.ui.plotly.ranges")` | The selection of the plot; this may be an interval along the name of an axis. **TYPE:** `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[float](https://docs.python.org/3/library/functions.html#float)]]` | | `[points](#marimo.ui.plotly.points "marimo.ui.plotly.points")` | The selected points data. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` | | `[indices](#marimo.ui.plotly.indices "marimo.ui.plotly.indices")` | The indices of selected points. **TYPE:** `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[int](https://docs.python.org/3/library/functions.html#int)]` | | PARAMETER | DESCRIPTION | | --- | --- | | `figure` | A plotly Figure object. **TYPE:** `Figure` | | `config` | Configuration for the plot. This is a dictionary that is passed directly to plotly. See the plotly documentation for more information: [https://plotly.com/javascript/configuration-options/](https://plotly.com/javascript/configuration-options/) This takes precedence over the default configuration of the renderer. Defaults to None. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `renderer_name` | Renderer to use for the plot. If this is not provided, the default renderer (`pio.renderers.default`) is used. Defaults to None. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `label` | Markdown label for the element. Defaults to "". **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `on_change` | Callback to run when this element's value changes. Defaults to None. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[JSONType], None]]` **DEFAULT:** `None` | ### indices `property` [¶](#marimo.ui.plotly.indices "Permanent link") Get the indices of selected points in the plot. | RETURNS | DESCRIPTION | | --- | --- | | `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[int](https://docs.python.org/3/library/functions.html#int)]` | List\[int\]: A list of indices corresponding to the selected points. Returns an empty list if no points are selected. | ### name `class-attribute` `instance-attribute` [¶](#marimo.ui.plotly.name "Permanent link") ### points `property` [¶](#marimo.ui.plotly.points "Permanent link") Get the selected points data from the plot. | RETURNS | DESCRIPTION | | --- | --- | | `[List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` | List\[Dict\[str, Any\]\]: A list of dictionaries containing the data for each selected point. Returns an empty list if no points are selected. | ### ranges `property` [¶](#marimo.ui.plotly.ranges "Permanent link") Get the range selection of the plot. | RETURNS | DESCRIPTION | | --- | --- | | `[Dict](https://docs.python.org/3/library/typing.html#typing.Dict "typing.Dict")[[str](https://docs.python.org/3/library/stdtypes.html#str), [List](https://docs.python.org/3/library/typing.html#typing.List "typing.List")[[float](https://docs.python.org/3/library/functions.html#float)]]` | Dict\[str, List\[float\]\]: A dictionary mapping field names to their selected ranges, where each range is a list of \[min, max\] values. Returns an empty dict if no range selection exists. | ### text `property` [¶](#marimo.ui.plotly.text "Permanent link") A string of HTML representing this element. ### value `property` `writable` [¶](#marimo.ui.plotly.value "Permanent link") The element's current value. ### batch [¶](#marimo.ui.plotly.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.ui.plotly.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.ui.plotly.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### form [¶](#marimo.ui.plotly.form "Permanent link") `[](#__codelineno-0-1)form( [](#__codelineno-0-2) label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "", [](#__codelineno-0-3) *, [](#__codelineno-0-4) bordered: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-5) loading: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) submit_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Submit", [](#__codelineno-0-7) submit_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) submit_button_disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-9) clear_on_submit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10) show_clear_button: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-11) clear_button_label: [str](https://docs.python.org/3/library/stdtypes.html#str) = "Clear", [](#__codelineno-0-12) clear_button_tooltip: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-13) validate: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-14) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]] [](#__codelineno-0-15) ] = None, [](#__codelineno-0-16) on_change: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[ [](#__codelineno-0-17) [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None] [](#__codelineno-0-18) ] = None [](#__codelineno-0-19)) -> [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form "marimo._plugins.ui._impl.input.form")[S, T]` Create a submittable form out of this `UIElement`. Creates a form that gates submission of a `UIElement`'s value until a submit button is clicked. The form's value is the value of the underlying element from the last submission. Examples: Convert any `UIElement` into a form: `[](#__codelineno-0-1)prompt = mo.ui.text_area().form()` Combine with `HTML.batch` to create a form made out of multiple `UIElements`: `[](#__codelineno-1-1)form = ( [](#__codelineno-1-2) mo.ui.md( [](#__codelineno-1-3) ''' [](#__codelineno-1-4) **Enter your prompt.** [](#__codelineno-1-5) [](#__codelineno-1-6) {prompt} [](#__codelineno-1-7) [](#__codelineno-1-8) **Choose a random seed.** [](#__codelineno-1-9) [](#__codelineno-1-10) {seed} [](#__codelineno-1-11) ''' [](#__codelineno-1-12) ) [](#__codelineno-1-13) .batch( [](#__codelineno-1-14) prompt=mo.ui.text_area(), [](#__codelineno-1-15) seed=mo.ui.number(), [](#__codelineno-1-16) ) [](#__codelineno-1-17) .form() [](#__codelineno-1-18))` | PARAMETER | DESCRIPTION | | --- | --- | | `label` | A text label for the form. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `''` | | `bordered` | Whether the form should have a border. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `loading` | Whether the form should be in a loading state. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `submit_button_label` | The label of the submit button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Submit'` | | `submit_button_tooltip` | The tooltip of the submit button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `submit_button_disabled` | Whether the submit button should be disabled. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_on_submit` | Whether the form should clear its contents after submitting. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `show_clear_button` | Whether the form should show a clear button. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `clear_button_label` | The label of the clear button. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'Clear'` | | `clear_button_tooltip` | The tooltip of the clear button. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `validate` | A function that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[JSONType]], [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]]]` **DEFAULT:** `None` | | `on_change` | A callback that takes the form's value and returns an error message if invalid, or `None` if valid. **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[T]], None]]` **DEFAULT:** `None` | ### left [¶](#marimo.ui.plotly.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.ui.plotly.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### send\_message [¶](#marimo.ui.plotly.send_message "Permanent link") Send a message to the element rendered on the frontend from the backend. ### style [¶](#marimo.ui.plotly.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | Interactive matplotlib[¶](#interactive-matplotlib "Permanent link") ------------------------------------------------------------------- marimo.mpl.interactive [¶](#marimo.mpl.interactive "Permanent link") -------------------------------------------------------------------- `[](#__codelineno-0-1)interactive(figure: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[Figure, SubFigure, Axes]) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Render a matplotlib figure using an interactive viewer. The interactive viewer allows you to pan, zoom, and see plot coordinates on mouse hover. Example `[](#__codelineno-0-1)plt.plot([1, 2]) [](#__codelineno-0-2)# plt.gcf() gets the current figure [](#__codelineno-0-3)mo.mpl.interactive(plt.gcf())` | PARAMETER | DESCRIPTION | | --- | --- | | `figure` | A matplotlib `Figure` or `Axes` object. **TYPE:** `matplotlib Figure or Axes` | | RETURNS | DESCRIPTION | | --- | --- | | `Html` | An interactive matplotlib figure as an `Html` object. **TYPE:** `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | Source code in `marimo/_plugins/stateless/mpl/_mpl.py`
@mddoc
def interactive(figure: Union[Figure, SubFigure, Axes]) -> Html:
    """Render a matplotlib figure using an interactive viewer.

    The interactive viewer allows you to pan, zoom, and see plot coordinates
    on mouse hover.

    Example:
        ```python
        plt.plot([1, 2])
        # plt.gcf() gets the current figure
        mo.mpl.interactive(plt.gcf())
        ```

    Args:
        figure (matplotlib Figure or Axes): A matplotlib `Figure` or `Axes` object.

    Returns:
        Html: An interactive matplotlib figure as an `Html` object.
    """
    # We can't support interactive plots in Pyodide
    # since they require a WebSocket connection
    if is_pyodide():
        LOGGER.error(
            "Interactive plots are not supported in Pyodide/WebAssembly"
        )
        return as_html(figure)

    # No top-level imports of matplotlib, since it isn't a required
    # dependency
    from matplotlib.axes import Axes

    if isinstance(figure, Axes):
        maybe_figure = figure.get_figure()
        assert maybe_figure is not None, "Axes object does not have a Figure"
        figure = maybe_figure

    ctx = get_context()
    if not isinstance(ctx, KernelRuntimeContext):
        return as_html(figure)

    # Figure Manager, Any type because matplotlib doesn't have typings
    figure_manager = new_figure_manager_given_figure(id(figure), figure)

    # TODO(akshayka): Proxy this server through the marimo server to help with
    # deployment.
    app = get_or_create_application()
    port = app.state.port

    class CleanupHandle(CellLifecycleItem):
        def create(self, context: RuntimeContext) -> None:
            del context

        def dispose(self, context: RuntimeContext, deletion: bool) -> bool:
            del context
            del deletion
            figure_managers.remove(figure_manager)
            return True

    figure_managers.add(figure_manager)
    assert ctx.execution_context is not None
    ctx.cell_lifecycle_registry.add(CleanupHandle())
    ctx.stream.cell_id = ctx.execution_context.cell_id

    content = _template(str(figure_manager.num), port)

    return Html(
        h.iframe(
            srcdoc=html.escape(content),
            width="100%",
            height="550px",
            onload="__resizeIframe(this)",
        )
    )
Leafmap support[¶](#leafmap-support "Permanent link") ----------------------------------------------------- marimo supports rendering [Leafmap](https://leafmap.org/) maps using the `folium` and `plotly` backends. Other plotting libraries[¶](#other-plotting-libraries "Permanent link") ----------------------------------------------------------------------- You can use all the popular plotting libraries with marimo. Such as: * [Matplotlib](https://matplotlib.org/) * [Plotly](https://plotly.com/) * [Seaborn](https://seaborn.pydata.org/) * [Bokeh](https://bokeh.org/) * [Altair](https://altair-viz.github.io/) * [HoloViews](http://holoviews.org/) * [hvPlot](https://hvplot.holoviz.org/) * [Leafmap](https://leafmap.org/) * [Pygwalker](https://kanaries.net/pygwalker)
Audio - marimo https://docs.marimo.io/api/media/audio/ marimo.audio [¶](#marimo.audio "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)audio(src: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO")]) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Render an audio file as HTML. | PARAMETER | DESCRIPTION | | --- | --- | | `src` | a path or URL to an audio file, bytes, or a file-like object opened in binary mode **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO")]` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An audio player as an `Html` object. | Example `[](#__codelineno-0-1)mo.audio( [](#__codelineno-0-2) src="https://upload.wikimedia.org/wikipedia/commons/8/8c/Ivan_Ili%C4%87-Chopin_-_Prelude_no._1_in_C_major.ogg" [](#__codelineno-0-3)) [](#__codelineno-0-4)[](#__codelineno-0-5)mo.audio(src="path/to/local/file.wav")` PDF - marimo https://docs.marimo.io/api/media/pdf/ marimo.pdf [¶](#marimo.pdf "Permanent link") -------------------------------------------- Render a PDF. This currently uses the native browser PDF viewer, but may be replaced with a custom viewer. Example `[](#__codelineno-0-1)mo.pdf( [](#__codelineno-0-2) src="https://arxiv.org/pdf/2104.00282.pdf", [](#__codelineno-0-3) width="100%", [](#__codelineno-0-4) height="50vh", [](#__codelineno-0-5)) [](#__codelineno-0-6)[](#__codelineno-0-7)with open("paper.pdf", "rb") as file: [](#__codelineno-0-8) mo.pdf(src=file)` | PARAMETER | DESCRIPTION | | --- | --- | | `src` | the URL of the pdf or a file-like object **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [IOBase](https://docs.python.org/3/library/io.html#io.IOBase "io.IOBase")]` | | `initial_page` | the page to open the pdf to. only works if `src` is a URL **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)]` **DEFAULT:** `None` | | `width` | the width of the pdf **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `'100%'` | | `height` | the height of the pdf. for a percentage of the user's viewport, use a string like `"50vh"` **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `'70vh'` | | `style` | a dictionary of CSS styles to apply to the pdf **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | `Html` object | Download - marimo https://docs.marimo.io/api/media/download/ Tip: paste this code into an empty cell, and the marimo editor will create cells for you `# /// script # requires-python = ">=3.12" # dependencies = [ # "marimo", # "pandas==2.2.3", # ] # /// import marimo __generated_with = "0.10.14" app = marimo.App() @app.cell def _(): import marimo as mo return (mo,) @app.cell(hide_code=True) def _(json, mo, pd): # Text file download text_download = mo.download( data="Hello, world!".encode("utf-8"), filename="hello.txt", mimetype="text/plain", label="Download text", ) # CSV download using pandas df = pd.DataFrame({"name": ["Alice", "Bob", "Charlie"], "age": [25, 30, 35]}) csv_download = mo.download( data=df.to_csv().encode("utf-8"), filename="data.csv", mimetype="text/csv", label="Download CSV", ) # JSON download data = {"message": "Hello", "count": 42} json_download = mo.download( data=json.dumps(data).encode("utf-8"), filename="data.json", mimetype="application/json", label="Download JSON", ) mo.hstack([text_download, csv_download, json_download]) return csv_download, data, df, json_download, text_download @app.cell(hide_code=True) def _(json, mo, pd): import time import asyncio # Text file download with lazy loading def get_text_data(): time.sleep(1) return "Hello, world!".encode("utf-8") text_download_lazy = mo.download( data=get_text_data, filename="hello.txt", mimetype="text/plain", label="Download text", ) # CSV download using pandas with lazy loading async def get_csv_data(): await asyncio.sleep(1) _df = pd.DataFrame( {"name": ["Alice", "Bob", "Charlie"], "age": [25, 30, 35]} ) return _df csv_download_lazy = mo.download( data=get_csv_data, filename="data.csv", mimetype="text/csv", label="Download CSV", ) # JSON download with lazy loading async def get_json_data(): await asyncio.sleep(1) _data = {"message": "Hello", "count": 42} return json.dumps(_data).encode("utf-8") json_download_lazy = mo.download( data=get_json_data, filename="data.json", mimetype="application/json", label="Download JSON", ) mo.hstack([text_download_lazy, csv_download_lazy, json_download_lazy]) return ( asyncio, csv_download_lazy, get_csv_data, get_json_data, get_text_data, json_download_lazy, text_download_lazy, time, ) @app.cell def _(): import pandas as pd import json return json, pd if __name__ == "__main__": app.run()` Image - marimo https://docs.marimo.io/api/media/image/ marimo.image [¶](#marimo.image "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)image( [](#__codelineno-0-2) src: ImageLike, [](#__codelineno-0-3) alt: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-4) width: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-5) height: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-6) rounded: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7) style: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]] = None, [](#__codelineno-0-8) caption: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-9)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Render an image as HTML. Examples: `[](#__codelineno-0-1)# Render an image from a local file [](#__codelineno-0-2)mo.image(src="path/to/image.png")` `[](#__codelineno-1-1)# Render an image from a URL [](#__codelineno-1-2)mo.image( [](#__codelineno-1-3) src="https://marimo.io/logo.png", [](#__codelineno-1-4) alt="Marimo logo", [](#__codelineno-1-5) width=100, [](#__codelineno-1-6) height=100, [](#__codelineno-1-7) rounded=True, [](#__codelineno-1-8) caption="Marimo logo", [](#__codelineno-1-9))` | PARAMETER | DESCRIPTION | | --- | --- | | `src` | a path or URL to an image, a file-like object (opened in binary mode), or array-like object. **TYPE:** `ImageLike` | | `alt` | the alt text of the image **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | `width` | the width of the image in pixels or a string with units **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `height` | the height of the image in pixels or a string with units **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `rounded` | whether to round the corners of the image **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `style` | a dictionary of CSS styles to apply to the image **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `caption` | the caption of the image **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)]` **DEFAULT:** `None` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | `Html` object | Plain Text - marimo https://docs.marimo.io/api/media/plain_text/ marimo.plain\_text [¶](#marimo.plain_text "Permanent link") ----------------------------------------------------------- Text that's fixed-width, with spaces and newlines preserved. | PARAMETER | DESCRIPTION | | --- | --- | | `text` | text to output **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object representing the text. | Video - marimo https://docs.marimo.io/api/media/video/ marimo.video [¶](#marimo.video "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)video( [](#__codelineno-0-2) src: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [bytes](https://docs.python.org/3/library/stdtypes.html#bytes), [BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO"), [BufferedReader](https://docs.python.org/3/library/io.html#io.BufferedReader "io.BufferedReader")], [](#__codelineno-0-3) controls: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-4) muted: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-5) autoplay: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6) loop: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-7) width: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-8) height: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]] = None, [](#__codelineno-0-9) rounded: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-10)) -> [Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` Render an video as HTML. Example `[](#__codelineno-0-1)mo.video( [](#__codelineno-0-2) src="https://v3.cdnpk.net/videvo_files/video/free/2013-08/large_watermarked/hd0992_preview.mp4", [](#__codelineno-0-3) controls=False, [](#__codelineno-0-4))` | PARAMETER | DESCRIPTION | | --- | --- | | `src` | the URL of the video or a file-like object **TYPE:** `[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [bytes](https://docs.python.org/3/library/stdtypes.html#bytes), [BytesIO](https://docs.python.org/3/library/io.html#io.BytesIO "io.BytesIO"), [BufferedReader](https://docs.python.org/3/library/io.html#io.BufferedReader "io.BufferedReader")]` | | `controls` | whether to show the controls **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `muted` | whether to mute the video **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `autoplay` | whether to autoplay the video. the video will only autoplay if `muted` is `True` **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `loop` | whether to loop the video **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `width` | the width of the video in pixels or a string with units **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `height` | the height of the video in pixels or a string with units **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[int](https://docs.python.org/3/library/functions.html#int), [str](https://docs.python.org/3/library/stdtypes.html#str)]]` **DEFAULT:** `None` | | `rounded` | whether to round the corners of the video **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | `Html` object | Outputs - marimo https://docs.marimo.io/api/outputs/ Cell outputs[¶](#cell-outputs "Permanent link") ----------------------------------------------- Cell outputs Every cell in a marimo notebook can have a visual **output**. When editing, outputs are displayed above cells. When running a notebook as an app, its UI is an arrangement of outputs. A cell's output is by default its last expression. You can also create outputs programmatically, using `mo.output.replace()` and `mo.output.append()`. marimo.output.replace [¶](#marimo.output.replace "Permanent link") ------------------------------------------------------------------ `[](#__codelineno-0-1)replace(value: [object](https://docs.python.org/3/glossary.html#term-object)) -> None` Replace a cell's output with a new one. Call `mo.output.replace()` to write to a cell's output area, replacing the existing output, if any. **Args:** * `value`: object to output marimo.output.append [¶](#marimo.output.append "Permanent link") ---------------------------------------------------------------- Append a new object to a cell's output. Call this function to incrementally build a cell's output. Appended outputs are stacked vertically. **Args:** * `value`: object to output marimo.output.clear [¶](#marimo.output.clear "Permanent link") -------------------------------------------------------------- Clear a cell's output. marimo.output.replace\_at\_index [¶](#marimo.output.replace_at_index "Permanent link") -------------------------------------------------------------------------------------- `[](#__codelineno-0-1)replace_at_index(value: [object](https://docs.python.org/3/glossary.html#term-object), idx: [int](https://docs.python.org/3/library/functions.html#int)) -> None` Replace a cell's output at the given index with value. Call this function to replace an existing object in a cell's output. If idx is equal to the length of the output, this is equivalent to an append. **Args:** * `value`: new object to replace an existing object * `idx`: index of output to replace Last expression replaces existing output Ending a cell with a non-`None` expression is the same as calling `mo.output.replace()` on it: the last expression replaces any output you may have already written. Wrap the last expression in `mo.output.append` if you want to add to an existing output instead of replacing it. ### Display cell code in marimo's app views[¶](#display-cell-code-in-marimos-app-views "Permanent link") Use `mo.show_code()` to display the cell's code in the output area, which will then be visible in all app views. marimo.show\_code [¶](#marimo.show_code "Permanent link") --------------------------------------------------------- Display an output along with the code of the current cell. Use `mo.show_code` to show the code of the current cell along with the cell's output. This is useful if you want a cell's code to appear in the app preview or when running the notebook as an app with `marimo run`. In the displayed code, all occurrences of mo.show\_code(...) will be replaced with ... Show code that produces the output `factorial(5)`: `[](#__codelineno-0-1)def factorial(n: int) -> int: [](#__codelineno-0-2) if n == 0: [](#__codelineno-0-3) return 1 [](#__codelineno-0-4) return n * factorial(n - 1) [](#__codelineno-0-5) [](#__codelineno-0-6)[](#__codelineno-0-7)mo.show_code(factorial(5))` Show code of a cell, without an output: `[](#__codelineno-1-1)def factorial(n: int) -> int: [](#__codelineno-1-2) if n == 0: [](#__codelineno-1-3) return 1 [](#__codelineno-1-4) return n * factorial(n - 1) [](#__codelineno-1-5) [](#__codelineno-1-6)[](#__codelineno-1-7)mo.show_code()` **Args:** * output: the output to display above the cell's code; omit the output to just show the cell's code, without an output. **Returns:** HTML of the `output` arg displayed with its code. Console outputs[¶](#console-outputs "Permanent link") ----------------------------------------------------- Console outputs Text written to `stdout`/`stderr`, including print statements and logs, shows up in a console output area below a cell. By default, these console outputs don't appear when running a marimo notebook as an app. If you do want them to appear in apps, marimo provides utility functions for capturing console outputs and redirecting them to cell outputs. marimo.redirect\_stdout [¶](#marimo.redirect_stdout "Permanent link") --------------------------------------------------------------------- Redirect stdout to a cell's output area. `[](#__codelineno-0-1)with mo.redirect_stdout(): [](#__codelineno-0-2) # These print statements will show up in the cell's output area [](#__codelineno-0-3) print("Hello!") [](#__codelineno-0-4) print("World!")` marimo.redirect\_stderr [¶](#marimo.redirect_stderr "Permanent link") --------------------------------------------------------------------- Redirect `stderr` to a cell's output area. `[](#__codelineno-0-1)with mo.redirect_stderr(): [](#__codelineno-0-2) # These messages will show up in the cell's output area [](#__codelineno-0-3) sys.stderr.write("Hello!") [](#__codelineno-0-4) sys.stderr.write("World!")` marimo.capture\_stdout [¶](#marimo.capture_stdout "Permanent link") ------------------------------------------------------------------- Capture standard output. Use this context manager to capture print statements and other output sent to standard output. **Example.** `[](#__codelineno-0-1)with mo.capture_stdout() as buffer: [](#__codelineno-0-2) print("Hello!") [](#__codelineno-0-3)output = buffer.getvalue()` marimo.capture\_stderr [¶](#marimo.capture_stderr "Permanent link") ------------------------------------------------------------------- Capture standard error. Use this context manager to capture output sent to standard error. **Example.** `[](#__codelineno-0-1)with mo.capture_stderr() as buffer: [](#__codelineno-0-2) sys.stderr.write("Hello!") [](#__codelineno-0-3)output = buffer.getvalue()` Progress Bars and Status - marimo https://docs.marimo.io/api/status/ Use progress bars or spinners to visualize loading status in your notebooks and apps. Useful when iterating over collections or loading data from files, databases, or APIs. Progress bar[¶](#progress-bar "Permanent link") ----------------------------------------------- You can display a progress bar while iterating over a collection, similar to `tqdm`. marimo.status.progress\_bar [¶](#marimo.status.progress_bar "Permanent link") ----------------------------------------------------------------------------- `[](#__codelineno-0-1)progress_bar( [](#__codelineno-0-2) collection: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Collection](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "collections.abc.Collection")[S | [int](https://docs.python.org/3/library/functions.html#int)]] = None, [](#__codelineno-0-3) *, [](#__codelineno-0-4) title: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-5) subtitle: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-6) completion_title: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-7) completion_subtitle: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[str](https://docs.python.org/3/library/stdtypes.html#str)] = None, [](#__codelineno-0-8) total: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[int](https://docs.python.org/3/library/functions.html#int)] = None, [](#__codelineno-0-9) show_rate: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-10) show_eta: [bool](https://docs.python.org/3/library/functions.html#bool) = True, [](#__codelineno-0-11) remove_on_exit: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-12) disabled: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-13))` Iterate over a collection and show a progress bar. Examples: `[](#__codelineno-0-1)for i in mo.status.progress_bar(range(10)): [](#__codelineno-0-2) ...` You can optionally provide a title and subtitle to show during iteration, and a title/subtitle to show upon completion: `[](#__codelineno-1-1)with mo.status.progress_bar(total=10) as bar: [](#__codelineno-1-2) for i in range(10): [](#__codelineno-1-3) ... [](#__codelineno-1-4) bar.update()` The `update` method accepts the optional keyword arguments `increment` (defaults to `1`), `title`, and `subtitle`. For performance reasons, the progress bar is only updated in the UI every 150ms. | PARAMETER | DESCRIPTION | | --- | --- | | `collection` | Optional collection to iterate over. **TYPE:** `[Collection](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "collections.abc.Collection")[Union[S, [int](https://docs.python.org/3/library/functions.html#int)]]` **DEFAULT:** `None` | | `title` | Optional title. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `subtitle` | Optional subtitle. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `completion_title` | Optional title to show during completion. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `completion_subtitle` | Optional subtitle to show during completion. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `total` | Optional total number of items to iterate over. **TYPE:** `[int](https://docs.python.org/3/library/functions.html#int)` **DEFAULT:** `None` | | `show_rate` | If True, show the rate of progress (items per second). **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `show_eta` | If True, show the estimated time of completion. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | | `remove_on_exit` | If True, remove the progress bar from output on exit. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | `disabled` | If True, disable the progress bar. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | ### collection `instance-attribute` [¶](#marimo.status.progress_bar.collection "Permanent link") ### completion\_subtitle `instance-attribute` [¶](#marimo.status.progress_bar.completion_subtitle "Permanent link") `[](#__codelineno-0-1)completion_subtitle = [completion_subtitle](#marimo.status.progress_bar.completion_subtitle "marimo._plugins.stateless.status._progress.progress_bar.completion_subtitle")` ### completion\_title `instance-attribute` [¶](#marimo.status.progress_bar.completion_title "Permanent link") `[](#__codelineno-0-1)completion_title = [completion_title](#marimo.status.progress_bar.completion_title "marimo._plugins.stateless.status._progress.progress_bar.completion_title")` ### disabled `instance-attribute` [¶](#marimo.status.progress_bar.disabled "Permanent link") ### progress `instance-attribute` [¶](#marimo.status.progress_bar.progress "Permanent link") `[](#__codelineno-0-1)progress = ProgressBar( [](#__codelineno-0-2) title=title, [](#__codelineno-0-3) subtitle=subtitle, [](#__codelineno-0-4) total=total, [](#__codelineno-0-5) show_rate=show_rate, [](#__codelineno-0-6) show_eta=show_eta, [](#__codelineno-0-7))` ### remove\_on\_exit `instance-attribute` [¶](#marimo.status.progress_bar.remove_on_exit "Permanent link") `[](#__codelineno-0-1)remove_on_exit = [remove_on_exit](#marimo.status.progress_bar.remove_on_exit "marimo._plugins.stateless.status._progress.progress_bar.remove_on_exit")` ### step `instance-attribute` [¶](#marimo.status.progress_bar.step "Permanent link") Spinner[¶](#spinner "Permanent link") ------------------------------------- marimo.status.spinner [¶](#marimo.status.spinner "Permanent link") ------------------------------------------------------------------ Show a loading spinner. Use `mo.status.spinner()` as a context manager to show a loading spinner. You can optionally pass a title and subtitle. Examples: `[](#__codelineno-0-1)with mo.status.spinner(subtitle="Loading data ...") as _spinner: [](#__codelineno-0-2) data = expensive_function() [](#__codelineno-0-3) _spinner.update(subtitle="Crunching numbers ...") [](#__codelineno-0-4) ... [](#__codelineno-0-5)[](#__codelineno-0-6)mo.ui.table(data)` You can also show the spinner without a context manager: `[](#__codelineno-1-1)mo.status.spinner(title="Loading ...") if condition else mo.md("Done!")` | PARAMETER | DESCRIPTION | | --- | --- | | `title` | Optional title. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `subtitle` | Optional subtitle. **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `None` | | `remove_on_exit` | If True, the spinner is removed from output on exit. Defaults to True. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `True` | ### remove\_on\_exit `instance-attribute` [¶](#marimo.status.spinner.remove_on_exit "Permanent link") `[](#__codelineno-0-1)remove_on_exit = [remove_on_exit](#marimo.status.spinner.remove_on_exit "marimo._plugins.stateless.status._progress.spinner.remove_on_exit")` ### spinner `instance-attribute` [¶](#marimo.status.spinner.spinner "Permanent link") `[](#__codelineno-0-1)spinner = Spinner(title=title, subtitle=subtitle)` ### subtitle `instance-attribute` [¶](#marimo.status.spinner.subtitle "Permanent link") ### title `instance-attribute` [¶](#marimo.status.spinner.title "Permanent link") HTML - marimo https://docs.marimo.io/api/html/ All marimo elements extend the HTML element class. marimo.as\_html [¶](#marimo.as_html "Permanent link") ----------------------------------------------------- Convert a value to HTML that can be embedded into markdown. This function returns an `Html` object representing `value`. Use it to embed values into Markdown or other HTML strings. | PARAMETER | DESCRIPTION | | --- | --- | | `value` | An object **TYPE:** `[object](https://docs.python.org/3/glossary.html#term-object)` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object | Example `[](#__codelineno-0-1)import matplotlib.pyplot as plt [](#__codelineno-0-2)plt.plot([1, 2]) [](#__codelineno-0-3)axis = plt.gca() [](#__codelineno-0-4)mo.md( [](#__codelineno-0-5) f""" [](#__codelineno-0-6) Here is a plot: [](#__codelineno-0-7) [](#__codelineno-0-8) {mo.as_html(axis)} [](#__codelineno-0-9) """ [](#__codelineno-0-10))` marimo.Html [¶](#marimo.Html "Permanent link") ---------------------------------------------- Bases: `MIME` A wrapper around HTML text that can be used as an output. Output an `Html` object as the last expression of a cell to render it in your app. Use f-strings to embed Html objects as text into other HTML or markdown strings. For example: `[](#__codelineno-0-1)hello_world = Html("

Hello, World

") [](#__codelineno-0-2)Html( [](#__codelineno-0-3) f''' [](#__codelineno-0-4)

Hello, Universe!

[](#__codelineno-0-5) {hello_world} [](#__codelineno-0-6) ''' [](#__codelineno-0-7))` | ATTRIBUTE | DESCRIPTION | | --- | --- | | `[text](#marimo.Html.text "marimo.Html.text")` | a string of HTML **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | PARAMETER | DESCRIPTION | | --- | --- | | `text` | a string of HTML **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | METHOD | DESCRIPTION | | --- | --- | | `[batch](#marimo.Html.batch "marimo.Html.batch")` | convert this HTML element into a batched UI element | | `[callout](#marimo.Html.callout "marimo.Html.callout")` | wrap this element in a callout | | `[center](#marimo.Html.center "marimo.Html.center")` | center this element in the output area | | `[right](#marimo.Html.right "marimo.Html.right")` | right-justify this element in the output area | Initialize the HTML element. Subclasses of HTML MUST call this method. ### text `property` [¶](#marimo.Html.text "Permanent link") A string of HTML representing this element. ### batch [¶](#marimo.Html.batch "Permanent link") `[](#__codelineno-0-1)batch(**elements: UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]) -> [batch](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch "marimo._plugins.ui._impl.batch.batch")` Convert an HTML object with templated text into a UI element. This method lets you create custom UI elements that are represented by arbitrary HTML. Example `[](#__codelineno-0-1)user_info = mo.md( [](#__codelineno-0-2) ''' [](#__codelineno-0-3) - What's your name?: {name} [](#__codelineno-0-4) - When were you born?: {birthday} [](#__codelineno-0-5) ''' [](#__codelineno-0-6)).batch(name=mo.ui.text(), birthday=mo.ui.date())` In this example, `user_info` is a UI Element whose output is markdown and whose value is a dict with keys `'name'` and '`birthday`' (and values equal to the values of their corresponding elements). | PARAMETER | DESCRIPTION | | --- | --- | | `elements` | the UI elements to interpolate into the HTML template. **TYPE:** `UIElement[JSONType, [object](https://docs.python.org/3/glossary.html#term-object)]` **DEFAULT:** `{}` | ### callout [¶](#marimo.Html.callout "Permanent link") `[](#__codelineno-0-1)callout( [](#__codelineno-0-2) kind: [Literal](https://docs.python.org/3/library/typing.html#typing.Literal "typing.Literal")[ [](#__codelineno-0-3) "neutral", "danger", "warn", "success", "info" [](#__codelineno-0-4) ] = "neutral" [](#__codelineno-0-5)) -> [Html](#marimo.Html "marimo._output.hypertext.Html")` Create a callout containing this HTML element. A callout wraps your HTML element in a raised box, emphasizing its importance. You can style the callout for different situations with the `kind` argument. Examples: `[](#__codelineno-0-1)mo.md("Hooray, you did it!").callout(kind="success")` `[](#__codelineno-1-1)mo.md("It's dangerous to go alone!").callout(kind="warn")` ### center [¶](#marimo.Html.center "Permanent link") Center an item. Example `[](#__codelineno-0-1)mo.md("# Hello, world").center()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### left [¶](#marimo.Html.left "Permanent link") Left-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").left()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### right [¶](#marimo.Html.right "Permanent link") Right-justify. Example `[](#__codelineno-0-1)mo.md("# Hello, world").right()` | RETURNS | DESCRIPTION | | --- | --- | | `[Html](#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | ### style [¶](#marimo.Html.style "Permanent link") Wrap an object in a styled container. Example `[](#__codelineno-0-1)mo.md("...").style({"max-height": "300px", "overflow": "auto"}) [](#__codelineno-0-2)mo.md("...").style(max_height="300px", overflow="auto")` | PARAMETER | DESCRIPTION | | --- | --- | | `style` | an optional dict of CSS styles, keyed by property name **TYPE:** `[Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[dict](https://docs.python.org/3/reference/expressions.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]` **DEFAULT:** `None` | | `**kwargs` | CSS styles as keyword arguments **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | marimo.iframe [¶](#marimo.iframe "Permanent link") -------------------------------------------------- `[](#__codelineno-0-1)iframe( [](#__codelineno-0-2) html: [str](https://docs.python.org/3/library/stdtypes.html#str), *, width: [str](https://docs.python.org/3/library/stdtypes.html#str) = "100%", height: [str](https://docs.python.org/3/library/stdtypes.html#str) = "400px" [](#__codelineno-0-3)) -> [Html](#marimo.Html "marimo._output.hypertext.Html")` Embed an HTML string in an iframe. Scripts by default are not executed using `mo.as_html` or `mo.Html`, so if you have a script tag (written as ``), you can use `mo.iframe` for scripts to be executed. You may also want to use this function to display HTML content that may contain styles that could interfere with the rest of the page. Example `[](#__codelineno-0-1)html = "

Hello, world!

" [](#__codelineno-0-2)mo.iframe(html)` | PARAMETER | DESCRIPTION | | --- | --- | | `html` | An HTML string **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | `width` | The width of the iframe **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'100%'` | | `height` | The height of the iframe **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` **DEFAULT:** `'400px'` |
Query Parameters - marimo https://docs.marimo.io/api/query_params/ Use `mo.query_params` to access query parameters passed to the notebook. You can also use `mo.query_params` to set query parameters in order to keep track of state in the URL. This is useful for bookmarking or sharing a particular state of the notebook while running as an application with `marimo run`. marimo.query\_params [¶](#marimo.query_params "Permanent link") --------------------------------------------------------------- `[](#__codelineno-0-1)query_params() -> QueryParams` Get the query parameters of a marimo app. Examples: Keep the text input in sync with the URL query parameters: `[](#__codelineno-0-1)# In it's own cell [](#__codelineno-0-2)query_params = mo.query_params() [](#__codelineno-0-3)[](#__codelineno-0-4)# In another cell [](#__codelineno-0-5)search = mo.ui.text( [](#__codelineno-0-6) value=query_params["search"] or "", [](#__codelineno-0-7) on_change=lambda value: query_params.set("search", value), [](#__codelineno-0-8)) [](#__codelineno-0-9)search` You can also set the query parameters reactively: `[](#__codelineno-1-1)toggle = mo.ui.switch(label="Toggle me") [](#__codelineno-1-2)toggle [](#__codelineno-1-3)[](#__codelineno-1-4)# In another cell [](#__codelineno-1-5)query_params["is_enabled"] = toggle.value` | RETURNS | DESCRIPTION | | --- | --- | | `QueryParams` | A QueryParams object containing the query parameters. You can directly interact with this object like a dictionary. If you mutate this object, changes will be persisted to the frontend query parameters and any other cells referencing the query parameters will automatically re-run. **TYPE:** `QueryParams` | CLI arguments You can also access command-line arguments passed to the notebook using `mo.cli_args`. This allows you to pass arguments to the notebook that are not controllable by the user. Command Line Arguments - marimo https://docs.marimo.io/api/cli_args/ Use `mo.cli_args` to access command-line arguments passed to the notebook. This allows you to pass arguments to the notebook that are not controllable by the user. The arguments will be parsed from the command line when running the notebook as an application with `marimo run` or `marimo edit`; they will also be parsed from the command line when running as a script. Some examples passing command-line arguments to the notebook when running as a script: `[](#__codelineno-0-1)python notebook.py -- --arg1 value1 --arg2 value2 [](#__codelineno-0-2)# mo.cli_args() == {'arg1': 'value1', 'arg2': 'value2'} [](#__codelineno-0-3)[](#__codelineno-0-4)python notebook.py -- --arg1=10 --arg2=true --arg3 [](#__codelineno-0-5)# mo.cli_args() == {'arg1': 10, 'arg2': True, 'arg3': ''} [](#__codelineno-0-6)[](#__codelineno-0-7)python notebook.py -- --arg1 10.5 --arg2 hello --arg2 world [](#__codelineno-0-8)# mo.cli_args() == {'arg1': 10.5, 'arg2': ['hello', 'world']}` In each example, `python` can be replaced as `marimo run` (for running as an app) or `marimo edit` (for running as a notebook). marimo.cli\_args [¶](#marimo.cli_args "Permanent link") ------------------------------------------------------- Get the command line arguments of a marimo notebook. Examples: `marimo edit notebook.py -- -size 10` `[](#__codelineno-0-1)# Access the command line arguments [](#__codelineno-0-2)size = mo.cli_args().get("size") or 100 [](#__codelineno-0-3)[](#__codelineno-0-4)for i in range(size): [](#__codelineno-0-5) print(i)` | RETURNS | DESCRIPTION | | --- | --- | | `CLIArgs` | A dictionary containing the command line arguments. This dictionary is read-only and cannot be mutated. **TYPE:** `CLIArgs` | Query Parameters You can also access query parameters passed to the notebook using `mo.query_params`. This allows you to pass arguments to the notebook that can be controlled by the user. Diagrams - marimo https://docs.marimo.io/api/diagrams/ Render a diagram with Mermaid. Mermaid is a tool for making diagrams such as flow charts and graphs. See the [Mermaid documentation](https://github.com/mermaid-js/mermaid#readme) for details. | PARAMETER | DESCRIPTION | | --- | --- | | `diagram` | a string containing a Mermaid diagram **TYPE:** `[str](https://docs.python.org/3/library/stdtypes.html#str)` | | RETURNS | DESCRIPTION | | --- | --- | | `[Html](https://docs.marimo.io/api/html/#marimo.Html "marimo._output.hypertext.Html")` | An `Html` object. | Example `[](#__codelineno-0-1)diagram = ''' [](#__codelineno-0-2)graph LR [](#__codelineno-0-3) A[Square Rect] -- Link text --> B((Circle)) [](#__codelineno-0-4) A --> C(Round Rect) [](#__codelineno-0-5) B --> D{Rhombus} [](#__codelineno-0-6) C --> D [](#__codelineno-0-7)''' [](#__codelineno-0-8)mo.mermaid(diagram)` State - marimo https://docs.marimo.io/api/state/ Advanced topic! This guide covers reactive state (`mo.state`), an advanced topic. **You likely don't need `mo.state`**. UI elements already have built-in state, their associated value, which you can access with their `value` attribute. For example, `mo.ui.slider()` has a value that is its current position on an interval, while `mo.ui.button()` has a value that can be configured to count the number of times it has been clicked, or to toggle between `True` and `False`. Additionally, interacting with UI elements bound to global variables [automatically executes cells](https://docs.marimo.io/guides/interactivity/) that reference those variables, letting you react to changes by just reading their `value` attributes. **This functional paradigm is the preferred way of reacting to UI interactions in marimo.** **Chances are, the reactive execution built into UI elements will suffice.** (For example, [you don't need reactive state to handle a button click](https://docs.marimo.io/recipes/#working-with-buttons).) That said, here are some signs you might need `mo.state`: * you need to maintain historical state related to a UI element that can't be computed from its built-in `value` (_e.g._, all values the user has ever input into a form) * you need to synchronize two different UI elements (_e.g._, so that interacting with either one controls the other) * you need to introduce cycles across cells **In over 99% of cases, you don't need and shouldn't use `mo.state`.** This feature can introduce hard-to-find bugs. marimo.state [¶](#marimo.state "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)state( [](#__codelineno-0-2) value: T, allow_self_loops: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-3)) -> [tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[State[T], [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[T], None]]` Mutable reactive state. Warning: reactive state is an advanced feature that you likely don't need; it makes it possible to introduce cycles and hard-to-debug code execution paths. **In almost all cases, you should prefer using marimo's built-in [reactive execution](https://docs.marimo.io/guides/reactivity) and [interactivity](https://docs.marimo.io/guides/interactivity).** This function takes an initial value and returns: * a getter function that reads the state value * a setter function to set the state's value When you call the setter function and update the state value in one cell, all _other_ cells that read any global variables assigned to the getter will automatically run. By default, the cell that called the setter function won't be re-run, even if it references the getter. To allow a state setter to possibly run the caller cell, set the keyword argument `allow_self_loops=True`. You can use this function with `UIElement` `on_change` handlers to trigger side-effects when an element's value is updated; however, you should prefer using marimo's built-in [reactive execution for interactive elements](https://docs.marimo.io/guides/interactivity). For example, you can tie multiple UI elements to derive their values from shared state. Examples: Create state: `[](#__codelineno-0-1)get_count, set_count = mo.state(0)` Read the value: Update the state: Update based on current value: `[](#__codelineno-3-1)set_count(lambda value: value + 1)` Never mutate the state directly. You should only change its value through its setter. **Synchronizing multiple UI elements:** `[](#__codelineno-0-1)get_state, set_state = mo.state(0)` `[](#__codelineno-1-1)# Updating the state through the slider will recreate the number (below) [](#__codelineno-1-2)slider = mo.ui.slider(0, 100, value=get_state(), on_change=set_state)` `[](#__codelineno-2-1)# Updating the state through the number will recreate the slider (above) [](#__codelineno-2-2)number = mo.ui.number(0, 100, value=get_state(), on_change=set_state)` `[](#__codelineno-3-1)# slider and number are synchronized to have the same value (try it!) [](#__codelineno-3-2)[slider, number]` Warning Do not store `marimo.ui` elements in state; doing so can cause hard-to-diagnose bugs. | PARAMETER | DESCRIPTION | | --- | --- | | `value` | Initial value of the state. **TYPE:** `T` | | `allow_self_loops` | If True, a cell that calls a state setter and also references its getter will be re-run. Defaults to False. **TYPE:** `[bool](https://docs.python.org/3/library/functions.html#bool)` **DEFAULT:** `False` | | RETURNS | DESCRIPTION | | --- | --- | | `State[T]` | A tuple of (getter function, setter function). The getter function | | `[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[T], None]` | retrieves the state value; the setter function takes a new value or a | | `[tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[State[T], [Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[[T], None]]` | function that updates the current value. | Caching - marimo https://docs.marimo.io/api/caching/ marimo comes with utilities to cache intermediate computations. These utilities come in two types: caching the return values of expensive functions in memory, and caching the values of variables to disk. Caching expensive functions[¶](#caching-expensive-functions "Permanent link") ----------------------------------------------------------------------------- Use [`mo.cache`](#marimo.cache) to cache the return values of functions in memory, based on the function arguments, closed-over values, and the notebook code defining the function. The resulting cache is similar to `functools.cache`, but with the benefit that [`mo.cache`](#marimo.cache) won't return stale values (because it keys on closed-over values) and isn't invalidated when the cell defining the decorated function is simply re-run (because it keys on notebook code). This means that like marimo notebooks, [`mo.cache`](#marimo.cache) has no hidden state associated with the cached function, which makes you more productive while developing iteratively. For a cache with bounded size, use [`mo.lru_cache`](#marimo.lru_cache). marimo.cache [¶](#marimo.cache "Permanent link") ------------------------------------------------ `[](#__codelineno-0-1)cache( [](#__codelineno-0-2) fn: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]] = None, [](#__codelineno-0-3) pin_modules: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-4) loader: LoaderPartial | LoaderType = MemoryLoader, [](#__codelineno-0-5)) -> _cache_call` `[](#__codelineno-0-1)cache( [](#__codelineno-0-2) name: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) pin_modules: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-4) loader: LoaderPartial [](#__codelineno-0-5) | Loader [](#__codelineno-0-6) | LoaderType = MemoryLoader, [](#__codelineno-0-7)) -> _cache_context` #### Cache the value of a function based on args and closed-over variables.[¶](#marimo.cache--cache-the-value-of-a-function-based-on-args-and-closed-over-variables "Permanent link") Decorating a function with `@mo.cache` will cache its value based on the function's arguments, closed-over values, and the notebook code. **Usage.** `[](#__codelineno-0-1)import marimo as mo [](#__codelineno-0-2) [](#__codelineno-0-3)[](#__codelineno-0-4)@mo.cache [](#__codelineno-0-5)def fib(n): [](#__codelineno-0-6) if n <= 1: [](#__codelineno-0-7) return n [](#__codelineno-0-8) return fib(n - 1) + fib(n - 2)` `mo.cache` is similar to `functools.cache`, but with three key benefits: 1. `mo.cache` persists its cache even if the cell defining the cached function is re-run, as long as the code defining the function (excluding comments and formatting) has not changed. 2. `mo.cache` keys on closed-over values in addition to function arguments, preventing accumulation of hidden state associated with `functools.cache`. 3. `mo.cache` does not require its arguments to be hashable (only pickleable), meaning it can work with lists, sets, NumPy arrays, PyTorch tensors, and more. `mo.cache` obtains these benefits at the cost of slightly higher overhead than `functools.cache`, so it is best used for expensive functions. Like `functools.cache`, `mo.cache` is thread-safe. The cache has an unlimited maximum size. To limit the cache size, use `@mo.lru_cache`. `mo.cache` is slightly faster than `mo.lru_cache`, but in most applications the difference is negligible. Note, `mo.cache` can also be used as a drop in replacement for context block caching like `mo.persistent_cache`. **Args**: * `pin_modules`: if True, the cache will be invalidated if module versions differ. #### Context manager to cache the return value of a block of code.[¶](#marimo.cache--context-manager-to-cache-the-return-value-of-a-block-of-code "Permanent link") The `mo.cache` context manager lets you delimit a block of code in which variables will be cached to memory when they are first computed. By default, the cache is stored in memory and is not persisted across kernel runs, for that functionality, refer to `mo.persistent_cache`. **Usage.** `[](#__codelineno-1-1)with mo.cache("my_cache") as cache: [](#__codelineno-1-2) variable = expensive_function()` **Args**: * `name`: the name of the cache, used to set saving path- to manually invalidate the cache, change the name. * `pin_modules`: if True, the cache will be invalidated if module versions differ. * `loader`: the loader to use for the cache, defaults to `MemoryLoader`. marimo.lru\_cache [¶](#marimo.lru_cache "Permanent link") --------------------------------------------------------- `[](#__codelineno-0-1)lru_cache( [](#__codelineno-0-2) name: [str](https://docs.python.org/3/library/stdtypes.html#str), maxsize: [int](https://docs.python.org/3/library/functions.html#int) = 128, pin_modules: [bool](https://docs.python.org/3/library/functions.html#bool) = False [](#__codelineno-0-3)) -> _cache_call` `[](#__codelineno-0-1)lru_cache( [](#__codelineno-0-2) name: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]] = None, [](#__codelineno-0-3) maxsize: [int](https://docs.python.org/3/library/functions.html#int) = 128, [](#__codelineno-0-4) *args: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [](#__codelineno-0-5) _internal_interface_not_for_external_use: None = None, [](#__codelineno-0-6) **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-7)) -> [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[_cache_call, _cache_context]` Decorator for LRU caching the return value of a function. `mo.lru_cache` is a version of `mo.cache` with a bounded cache size. As an LRU (Least Recently Used) cache, only the last used `maxsize` values are retained, with the oldest values being discarded. For more information, see the documentation of `mo.cache`. **Usage.** `[](#__codelineno-0-1)import marimo as mo [](#__codelineno-0-2) [](#__codelineno-0-3)[](#__codelineno-0-4)@mo.lru_cache [](#__codelineno-0-5)def factorial(n): [](#__codelineno-0-6) return n * factorial(n - 1) if n else 1` **Args**: * `maxsize`: the maximum number of entries in the cache; defaults to 128. Setting to -1 disables cache limits. * `pin_modules`: if True, the cache will be invalidated if module versions differ. #### Context manager for LRU caching the return value of a block of code.[¶](#marimo.lru_cache--context-manager-for-lru-caching-the-return-value-of-a-block-of-code "Permanent link") **Args**: * `name`: Namespace key for the cache. * `maxsize`: the maximum number of entries in the cache; defaults to 128. Setting to -1 disables cache limits. * `pin_modules`: if True, the cache will be invalidated if module versions differ. Caching variables to disk[¶](#caching-variables-to-disk "Permanent link") ------------------------------------------------------------------------- Use [`mo.persistent_cache`](#marimo.persistent_cache) to cache variables computed in an expensive block of code to disk. The next time this block of code is run, if marimo detects a cache hit, the code will be skipped and your variables will be loaded into memory, letting you pick up where you left off. Cache location By default, caches are stored in `__marimo__/cache/`, in the directory of the current notebook. For projects versioned with `git`, consider adding `**/__marimo__/cache/` to your `.gitignore`. marimo.persistent\_cache [¶](#marimo.persistent_cache "Permanent link") ----------------------------------------------------------------------- `[](#__codelineno-0-1)persistent_cache( [](#__codelineno-0-2) name: [str](https://docs.python.org/3/library/stdtypes.html#str), [](#__codelineno-0-3) save_path: [str](https://docs.python.org/3/library/stdtypes.html#str) | None = None, [](#__codelineno-0-4) method: LoaderKey = "pickle", [](#__codelineno-0-5) pin_modules: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6)) -> _cache_context` `[](#__codelineno-0-1)persistent_cache( [](#__codelineno-0-2) fn: [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]] = None, [](#__codelineno-0-3) save_path: [str](https://docs.python.org/3/library/stdtypes.html#str) | None = None, [](#__codelineno-0-4) method: LoaderKey = "pickle", [](#__codelineno-0-5) pin_modules: [bool](https://docs.python.org/3/library/functions.html#bool) = False, [](#__codelineno-0-6)) -> _cache_call` `[](#__codelineno-0-1)persistent_cache( [](#__codelineno-0-2) name: [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Optional](https://docs.python.org/3/library/typing.html#typing.Optional "typing.Optional")[[Callable](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable")[..., [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]] = None, [](#__codelineno-0-3) save_path: [str](https://docs.python.org/3/library/stdtypes.html#str) | None = None, [](#__codelineno-0-4) method: LoaderKey = "pickle", [](#__codelineno-0-5) *args: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [](#__codelineno-0-6) _internal_interface_not_for_external_use: None = None, [](#__codelineno-0-7) **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any") [](#__codelineno-0-8)) -> [Union](https://docs.python.org/3/library/typing.html#typing.Union "typing.Union")[_cache_call, _cache_context]` #### Context manager to save variables to disk and restore them thereafter.[¶](#marimo.persistent_cache--context-manager-to-save-variables-to-disk-and-restore-them-thereafter "Permanent link") The `mo.persistent_cache` context manager lets you delimit a block of code in which variables will be cached to disk when they are first computed. On subsequent runs of the cell, if marimo determines that this block of code hasn't changed and neither has its ancestors, it will restore the variables from disk instead of re-computing them, skipping execution of the block entirely. Restoration happens even across notebook runs, meaning you can use `mo.persistent_cache` to make notebooks start _instantly_, with variables that would otherwise be expensive to compute already materialized in memory. **Usage.** `[](#__codelineno-0-1)with persistent_cache(name="my_cache"): [](#__codelineno-0-2) variable = expensive_function() # This will be cached to disk. [](#__codelineno-0-3) print("hello, cache") # this will be skipped on cache hits` In this example, `variable` will be cached the first time the block is executed, and restored on subsequent runs of the block. If cache conditions are hit, the contents of `with` block will be skipped on execution. This means that side-effects such as writing to stdout and stderr will be skipped on cache hits. Note that `mo.state` and `UIElement` changes will also trigger cache invalidation, and be accordingly updated. **Warning.** Since context abuses sys frame trace, this may conflict with debugging tools or libraries that also use `sys.settrace`. **Args**: * `name`: the name of the cache, used to set saving path- to manually invalidate the cache, change the name. * `save_path`: the folder in which to save the cache, defaults to `__marimo__/cache` in the directory of the notebook file * `method`: the serialization method to use, current options are "json", and "pickle" (default). * `pin_modules`: if True, the cache will be invalidated if module versions differ between runs, defaults to False. #### Decorator for persistently caching the return value of a function.[¶](#marimo.persistent_cache--decorator-for-persistently-caching-the-return-value-of-a-function "Permanent link") `persistent_cache` can also be used as a drop in function-level memoization for `@mo.cache` or `@mo.lru_cache`. This is much slower than cache, but can be useful for saving function values between kernel restarts. For more details, refer to `mo.cache`. **Usage.** `[](#__codelineno-1-1)import marimo as mo [](#__codelineno-1-2) [](#__codelineno-1-3)[](#__codelineno-1-4)@mo.persistent_cache [](#__codelineno-1-5)def my_expensive_function(): [](#__codelineno-1-6) # Do expensive things [](#__codelineno-1-7)[](#__codelineno-1-8)# or [](#__codelineno-1-9)[](#__codelineno-1-10)@mo.persistent_cache(save_path="my/path/to/cache") [](#__codelineno-1-11)def my_expensive_function_cached_in_a_certain_location(): [](#__codelineno-1-12) # Do expensive things` **Args**: * `fn`: the wrapped function if no settings are passed. * `save_path`: the folder in which to save the cache, defaults to `__marimo__/cache` in the directory of the notebook file * `method`: the serialization method to use, current options are "json", and "pickle" (default). * `pin_modules`: if True, the cache will be invalidated if module versions differ between runs, defaults to False. App - marimo https://docs.marimo.io/api/app/ Get the metadata of a marimo app. The `AppMeta` class provides access to runtime metadata about a marimo app, such as its display theme and execution mode. Examples: Get the current theme and conditionally set a plotting library's theme: `[](#__codelineno-0-1)import altair as alt [](#__codelineno-0-2)[](#__codelineno-0-3)# Enable dark theme for Altair when marimo is in dark mode [](#__codelineno-0-4)alt.themes.enable( [](#__codelineno-0-5) "dark" if mo.app_meta().theme == "dark" else "default" [](#__codelineno-0-6))` Show content only in edit mode: `[](#__codelineno-1-1)# Only show this content when editing the notebook [](#__codelineno-1-2)mo.md("# Developer Notes") if mo.app_meta().mode == "edit" else None` Get the current request headers or user info: `[](#__codelineno-2-1)request = mo.app_meta().request [](#__codelineno-2-2)print(request.headers) [](#__codelineno-2-3)print(request.user)` | RETURNS | DESCRIPTION | | --- | --- | | `AppMeta` | An AppMeta object containing the app's metadata. **TYPE:** `AppMeta` | Cell - marimo https://docs.marimo.io/api/cell/ Run this cell and return its visual output and definitions. Use this method to run **named cells** and retrieve their output and definitions. This lets you reuse cells defined in one notebook in another notebook or Python file. It also makes it possible to write and execute unit tests for notebook cells using a test framework like `pytest`. Examples: marimo cells can be given names either through the editor cell menu or by manually changing the function name in the notebook file. For example, consider a notebook `notebook.py`: `[](#__codelineno-0-1)import marimo [](#__codelineno-0-2)[](#__codelineno-0-3)app = marimo.App() [](#__codelineno-0-4) [](#__codelineno-0-5)[](#__codelineno-0-6)@app.cell [](#__codelineno-0-7)def __(): [](#__codelineno-0-8) import marimo as mo [](#__codelineno-0-9) [](#__codelineno-0-10) return (mo,) [](#__codelineno-0-11) [](#__codelineno-0-12)[](#__codelineno-0-13)@app.cell [](#__codelineno-0-14)def __(): [](#__codelineno-0-15) x = 0 [](#__codelineno-0-16) y = 1 [](#__codelineno-0-17) return (x, y) [](#__codelineno-0-18) [](#__codelineno-0-19)[](#__codelineno-0-20)@app.cell [](#__codelineno-0-21)def add(mo, x, y): [](#__codelineno-0-22) z = x + y [](#__codelineno-0-23) mo.md(f"The value of z is {z}") [](#__codelineno-0-24) return (z,) [](#__codelineno-0-25) [](#__codelineno-0-26)[](#__codelineno-0-27)if __name__ == "__main__": [](#__codelineno-0-28) app.run()` To reuse the `add` cell in another notebook, you'd simply write: ``[](#__codelineno-1-1)from notebook import add [](#__codelineno-1-2)[](#__codelineno-1-3)# `output` is the markdown rendered by `add` [](#__codelineno-1-4)# defs["z"] == `1` [](#__codelineno-1-5)output, defs = add.run()`` When `run` is called without arguments, it automatically computes the values that the cell depends on (in this case, `mo`, `x`, and `y`). You can override these values by providing any subset of them as keyword arguments. For example, `[](#__codelineno-2-1)# defs["z"] == 4 [](#__codelineno-2-2)output, defs = add.run(x=2, y=2)` Defined UI Elements If the cell's `output` has UI elements that are in `defs`, interacting with the output in the frontend will trigger reactive execution of cells that reference the `defs` object. For example, if `output` has a slider defined by the cell, then scrubbing the slider will cause cells that reference `defs` to run. Async cells If this cell is a coroutine function (starting with `async`), or if any of its ancestors are coroutine functions, then you'll need to `await` the result: `output, defs = await cell.run()`. You can check whether the result is an awaitable using: `[](#__codelineno-0-1)from collections.abc import Awaitable [](#__codelineno-0-2)[](#__codelineno-0-3)ret = cell.run() [](#__codelineno-0-4)if isinstance(ret, Awaitable): [](#__codelineno-0-5) output, defs = await ret [](#__codelineno-0-6)else: [](#__codelineno-0-7) output, defs = ret` | PARAMETER | DESCRIPTION | | --- | --- | | `**refs` | You may pass values for any of this cell's references as keyword arguments. marimo will automatically compute values for any refs that are not provided by executing the parent cells that compute them. **TYPE:** `[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` **DEFAULT:** `{}` | | RETURNS | DESCRIPTION | | --- | --- | | `[tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Mapping](https://docs.python.org/3/library/typing.html#typing.Mapping "typing.Mapping")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]] | [Awaitable](https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable "collections.abc.Awaitable")[[tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[[Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), [Mapping](https://docs.python.org/3/library/typing.html#typing.Mapping "typing.Mapping")[[str](https://docs.python.org/3/library/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")]]]` | tuple `(output, defs)`, or an awaitable of the same: `output` is the cell's last expression and `defs` is a `Mapping` from the cell's defined names to their values. | Miscellaneous - marimo https://docs.marimo.io/api/miscellaneous/ marimo.running\_in\_notebook [¶](#marimo.running_in_notebook "Permanent link") ------------------------------------------------------------------------------ `[](#__codelineno-0-1)running_in_notebook() -> [bool](https://docs.python.org/3/library/functions.html#bool)` Returns True if running in a marimo notebook, False otherwise marimo.defs [¶](#marimo.defs "Permanent link") ---------------------------------------------- Get the definitions of the currently executing cell. | RETURNS | DESCRIPTION | | --- | --- | | `[tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[[str](https://docs.python.org/3/library/stdtypes.html#str), ...]` | tuple\[str, ...\]: A tuple of the currently executing cell's defs. | marimo.refs [¶](#marimo.refs "Permanent link") ---------------------------------------------- Get the references of the currently executing cell. | RETURNS | DESCRIPTION | | --- | --- | | `[tuple](https://docs.python.org/3/library/stdtypes.html#tuple)[[str](https://docs.python.org/3/library/stdtypes.html#str), ...]` | tuple\[str, ...\]: A tuple of the currently executing cell's refs. | marimo.notebook\_dir [¶](#marimo.notebook_dir "Permanent link") --------------------------------------------------------------- `[](#__codelineno-0-1)notebook_dir() -> [Path](https://docs.python.org/3/library/pathlib.html#pathlib.Path "pathlib.Path") | None` Get the directory of the currently executing notebook. | RETURNS | DESCRIPTION | | --- | --- | | `[Path](https://docs.python.org/3/library/pathlib.html#pathlib.Path "pathlib.Path") | None` | pathlib.Path | None: A pathlib.Path object representing the directory of the current notebook, or None if the notebook's directory cannot be determined. | Examples: `[](#__codelineno-0-1)data_file = mo.notebook_dir() / "data" / "example.csv" [](#__codelineno-0-2)# Use the directory to read a file [](#__codelineno-0-3)if data_file.exists(): [](#__codelineno-0-4) print(f"Found data file: {data_file}") [](#__codelineno-0-5)else: [](#__codelineno-0-6) print("No data file found")` marimo.notebook\_location [¶](#marimo.notebook_location "Permanent link") ------------------------------------------------------------------------- Get the location of the currently executing notebook. In WASM, this is the URL of webpage, for example, `https://my-site.com`. For nested paths, this is the URL including the origin and pathname. `https://.github.io//folder`. In non-WASM, this is the directory of the notebook, which is the same as `mo.notebook_dir()`. Examples: In order to access data both locally and when a notebook runs via WebAssembly (e.g. hosted on GitHub Pages), you can use this approach to fetch data from the notebook's location. `[](#__codelineno-0-1)import polars as pl [](#__codelineno-0-2)[](#__codelineno-0-3)data_path = mo.notebook_location() / "public" / "data.csv" [](#__codelineno-0-4)df = pl.read_csv(str(data_path)) [](#__codelineno-0-5)df.head()` | RETURNS | DESCRIPTION | | --- | --- | | `[PurePath](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath "pathlib.PurePath") | None` | Path | None: A Path object representing the URL or directory of the current notebook, or None if the notebook's directory cannot be determined. | marimo.Thread [¶](#marimo.Thread "Permanent link") -------------------------------------------------- `[](#__codelineno-0-1)Thread(*args: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"), **kwargs: [Any](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"))` Bases: `[Thread](https://docs.python.org/3/library/threading.html#threading.Thread "threading.Thread")` A Thread subclass that is aware of marimo internals. `mo.Thread` has the same API as threading.Thread, but `mo.Thread`s are able to communicate with the marimo frontend, whereas `threading.Thread` can't. Threads can append to a cell's output using `mo.output.append`, or to the console output area using `print`. The corresponding outputs will be forwarded to the frontend. Writing directly to sys.stdout or sys.stderr, or to file descriptors 1 and 2, is not yet supported. ### run [¶](#marimo.Thread.run "Permanent link") Recipes - marimo https://docs.marimo.io/recipes/ This page includes code snippets or "**recipes**" for a variety of common tasks. Use them as building blocks or examples when making your own notebooks. In these recipes, **each code block represents a cell**. Control Flow[¶](#control-flow "Permanent link") ----------------------------------------------- ### Show an output conditionally[¶](#show-an-output-conditionally "Permanent link") **Use cases.** Hide an output until a condition is met (_e.g._, until algorithm parameters are valid), or show different outputs depending on the value of a UI element or some other Python object **Recipe.** 1. Use an `if` expression to choose which output to show. `[](#__codelineno-0-1)# condition is a boolean, True of False [](#__codelineno-0-2)condition = True [](#__codelineno-0-3)"condition is True" if condition else None` ### Run a cell on a timer[¶](#run-a-cell-on-a-timer "Permanent link") **Use cases.** * Load new data periodically, and show updated plots or other outputs. For example, in a dashboard monitoring a training run, experiment trial, real-time weather data, ... * Run a job periodically **Recipe.** 1. Import packages 2. Create a [`mo.ui.refresh`](https://docs.marimo.io/api/inputs/refresh/#marimo.ui.refresh) timer that fires once a second: `[](#__codelineno-2-1)refresh = mo.ui.refresh(default_interval="1s") [](#__codelineno-2-2)# This outputs a timer that fires once a second [](#__codelineno-2-3)refresh` 3. Reference the timer by name to make this cell run once a second `[](#__codelineno-3-1)import random [](#__codelineno-3-2)[](#__codelineno-3-3)# This cell will run once a second! [](#__codelineno-3-4)refresh [](#__codelineno-3-5)[](#__codelineno-3-6)mo.md("#" + "🍃" * random.randint(1, 10))` Requires 'on cell change' autorun For this to work, the [runtime configuration's](https://docs.marimo.io/guides/configuration/runtime_configuration/) `on cell change` should be set to `autorun` ### Require form submission before sending UI value[¶](#require-form-submission-before-sending-ui-value "Permanent link") **Use cases.** UI elements automatically send their values to the Python when they are interacted with, and run all cells referencing the elements. This makes marimo notebooks responsive, but it can be an issue when the downstream cells are expensive, or when the input (such as a text box) needs to be filled out completely before it is considered valid. Forms let you gate submission of UI element values on manual confirmation, via a button press. **Recipe.** 1. Import packages 2. Create a submittable form. `[](#__codelineno-5-1)form = mo.ui.text(label="Your name").form() [](#__codelineno-5-2)form` 3. Get the value of the form. ### Stop execution of a cell and its descendants[¶](#stop-execution-of-a-cell-and-its-descendants "Permanent link") **Use cases.** For example, don't run a cell or its descendants if a form is unsubmitted. **Recipe.** 1. Import packages 2. Create a submittable form. `[](#__codelineno-8-1)form = mo.ui.text(label="Your name").form() [](#__codelineno-8-2)form` 3. Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to stop execution when the form is unsubmitted. `[](#__codelineno-9-1)mo.stop(form.value is None, mo.md("Submit the form to continue")) [](#__codelineno-9-2)[](#__codelineno-9-3)mo.md(f"Hello, {form.value}!")` Grouping UI elements together[¶](#grouping-ui-elements-together "Permanent link") --------------------------------------------------------------------------------- ### Create an array of UI elements[¶](#create-an-array-of-ui-elements "Permanent link") **Use cases.** In order to synchronize UI elements between the frontend and backend (Python), marimo requires you to [assign UI elements to global variables](https://docs.marimo.io/guides/interactivity/). But sometimes you don't know the number of elements to make until runtime: for example, maybe you want to make a list of sliders, and the number of sliders to make depends on the value of some other UI element. You might be tempted to create a Python list of UI elements, such as `l = [mo.ui.slider(1, 10) for i in range(number.value)]`: _however, this won't work, because the sliders are not bound to global variables_. For such cases, marimo provides the "higher-order" UI element [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), which lets you make a new UI element out of a list of UI elements: `l = mo.ui.array([mo.ui.slider(1, 10) for i in range(number.value)])`. The value of an `array` element is a list of the values of the elements it wraps (in this case, a list of the slider values). Any time you interact with any of the UI elements in the array, all cells referencing the array by name (in this case, "`l`") will run automatically. **Recipe.** 1. Import packages. 2. Use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) to group together many UI elements into a list. `[](#__codelineno-11-1)import random [](#__codelineno-11-2)[](#__codelineno-11-3)# instead of random.randint, in your notebook you'd use the value of [](#__codelineno-11-4)# an upstream UI element or other Python object [](#__codelineno-11-5)array = mo.ui.array([mo.ui.text() for i in range(random.randint(1, 10))]) [](#__codelineno-11-6)array` 3. Get the value of the UI elements using `array.value` ### Create a dictionary of UI elements[¶](#create-a-dictionary-of-ui-elements "Permanent link") **Use cases.** Same as for creating an array of UI elements, but lets you name each of the wrapped elements with a string key. **Recipe.** 1. Import packages. 2. Use [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) to group together many UI elements into a list. `[](#__codelineno-14-1)import random [](#__codelineno-14-2)[](#__codelineno-14-3)# instead of random.randint, in your notebook you'd use the value of [](#__codelineno-14-4)# an upstream UI element or other Python object [](#__codelineno-14-5)dictionary = mo.ui.dictionary({str(i): mo.ui.text() for i in range(random.randint(1, 10))}) [](#__codelineno-14-6)dictionary` 3. Get the value of the UI elements using `dictionary.value` ### Embed a dynamic number of UI elements in another output[¶](#embed-a-dynamic-number-of-ui-elements-in-another-output "Permanent link") **Use cases.** When you want to embed a dynamic number of UI elements in other outputs (like tables or markdown). **Recipe.** 1. Import packages 2. Group the elements with [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) or [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), then retrieve them from the container and display them elsewhere. ``[](#__codelineno-17-1)import random [](#__codelineno-17-2)[](#__codelineno-17-3)n_items = random.randint(2, 5) [](#__codelineno-17-4)[](#__codelineno-17-5)# Create a dynamic number of elements using `mo.ui.dictionary` and [](#__codelineno-17-6)# `mo.ui.array` [](#__codelineno-17-7)elements = mo.ui.dictionary( [](#__codelineno-17-8) { [](#__codelineno-17-9) "checkboxes": mo.ui.array([mo.ui.checkbox() for _ in range(n_items)]), [](#__codelineno-17-10) "texts": mo.ui.array( [](#__codelineno-17-11) [mo.ui.text(placeholder="task ...") for _ in range(n_items)] [](#__codelineno-17-12) ), [](#__codelineno-17-13) } [](#__codelineno-17-14)) [](#__codelineno-17-15)[](#__codelineno-17-16)mo.md( [](#__codelineno-17-17) f""" [](#__codelineno-17-18) Here's a TODO list of {n_items} items\n\n [](#__codelineno-17-19) """ [](#__codelineno-17-20) + "\n\n".join( [](#__codelineno-17-21) # Iterate over the elements and embed them in markdown [](#__codelineno-17-22) [ [](#__codelineno-17-23) f"{checkbox} {text}" [](#__codelineno-17-24) for checkbox, text in zip( [](#__codelineno-17-25) elements["checkboxes"], elements["texts"] [](#__codelineno-17-26) ) [](#__codelineno-17-27) ] [](#__codelineno-17-28) ) [](#__codelineno-17-29))`` 3. Get the value of the elements ### Create a hstack (or vstack) of UI elements with `on_change` handlers[¶](#create-a-hstack-or-vstack-of-ui-elements-with-on_change-handlers "Permanent link") **Use cases.** Arrange a dynamic number of UI elements in a hstack or vstack, for example some number of buttons, and execute some side-effect when an element is interacted with, e.g. when a button is clicked. **Recipe.** 1. Import packages 2. Create buttons in `mo.ui.array` and pass them to hstack -- a regular Python list won't work. Make sure to assign the array to a global variable. `[](#__codelineno-20-1)import random [](#__codelineno-20-2) [](#__codelineno-20-3)[](#__codelineno-20-4)# Create a state object that will store the index of the [](#__codelineno-20-5)# clicked button [](#__codelineno-20-6)get_state, set_state = mo.state(None) [](#__codelineno-20-7)[](#__codelineno-20-8)# Create an mo.ui.array of buttons - a regular Python list won't work. [](#__codelineno-20-9)buttons = mo.ui.array( [](#__codelineno-20-10) [ [](#__codelineno-20-11) mo.ui.button( [](#__codelineno-20-12) label="button " + str(i), on_change=lambda v, i=i: set_state(i) [](#__codelineno-20-13) ) [](#__codelineno-20-14) for i in range(random.randint(2, 5)) [](#__codelineno-20-15) ] [](#__codelineno-20-16)) [](#__codelineno-20-17)[](#__codelineno-20-18)mo.hstack(buttons)` 3. Get the state value ### Create a table column of buttons with `on_change` handlers[¶](#create-a-table-column-of-buttons-with-on_change-handlers "Permanent link") **Use cases.** Arrange a dynamic number of UI elements in a column of a table, and execute some side-effect when an element is interacted with, e.g. when a button is clicked. **Recipe.** 1. Import packages 2. Create buttons in `mo.ui.array` and pass them to `mo.ui.table`. Make sure to assign the table and array to global variables `[](#__codelineno-23-1)import random [](#__codelineno-23-2) [](#__codelineno-23-3)[](#__codelineno-23-4)# Create a state object that will store the index of the [](#__codelineno-23-5)# clicked button [](#__codelineno-23-6)get_state, set_state = mo.state(None) [](#__codelineno-23-7)[](#__codelineno-23-8)# Create an mo.ui.array of buttons - a regular Python list won't work. [](#__codelineno-23-9)buttons = mo.ui.array( [](#__codelineno-23-10) [ [](#__codelineno-23-11) mo.ui.button( [](#__codelineno-23-12) label="button " + str(i), on_change=lambda v, i=i: set_state(i) [](#__codelineno-23-13) ) [](#__codelineno-23-14) for i in range(random.randint(2, 5)) [](#__codelineno-23-15) ] [](#__codelineno-23-16)) [](#__codelineno-23-17)[](#__codelineno-23-18)# Put the buttons array into the table [](#__codelineno-23-19)table = mo.ui.table( [](#__codelineno-23-20) { [](#__codelineno-23-21) "Action": ["Action Name"] * len(buttons), [](#__codelineno-23-22) "Trigger": list(buttons), [](#__codelineno-23-23) } [](#__codelineno-23-24)) [](#__codelineno-23-25)table` 3. Get the state value ### Create a form with multiple UI elements[¶](#create-a-form-with-multiple-ui-elements "Permanent link") **Use cases.** Combine multiple UI elements into a form so that submission of the form sends all its elements to Python. **Recipe.** 1. Import packages. 2. Use [`mo.ui.form`](https://docs.marimo.io/api/inputs/form/#marimo.ui.form) and [`Html.batch`](https://docs.marimo.io/api/html/#marimo.Html.batch) to create a form with multiple elements. `[](#__codelineno-26-1)form = mo.md( [](#__codelineno-26-2) r""" [](#__codelineno-26-3) Choose your algorithm parameters: [](#__codelineno-26-4) [](#__codelineno-26-5) - $\epsilon$: {epsilon} [](#__codelineno-26-6) - $\delta$: {delta} [](#__codelineno-26-7) """ [](#__codelineno-26-8)).batch(epsilon=mo.ui.slider(0.1, 1, step=0.1), delta=mo.ui.number(1, 10)).form() [](#__codelineno-26-9)form` 3. Get the submitted form value. ### Populating form with pre-defined examples[¶](#populating-form-with-pre-defined-examples "Permanent link") **Use cases.** To give examples of how a filled form looks like. Useful for illustrating complex API requests or database queries. The form can also be populated from [URL query parameters](https://docs.marimo.io/api/query_params/) ([notebook example](https://marimo.app/l/w21a3x?t1=query&t2=params)). **Recipe.** 1. Import packages 2. Create dropdown of examples `[](#__codelineno-29-1)examples = mo.ui.dropdown( [](#__codelineno-29-2) options={ [](#__codelineno-29-3) "ex 1": {"t1": "hello", "t2": "world"}, [](#__codelineno-29-4) "ex 2": {"t1": "marimo", "t2": "notebook"}, [](#__codelineno-29-5) }, [](#__codelineno-29-6) value="ex 1", [](#__codelineno-29-7) label="examples", [](#__codelineno-29-8))` 3. Create form from examples. `[](#__codelineno-30-1)form = ( [](#__codelineno-30-2) mo.md( [](#__codelineno-30-3) """ [](#__codelineno-30-4) ### Your form [](#__codelineno-30-5) [](#__codelineno-30-6) {t1} [](#__codelineno-30-7) {t2} [](#__codelineno-30-8)""" [](#__codelineno-30-9) ) [](#__codelineno-30-10) .batch( [](#__codelineno-30-11) t1=mo.ui.text(label="enter text", value=examples.value.get("t1", "")), [](#__codelineno-30-12) t2=mo.ui.text(label="more text", value=examples.value.get("t2", "")), [](#__codelineno-30-13) ) [](#__codelineno-30-14) .form( [](#__codelineno-30-15) submit_button_label="go" [](#__codelineno-30-16) ) [](#__codelineno-30-17))` 4. Run pre-populated from or recompute with new input. `[](#__codelineno-31-1)output = ( [](#__codelineno-31-2) " ".join(form.value.values()).upper() [](#__codelineno-31-3) if form.value is not None [](#__codelineno-31-4) else " ".join(examples.value.values()).upper() [](#__codelineno-31-5)) [](#__codelineno-31-6)examples, form, output` Working with buttons[¶](#working-with-buttons "Permanent link") --------------------------------------------------------------- ### Create a button that triggers computation when clicked[¶](#create-a-button-that-triggers-computation-when-clicked "Permanent link") **Use cases.** To trigger a computation on button click and only on button click, use [`mo.ui.run_button()`](https://docs.marimo.io/api/inputs/run_button/). **Recipe.** 1. Import packages 2. Create a run button `[](#__codelineno-33-1)button = mo.ui.run_button() [](#__codelineno-33-2)button` 3. Run something only if the button has been clicked. `[](#__codelineno-34-1)mo.stop(not button.value, "Click 'run' to generate a random number") [](#__codelineno-34-2)[](#__codelineno-34-3)import random [](#__codelineno-34-4)random.randint(0, 1000)` ### Create a counter button[¶](#create-a-counter-button "Permanent link") **Use cases.** A counter button, i.e. a button that counts the number of times it has been clicked, is a helpful building block for reacting to button clicks (see other recipes in this section). **Recipe.** 1. Import packages 2. Use [`mo.ui.button`](https://docs.marimo.io/api/inputs/button/#marimo.ui.button) and its `on_click` argument to create a counter button. `[](#__codelineno-36-1)# Initialize the button value to 0, increment it on every click [](#__codelineno-36-2)button = mo.ui.button(value=0, on_click=lambda count: count + 1) [](#__codelineno-36-3)button` 3. Get the button value ### Create a toggle button[¶](#create-a-toggle-button "Permanent link") **Use cases.** Toggle between two states using a button with a button that toggles between `True` and `False`. (Tip: you can also just use [`mo.ui.switch`](https://docs.marimo.io/api/inputs/switch/#marimo.ui.switch).) **Recipe.** 1. Import packages 2. Use [`mo.ui.button`](https://docs.marimo.io/api/inputs/button/#marimo.ui.button) and its `on_click` argument to create a toggle button. `[](#__codelineno-39-1)# Initialize the button value to False, flip its value on every click. [](#__codelineno-39-2)button = mo.ui.button(value=False, on_click=lambda value: not value) [](#__codelineno-39-3)button` 3. Toggle between two outputs using the button value. `[](#__codelineno-40-1)mo.md("True!") if button.value else mo.md("False!")` ### Re-run a cell when a button is pressed[¶](#re-run-a-cell-when-a-button-is-pressed "Permanent link") **Use cases.** For example, you have a cell showing a random sample of data, and you want to resample on button press. **Recipe.** 1. Import packages 2. Create a button without a value, to function as a _trigger_. `[](#__codelineno-42-1)button = mo.ui.button() [](#__codelineno-42-2)button` 3. Reference the button in another cell. `[](#__codelineno-43-1)# the button acts as a trigger: every time it is clicked, this cell is run [](#__codelineno-43-2)button [](#__codelineno-43-3)[](#__codelineno-43-4)# Replace with your custom logic [](#__codelineno-43-5)import random [](#__codelineno-43-6)random.randint(0, 100)` ### Run a cell when a button is pressed, but not before[¶](#run-a-cell-when-a-button-is-pressed-but-not-before "Permanent link") **Use cases.** Wait for confirmation before executing downstream cells (similar to a form). **Recipe.** 1. Import packages 2. Create a counter button. `[](#__codelineno-45-1)button = mo.ui.button(value=0, on_click=lambda count: count + 1) [](#__codelineno-45-2)button` 3. Only execute when the count is greater than 0. `[](#__codelineno-46-1)# Don't run this cell if the button hasn't been clicked, using mo.stop. [](#__codelineno-46-2)# Alternatively, use an if expression. [](#__codelineno-46-3)mo.stop(button.value == 0) [](#__codelineno-46-4)[](#__codelineno-46-5)mo.md(f"The button was clicked {button.value} times")` ### Reveal an output when a button is pressed[¶](#reveal-an-output-when-a-button-is-pressed "Permanent link") **Use cases.** Incrementally reveal a user interface. **Recipe.** 1. Import packages 2. Create a counter button. `[](#__codelineno-48-1)button = mo.ui.button(value=0, on_click=lambda count: count + 1) [](#__codelineno-48-2)button` 3. Show an output after the button is clicked. `[](#__codelineno-49-1)mo.md("#" + "🍃" * button.value) if button.value > 0 else None` Caching[¶](#caching "Permanent link") ------------------------------------- ### Cache function outputs in memory[¶](#cache-function-outputs-in-memory "Permanent link") **Use case.** Because marimo runs cells automatically as code and UI elements change, it can be helpful to cache expensive intermediate computations. For example, perhaps your notebook computes t-SNE, UMAP, or PyMDE embeddings, and exposes their parameters as UI elements. Caching the embeddings for different configurations of the elements would greatly speed up your notebook. **Recipe.** 1. Use [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) to cache function outputs given inputs. `[](#__codelineno-50-1)import marimo as mo [](#__codelineno-50-2)[](#__codelineno-50-3)@mo.cache [](#__codelineno-50-4)def compute_predictions(problem_parameters): [](#__codelineno-50-5) # replace with your own function/parameters [](#__codelineno-50-6) ...` Whenever `compute_predictions` is called with a value of `problem_parameters` it has not seen, it will compute the predictions and store them in a cache. The next time it is called with the same parameters, instead of recomputing the predictions, it will return the previously computed value from the cache. ### Persistent caching for very expensive computations[¶](#persistent-caching-for-very-expensive-computations "Permanent link") **Use case.** If you are using marimo to capture very compute intensive results, you may want to save the state of your computations to disk. Ideally, if you update your code, then this save should be invalidated. It may also be advantageous to add UI elements to explore your results, without having to recompute expensive computations. You can achieve this with [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache). **Recipe.** 1. Use `mo.persistent_cache` to cache blocks of code to disk. `[](#__codelineno-51-1)import marimo as mo [](#__codelineno-51-2)[](#__codelineno-51-3)with mo.persistent_cache("my_cache"): [](#__codelineno-51-4) # This block of code, and results will be cached to disk [](#__codelineno-51-5) ...` If the execution conditions are the same, then cache will load results from disk, and populate variable definitions. Islands - marimo https://docs.marimo.io/guides/island_example/ Preview Islands are an early feature. While the API likely won't change, there are some improvements we'd like to make before we consider them stable. Please let us know on [GitHub](https://github.com/marimo-team/marimo/issues) if you run into any issues or have any feedback! > This content below is powered by marimo's reactive runtime. It will become interactive after initializing the marimo runtime. * * * Hello, islands! 🏝️🏝️ * * * See the HTML `[](#__codelineno-0-1) [](#__codelineno-0-2) [](#__codelineno-0-3) [](#__codelineno-0-4) [](#__codelineno-0-5) [](#__codelineno-0-6) [](#__codelineno-0-7) [](#__codelineno-0-8) [](#__codelineno-0-19) [](#__codelineno-0-20) [](#__codelineno-0-21) [](#__codelineno-0-22) [](#__codelineno-0-23) [](#__codelineno-0-24) [](#__codelineno-0-25) Hello, islands! 🏝️🏝️ [](#__codelineno-0-26) [](#__codelineno-0-27) [](#__codelineno-0-28) [](#__codelineno-0-35) [](#__codelineno-0-36)` BigQuery - marimo https://docs.marimo.io/integrations/google_cloud_bigquery/ Google Cloud BigQuery[¶](#google-cloud-bigquery "Permanent link") ----------------------------------------------------------------- Getting Started[¶](#getting-started "Permanent link") ----------------------------------------------------- To use Google Cloud BigQuery as a data source, you will need to install the `google-cloud-bigquery` Python package. You can install this package using `pip`: `[](#__codelineno-0-1)pip install google-cloud-bigquery db-dtypes` Authentication[¶](#authentication "Permanent link") --------------------------------------------------- ### Application Default Credentials (Recommended)[¶](#application-default-credentials-recommended "Permanent link") The easiest way to authenticate with Google Cloud BigQuery is to use [Application Default Credentials](https://cloud.google.com/docs/authentication/production). If you are running marimo on Google Cloud and your resource has a service account attached, then Application Default Credentials will automatically be used. If you are running marimo locally, you can authenticate with Application Default Credentials by running the following command: `[](#__codelineno-1-1)gcloud auth application-default login` ### Service Account Key File[¶](#service-account-key-file "Permanent link") To authenticate with Google Cloud BigQuery, you will need to create a service account and download the service account key file. You can create a service account and download the key file by following the instructions [here](https://cloud.google.com/iam/docs/creating-managing-service-account-keys). Once you have downloaded the key file, you can authenticate with Google Cloud BigQuery by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the key file: `[](#__codelineno-2-1)export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key/file.json` Reading Data[¶](#reading-data "Permanent link") ----------------------------------------------- To read data from Google Cloud BigQuery, you will need to create a `BigQueryClient` object. You can then use this object to read data from Google Cloud BigQuery. `[](#__codelineno-3-1)# Cell 1 - Load libraries [](#__codelineno-3-2)import marimo as mo [](#__codelineno-3-3)from google.cloud import bigquery [](#__codelineno-3-4)[](#__codelineno-3-5)# Cell 2 - Load datasets [](#__codelineno-3-6)client = bigquery.Client() [](#__codelineno-3-7)datasets = list(client.list_datasets()) [](#__codelineno-3-8)[](#__codelineno-3-9)# Cell 3 - Select dataset [](#__codelineno-3-10)selected_dataset = mo.ui.dropdown( [](#__codelineno-3-11) label="Select dataset", options=[d.dataset_id for d in datasets] [](#__codelineno-3-12)) [](#__codelineno-3-13)selected_dataset [](#__codelineno-3-14)[](#__codelineno-3-15)# Cell 4 - Load tables [](#__codelineno-3-16)dataset = client.dataset(selected_dataset.value) [](#__codelineno-3-17)tables = list(client.list_tables(dataset)) [](#__codelineno-3-18)selected_table = mo.ui.dropdown( [](#__codelineno-3-19) label="Select table", options=[t.table_id for t in tables] [](#__codelineno-3-20)) [](#__codelineno-3-21)selected_table [](#__codelineno-3-22)[](#__codelineno-3-23)# Cell 5 - Load table data [](#__codelineno-3-24)results = client.list_rows(dataset.table(selected_table.value), max_results=10) [](#__codelineno-3-25)mo.ui.table(results.to_dataframe(), selection=None)` Example[¶](#example "Permanent link") ------------------------------------- Check out our full example using Google Cloud BigQuery [here](https://github.com/marimo-team/marimo/blob/main/examples/cloud/gcp/google_cloud_bigquery.py) Or run it yourself: `[](#__codelineno-4-1)marimo run https://raw.githubusercontent.com/marimo-team/marimo/main/examples/cloud/gcp/google_cloud_bigquery.py` Google Cloud Storage - marimo https://docs.marimo.io/integrations/google_cloud_storage/ Getting Started[¶](#getting-started "Permanent link") ----------------------------------------------------- To use Google Cloud Storage as a data source, you will need to install the `google-cloud-storage` Python package. You can install this package using `pip`: `[](#__codelineno-0-1)pip install google-cloud-storage` Authentication[¶](#authentication "Permanent link") --------------------------------------------------- ### Application Default Credentials (Recommended)[¶](#application-default-credentials-recommended "Permanent link") The easiest way to authenticate with Google Cloud Storage is to use [Application Default Credentials](https://cloud.google.com/docs/authentication/production). If you are running marimo on Google Cloud and your resource has a service account attached, then Application Default Credentials will automatically be used. If you are running marimo locally, you can authenticate with Application Default Credentials by running the following command: `[](#__codelineno-1-1)gcloud auth application-default login` ### Service Account Key File[¶](#service-account-key-file "Permanent link") To authenticate with Google Cloud Storage, you will need to create a service account and download the service account key file. You can create a service account and download the key file by following the instructions [here](https://cloud.google.com/iam/docs/creating-managing-service-account-keys). Once you have downloaded the key file, you can authenticate with Google Cloud Storage by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the key file: `[](#__codelineno-2-1)export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key/file.json` Reading Data[¶](#reading-data "Permanent link") ----------------------------------------------- To read data from Google Cloud Storage, you will need to create a `StorageClient` object. You can then use this object to read data from Google Cloud Storage. `[](#__codelineno-3-1)# Cell 1 - Load libraries [](#__codelineno-3-2)import marimo as mo [](#__codelineno-3-3)from google.cloud import storage [](#__codelineno-3-4)[](#__codelineno-3-5)# Cell 2 - Load buckets [](#__codelineno-3-6)client = storage.Client() [](#__codelineno-3-7)buckets = client.list_buckets() [](#__codelineno-3-8)[](#__codelineno-3-9)# Cell 3 - Select bucket [](#__codelineno-3-10)selected_bucket = mo.ui.dropdown( [](#__codelineno-3-11) label="Select bucket", options=[b.name for b in buckets] [](#__codelineno-3-12)) [](#__codelineno-3-13)selected_bucket [](#__codelineno-3-14)[](#__codelineno-3-15)# Cell 4 - Load files [](#__codelineno-3-16)files = list(bucket.list_blobs()) [](#__codelineno-3-17)items = [ [](#__codelineno-3-18) { [](#__codelineno-3-19) "Name": f.name, [](#__codelineno-3-20) "Updated": f.updated.strftime("%h %d, %Y"), [](#__codelineno-3-21) "Size": f.size, [](#__codelineno-3-22) } [](#__codelineno-3-23) for f in files [](#__codelineno-3-24)] [](#__codelineno-3-25)file_table = mo.ui.table(items, selection="single") [](#__codelineno-3-26)file_table if items else mo.md("No files found").callout()` Example[¶](#example "Permanent link") ------------------------------------- Check out our full example using Google Cloud Storage [here](https://github.com/marimo-team/marimo/blob/main/examples/cloud/gcp/google_cloud_storage.py) Or run it yourself: `[](#__codelineno-4-1)marimo run https://raw.githubusercontent.com/marimo-team/marimo/main/examples/cloud/gcp/google_cloud_storage.py` MotherDuck - marimo https://docs.marimo.io/integrations/motherduck/ [MotherDuck](https://motherduck.com/) is a cloud-based data warehouse that combines the power of DuckDB with the scalability of the cloud. This guide will help you integrate MotherDuck with marimo. 1\. Connecting to MotherDuck[¶](#1-connecting-to-motherduck "Permanent link") ----------------------------------------------------------------------------- To use MotherDuck as a data source, you'll need to install the `marimo[sql]` Python package. install with pipinstall with uvinstall with conda `[](#__codelineno-0-1)pip install "marimo[sql]"` `[](#__codelineno-1-1)uv pip install "marimo[sql]"` `[](#__codelineno-2-1)conda install -c conda-forge marimo duckdb polars` To connect to MotherDuck, import `duckdb` and `ATTACH` your MotherDuck database. Using MotherDuck[¶](#using-motherduck "Permanent link") ------------------------------------------------------- ### 1\. Connecting and Database Discovery[¶](#1-connecting-and-database-discovery "Permanent link") SQLPython `[](#__codelineno-3-1)ATTACH IF NOT EXISTS 'md:my_db'` `[](#__codelineno-4-1)import duckdb [](#__codelineno-4-2)# Connect to MotherDuck [](#__codelineno-4-3)duckdb.sql("ATTACH IF NOT EXISTS 'md:my_db'")` You will be prompted to authenticate with MotherDuck when you run the above cell. This will open a browser window where you can log in and authorize your marimo notebook to access your MotherDuck database. In order to avoid being prompted each time you open a notebook, you can set the `motherduck_token` environment variable: `[](#__codelineno-5-1)export motherduck_token="your_token" [](#__codelineno-5-2)marimo edit` Once connected, your MotherDuck tables are automatically discovered in the Datasources Panel: Browse your MotherDuck databases ### 2\. Writing SQL Queries[¶](#2-writing-sql-queries "Permanent link") You can query your MotherDuck tables using SQL cells in marimo. Here's an example of how to query a table and display the results using marimo: Query a MotherDuck table marimo's reactive execution model extends into SQL queries, so changes to your SQL will automatically trigger downstream computations for dependent cells (or optionally mark cells as stale for expensive computations). ### 3\. Mixing SQL and Python[¶](#3-mixing-sql-and-python "Permanent link") MotherDuck allows you to seamlessly mix SQL queries with Python code, enabling powerful data manipulation and analysis. Here's an example: Mixing SQL and Python This example demonstrates how you can use SQL to query your data, then use Python and marimo to further analyze and visualize the results. Example Notebook[¶](#example-notebook "Permanent link") ------------------------------------------------------- For a full example of using MotherDuck with marimo, check out our [MotherDuck example notebook](https://github.com/marimo-team/marimo/blob/main/examples/sql/connect_to_motherduck.py). `[](#__codelineno-6-1)marimo edit https://github.com/marimo-team/marimo/blob/main/examples/sql/connect_to_motherduck.py` Google Sheets - marimo https://docs.marimo.io/integrations/google_sheets/ Getting Started[¶](#getting-started "Permanent link") ----------------------------------------------------- To use Google Sheets as a data source, you will need to install the `gspread` and `oauth2client` Python packages. You can install this package using `pip`: `[](#__codelineno-0-1)pip install gspread oauth2client` Authentication[¶](#authentication "Permanent link") --------------------------------------------------- ### Application Default Credentials (Recommended)[¶](#application-default-credentials-recommended "Permanent link") The easiest way to authenticate with Google Sheets is to use [Application Default Credentials](https://cloud.google.com/docs/authentication/production). If you are running marimo on Google Cloud and your resource has a service account attached, then Application Default Credentials will automatically be used. If you are running marimo locally, you can authenticate with Application Default Credentials by running the following command: `[](#__codelineno-1-1)gcloud auth application-default login` ### Service Account Key File[¶](#service-account-key-file "Permanent link") To authenticate with Google Sheets, you will need to create a service account and download the service account key file. You can create a service account and download the key file by following the instructions [here](https://cloud.google.com/iam/docs/creating-managing-service-account-keys). Once you have downloaded the key file, you can authenticate with Google Sheets by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the key file: `[](#__codelineno-2-1)export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key/file.json` Reading Data[¶](#reading-data "Permanent link") ----------------------------------------------- To read data from Google Sheets, you will need to authenticate and create a `gspread.Client`. You can then use this object to read data from Google Sheets. `[](#__codelineno-3-1)# Cell 1 - Load libraries [](#__codelineno-3-2)import marimo as mo [](#__codelineno-3-3)import pandas as pd [](#__codelineno-3-4)import os [](#__codelineno-3-5)import gspread [](#__codelineno-3-6)from oauth2client.service_account import ServiceAccountCredentials [](#__codelineno-3-7)[](#__codelineno-3-8)# Authenticate with Google Sheets [](#__codelineno-3-9)scope = [ [](#__codelineno-3-10) "https://spreadsheets.google.com/feeds", [](#__codelineno-3-11) "https://www.googleapis.com/auth/drive", [](#__codelineno-3-12)] [](#__codelineno-3-13)credentials = ServiceAccountCredentials.from_json_keyfile_name( [](#__codelineno-3-14) os.environ["GOOGLE_APPLICATION_CREDENTIALS"], scope [](#__codelineno-3-15)) [](#__codelineno-3-16)gc = gspread.authorize(credentials) [](#__codelineno-3-17)[](#__codelineno-3-18)# Cell 2 - Load the sheet [](#__codelineno-3-19)wks = gc.open("marimo").sheet1 [](#__codelineno-3-20)mo.ui.table(pd.DataFrame(wks.get_all_records()))` Example[¶](#example "Permanent link") ------------------------------------- Check out our full example using Google Sheets [here](https://github.com/marimo-team/marimo/blob/main/examples/cloud/gcp/google_sheets.py) Or run it yourself: `[](#__codelineno-4-1)marimo run https://raw.githubusercontent.com/marimo-team/marimo/main/examples/cloud/gcp/google_sheets.py` FAQ - marimo https://docs.marimo.io/faq.html#faq-jupyter Choosing marimo[¶](#choosing-marimo "Permanent link") ----------------------------------------------------- ### How is marimo different from Jupyter?[¶](#how-is-marimo-different-from-jupyter "Permanent link") marimo is a reinvention of the Python notebook as a reproducible, interactive, and shareable Python program that can be executed as scripts or deployed as interactive web apps. **Consistent state.** In marimo, your notebook code, outputs, and program state are guaranteed to be consistent. Run a cell and marimo reacts by automatically running the cells that reference its variables. Delete a cell and marimo scrubs its variables from program memory, eliminating hidden state. **Built-in interactivity.** marimo also comes with [UI elements](https://docs.marimo.io/guides/interactivity/) like sliders, a dataframe transformer, and interactive plots that are automatically synchronized with Python. Interact with an element and the cells that use it are automatically re-run with its latest value. **Pure Python programs.** Unlike Jupyter notebooks, marimo notebooks are stored as pure Python files that can be executed as scripts, deployed as interactive web apps, and versioned easily with Git. ### What problems does marimo solve?[¶](#what-problems-does-marimo-solve "Permanent link") marimo solves problems in reproducibility, maintainability, interactivity, reusability, and shareability of notebooks. **Reproducibility.** In Jupyter notebooks, the code you see doesn't necessarily match the outputs on the page or the program state. If you delete a cell, its variables stay in memory, which other cells may still reference; users can execute cells in arbitrary order. This leads to widespread reproducibility issues. [One study](https://blog.jetbrains.com/datalore/2020/12/17/we-downloaded-10-000-000-jupyter-notebooks-from-github-this-is-what-we-learned/#consistency-of-notebooks) analyzed 10 million Jupyter notebooks and found that 36% of them weren't reproducible. In contrast, marimo guarantees that your code, outputs, and program state are consistent, eliminating hidden state and making your notebook reproducible. marimo achieves this by intelligently analyzing your code and understanding the relationships between cells, and automatically re-running cells as needed. In addition, marimo notebooks can serialize package requirements inline; marimo runs these "sandboxed" notebooks in temporary virtual environments, making them [reproducible down to the packages](https://docs.marimo.io/guides/editor_features/package_management/). **Maintainability.** marimo notebooks are stored as pure Python programs (`.py` files). This lets you version them with Git; in contrast, Jupyter notebooks are stored as JSON and require extra steps to version. **Interactivity.** marimo notebooks come with [UI elements](https://docs.marimo.io/guides/interactivity/) that are automatically synchronized with Python (like sliders, dropdowns); _eg_, scrub a slider and all cells that reference it are automatically re-run with the new value. This is difficult to get working in Jupyter notebooks. **Reusability.** marimo notebooks can be executed as Python scripts from the command-line (since they're stored as `.py` files). In contrast, this requires extra steps to do for Jupyter, such as copying and pasting the code out or using external frameworks. In the future, we'll also let you import symbols (functions, classes) defined in a marimo notebook into other Python programs/notebooks, something you can't easily do with Jupyter. **Shareability.** Every marimo notebook can double as an interactive web app, complete with UI elements, which you can serve using the `marimo run` command. This isn't possible in Jupyter without substantial extra effort. _To learn more about problems with traditional notebooks, see these references [\[1\]](https://austinhenley.com/pubs/Chattopadhyay2020CHI_NotebookPainpoints.pdf) [\[2\]](https://www.youtube.com/watch?v=7jiPeIFXb6U&t=1s)._ ### How is `marimo.ui` different from Jupyter widgets?[¶](#how-is-marimoui-different-from-jupyter-widgets "Permanent link") Unlike Jupyter widgets, marimo's interactive elements are automatically synchronized with the Python kernel: no callbacks, no observers, no manually re-running cells. Using marimo[¶](#using-marimo "Permanent link") ----------------------------------------------- ### Is marimo a notebook or a library?[¶](#is-marimo-a-notebook-or-a-library "Permanent link") marimo is both a notebook and a library. * Create _marimo notebooks_ with the editor that opens in your browser when you run `marimo edit`. * Use the _marimo library_ (`import marimo as mo`) in marimo notebooks. Write markdown with `mo.md(...)`, create stateful interactive elements with `mo.ui` (`mo.ui.slider(...)`), and more. See the docs for an [API reference](https://docs.marimo.io/api/). ### What's the difference between a marimo notebook and a marimo app?[¶](#whats-the-difference-between-a-marimo-notebook-and-a-marimo-app "Permanent link") marimo programs are notebooks, apps, or both, depending on how you use them. There are two ways to interact with a marimo program: 1. open it as a computational _notebook_ with `marimo edit` 2. run it as an interactive _app_ with `marimo run` All marimo programs start as notebooks, since they are created with `marimo edit`. Because marimo notebooks are reactive and have built-in interactive elements, many can easily be made into useful and beautiful apps by simply hiding the notebook code: this is what `marimo run` does. Not every notebook needs to be run as an app — marimo notebooks are useful in and of themselves for rapidly exploring data and doing reproducible science. And not every app is improved by interacting with the notebook. In some settings, such as collaborative research, education, and technical presentations, going back and forth between the notebook view and app view (which you can do from `marimo edit`) can be useful! ### How does marimo know what cells to run?[¶](#how-does-marimo-know-what-cells-to-run "Permanent link") marimo reads each cell once to determine what global names it defines and what global names it reads. When a cell is run, marimo runs all other cells that read any of the global names it defines. A global name can refer to a variable, class, function, or import. In other words, marimo uses _static analysis_ to make a dataflow graph out of your cells. Each cell is a node in the graph across which global variables "flow". Whenever a cell is run, either because you changed its code or interacted with a UI element it reads, all its descendants run in turn. ### Does marimo slow my code down?[¶](#does-marimo-slow-my-code-down "Permanent link") No, marimo doesn't slow your code down. marimo determines the dependencies among cells by reading your code, not running or tracing it, so there's zero runtime overhead. ### How do I prevent automatic execution from running expensive cells?[¶](#how-do-i-prevent-automatic-execution-from-running-expensive-cells "Permanent link") Reactive (automatic) execution ensures your code and outputs are always in sync, improving reproducibility by eliminating hidden state and out-of-order execution; marimo also takes care to run only the minimal set of cells needed to keep your notebook up to date. But when some cells take a long time to run, it's understandable to be concerned that automatic execution will kick off expensive cells before you're ready to run them. _Here are some tips to avoid accidental execution of expensive cells:_ * [Disable expensive cells](https://docs.marimo.io/guides/reactivity/#disabling-cells). When a cell is disabled, it and its descendants are blocked from running. * Wrap UI elements in a [form](https://docs.marimo.io/api/inputs/form/#marimo.ui.form). * Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to conditionally stop execution of a cell and its descendants. * Decorate functions with marimo's [`mo.cache`](https://docs.marimo.io/api/caching/#marimo.cache) to cache expensive intermediate computations. * Use [`mo.persistent_cache`](https://docs.marimo.io/api/caching/#marimo.persistent_cache) to cache variables to disk; on re-run, marimo will read values from disk instead of recalculating them as long as the cell is not stale. * Disable automatic execution in the [runtime configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/). ### How do I disable automatic execution?[¶](#how-do-i-disable-automatic-execution "Permanent link") You can disable automatic execution through the notebook runtime settings; see the [guide on runtime configuration](https://docs.marimo.io/guides/configuration/runtime_configuration/). When automatic execution is disabled, marimo still gives you guarantees on your notebook state and automatically marks cells as stale when appropriate. ### How do I use sliders and other interactive elements?[¶](#how-do-i-use-sliders-and-other-interactive-elements "Permanent link") Interactive UI elements like sliders are available in `marimo.ui`. * Assign the UI element to a global variable (`slider = mo.ui.slider(0, 100)`) * Include it in the last expression of a cell to display it (`slider` or `mo.md(f"Choose a value: {slider}")`) * Read its current value in another cell via its `value` attribute (`slider.value`) _When a UI element bound to a global variable is interacted with, all cells referencing the global variable are run automatically_. If you have many UI elements or don't know the elements you'll create until runtime, use `marimo.ui.array` and `marimo.ui.dictionary` to create UI elements that wrap other UI elements (`sliders = mo.ui.array([slider(1, 100) for _ in range(n_sliders)])`). All this and more is explained in the UI tutorial. Run it with at the command line. ### How do I add a submit button to UI elements?[¶](#how-do-i-add-a-submit-button-to-ui-elements "Permanent link") Use the `form` method to add a submit button to a UI element. For example, `[](#__codelineno-1-1)form = marimo.ui.text_area().form()` When wrapped in a form, the text area's value will only be sent to Python when you click the submit button. Access the last submitted value of the text area with `form.value`. ### How do I write markdown?[¶](#how-do-i-write-markdown "Permanent link") Import `marimo` (as `mo`) in a notebook, and use the `mo.md` function. Learn more in the [outputs guide](https://docs.marimo.io/guides/outputs/#markdown) or by running `marimo tutorial markdown`. ### How do I display plots?[¶](#how-do-i-display-plots "Permanent link") Include plots in the last expression of a cell to display them, just like all other outputs. If you're using matplotlib, you can display the `Figure` object (get the current figure with `plt.gcf()`). For examples, run the plots tutorial: Also see the [plotting API reference](https://docs.marimo.io/api/plotting/). ### How do I prevent matplotlib plots from being cut off?[¶](#how-do-i-prevent-matplotlib-plots-from-being-cut-off "Permanent link") If your legend or axes labels are cut off, try calling `plt.tight_layout()` before outputting your plot: `[](#__codelineno-3-1)import matplotlib.pyplot as plt [](#__codelineno-3-2)[](#__codelineno-3-3)plt.plot([-8, 8]) [](#__codelineno-3-4)plt.ylabel("my variable") [](#__codelineno-3-5)plt.tight_layout() [](#__codelineno-3-6)plt.gca()` ### How do I display interactive matplotlib plots?[¶](#how-do-i-display-interactive-matplotlib-plots "Permanent link") Use [`marimo.mpl.interactive`](https://docs.marimo.io/api/plotting/#marimo.mpl.interactive). `[](#__codelineno-4-1)fig, ax = plt.subplots() [](#__codelineno-4-2)ax.plot([1, 2]) [](#__codelineno-4-3)mo.mpl.interactive(ax)` ### How do I display objects in rows and columns?[¶](#how-do-i-display-objects-in-rows-and-columns "Permanent link") Use `marimo.hstack` and `marimo.vstack`. See the layout tutorial for details: ### How do I show cell code in the app view?(#faq-show-code)[¶](#how-do-i-show-cell-code-in-the-app-viewfaq-show-code "Permanent link") Use [`mo.show_code`](https://docs.marimo.io/api/outputs/#marimo.show_code). ### How do I create an output with a dynamic number of UI elements?[¶](#how-do-i-create-an-output-with-a-dynamic-number-of-ui-elements "Permanent link") Use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary), or [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch) to create a UI element that wraps a dynamic number of other UI elements. If you need custom formatting, use [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch), otherwise use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) or [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary). For usage examples, see the [recipes for grouping UI elements together](https://docs.marimo.io/recipes/#grouping-ui-elements-together). ### How do I restart a notebook?[¶](#how-do-i-restart-a-notebook "Permanent link") To clear all program memory and restart the notebook from scratch, open the notebook menu in the top right and click "Restart kernel". ### How do I reload modules?[¶](#how-do-i-reload-modules "Permanent link") Enable automatic reloading of modules via the runtime settings in your marimo installation's user configuration. (Click the "gear" icon in the top right of a marimo notebook). When enabled, marimo will automatically hot-reload modified modules before executing a cell. ### Why aren't my `on_change`/`on_click` handlers being called?[¶](#why-arent-my-on_changeon_click-handlers-being-called "Permanent link") A UI Element's `on_change` (or for buttons, `on_click`) handlers are only called if the element is bound to a global variable. For example, this won't work `[](#__codelineno-6-1)mo.vstack([mo.ui.button(on_change=lambda _: print("I was called")) for _ in range(10)])` In such cases (when you want to output a dynamic number of UI elements), you need to use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array), [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary), or [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch). See the [recipes for grouping UI elements together](https://docs.marimo.io/recipes/#grouping-ui-elements-together) for example code. ### Why are my `on_change` handlers in an array all referencing the last element?[¶](#why-are-my-on_change-handlers-in-an-array-all-referencing-the-last-element "Permanent link") **Don't do this**: In the below snippet, every `on_change` will print `9`!. `[](#__codelineno-7-1)array = mo.ui.array( [](#__codelineno-7-2) [mo.ui.button(on_change=lambda value: print(i)) for i in range(10) [](#__codelineno-7-3)])` **Instead, do this**: Explicitly bind `i` to the current loop value: `[](#__codelineno-8-1)array = mo.ui.array( [](#__codelineno-8-2) [mo.ui.button(on_change=lambda value, i=i: print(i)) for i in range(10)] [](#__codelineno-8-3)) [](#__codelineno-8-4)array` This is necessary because [in Python, closures are late-binding](https://docs.python-guide.org/writing/gotchas/#late-binding-closures). ### Why aren't my SQL brackets working?[¶](#why-arent-my-sql-brackets-working "Permanent link") Our "SQL" cells are really just Python under the hood to keep notebooks as pure Python scripts. By default, we use `f-strings` for SQL strings, which allows for parameterized SQL like `SELECT * from table where value < {min}`. To escape real `{` / `}` that you don't want parameterized, use double `\{\{...\}\}`: `[](#__codelineno-9-1)SELECT unnest([\{\{'a': 42, 'b': 84\}\}, \{\{'a': 100, 'b': NULL\}\}]);` ### How does marimo treat type annotations?[¶](#how-does-marimo-treat-type-annotations "Permanent link") Type annotations are registered as references of a cell, unless they are explicitly written as strings. This helps ensure correctness of code that depends on type annotations at runtime (_e.g._, Pydantic), while still providing a way to omit annotations from affecting dataflow graph. For example, in `A` is treated as a reference, used in determining the dataflow graph, but in `A` isn't made a reference. For Python 3.12+, marimo additionally implements annotation scoping. ### How do I use dotenv?[¶](#how-do-i-use-dotenv "Permanent link") The package `dotenv`'s `loadenv()` function does not work out-of-the box in marimo. Instead, use `dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))`. ### What packages can I use?[¶](#what-packages-can-i-use "Permanent link") You can use any Python package. marimo cells run arbitrary Python code. ### How do I use marimo on a remote server?[¶](#how-do-i-use-marimo-on-a-remote-server "Permanent link") Use SSH port-forwarding to run marimo on a remote server and connect to it from a browser on your local machine. Make sure to pass the `--headless` flag when starting marimo on remote: You may also want to set a custom host and port: `[](#__codelineno-13-1)marimo edit --headless --host 0.0.0.0 --port 8080` ### How do I make marimo accessible on all network interfaces?[¶](#how-do-i-make-marimo-accessible-on-all-network-interfaces "Permanent link") Use `--host 0.0.0.0` with `marimo edit`, `marimo run`, or `marimo tutorial`: `[](#__codelineno-14-1)marimo edit --host 0.0.0.0` ### How do I use marimo behind JupyterHub?[¶](#how-do-i-use-marimo-behind-jupyterhub "Permanent link") JupyterHub can be configured to launch marimo using the [`jupyter-marimo-proxy` package](https://github.com/jyio/jupyter-marimo-proxy). ### How do I use marimo with JupyterBook?[¶](#how-do-i-use-marimo-with-jupyterbook "Permanent link") [JupyterBook](https://jupyterbook.org/en/stable/intro.html) makes it easy to create static websites with markdown and Jupyter notebooks. To include a marimo notebook in a JupyterBook, you can either export your notebook to an `ipynb` file, or export to `HTML`: 1. export to ipynb: `marimo export ipynb my_notebook.py -o my_notebook.ipynb --include-outputs` 2. export to HTML: `marimo export html my_notebook.py -o my_notebook.html` ### How do I deploy apps?[¶](#how-do-i-deploy-apps "Permanent link") Use the marimo CLI's `run` command to serve a notebook as an app: If you are running marimo inside a Docker container, you may want to run under a different host and port: `[](#__codelineno-16-1)marimo run notebook.py --host 0.0.0.0 --port 8080` ### Is marimo free?[¶](#is-marimo-free "Permanent link") Yes! Key Concepts - marimo https://docs.marimo.io/getting_started/key_concepts This page covers marimo's key concepts: * marimo lets you rapidly experiment with data using Python, SQL, and interactive elements in a reproducible **notebook environment**. * Unlike Jupyter notebooks, marimo notebooks are reusable software artifacts. marimo notebooks can be shared as as **interactive web apps** and executed as **Python scripts**. Editing notebooks[¶](#editing-notebooks "Permanent link") --------------------------------------------------------- marimo notebooks are **reactive**: they automatically react to your code changes and UI interactions and keep your notebook up-to-date, not unlike a spreadsheet. This makes your notebooks reproducible, [eliminating hidden state](https://docs.marimo.io/faq/#faq-problems); it's also what enables marimo notebooks to double as apps and Python scripts. Working with expensive notebooks If you don't want cells to run automatically, the [runtime can be configured](https://docs.marimo.io/guides/configuration/runtime_configuration/) to be lazy, only running cells when you ask for them to be run and marking affected cells as stale. **See our guide on working with [expensive notebooks](https://docs.marimo.io/guides/expensive_notebooks/) for more tips.** **Create your first notebook.** After [installing marimo](https://docs.marimo.io/installation/), create your first notebook with `[](#__codelineno-0-1)marimo edit my_notebook.py` at the command-line. **The marimo library**. We recommend starting each marimo notebook with a cell containing a single line of code, The marimo library lets you use interactive UI elements, layout elements, dynamic markdown, and more in your marimo notebooks. ### How marimo executes cells[¶](#how-marimo-executes-cells "Permanent link") A marimo notebook is made of small blocks of Python code called **cells**. _When you run a cell, marimo automatically runs all cells that read any global variables defined by that cell._ This is reactive execution. **Execution order.** The order of cells on the page has no bearing on the order cells are executed in: execution order is determined by the variables cells define and the variables they read. You have full freedom over how to organize your code and tell your stories: move helper functions and other "appendices" to the bottom of your notebook, or put cells with important outputs at the top. **No hidden state.** marimo notebooks have no hidden state because the program state is automatically synchronized with your code changes and UI interactions. And if you delete a cell, marimo automatically deletes that cell's variables, preventing painful bugs that arise in traditional notebooks. **No magical syntax.** There's no magical syntax or API required to opt-in to reactivity: cells are Python and _only Python_. Behind-the-scenes, marimo statically analyzes each cell's code just once, creating a directed acyclic graph based on the global names each cell defines and reads. This is how data flows in a marimo notebook. Minimize variable mutation. marimo's understanding of your code is based on variable definitions and references; marimo does not track mutations to objects at runtime. For this reason, if you need to mutate a variable (such as adding a new column to a dataframe), you should perform the mutation in the same cell as the one that defines it. Learn more in our [reactivity guide](https://docs.marimo.io/guides/reactivity/#reactivity-mutations). For more on reactive execution, open the dataflow tutorial or read the [reactivity guide](https://docs.marimo.io/guides/reactivity/). ### Visualizing outputs[¶](#visualizing-outputs "Permanent link") marimo visualizes the last expression of each cell as its **output**. Outputs can be any Python value, including markdown and interactive elements created with the marimo library, (_e.g._, [`mo.md`](https://docs.marimo.io/api/markdown/#marimo.md), [`mo.ui.slider`](https://docs.marimo.io/api/inputs/slider/#marimo.ui.slider)). You can even interpolate Python values into markdown (using `mo.md(f"...")`) and other marimo elements to build rich composite outputs: > Thanks to reactive execution, running a cell refreshes all the relevant outputs in your notebook. The marimo library also comes with elements for laying out outputs, including [`mo.hstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.hstack), [`mo.vstack`](https://docs.marimo.io/api/layouts/stacks/#marimo.vstack), [`mo.accordion`](https://docs.marimo.io/api/layouts/accordion/#marimo.accordion), [`mo.ui.tabs`](https://docs.marimo.io/api/inputs/tabs/#marimo.ui.tabs), [`mo.sidebar`](https://docs.marimo.io/api/layouts/sidebar/#marimo.sidebar), [`mo.nav_menu`](https://docs.marimo.io/api/inputs/nav_menu/#marimo.nav_menu), [`mo.ui.table`](https://docs.marimo.io/api/inputs/table/#marimo.ui.table), and [many more](https://docs.marimo.io/api/layouts/). For more on outputs, try these tutorials: `[](#__codelineno-3-1)marimo tutorial markdown [](#__codelineno-3-2)marimo tutorial plots [](#__codelineno-3-3)marimo tutorial layout` or read the [visualizing outputs guide](https://docs.marimo.io/guides/outputs/). ### Creating interactive elements[¶](#creating-interactive-elements "Permanent link") The marimo library comes with many interactive stateful elements in [`marimo.ui`](https://docs.marimo.io/api/inputs/), including simple ones like sliders, dropdowns, text fields, and file upload areas, as well as composite ones like forms, arrays, and dictionaries that can wrap other UI elements. **Using UI elements.** To use a UI element, create it with `mo.ui` and **assign it to a global variable.** When you interact with a UI element in your browser (_e.g._, sliding a slider), _marimo sends the new value back to Python and reactively runs all cells that use the element_, which you can access via its `value` attribute. > **This combination of interactivity and reactivity is very powerful**: use it to make your data tangible during exploration and to build all kinds of tools and apps. _marimo can only synchronize UI elements that are assigned to global variables._ Use composite elements like [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) and [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) if the set of UI elements is not known until runtime. Using buttons to execute cells Use [`mo.ui.run_button`](https://docs.marimo.io/api/inputs/run_button/#marimo.ui.run_button) to create a button that triggers computation when clicked; see our recipes for [an example](https://docs.marimo.io/recipes/#create-a-button-that-triggers-computation-when-clicked). For more on interactive elements, run the UI tutorial or read the [interactivity guide](https://docs.marimo.io/guides/interactivity/). ### Querying dataframes and databases with SQL[¶](#querying-dataframes-and-databases-with-sql "Permanent link") marimo has built-in support for SQL: you can query Python dataframes, databases, CSVs, Google Sheets, or anything else. After executing your query, marimo returns the result to you as a dataframe, making it seamless to go back and forth between SQL and Python. Query a dataframe using SQL! To create a SQL cell, click on the SQL button that appears at the bottom of the cell array, or right click the create cell button next to a cell. Today, SQL in marimo is executed using [duckdb](https://duckdb.org/docs/). To learn more, run the SQL tutorial or read the [SQL guide](https://docs.marimo.io/guides/working_with_data/sql/). Running notebooks as applications[¶](#running-notebooks-as-applications "Permanent link") ----------------------------------------------------------------------------------------- You can use marimo as a notebook, similar to how you might use Jupyter. But you can also do more: because marimo notebooks are reactive and can include interactive elements, hiding notebook code gives you a simple web app! You can run your notebook as a read-only web app from the command-line: `[](#__codelineno-6-1)marimo run my_notebook.py` The default renderer just hides the notebook code and concatenates outputs vertically. But marimo also supports [other layouts](https://docs.marimo.io/guides/apps/), such as slides and grid. Running notebooks as scripts[¶](#running-notebooks-as-scripts "Permanent link") ------------------------------------------------------------------------------- Because marimo notebooks are stored as pure Python files, each notebook can be executed as a script from the command-line: You can also [pass command-line arguments](https://docs.marimo.io/guides/scripts/) to scripts. Programmatic - marimo https://docs.marimo.io/guides/deploying/programmatically.html Running the marimo backend programmatically[¶](#running-the-marimo-backend-programmatically "Permanent link") ------------------------------------------------------------------------------------------------------------- marimo can be run programmatically using the `marimo` module. This is useful when you want to run marimo as part of a larger application or when you need to customize the behavior of marimo (e.g. middleware, custom error handling, authentication, routing, etc). FastAPI Example[¶](#fastapi-example "Permanent link") ----------------------------------------------------- Here's an example of how you can run a marimo application programmatically using FastAPI: `[](#__codelineno-0-1)from typing import Annotated, Callable, Coroutine [](#__codelineno-0-2)from fastapi.responses import HTMLResponse, RedirectResponse [](#__codelineno-0-3)import marimo [](#__codelineno-0-4)from fastapi import FastAPI, Form, Request, Response [](#__codelineno-0-5) [](#__codelineno-0-6)[](#__codelineno-0-7)# Create a marimo asgi app [](#__codelineno-0-8)server = ( [](#__codelineno-0-9) marimo.create_asgi_app() [](#__codelineno-0-10) .with_app(path="", root="./pages/index.py") [](#__codelineno-0-11) .with_app(path="/dashboard", root="./pages/dashboard.py") [](#__codelineno-0-12) .with_app(path="/sales", root="./pages/sales.py") [](#__codelineno-0-13)) [](#__codelineno-0-14)[](#__codelineno-0-15)# Create a FastAPI app [](#__codelineno-0-16)app = FastAPI() [](#__codelineno-0-17)[](#__codelineno-0-18)app.add_middleware(auth_middleware) [](#__codelineno-0-19)app.add_route("/login", my_login_route, methods=["POST"]) [](#__codelineno-0-20)[](#__codelineno-0-21)app.mount("/", server.build()) [](#__codelineno-0-22)[](#__codelineno-0-23)# Run the server [](#__codelineno-0-24)if __name__ == "__main__": [](#__codelineno-0-25) import uvicorn [](#__codelineno-0-26) [](#__codelineno-0-27) uvicorn.run(app, host="localhost", port=8000)` For a more complete example, see the [FastAPI example](https://github.com/marimo-team/marimo/tree/main/examples/frameworks/fastapi). Dynamic directory[¶](#dynamic-directory "Permanent link") --------------------------------------------------------- If you'd like to create a server to dynamically load marimo notebooks from a directory, you can use the `with_dynamic_directory` method. This is useful if the contents of the directory change often, such as a directory of notebooks for a dashboard, without restarting the server. `[](#__codelineno-1-1)server = ( [](#__codelineno-1-2) marimo.create_asgi_app() [](#__codelineno-1-3) .with_dynamic_directory(path="/dashboard", directory="./notebooks") [](#__codelineno-1-4))` If the notebooks in the directory are expected to be static, it is better to use the `with_app` method and loop through the directory contents. `[](#__codelineno-2-1)from pathlib import Path [](#__codelineno-2-2)server = marimo.create_asgi_app() [](#__codelineno-2-3)app_names: list[str] = [] [](#__codelineno-2-4)[](#__codelineno-2-5)notebooks_dir = Path(__file__).parent / "notebooks" [](#__codelineno-2-6)[](#__codelineno-2-7)for filename in sorted(notebooks_dir.iterdir()): [](#__codelineno-2-8) if filename.suffix == ".py": [](#__codelineno-2-9) app_name = filename.stem [](#__codelineno-2-10) server = server.with_app(path=f"/{app_name}", root=filename) [](#__codelineno-2-11) app_names.append(app_name)` Accessing Request Data[¶](#accessing-request-data "Permanent link") ------------------------------------------------------------------- Inside your marimo notebooks, you can access the current request data using `mo.app_meta().request`. This is particularly useful when implementing authentication or accessing user data. `[](#__codelineno-3-1)import marimo as mo [](#__codelineno-3-2)[](#__codelineno-3-3)# Access request data in your notebook [](#__codelineno-3-4)request = mo.app_meta().request [](#__codelineno-3-5)if request and request.user and request.user["is_authenticated"]: [](#__codelineno-3-6) content = f"Welcome {request.user['username']}!" [](#__codelineno-3-7)else: [](#__codelineno-3-8) content = "Please log in" [](#__codelineno-3-9)[](#__codelineno-3-10)mo.md(content)` ### Authentication Middleware Example[¶](#authentication-middleware-example "Permanent link") Here's an example of how to implement authentication middleware that populates `request.user`: `[](#__codelineno-4-1)from starlette.middleware.base import BaseHTTPMiddleware [](#__codelineno-4-2)from starlette.requests import Request [](#__codelineno-4-3)[](#__codelineno-4-4)class AuthMiddleware(BaseHTTPMiddleware): [](#__codelineno-4-5) async def dispatch(self, request: Request, call_next): [](#__codelineno-4-6) # Add user data to the request scope [](#__codelineno-4-7) # This will be accessible via mo.app_meta().request.user [](#__codelineno-4-8) request.scope["user"] = { [](#__codelineno-4-9) "is_authenticated": True, [](#__codelineno-4-10) "username": "example_user", [](#__codelineno-4-11) # Add any other user data [](#__codelineno-4-12) } [](#__codelineno-4-13) response = await call_next(request) [](#__codelineno-4-14) return response [](#__codelineno-4-15)[](#__codelineno-4-16)# Add the middleware to your FastAPI app [](#__codelineno-4-17)app.add_middleware(AuthMiddleware)` The `request` object provides access to: * `request.headers`: Request headers * `request.cookies`: Request cookies * `request.query_params`: Query parameters * `request.path_params`: Path parameters * `request.user`: User data added by authentication middleware * `request.url`: URL information including path, query parameters Running cells - marimo https://docs.marimo.io/guides/reactivity marimo _reacts_ to your code changes: run a cell, and all other cells that refer to the variables it defines are automatically run with the latest data. This keeps your code and outputs consistent, and eliminates bugs before they happen. Why run cells reactively? marimo's "reactive" execution model makes your notebooks more reproducible by eliminating hidden state and providing a deterministic execution order. It also powers marimo's support for [interactive elements](https://docs.marimo.io/interactivity/), for running as apps, and executing as scripts. How marimo runs cells is one of the biggest differences between marimo and traditional notebooks like Jupyter. Learn more at our [FAQ](https://docs.marimo.io/faq/#faq-jupyter). Working with expensive notebooks marimo provides tools for working with expensive notebooks, in which cells might take a long time to run or have side-effects. * The [runtime can be configured](https://docs.marimo.io/configuration/runtime_configuration/) to be **lazy** instead of automatic, marking cells as stale instead of running them. * Use [`mo.stop`](https://docs.marimo.io/api/control_flow/#marimo.stop) to conditionally stop execution at runtime. See [the expensive notebooks guide](https://docs.marimo.io/expensive_notebooks/) for more tips. How marimo runs cells[¶](#how-marimo-runs-cells "Permanent link") ----------------------------------------------------------------- marimo statically analyzes each cell (i.e., without running it) to determine its * references, the global variables it reads but doesn't define; * definitions, the global variables it defines. It then forms a directed acyclic graph (DAG) on cells, with an edge from one cell to another if the latter references any of the definitions of the former. When a cell is run, its descendants are marked for execution. Runtime Rule When a cell is run, marimo automatically runs all other cells that **reference** any of the global variables it **defines**. marimo [does not track mutations](#variable-mutations-are-not-tracked) to variables, nor assignments to attributes. That means that if you assign an attribute like `foo.bar = 10`, other cells referencing `foo.bar` will _not_ be run. ### Execution order[¶](#execution-order "Permanent link") The order cells are executed in is determined by the relationships between cells and their variables, not by the order of cells on the page (similar to a spreadsheet). This lets you organize your code in whatever way makes the most sense to you. For example, you can put helper functions at the bottom of your notebook. ### Deleting a cell deletes its variables[¶](#deleting-a-cell-deletes-its-variables "Permanent link") In marimo, _deleting a cell deletes its global variables from program memory_. Cells that previously referenced these variables are automatically re-run and invalidated (or marked as stale, depending on your [runtime configuration](https://docs.marimo.io/configuration/runtime_configuration/)). In this way, marimo eliminates a common cause of bugs in traditional notebooks like Jupyter. ### Variable mutations are not tracked[¶](#variable-mutations-are-not-tracked "Permanent link") marimo does not track mutations to objects, _e.g._, mutations like `my_list.append(42)` or `my_object.value = 42` don't trigger reactive re-runs of other cells. **Avoid defining a variable in one cell and mutating it in another**. Why not track mutations? Tracking mutations reliably is impossible in Python. Reacting to mutations could result in surprising re-runs of notebook cells. If you need to mutate a variable (such as adding a new column to a dataframe), you should perform the mutation in the same cell as the one that defines it, or try creating a new variable instead. Create new variables, don't mutate existing ones Mutate variables in the cells that define them Do this ...... not this `[](#__codelineno-4-1)df = pd.DataFrame({"my_column": [1, 2]}) [](#__codelineno-4-2)df["another_column"] = [3, 4]` `[](#__codelineno-5-1)df = pd.DataFrame({"my_column": [1, 2]})` `[](#__codelineno-6-1)df["another_column"] = [3, 4]` Global variable names must be unique[¶](#global-variable-names-must-be-unique "Permanent link") ----------------------------------------------------------------------------------------------- **marimo requires that every global variable be defined by only one cell.** This lets marimo keep code and outputs consistent. Global variables A variable can refer to any Python object. Functions, classes, and imported names are all variables. This rule encourages you to keep the number of global variables in your program small, which is generally considered good practice. ### Creating temporary variables[¶](#creating-temporary-variables "Permanent link") marimo provides two ways to define temporary variables, which can help keep the number of global variables in your notebook small. #### Creating local variables[¶](#creating-local-variables "Permanent link") Variables prefixed with an underscore (_e.g._, `_x`) are "local" to a cell: they can't be read by other cells. Multiple cells can reuse the same local variables names. #### Encapsulating code in functions[¶](#encapsulating-code-in-functions "Permanent link") If you want most or all the variables in a cell to be temporary, prefixing each variable with an underscore to make it local may feel inconvenient. In these situations we recommend encapsulating the temporary variables in a function. For example, if you find yourself copy-pasting the same plotting code across multiple cells and only tweaking a few parameters, try the following pattern: `[](#__codelineno-7-1)def _(): [](#__codelineno-7-2) import matplotlib.pyplot as plt [](#__codelineno-7-3) fig, ax = plt.subplots() [](#__codelineno-7-4) ax.plot([1, 2]) [](#__codelineno-7-5) return ax [](#__codelineno-7-6)[](#__codelineno-7-7)_()` Here, the variables `plt`, `fig`, and `ax` aren't added to the globals. Configuring how marimo runs cells[¶](#configuring-how-marimo-runs-cells "Permanent link") ----------------------------------------------------------------------------------------- Through the notebook settings menu, you can configure how and when marimo runs cells. In particular, you can disable autorun on startup, disable autorun on cell execution, and enable a module autoreloader. Read our [runtime configuration guide](https://docs.marimo.io/configuration/runtime_configuration/) to learn more. Disabling cells[¶](#disabling-cells "Permanent link") ----------------------------------------------------- Sometimes, you may want to edit one part of a notebook without triggering automatic execution of its dependent cells. For example, the dependent cells may take a long time to execute, and you only want to iterate on the first part of a multi-cell computation. For cases like this, marimo lets you **disable** cells: when a cell is disabled, it and its dependents are blocked from running. Disabling a cell blocks it from running. When you re-enable a cell, if any of the cell's ancestors ran while it was disabled, marimo will automatically run it. Enable a cell through the context menu. Stale cells run automatically. Interactive elements - marimo https://docs.marimo.io/guides/interactivity One of marimo's most powerful features is its first-class support for interactive user interface (UI) elements, or "widgets", created using [`marimo.ui`](https://docs.marimo.io/api/inputs/). **Interacting with a UI element bound to a global variable automatically runs all cells that reference it.** How interactions run cells[¶](#how-interactions-run-cells "Permanent link") --------------------------------------------------------------------------- Every UI element you make using [`marimo.ui`](https://docs.marimo.io/api/inputs/) has a value, accessible via its `value` attribute. When you interact with a UI element bound to a global variable, its value is sent back to Python. A single rule determines what happens next: Interaction rule When a UI element assigned to a global variable is interacted with, marimo automatically runs all cells that reference the variable (but don't define it). In the clip at the top of this page, interacting with the slider in the second cell re-runs the third cell (which outputs markdown) because it references the slider variable `x`. It doesn't re-run the second cell, because that cell defines `x`. **For interactions on a UI element to have any effect, the element must be assigned to a global variable.** Displaying UI elements[¶](#displaying-ui-elements "Permanent link") ------------------------------------------------------------------- Display UI elements in the output area above a cell by including them in the last expression, just like any other object. You can also embed elements in [markdown](https://docs.marimo.io/api/markdown/#marimo.md) using Python f-strings, like so: `[](#__codelineno-0-1)slider = mo.ui.slider(1, 10) [](#__codelineno-0-2)mo.md(f"Choose a value: {slider})")` Composite elements[¶](#composite-elements "Permanent link") ----------------------------------------------------------- Composite elements are advanced elements let you build UI elements out of other UI elements. The following composite elements are available: * [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) * [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) * [`mo.ui.batch`](https://docs.marimo.io/api/inputs/batch/#marimo.ui.batch) * [`mo.ui.form`](https://docs.marimo.io/api/inputs/form/#marimo.ui.form) **Arrays and dictionaries.** Use [`mo.ui.array`](https://docs.marimo.io/api/inputs/array/#marimo.ui.array) and [`mo.ui.dictionary`](https://docs.marimo.io/api/inputs/dictionary/#marimo.ui.dictionary) to logically group together related elements. These elements are especially useful when a set of UI elements is only known at runtime (so you can't assign each to a global variable individually, but can assign them to an array or dictionary). You can access the elements contained in an array or dictionary using Pythonic syntax, and embed these elements in other outputs. See their docstrings for code examples. **Batch and form.** Use these powerful elements to group together multiple UI elements into a single element with custom formatting, and gate the sending of an element's value on form submission. Use a form to gate value updates on submission Use an array to group together elements or create a collection of elements that is determined at runtime Building custom UI elements using our plugin API[¶](#building-custom-ui-elements-using-our-plugin-api "Permanent link") ----------------------------------------------------------------------------------------------------------------------- You can build your own reactive and interactive UI elements using [anywidget](https://github.com/manzt/anywidget). See [our docs on building custom UI elements](https://docs.marimo.io/integrating_with_marimo/custom_ui_plugins/) to learn more. Plotting - marimo https://docs.marimo.io/guides/working_with_data/plotting marimo supports most major plotting libraries, including Matplotlib, Seaborn, Plotly, Altair, and HoloViews. Just import your plotting library of choice and use it as you normally would. For Altair and Plotly plots, marimo does something special: use [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) or [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) to connect frontend selections to Python! Reactive plots! marimo supports reactive plots via [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) and [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly)! Select and filter with your mouse, and marimo _automatically makes the selected data available in Python as a Pandas dataframe_! Reactive plots! ⚡[¶](#reactive-plots "Permanent link") ------------------------------------------------------ Requirements Reactive plots currently require Altair or Plotly. Install with `pip install altair` or `pip install plotly`, depending on which library you are using. Selections in plotly are limited to scatter plots, treemaps charts, and sunbursts charts, while Altair supports a larger class of plots for selections. ### Altair[¶](#altair "Permanent link") Use [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) to easily create interactive, selectable plots: _selections you make on the frontend are automatically made available as Pandas dataframes in Python._ Wrap an Altair chart in [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) to make it **reactive**: select data on the frontend, access it via the chart's `value` attribute (`chart.value`). #### Disabling automatic selection[¶](#disabling-automatic-selection "Permanent link") marimo automatically adds a default selection based on the mark type, however, you may want to customize the selection behavior of your Altair chart. You can do this by setting `chart_selection` and `legend_selection` to `False`, and using `.add_params` directly on your Altair chart. `[](#__codelineno-1-1)# Create an interval selection [](#__codelineno-1-2)brush = alt.selection_interval(encodings=["x"]) [](#__codelineno-1-3)[](#__codelineno-1-4)_chart = ( [](#__codelineno-1-5) alt.Chart(traces, height=150) [](#__codelineno-1-6) .mark_line() [](#__codelineno-1-7) .encode(x="index:Q", y="value:Q", color="traces:N") [](#__codelineno-1-8) .add_params(brush) # add the selection to the chart [](#__codelineno-1-9)) [](#__codelineno-1-10)[](#__codelineno-1-11)chart = mo.ui.altair_chart( [](#__codelineno-1-12) _chart, [](#__codelineno-1-13) # disable automatic selection [](#__codelineno-1-14) chart_selection=False, [](#__codelineno-1-15) legend_selection=False [](#__codelineno-1-16)) [](#__codelineno-1-17)chart # You can now access chart.value to get the selected data` _Reactive plots are just one way that marimo **makes your data tangible**._ #### Example[¶](#example "Permanent link") `[](#__codelineno-2-1)import marimo as mo [](#__codelineno-2-2)import altair as alt [](#__codelineno-2-3)import vega_datasets [](#__codelineno-2-4)[](#__codelineno-2-5)# Load some data [](#__codelineno-2-6)cars = vega_datasets.data.cars() [](#__codelineno-2-7)[](#__codelineno-2-8)# Create an Altair chart [](#__codelineno-2-9)chart = alt.Chart(cars).mark_point().encode( [](#__codelineno-2-10) x='Horsepower', # Encoding along the x-axis [](#__codelineno-2-11) y='Miles_per_Gallon', # Encoding along the y-axis [](#__codelineno-2-12) color='Origin', # Category encoding by color [](#__codelineno-2-13)) [](#__codelineno-2-14)[](#__codelineno-2-15)# Make it reactive ⚡ [](#__codelineno-2-16)chart = mo.ui.altair_chart(chart)` `[](#__codelineno-3-1)# In a new cell, display the chart and its data filtered by the selection [](#__codelineno-3-2)mo.vstack([chart, chart.value.head()])` #### Learning Altair[¶](#learning-altair "Permanent link") If you're new to **Altair**, we highly recommend exploring the [Altair documentation](https://altair-viz.github.io/). Altair provides a declarative, concise, and simple way to create highly interactive and sophisticated plots. Altair is based on [Vega-Lite](https://vega.github.io/vega-lite/), an exceptional tool for creating interactive charts that serves as the backbone for marimo's reactive charting capabilities. ##### Concepts[¶](#concepts "Permanent link") Learn by doing? Skip this section! This section summarizes the main concepts used by Altair (and Vega-Lite). Feel free to skip this section and return later. Our choice to use the Vega-Lite specification was driven by its robust data model, which is well-suited for data analysis. Some key concepts are summarized below. (For a more detailed explanation, with examples, we recommend the [Basic Statistical Visualization](https://altair-viz.github.io/getting_started/starting.html) tutorial from Altair.) * **Data Source**: This is the information that will be visualized in the chart. It can be provided in various formats such as a dataframe, a list of dictionaries, or a URL pointing to the data source. * **Mark Type**: This refers to the visual representation used for each data point on the chart. The options include 'bar', 'dot', 'circle', 'area', and 'line'. Each mark type offers a different way to visualize and interpret the data. * **Encoding**: This is the process of mapping various aspects or dimensions of the data to visual characteristics of the marks. Encodings can be of different types: * **Positional Encodings**: These are encodings like 'x' and 'y' that determine the position of the marks in the chart. * **Categorical Encodings**: These are encodings like 'color' and 'shape' that categorize data points. They are typically represented in a legend for easy reference. * **Transformations**: These are operations that can be applied to the data before it is visualized, for example, filtering and aggregation. These transformations allow for more complex and nuanced visualizations. **Automatically interactive.** marimo adds interactivity automatically, based on the mark used and the encodings. For example, if you use a `mark_point` and an `x` encoding, marimo will automatically add a brush selection to the chart. If you add a `color` encoding, marimo will add a legend and a click selection. #### Automatic Selections[¶](#automatic-selections "Permanent link") By default [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) will make the chart and legend selectable. Depending on the mark type, the chart will either have a `point` or `interval` ("brush") selection. When using non-positional encodings (color, size, etc), [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) will also make the legend selectable. Selection configurable through `*_selection` params in [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart). See the [API docs](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart) for details. Note You may still add your own selection parameters via Altair or Vega-Lite. marimo will not override your selections. #### Altair transformations[¶](#altair-transformations "Permanent link") Altair supports a variety of transformations, such as filtering, aggregation, and sorting. These transformations can be used to create more complex and nuanced visualizations. For example, you can use a filter to show only the points that meet a certain condition, or use an aggregation to show the average value of a variable. In order for marimo's reactive plots to work with transformations, you must install `vegafusion`, as this feature uses `chart.transformed_data` (which requires version 1.4.0 or greater of the `vegafusion` packages). `[](#__codelineno-4-1)# These can be installed with pip using: [](#__codelineno-4-2)pip install "vegafusion[embed]>=1.4.0" [](#__codelineno-4-3)# Or with conda using: [](#__codelineno-4-4)conda install -c conda-forge "vegafusion-python-embed>=1.4.0" "vegafusion>=1.4.0"` ### Plotly[¶](#plotly "Permanent link") mo.ui.plotly only supports scatter plots, treemaps charts, and sunbursts charts marimo can render any Plotly plot, but [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) only supports reactive selections for scatter plots, treemaps charts, and sunbursts charts. If you require other kinds of selection, consider using [`mo.ui.altair_chart`](https://docs.marimo.io/api/plotting/#marimo.ui.altair_chart). Use [`mo.ui.plotly`](https://docs.marimo.io/api/plotting/#marimo.ui.plotly) to create selectable Plotly plots whose values are sent back to Python on selection. matplotlib[¶](#matplotlib "Permanent link") ------------------------------------------- To output a matplotlib plot in a cell's output area, include its `Axes` or `Figure` object as the last expression in your notebook. For example: ``[](#__codelineno-6-1)plt.plot([1, 2]) [](#__codelineno-6-2)# plt.gca() gets the current `Axes` [](#__codelineno-6-3)plt.gca()`` or `[](#__codelineno-7-1)fig, ax = plt.subplots() [](#__codelineno-7-2)[](#__codelineno-7-3)ax.plot([1, 2]) [](#__codelineno-7-4)ax` If you want to output the plot in the console area, use `plt.show()` or `fig.show()`. ### Interactive plots[¶](#interactive-plots "Permanent link") To make matplotlib plots interactive, use [mo.mpl.interactive](https://docs.marimo.io/api/plotting/#marimo.mpl.interactive). (Matplotlib plots are not yet reactive.) Documentation Apps - marimo https://docs.marimo.io/apps/ This directory contains marimo apps that are used in the documentation.