From 01f7611d3b36561a6cf1667fc6361b1f9b673a19 Mon Sep 17 00:00:00 2001 From: Alex Fernandez Luces Date: Thu, 16 Oct 2025 11:54:03 +0200 Subject: [PATCH 1/5] feat(plotly): Add night mode button --- .../01-basic-plotly-examples/plain-usage.py | 2 +- .../backends/plotly/plotly_interface.py | 10 +++- .../backends/plotly/widgets/button_manager.py | 47 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/examples/01-basic-plotly-examples/plain-usage.py b/examples/01-basic-plotly-examples/plain-usage.py index 94c21950..4fa60bde 100644 --- a/examples/01-basic-plotly-examples/plain-usage.py +++ b/examples/01-basic-plotly-examples/plain-usage.py @@ -127,4 +127,4 @@ def name(self): # # code-block:: python # -# pl.show() \ No newline at end of file +pl.show() \ No newline at end of file diff --git a/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py b/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py index 237ec8d9..deb44bff 100644 --- a/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py +++ b/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py @@ -33,7 +33,14 @@ class PlotlyBackend(BaseBackend): - """Plotly interface for visualization.""" + """Plotly interface for visualization. + + Parameters + ---------- + theme : str, default: "plotly" + Theme for the Plotly figure. See available themes at + `Plotly Templates `_. + """ def __init__(self) -> None: """Initialize the Plotly backend.""" @@ -44,6 +51,7 @@ def __init__(self) -> None: self._button_manager.add_plane_view_buttons() self._button_manager.add_coordinate_system_toggle_button() self._button_manager.add_projection_toggle_button() + self._button_manager.add_theme_toggle_button() def _pv_to_mesh3d(self, pv_mesh: Union[PolyData, pv.MultiBlock]) -> Union[go.Mesh3d, list]: """Convert a PyVista PolyData or MultiBlock mesh to Plotly Mesh3d format. diff --git a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py index ba9bf6d2..2a98a884 100644 --- a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py +++ b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py @@ -23,6 +23,7 @@ from typing import Any, List import plotly.graph_objects as go +import plotly.io as pio class ButtonManager: @@ -392,3 +393,49 @@ def add_projection_toggle_button( x=x, y=y ) + + def add_theme_toggle_button( + self, + label: str = "Toggle Theme", + x: float = 0.2175, + y: float = 1.02 + ) -> None: + """Add a button to toggle between light and dark themes. + + Parameters + ---------- + label : str, optional + The text to display on the button, by default "Toggle Theme". + x : float, optional + X position of the button (0-1), by default 0.22. + y : float, optional + Y position of the button (0-1), by default 1.02. + """ + # Light theme with light button styling for all updatemenus + light_theme = { + "template": pio.templates["plotly"] + } + + # Dark theme with dark button styling for all updatemenus + dark_theme = { + "template": pio.templates["plotly_dark"] + } + + # Add styling updates for all existing updatemenus + for i in range(10): # Support up to 10 button groups + light_theme[f"updatemenus[{i}].bgcolor"] = "rgba(255,255,255,0.95)" + light_theme[f"updatemenus[{i}].bordercolor"] = "rgba(0,0,0,0.3)" + light_theme[f"updatemenus[{i}].font.color"] = "black" + + dark_theme[f"updatemenus[{i}].bgcolor"] = "rgba(50,50,50,0.95)" + dark_theme[f"updatemenus[{i}].bordercolor"] = "rgba(255,255,255,0.3)" + dark_theme[f"updatemenus[{i}].font.color"] = "grey" + + self.add_button( + label=label, + method="relayout", + args=[light_theme], + args2=[dark_theme], + x=x, + y=y + ) \ No newline at end of file From 9684d30a1b7071543a01789c82a8a209b3bc04f8 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 16 Oct 2025 09:55:32 +0000 Subject: [PATCH 2/5] chore: adding changelog file 394.miscellaneous.md [dependabot-skip] --- doc/changelog.d/394.miscellaneous.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/394.miscellaneous.md diff --git a/doc/changelog.d/394.miscellaneous.md b/doc/changelog.d/394.miscellaneous.md new file mode 100644 index 00000000..f4a74d36 --- /dev/null +++ b/doc/changelog.d/394.miscellaneous.md @@ -0,0 +1 @@ +Feat(plotly): Add night mode button From e693679442c05262c5922b7b1d0be6625ca80eb0 Mon Sep 17 00:00:00 2001 From: Alex Fernandez Luces Date: Thu, 16 Oct 2025 15:57:02 +0200 Subject: [PATCH 3/5] fix: Avoid using template due to serialization issues --- .../backends/plotly/widgets/button_manager.py | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py index 2a98a884..66695118 100644 --- a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py +++ b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py @@ -23,7 +23,6 @@ from typing import Any, List import plotly.graph_objects as go -import plotly.io as pio class ButtonManager: @@ -411,14 +410,45 @@ def add_theme_toggle_button( y : float, optional Y position of the button (0-1), by default 1.02. """ - # Light theme with light button styling for all updatemenus + # Define light theme properties manually to avoid JSON serialization issues + # Use dot notation to target specific properties without overriding the entire scene + # Colors extracted from official plotly template light_theme = { - "template": pio.templates["plotly"] + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "font.color": "#2a3f5f", + "scene.xaxis.backgroundcolor": "#E5ECF6", + "scene.xaxis.gridcolor": "white", + "scene.xaxis.linecolor": "white", + "scene.xaxis.zerolinecolor": "white", + "scene.yaxis.backgroundcolor": "#E5ECF6", + "scene.yaxis.gridcolor": "white", + "scene.yaxis.linecolor": "white", + "scene.yaxis.zerolinecolor": "white", + "scene.zaxis.backgroundcolor": "#E5ECF6", + "scene.zaxis.gridcolor": "white", + "scene.zaxis.linecolor": "white", + "scene.zaxis.zerolinecolor": "white" } - # Dark theme with dark button styling for all updatemenus + # Define dark theme properties manually + # Colors extracted from official plotly_dark template dark_theme = { - "template": pio.templates["plotly_dark"] + "paper_bgcolor": "rgb(17,17,17)", + "plot_bgcolor": "rgb(17,17,17)", + "font.color": "#f2f5fa", + "scene.xaxis.backgroundcolor": "rgb(17,17,17)", + "scene.xaxis.gridcolor": "#506784", + "scene.xaxis.linecolor": "#506784", + "scene.xaxis.zerolinecolor": "#C8D4E3", + "scene.yaxis.backgroundcolor": "rgb(17,17,17)", + "scene.yaxis.gridcolor": "#506784", + "scene.yaxis.linecolor": "#506784", + "scene.yaxis.zerolinecolor": "#C8D4E3", + "scene.zaxis.backgroundcolor": "rgb(17,17,17)", + "scene.zaxis.gridcolor": "#506784", + "scene.zaxis.linecolor": "#506784", + "scene.zaxis.zerolinecolor": "#C8D4E3" } # Add styling updates for all existing updatemenus From 5a9443ff4b1b9609344adfa76f0aa9a2c602ea35 Mon Sep 17 00:00:00 2001 From: Alex Fernandez Luces Date: Fri, 17 Oct 2025 09:42:38 +0200 Subject: [PATCH 4/5] fix: Example --- examples/01-basic-plotly-examples/plain-usage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/01-basic-plotly-examples/plain-usage.py b/examples/01-basic-plotly-examples/plain-usage.py index 4fa60bde..94c21950 100644 --- a/examples/01-basic-plotly-examples/plain-usage.py +++ b/examples/01-basic-plotly-examples/plain-usage.py @@ -127,4 +127,4 @@ def name(self): # # code-block:: python # -pl.show() \ No newline at end of file +# pl.show() \ No newline at end of file From 9472623e60d051a58b40f7f6f1d279aa99c06e4c Mon Sep 17 00:00:00 2001 From: Alex Fernandez Luces Date: Fri, 17 Oct 2025 10:06:42 +0200 Subject: [PATCH 5/5] fix: Magic number --- .../backends/plotly/plotly_interface.py | 9 +-------- .../backends/plotly/widgets/button_manager.py | 11 +++++++---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py b/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py index deb44bff..c74b7708 100644 --- a/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py +++ b/src/ansys/tools/visualization_interface/backends/plotly/plotly_interface.py @@ -33,14 +33,7 @@ class PlotlyBackend(BaseBackend): - """Plotly interface for visualization. - - Parameters - ---------- - theme : str, default: "plotly" - Theme for the Plotly figure. See available themes at - `Plotly Templates `_. - """ + """Plotly interface for visualization.""" def __init__(self) -> None: """Initialize the Plotly backend.""" diff --git a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py index 66695118..c55417ae 100644 --- a/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py +++ b/src/ansys/tools/visualization_interface/backends/plotly/widgets/button_manager.py @@ -387,8 +387,8 @@ def add_projection_toggle_button( self.add_button( label=label, method="relayout", - args=[orthographic_projection], - args2=[perspective_projection], + args=[perspective_projection], + args2=[orthographic_projection], x=x, y=y ) @@ -451,8 +451,11 @@ def add_theme_toggle_button( "scene.zaxis.zerolinecolor": "#C8D4E3" } - # Add styling updates for all existing updatemenus - for i in range(10): # Support up to 10 button groups + # Add styling updates for all existing updatemenus + the theme button we're about to add + # Get the actual number of updatemenus in the figure + current_updatemenus = self._fig.layout.updatemenus or [] + # Add 1 to include the theme button we're about to create + for i in range(len(current_updatemenus) + 1): light_theme[f"updatemenus[{i}].bgcolor"] = "rgba(255,255,255,0.95)" light_theme[f"updatemenus[{i}].bordercolor"] = "rgba(0,0,0,0.3)" light_theme[f"updatemenus[{i}].font.color"] = "black"