From 41733e6118af1c45ce3abb5ff0990e16cbdccf2c Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Thu, 4 Sep 2025 11:51:28 -0700 Subject: [PATCH 1/2] add popup option for redirect --- reflex/.templates/web/utils/state.js | 6 +++++- reflex/event.py | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index 1e11dd9c3f3..01eaa4dd915 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -210,7 +210,11 @@ export const applyEvent = async (event, socket, navigate, params) => { return false; } if (event.payload.external) { - window.open(event.payload.path, "_blank", "noopener"); + window.open( + event.payload.path, + "_blank", + "noopener" + (event.payload.popup ? ",popup" : ""), + ); return false; } const url = urlFrom(event.payload.path); diff --git a/reflex/event.py b/reflex/event.py index d2b37b024f3..ff4b84e9616 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -13,6 +13,7 @@ Annotated, Any, Generic, + Literal, NoReturn, Protocol, TypeVar, @@ -962,9 +963,29 @@ def fn(): ) +@overload +def redirect( + path: str | Var[str], + *, + is_external: Literal[False] = False, + replace: bool = False, +) -> EventSpec: ... + + +@overload +def redirect( + path: str | Var[str], + *, + is_external: Literal[True], + popup: bool = False, +) -> EventSpec: ... + + def redirect( path: str | Var[str], + *, is_external: bool = False, + popup: bool = False, replace: bool = False, ) -> EventSpec: """Redirect to a new path. @@ -972,6 +993,7 @@ def redirect( Args: path: The path to redirect to. is_external: Whether to open in new tab or not. + popup: Whether to open in a new window or not. replace: If True, the current page will not create a new history entry. Returns: @@ -982,6 +1004,7 @@ def redirect( get_fn_signature(redirect), path=path, external=is_external, + popup=popup, replace=replace, ) From 8f3ee24b7fe9dca5de8ef211fc2665c0e2c354df Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Thu, 4 Sep 2025 12:09:14 -0700 Subject: [PATCH 2/2] fix test event --- tests/units/test_event.py | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/tests/units/test_event.py b/tests/units/test_event.py index c7c95709afa..c0def927ea2 100644 --- a/tests/units/test_event.py +++ b/tests/units/test_event.py @@ -1,3 +1,4 @@ +import json from collections.abc import Callable import pytest @@ -169,29 +170,13 @@ def fn_with_args(_, arg1, arg2): ("input", "output"), [ ( - ("/path", None, None), - 'ReflexEvent("_redirect", {path:"/path",external:false,replace:false})', - ), - ( - ("/path", True, None), - 'ReflexEvent("_redirect", {path:"/path",external:true,replace:false})', - ), - ( - ("/path", False, None), - 'ReflexEvent("_redirect", {path:"/path",external:false,replace:false})', - ), - ( - (Var(_js_expr="path"), None, None), - 'ReflexEvent("_redirect", {path:path,external:false,replace:false})', - ), - ( - ("/path", None, True), - 'ReflexEvent("_redirect", {path:"/path",external:false,replace:true})', - ), - ( - ("/path", True, True), - 'ReflexEvent("_redirect", {path:"/path",external:true,replace:true})', - ), + (path, is_external, replace, popup), + f'ReflexEvent("_redirect", {{path:{json.dumps(path) if isinstance(path, str) else path._js_expr},external:{"true" if is_external else "false"},popup:{"true" if popup else "false"},replace:{"true" if replace else "false"}}})', + ) + for path in ("/path", Var(_js_expr="path")) + for is_external in (None, True, False) + for replace in (None, True, False) + for popup in (None, True, False) ], ) def test_event_redirect(input, output): @@ -201,12 +186,14 @@ def test_event_redirect(input, output): input: The input for running the test. output: The expected output to validate the test. """ - path, is_external, replace = input + path, is_external, replace, popup = input kwargs = {} if is_external is not None: kwargs["is_external"] = is_external if replace is not None: kwargs["replace"] = replace + if popup is not None: + kwargs["popup"] = popup spec = event.redirect(path, **kwargs) assert isinstance(spec, EventSpec) assert spec.handler.fn.__qualname__ == "_redirect"