Support aria and data props (#4149)
* Support aria and data props
* Fix busted docstring
* Ignore special_attributes logic for defined props
* simplify special attribute checking logic
avoid special cases in the special case handling code 🙄
This commit is contained in:
parent
b2d2719f90
commit
1d268f8b13
@ -36,6 +36,7 @@ from reflex.constants import (
|
||||
MemoizationMode,
|
||||
PageNames,
|
||||
)
|
||||
from reflex.constants.compiler import SpecialAttributes
|
||||
from reflex.event import (
|
||||
EventChain,
|
||||
EventChainVar,
|
||||
@ -474,6 +475,17 @@ class Component(BaseComponent, ABC):
|
||||
for key in kwargs["event_triggers"]:
|
||||
del kwargs[key]
|
||||
|
||||
# Place data_ and aria_ attributes into custom_attrs
|
||||
special_attributes = tuple(
|
||||
key
|
||||
for key in kwargs
|
||||
if key not in fields and SpecialAttributes.is_special(key)
|
||||
)
|
||||
if special_attributes:
|
||||
custom_attrs = kwargs.setdefault("custom_attrs", {})
|
||||
for key in special_attributes:
|
||||
custom_attrs[format.to_kebab_case(key)] = kwargs.pop(key)
|
||||
|
||||
# Add style props to the component.
|
||||
style = kwargs.get("style", {})
|
||||
if isinstance(style, List):
|
||||
@ -493,8 +505,6 @@ class Component(BaseComponent, ABC):
|
||||
**{attr: value for attr, value in kwargs.items() if attr not in fields},
|
||||
}
|
||||
)
|
||||
if "custom_attrs" not in kwargs:
|
||||
kwargs["custom_attrs"] = {}
|
||||
|
||||
# Convert class_name to str if it's list
|
||||
class_name = kwargs.get("class_name", "")
|
||||
|
@ -160,3 +160,28 @@ class MemoizationMode(Base):
|
||||
|
||||
# Whether children of this component should be memoized first.
|
||||
recursive: bool = True
|
||||
|
||||
|
||||
class SpecialAttributes(enum.Enum):
|
||||
"""Special attributes for components.
|
||||
|
||||
These are placed in custom_attrs and rendered as-is rather than converting
|
||||
to a style prop.
|
||||
"""
|
||||
|
||||
DATA_UNDERSCORE = "data_"
|
||||
DATA_DASH = "data-"
|
||||
ARIA_UNDERSCORE = "aria_"
|
||||
ARIA_DASH = "aria-"
|
||||
|
||||
@classmethod
|
||||
def is_special(cls, attr: str) -> bool:
|
||||
"""Check if the attribute is special.
|
||||
|
||||
Args:
|
||||
attr: the attribute to check
|
||||
|
||||
Returns:
|
||||
True if the attribute is special.
|
||||
"""
|
||||
return any(attr.startswith(value.value) for value in cls)
|
||||
|
@ -2217,3 +2217,56 @@ class TriggerState(rx.State):
|
||||
)
|
||||
def test_has_state_event_triggers(component, output):
|
||||
assert component._has_stateful_event_triggers() == output
|
||||
|
||||
|
||||
class SpecialComponent(Box):
|
||||
"""A special component with custom attributes."""
|
||||
|
||||
data_prop: Var[str]
|
||||
aria_prop: Var[str]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("component_kwargs", "exp_custom_attrs", "exp_style"),
|
||||
[
|
||||
(
|
||||
{"data_test": "test", "aria_test": "test"},
|
||||
{"data-test": "test", "aria-test": "test"},
|
||||
{},
|
||||
),
|
||||
(
|
||||
{"data-test": "test", "aria-test": "test"},
|
||||
{"data-test": "test", "aria-test": "test"},
|
||||
{},
|
||||
),
|
||||
(
|
||||
{"custom_attrs": {"data-existing": "test"}, "data_new": "test"},
|
||||
{"data-existing": "test", "data-new": "test"},
|
||||
{},
|
||||
),
|
||||
(
|
||||
{"data_test": "test", "data_prop": "prop"},
|
||||
{"data-test": "test"},
|
||||
{},
|
||||
),
|
||||
(
|
||||
{"aria_test": "test", "aria_prop": "prop"},
|
||||
{"aria-test": "test"},
|
||||
{},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_special_props(component_kwargs, exp_custom_attrs, exp_style):
|
||||
"""Test that data_ and aria_ special props are correctly added to the component.
|
||||
|
||||
Args:
|
||||
component_kwargs: The component kwargs.
|
||||
exp_custom_attrs: The expected custom attributes.
|
||||
exp_style: The expected style.
|
||||
"""
|
||||
component = SpecialComponent.create(**component_kwargs)
|
||||
assert component.custom_attrs == exp_custom_attrs
|
||||
assert component.style == exp_style
|
||||
for prop in SpecialComponent.get_props():
|
||||
if prop in component_kwargs:
|
||||
assert getattr(component, prop)._var_value == component_kwargs[prop]
|
||||
|
Loading…
Reference in New Issue
Block a user