# FormulaAnimation API


`FormulaAnimation` steps through a LaTeX derivation one line at a time. Give it a list of `{"tex": ..., "note": ...}` dicts and the current line sits centered while the previous line floats above it dimmed, with a short caption under the active line. Playback is manual: move with the built-in prev/next buttons, with the arrow keys (click the widget to opt into keyboard control), or by driving the reactive `step` trait from Python — for example, an `mo.ui.slider` in another cell. With `spotlight=True` a final step frames the finished formula alone in an elevated card. The `steps` list is plain JSON, so an LLM can emit a derivation directly.


See also: TangleLatex for a single formula with draggable numbers, and FramePlayer for stepping through a sequence of rendered images.


 Bases: `AnyWidget`


Animate a LaTeX derivation one step at a time.


Give it a list of `{"tex": ..., "note": ...}` steps and it renders a stack of KaTeX equations where the current line sits centered, the previous line floats above it dimmed, and a short caption shows under the active line. Playback is manual: move through the derivation with the built-in prev/next buttons, with the arrow keys (after clicking the widget to enable them), or by driving the `step` trait from Python (e.g. a marimo slider).


With `spotlight=True` a final step frames the last formula alone in a boxed, slightly zoomed state so the finished result stands out.



```
from wigglystuff import FormulaAnimation

import marimo as mo
from wigglystuff import FormulaAnimation

anim = mo.ui.anywidget(
    FormulaAnimation(
        title="The abc-formula",
        steps=[
            {"tex": r"ax^2 + bx + c = 0", "note": "A quadratic equation, with a ≠ 0."},
            {"tex": r"x^2 + \tfrac{b}{a}x + \tfrac{c}{a} = 0", "note": "Make the leading coefficient 1."},
            {"tex": r"x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a}", "note": "The abc-formula."},
        ],
    )
)
anim
```


Create a FormulaAnimation widget.


  Source code in `wigglystuff/formula_animation.py`

```
def __init__(
    self,
    steps: Sequence[Mapping[str, Any]],
    *,
    title: str | None = None,
    spotlight: bool = True,
    height: int = 360,
    theme: str = "auto",
    **kwargs: Any,
) -> None:
    """Create a FormulaAnimation widget.

    Args:
        steps: List of ``{"tex": str, "note": str}`` dicts. ``tex`` is
            required (raw LaTeX passed to KaTeX); ``note`` is an optional
            caption shown under the active line.
        title: Optional heading rendered above the animation.
        spotlight: Append a final step framing the last formula alone.
        height: Height of the animation stage in pixels.
        theme: Color theme: ``"auto"``, ``"light"``, or ``"dark"``.
        **kwargs: Forwarded to ``anywidget.AnyWidget``.
    """
    if title is not None and not isinstance(title, str):
        raise ValueError("title must be a string or None.")
    if theme not in {"auto", "light", "dark"}:
        raise ValueError("theme must be 'auto', 'light', or 'dark'.")
    if isinstance(height, bool) or not isinstance(height, int) or height <= 0:
        raise ValueError("height must be a positive integer.")

    normalized = _normalize_steps(steps)
    super().__init__(
        steps=normalized,
        title=title,
        spotlight=spotlight,
        height=height,
        theme=theme,
        **kwargs,
    )
```


## Synced traitlets


| Traitlet | Type | Notes |
| --- | --- | --- |
| `steps` | `list[dict]` | Normalized `{"tex": str, "note": str}` derivation lines. |
| `title` | `str \\| None` | Optional heading rendered above the animation. |
| `spotlight` | `bool` | Append a final step framing the last formula alone. |
| `step` | `int` | Current index; reactive, slider-drivable, moved by buttons/keys. |
| `height` | `int` | Height of the animation stage in pixels. |
| `theme` | `str` | `"auto"`, `"light"`, or `"dark"`. |
| `error` | `str` | Set if KaTeX fails to load in the browser. |
