Presentaciones composables para marimo
Project description
Overview
banners is a Python package for building composable slide
presentations inside marimo notebooks.
Each slide is a Python object. Content is declared with dedicated classes and the layout adjusts automatically depending on what you pass.
Personal note: This project is a personal initiative to explore the capabilities of generative AI for developing complete, production-quality software projects --- from architecture decisions to implementation, testing, and documentation --- using Claude Code as the primary development partner.
Installation
The package is not yet published to PyPI. Install directly from GitHub:
uv pip install git+https://github.com/kascesar/banners.git
For local development in editable mode:
uv venv
uv pip install -e .
For animated diagrams (FlowAnimation, Manim):
uv pip install -e ".[dev]"
FlowAnimation and Manim depend on system
libraries for text rendering. Install them before running any animated
content:
sudo apt install python3-dev libpango1.0-dev pkg-config
Quick start
from banners import configure, Cover, Intro, Section, Closing
from banners.content import Text, Image, Graph
from banners.palette import BLUE
# Set shared values once — all slides inherit them automatically.
configure(
team="Analytics Team",
date="April 2026",
icon={"src": "img/logo.png"},
)
Cover(
title="Churn Prediction v2",
subtitle="Model migration and deployment.",
content=[
Text("**Accuracy** — 91% AUC on holdout."),
Text("**Latency** — p99 under 30 ms."),
Text("**Coverage** — All active segments."),
],
content_kind="neutral",
).render()
Global configuration
configure() sets values shared across all slides. Call it
once at the top of the notebook.
Parameter Used by Description
team Cover, Intro, Closing Label shown in the banner
date Cover Date line at the bottom of the banner
palette Cover, Intro, Closing Color palette (BLUE, GREEN, etc.)
icon All slides Logo/icon placed on the banner
Calling configure() also resets the Section
auto-number counter to zero.
Any slide parameter passed explicitly overrides the global value.
Slides
Class Purpose Typical position
Cover Large centered banner First slide
Intro Context or problem statement Slides 2--3
Section Intermediate slide with left border Middle slides
Closing Closing banner with optional metrics Last slide
All slides share these parameters:
Parameter Description
title Main heading
subtitle Support phrase shown inside the banner
content Content element(s) displayed below the banner
palette Color palette. Defaults to orange
content_kind Box style for Text lists: neutral, info, success, warn, danger
footer Quote rendered as a blockquote at the bottom of the slide
icon Banner icon. Falls back to the global configure() value
background Custom slide background (see [*Slide backgrounds]{.spurious-link target="*Slide backgrounds"})
Section --- auto-numbering
Section slides assign their number automatically, starting
from 01 and incrementing with each new instance. The
counter resets when configure() is called.
configure(team="My Team") # counter resets to 0
Section(title="Context") # number = "01"
Section(title="Results") # number = "02"
Section(title="Conclusions") # number = "03"
# Override:
Section(title="Appendix", number="A1")
# Suppress:
Section(title="No number", number="")
Content elements
Class Renders
Text(body) Markdown --- paragraphs, lists, tables
Image(src) Image from file path, bytes, or URL
Graph(code) Static Mermaid diagram
AnimatedGraph(code) Interactive Mermaid diagram --- click to highlight nodes
Table(df) pandas DataFrame
Plot(fig) matplotlib or plotly figure (auto-detected)
FlowAnimation(...) Click-to-advance animated pipeline diagram
Manim(scene) Custom Manim Scene subclass (static or interactive)
Content is passed to the content parameter of any slide.
Layout is resolved automatically:
- Single item → full width.
- List of
Textonly → equal columns; passcontent_kindto add a styled box. - List with any other element → equal-width CSS grid, one column per item.
AnimatedGraph
Accepts graph LR / graph TD Mermaid syntax.
Clicking a node toggles a highlight color.
from banners.content import AnimatedGraph
AnimatedGraph("""
graph LR
A[Ingest] --> B[Validate]
B --> C[Transform]
C --> D[Load]
""", highlight_color="#3b82f6")
FlowAnimation
Step-by-step pipeline animation. Each node appears on click. Requires
the manim dependency.
Three input formats:
from banners.content import FlowAnimation
# Flat list — linear chain
FlowAnimation(["S3", "Glue", "Athena"])
# Nested list — layered topology
FlowAnimation([
["Ingest"],
[{"name": "Transform A", "detail": "features"},
{"name": "Transform B", "detail": "filters"}],
["Load"],
])
# Explicit graph — arbitrary connections
FlowAnimation(
nodes=["Ingest A", "Ingest B", "Validate", "Train"],
edges=[
("Ingest A", "Validate"),
("Ingest B", "Validate"),
("Validate", "Train"),
],
)
Parameter Default Description
direction "LR" / "TD" Flow direction --- left-right or top-down
quality "low" Render quality: "low", "medium", "high"
width "100%" Player width --- any CSS value
Default direction: "LR" for flat lists and graphs,
"TD" for nested lists.
Palettes
All slides accept a palette parameter. The default is
orange.
Constant Colors
ORANGE #7c2d12 → #c2410c → #ea580c
BLUE #1e3a5f → #1d4ed8 → #3b82f6
GREEN #14532d → #15803d → #22c55e
PURPLE #3b0764 → #7e22ce → #a855f7
GRAY #111827 → #374151 → #6b7280
Custom palettes: Palette(start, mid, end) for full-banner
slides, SectionPalette(border, bg_start, bg_end) for
Section.
Slide backgrounds
The background parameter paints the full slide area
(banner + content) with a custom background. Use the
Background factory class:
from banners import Background
# Solid color
Cover(title="Dark slide", background=Background.color("#0f172a"))
# Custom gradient
Section(title="Gradient", background=Background.gradient("#0d1b2a", "#4a1a6e"))
Section(title="3-stop", background=Background.gradient("#0d1b2a", "#4a1a6e",
mid="#1a2a5e", angle=45))
# Image — dark overlay applied automatically for legibility
Cover(title="Photo", background=Background.image("assets/photo.jpg"))
Cover(title="URL", background=Background.image("https://...", overlay="rgba(0,0,0,0.7)"))
Cover(title="Raw", background=Background.image(raw_bytes, overlay=None))
When background is set and content_kind is
not, the content text color is chosen automatically based on the
background luminance (white for dark backgrounds, dark for light ones).
Passing content_kind explicitly disables this --- the
callout boxes handle their own colors.
Documentation
make docs
Generated HTML is written to docs/.
Reference notebooks
Each element and feature has its own notebook inside test/:
Notebook Content
test/01_intro.py configure(), all slide types, all palettes
test/02_text.py Text, content_kind, columns, tables
test/03_image.py Image --- path, bytes, URL, grid layout
test/04_graph.py Static Graph (Mermaid)
test/05_animated_graph.py AnimatedGraph --- interactive highlight
test/06_table.py Table with pandas DataFrames
test/07_plot.py Plot --- matplotlib and plotly
test/08_manim.py Manim --- static and interactive
test/09_flow_animation.py FlowAnimation --- all three input formats
test/10_background.py Background --- color, gradient, image
Run any notebook with:
uv run marimo edit test/01_intro.py
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters