From ce867d2f81c898ae8104a3756af740574184c2c7 Mon Sep 17 00:00:00 2001 From: Elijah Ahianyo Date: Wed, 7 Feb 2024 20:05:04 +0000 Subject: [PATCH] Support for Shorthand css props. (#2547) --- reflex/style.py | 41 +++++++++++++++++--- tests/components/typography/test_markdown.py | 6 ++- tests/test_style.py | 13 +++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/reflex/style.py b/reflex/style.py index accd25db4..692965c8a 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Any +from typing import Any, Tuple from reflex import constants from reflex.event import EventChain @@ -37,6 +37,15 @@ toggle_color_mode = BaseVar( breakpoints = ["0", "30em", "48em", "62em", "80em", "96em"] +STYLE_PROP_SHORTHAND_MAPPING = { + "paddingX": ("padding-inline-start", "padding-inline-end"), + "paddingY": ("padding-top", "padding-bottom"), + "marginX": ("margin-inline-start", "margin-inline-end"), + "marginY": ("margin-top", "margin-bottom"), + "bg": ("background",), + "bgColor": ("background-color",), +} + def media_query(breakpoint_index: int): """Create a media query selector. @@ -107,21 +116,43 @@ def convert(style_dict): """ var_data = None # Track import/hook data from any Vars in the style dict. out = {} + + def update_out_dict(return_value, keys_to_update): + for k in keys_to_update: + out[k] = return_value + for key, value in style_dict.items(): - key = format.to_camel_case(key, allow_hyphens=True) + keys = format_style_key(key) if isinstance(value, dict): # Recursively format nested style dictionaries. - out[key], new_var_data = convert(value) + return_val, new_var_data = convert(value) + update_out_dict(return_val, keys) elif isinstance(value, list): # Responsive value is a list of dict or value - out[key], new_var_data = convert_list(value) + return_val, new_var_data = convert_list(value) + update_out_dict(return_val, keys) else: - out[key], new_var_data = convert_item(value) + return_val, new_var_data = convert_item(value) + update_out_dict(return_val, keys) # Combine all the collected VarData instances. var_data = VarData.merge(var_data, new_var_data) return out, var_data +def format_style_key(key: str) -> Tuple[str, ...]: + """Convert style keys to camel case and convert shorthand + styles names to their corresponding css names. + + Args: + key: The style key to convert. + + Returns: + Tuple of css style names corresponding to the key provided. + """ + key = format.to_camel_case(key, allow_hyphens=True) + return STYLE_PROP_SHORTHAND_MAPPING.get(key, (key,)) + + class Style(dict): """A style dictionary.""" diff --git a/tests/components/typography/test_markdown.py b/tests/components/typography/test_markdown.py index 69c8e4a0c..2d136b498 100644 --- a/tests/components/typography/test_markdown.py +++ b/tests/components/typography/test_markdown.py @@ -56,4 +56,8 @@ def test_pass_custom_styles(): md = Markdown.create("# Hello", custom_styles={"h1": {"color": "red"}}) comp = md.get_component("h1") # type: ignore - assert comp.style == {"color": "red", "marginY": "0.5em"} + assert comp.style == { + "color": "red", + "margin-bottom": "0.5em", + "margin-top": "0.5em", + } diff --git a/tests/test_style.py b/tests/test_style.py index 41a6c765c..79ecee23c 100644 --- a/tests/test_style.py +++ b/tests/test_style.py @@ -20,6 +20,19 @@ test_style = [ {"::-webkit-scrollbar": {"display": "none"}}, {"::-webkit-scrollbar": {"display": "none"}}, ), + ({"margin_y": "2rem"}, {"margin-bottom": "2rem", "margin-top": "2rem"}), + ({"marginY": "2rem"}, {"margin-bottom": "2rem", "margin-top": "2rem"}), + ( + {"::-webkit-scrollbar": {"bgColor": "red"}}, + {"::-webkit-scrollbar": {"background-color": "red"}}, + ), + ( + {"paddingX": ["2rem", "3rem"]}, + { + "padding-inline-start": ["2rem", "3rem"], + "padding-inline-end": ["2rem", "3rem"], + }, + ), ]