Repository: projectmesa/mesa

Issue:
JupyterViz: Changing simulation parameters shouldn't automatically start the simulation
**Describe the bug**
Currently, changing the parameters auto-play the simulation.

**Expected behavior**
It shouldn't.

**To Reproduce**
Run any `JupyterViz` simulation.

Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/projectmesa/mesa/pull/1796?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) Report
Patch coverage has no change and project coverage change: **`-0.51%`** :warning:
> Comparison is base [(`20dbf9e`)](https://app.codecov.io/gh/projectmesa/mesa/commit/20dbf9e0643e11cff36a095d1123b5ec895b0d11?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) 82.05% compared to head [(`298788e`)](https://app.codecov.io/gh/projectmesa/mesa/pull/1796?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) 81.55%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1796      +/-   ##
==========================================
- Coverage   82.05%   81.55%   -0.51%     
==========================================
  Files          15       15              
  Lines         886      889       +3     
  Branches      191      166      -25     
==========================================
- Hits          727      725       -2     
- Misses        135      140       +5     
  Partials       24       24              
```


| [Files Changed](https://app.codecov.io/gh/projectmesa/mesa/pull/1796?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) | Coverage Δ | |
|---|---|---|
| [mesa/experimental/jupyter\_viz.py](https://app.codecov.io/gh/projectmesa/mesa/pull/1796?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa#diff-bWVzYS9leHBlcmltZW50YWwvanVweXRlcl92aXoucHk=) | `33.33% <0.00%> (-1.67%)` | :arrow_down: |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/projectmesa/mesa/pull/1796/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/projectmesa/mesa/pull/1796?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).


Patch:
diff --git a/docs/tutorials/visualization_tutorial.ipynb b/docs/tutorials/visualization_tutorial.ipynb
index 37564241..cead72ac 100644
--- a/docs/tutorials/visualization_tutorial.ipynb
+++ b/docs/tutorials/visualization_tutorial.ipynb
@@ -198,18 +198,16 @@
     "from matplotlib.figure import Figure\n",
     "\n",
     "\n",
-    "def make_histogram(viz):\n",
+    "def make_histogram(model):\n",
     "    # Note: you must initialize a figure using this method instead of\n",
     "    # plt.figure(), for thread safety purpose\n",
     "    fig = Figure()\n",
     "    ax = fig.subplots()\n",
-    "    wealth_vals = [agent.wealth for agent in viz.model.schedule.agents]\n",
+    "    wealth_vals = [agent.wealth for agent in model.schedule.agents]\n",
     "    # Note: you have to use Matplotlib's OOP API instead of plt.hist\n",
     "    # because plt.hist is not thread-safe.\n",
     "    ax.hist(wealth_vals, bins=10)\n",
-    "    # You have to specify the dependencies as follows, so that the figure\n",
-    "    # auto-updates when viz.model or viz.df is changed.\n",
-    "    solara.FigureMatplotlib(fig, dependencies=[viz.model, viz.df])"
+    "    solara.FigureMatplotlib(fig)"
    ]
   },
   {
diff --git a/mesa/experimental/jupyter_viz.py b/mesa/experimental/jupyter_viz.py
index a7eefb51..96970b8c 100644
--- a/mesa/experimental/jupyter_viz.py
+++ b/mesa/experimental/jupyter_viz.py
@@ -89,15 +89,25 @@ def ModelController(
 ):
     playing = solara.use_reactive(False)
     thread = solara.use_reactive(None)
+    # We track the previous step to detect if user resets the model via
+    # clicking the reset button or changing the parameters. If previous_step >
+    # current_step, it means a model reset happens while the simulation is
+    # still playing.
+    previous_step = solara.use_reactive(0)
 
     def on_value_play(change):
-        if model.running:
+        if previous_step.value > current_step and current_step == 0:
+            # We add extra checks for current_step == 0, just to be sure.
+            # We automatically stop the playing if a model is reset.
+            playing.value = False
+        elif model.running:
             do_step()
         else:
             playing.value = False
 
     def do_step():
         model.step()
+        previous_step.value = current_step
         set_current_step(model.schedule.steps)
 
     def do_play():
@@ -174,7 +184,7 @@ def check_param_is_fixed(param):
 def UserInputs(user_params, on_change=None):
     """Initialize user inputs for configurable model parameters.
     Currently supports :class:`solara.SliderInt`, :class:`solara.SliderFloat`,
-    and :class:`solara.Select`.
+    :class:`solara.Select`, and :class:`solara.Checkbox`.
 
     Props:
         user_params: dictionary with options for the input, including label,
@@ -215,6 +225,11 @@ def UserInputs(user_params, on_change=None):
                 on_value=change_handler,
                 values=options.get("values"),
             )
+        elif input_type == "Checkbox":
+            solara.Checkbox(
+                label=label,
+                value=options.get("value"),
+            )
         else:
             raise ValueError(f"{input_type} is not a supported input type")
 


Test patch:
diff --git a/tests/test_jupyter_viz.py b/tests/test_jupyter_viz.py
index f1d7371c..97021252 100644
--- a/tests/test_jupyter_viz.py
+++ b/tests/test_jupyter_viz.py
@@ -45,6 +45,19 @@ class TestMakeUserInput(unittest.TestCase):
         assert slider_int.max == options["max"]
         assert slider_int.step == options["step"]
 
+    def test_checkbox(self):
+        @solara.component
+        def Test(user_params):
+            UserInputs(user_params)
+
+        options = {"type": "Checkbox", "value": True, "label": "On"}
+        user_params = {"num_agents": options}
+        _, rc = solara.render(Test(user_params), handle_error=False)
+        checkbox = rc.find(vw.Checkbox).widget
+
+        assert checkbox.v_model == options["value"]
+        assert checkbox.label == options["label"]
+
     def test_label_fallback(self):
         """name should be used as fallback label"""