From 98a5196180083d7bd74600f282d9da968c3422fc Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Mon, 5 Oct 2026 10:51:17 +0200 Subject: [PATCH 1/3] fix: let rx.input take the HTML autocomplete string, and turn a bool into "on" or "off" instead of a value React drops --- .../news/+text-field-auto-complete.bugfix.md | 1 + .../themes/components/text_field.py | 17 +++++++++-- .../units/components/radix/test_text_field.py | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 packages/reflex-components-radix/news/+text-field-auto-complete.bugfix.md create mode 100644 tests/units/components/radix/test_text_field.py diff --git a/packages/reflex-components-radix/news/+text-field-auto-complete.bugfix.md b/packages/reflex-components-radix/news/+text-field-auto-complete.bugfix.md new file mode 100644 index 00000000000..cd90176b20c --- /dev/null +++ b/packages/reflex-components-radix/news/+text-field-auto-complete.bugfix.md @@ -0,0 +1 @@ +`rx.input`'s `auto_complete` now takes the HTML autocomplete value, such as `"off"` or `"email"`, which used to raise a `TypeError`. A bool still works and now becomes `"on"` or `"off"`; before, React dropped it and browser autocomplete stayed on. diff --git a/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py b/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py index d23e1dd7c40..e01fcc3f3a1 100644 --- a/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py +++ b/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py @@ -6,7 +6,7 @@ from reflex_base.components.component import Component, ComponentNamespace, field from reflex_base.event import EventHandler, input_event, key_event -from reflex_base.utils.types import is_optional +from reflex_base.utils.types import is_optional, safe_issubclass from reflex_base.vars.base import Var from reflex_base.vars.number import ternary_operation from reflex_components_core.core.breakpoints import Responsive @@ -42,8 +42,8 @@ class TextFieldRoot(elements.Input, RadixThemesComponent): doc='Override theme radius for text field: "none" | "small" | "medium" | "large" | "full"' ) - auto_complete: Var[bool] = field( - doc="Whether the input should have autocomplete enabled" + auto_complete: Var[str] = field( + doc='The autocomplete hint, e.g. "off", "on" or "email". True and False become "on" and "off".' ) default_value: Var[str] = field( @@ -103,6 +103,17 @@ def create(cls, *children, **props) -> Component: Returns: The component. """ + # React drops a bool autoComplete, the DOM takes a string + auto_complete = props.get("auto_complete") + if isinstance(auto_complete, bool): + props["auto_complete"] = "on" if auto_complete else "off" + elif isinstance(auto_complete, Var) and safe_issubclass( + auto_complete._var_type, bool + ): + props["auto_complete"] = ternary_operation( + auto_complete, Var.create("on"), Var.create("off") + ) + value = props.get("value") # React expects an empty string(instead of null) for controlled inputs. diff --git a/tests/units/components/radix/test_text_field.py b/tests/units/components/radix/test_text_field.py new file mode 100644 index 00000000000..1c3913e2e07 --- /dev/null +++ b/tests/units/components/radix/test_text_field.py @@ -0,0 +1,28 @@ +from typing import Any + +import pytest +from reflex_base.vars.base import Var +from reflex_components_radix.themes.components.text_field import TextFieldRoot + + +@pytest.mark.parametrize( + ("auto_complete", "expected"), + [ + ("off", '"off"'), + ("email", '"email"'), + (False, '"off"'), + (True, '"on"'), + (Var(_js_expr="enabled", _var_type=bool), '(enabled ? "on" : "off")'), + (Var(_js_expr="hint", _var_type=str), "hint"), + ], +) +def test_auto_complete_renders_a_string(auto_complete: Any, expected: str): + """React drops a bool autoComplete, so a bool becomes "on" or "off". + + Args: + auto_complete: The auto_complete prop, typed str but still accepting a bool. + expected: The rendered autoComplete value. + """ + text_field = TextFieldRoot.create(auto_complete=auto_complete) + + assert f"autoComplete:{expected}" in str(text_field) From 5e23589a0b8f90f522a4505c09676ee84562d00c Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Mon, 5 Oct 2026 20:04:10 +0200 Subject: [PATCH 2/3] test: move the text field test to the path mirroring its module below src/ --- tests/units/reflex_components_radix/__init__.py | 0 tests/units/reflex_components_radix/themes/__init__.py | 0 tests/units/reflex_components_radix/themes/components/__init__.py | 0 .../themes/components}/test_text_field.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/units/reflex_components_radix/__init__.py create mode 100644 tests/units/reflex_components_radix/themes/__init__.py create mode 100644 tests/units/reflex_components_radix/themes/components/__init__.py rename tests/units/{components/radix => reflex_components_radix/themes/components}/test_text_field.py (100%) diff --git a/tests/units/reflex_components_radix/__init__.py b/tests/units/reflex_components_radix/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/units/reflex_components_radix/themes/__init__.py b/tests/units/reflex_components_radix/themes/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/units/reflex_components_radix/themes/components/__init__.py b/tests/units/reflex_components_radix/themes/components/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/units/components/radix/test_text_field.py b/tests/units/reflex_components_radix/themes/components/test_text_field.py similarity index 100% rename from tests/units/components/radix/test_text_field.py rename to tests/units/reflex_components_radix/themes/components/test_text_field.py From 5675851335913087d989096ba583478edeeb9a21 Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Thu, 8 Oct 2026 22:46:05 +0200 Subject: [PATCH 3/3] fix: convert an optional bool auto_complete var to "on" or "off" too A bool | None var skipped the bool check and failed the Var[str] prop validation, so unwrap the Optional before checking. --- .../reflex_components_radix/themes/components/text_field.py | 4 ++-- .../themes/components/test_text_field.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py b/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py index e01fcc3f3a1..ca4f0018593 100644 --- a/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py +++ b/packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.py @@ -6,7 +6,7 @@ from reflex_base.components.component import Component, ComponentNamespace, field from reflex_base.event import EventHandler, input_event, key_event -from reflex_base.utils.types import is_optional, safe_issubclass +from reflex_base.utils.types import is_optional, safe_issubclass, value_inside_optional from reflex_base.vars.base import Var from reflex_base.vars.number import ternary_operation from reflex_components_core.core.breakpoints import Responsive @@ -108,7 +108,7 @@ def create(cls, *children, **props) -> Component: if isinstance(auto_complete, bool): props["auto_complete"] = "on" if auto_complete else "off" elif isinstance(auto_complete, Var) and safe_issubclass( - auto_complete._var_type, bool + value_inside_optional(auto_complete._var_type), bool ): props["auto_complete"] = ternary_operation( auto_complete, Var.create("on"), Var.create("off") diff --git a/tests/units/reflex_components_radix/themes/components/test_text_field.py b/tests/units/reflex_components_radix/themes/components/test_text_field.py index 1c3913e2e07..3963da7af21 100644 --- a/tests/units/reflex_components_radix/themes/components/test_text_field.py +++ b/tests/units/reflex_components_radix/themes/components/test_text_field.py @@ -13,7 +13,9 @@ (False, '"off"'), (True, '"on"'), (Var(_js_expr="enabled", _var_type=bool), '(enabled ? "on" : "off")'), + (Var(_js_expr="flag", _var_type=bool | None), '(flag ? "on" : "off")'), (Var(_js_expr="hint", _var_type=str), "hint"), + (Var(_js_expr="maybe_hint", _var_type=str | None), "maybe_hint"), ], ) def test_auto_complete_renders_a_string(auto_complete: Any, expected: str):