diff --git a/reflex/.templates/jinja/web/pages/base_page.js.jinja2 b/reflex/.templates/jinja/web/pages/base_page.js.jinja2 index 3fce5849fc..2a1a509443 100644 --- a/reflex/.templates/jinja/web/pages/base_page.js.jinja2 +++ b/reflex/.templates/jinja/web/pages/base_page.js.jinja2 @@ -1,5 +1,7 @@ {% import 'web/pages/utils.js.jinja2' as utils %} +/** @jsxImportSource @emotion/react */ + {%- block imports_libs %} {% for module in imports%} {{- utils.get_import(module) }} diff --git a/reflex/app.py b/reflex/app.py index b0be08f559..63930acea1 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -667,6 +667,9 @@ def mark_complete(_=None): # Merge the component style with the app style. component.add_style(self.style) + if self.theme is not None: + component.apply_theme(self.theme) + # Add component.get_imports() to all_imports. all_imports.update(component.get_imports()) diff --git a/reflex/components/component.py b/reflex/components/component.py index e85b6dd364..211a85b0ba 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -288,6 +288,7 @@ def __init__(self, *args, **kwargs): kwargs["style"] = Style( { + **self.get_fields()["style"].default, **style, **{attr: value for attr, value in kwargs.items() if attr not in fields}, } @@ -445,6 +446,26 @@ def __str__(self) -> str: return _compile_component(self) + def _apply_theme(self, theme: Component): + """Apply the theme to this component. + + Args: + theme: The theme to apply. + """ + pass + + def apply_theme(self, theme: Component): + """Apply a theme to the component and its children. + + Args: + theme: The theme to apply. + """ + self._apply_theme(theme) + for child in self.children: + if not isinstance(child, Component): + continue + child.apply_theme(theme) + def _render(self, props: dict[str, Any] | None = None) -> Tag: """Define how to render the component in React. @@ -603,7 +624,7 @@ def _get_style(self) -> dict: Returns: The dictionary of the component style as value and the style notation as key. """ - return {"style": self.style} + return {"css": self.style} def render(self) -> Dict: """Render the component. diff --git a/reflex/components/radix/primitives/__init__.py b/reflex/components/radix/primitives/__init__.py new file mode 100644 index 0000000000..82e4c55e42 --- /dev/null +++ b/reflex/components/radix/primitives/__init__.py @@ -0,0 +1,3 @@ +"""Radix primitive components (https://www.radix-ui.com/primitives).""" + +from .accordion import accordion diff --git a/reflex/components/radix/primitives/accordion.py b/reflex/components/radix/primitives/accordion.py new file mode 100644 index 0000000000..c3cb662861 --- /dev/null +++ b/reflex/components/radix/primitives/accordion.py @@ -0,0 +1,279 @@ +"""Radix accordion components.""" + +from typing import Literal + +from reflex.components.component import Component +from reflex.components.tags import Tag +from reflex.style import Style +from reflex.utils import format, imports +from reflex.vars import Var + +LiteralAccordionType = Literal["single", "multiple"] +LiteralAccordionDir = Literal["ltr", "rtl"] +LiteralAccordionOrientation = Literal["vertical", "horizontal"] + + +DEFAULT_ANIMATION_DURATION = 250 + + +class AccordionComponent(Component): + """Base class for all @radix-ui/accordion components.""" + + library = "@radix-ui/react-accordion@^1.1.2" + + # Change the default rendered element for the one passed as a child. + as_child: Var[bool] + + def _render(self) -> Tag: + return ( + super() + ._render() + .add_props( + **{ + "class_name": format.to_title_case(self.tag or ""), + } + ) + ) + + +class AccordionRoot(AccordionComponent): + """An accordion component.""" + + tag = "Root" + + alias = "RadixAccordionRoot" + + # The type of accordion (single or multiple). + type_: Var[LiteralAccordionType] + + # The value of the item to expand. + value: Var[str] + + # The default value of the item to expand. + default_value: Var[str] + + # Whether or not the accordion is collapsible. + collapsible: Var[bool] + + # Whether or not the accordion is disabled. + disabled: Var[bool] + + # The reading direction of the accordion when applicable. + dir: Var[LiteralAccordionDir] + + # The orientation of the accordion. + orientation: Var[LiteralAccordionOrientation] + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "border_radius": "6px", + "background_color": "var(--accent-6)", + "box_shadow": "0 2px 10px var(--black-a4)", + **self.style, + } + ) + + +class AccordionItem(AccordionComponent): + """An accordion component.""" + + tag = "Item" + + alias = "RadixAccordionItem" + + # A unique identifier for the item. + value: Var[str] + + # When true, prevents the user from interacting with the item. + disabled: Var[bool] + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "overflow": "hidden", + "margin_top": "1px", + "&:first-child": { + "margin_top": 0, + "border_top_left_radius": "4px", + "border_top_right_radius": "4px", + }, + "&:last-child": { + "border_bottom_left_radius": "4px", + "border_bottom_right_radius": "4px", + }, + "&:focus-within": { + "position": "relative", + "z_index": 1, + "box_shadow": "0 0 0 2px var(--accent-7)", + }, + **self.style, + } + ) + + +class AccordionHeader(AccordionComponent): + """An accordion component.""" + + tag = "Header" + + alias = "RadixAccordionHeader" + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "display": "flex", + **self.style, + } + ) + + +class AccordionTrigger(AccordionComponent): + """An accordion component.""" + + tag = "Trigger" + + alias = "RadixAccordionTrigger" + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "font_family": "inherit", + "padding": "0 20px", + "height": "45px", + "flex": 1, + "display": "flex", + "align_items": "center", + "justify_content": "space-between", + "font_size": "15px", + "line_height": 1, + "color": "var(--accent-11)", + "box_shadow": "0 1px 0 var(--accent-6)", + "&:hover": { + "background_color": "var(--gray-2)", + }, + "&[data-state='open'] > .AccordionChevron": { + "transform": "rotate(180deg)", + }, + **self.style, + } + ) + + +class AccordionContent(AccordionComponent): + """An accordion component.""" + + tag = "Content" + + alias = "RadixAccordionContent" + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "overflow": "hidden", + "fontSize": "15px", + "color": "var(--accent-11)", + "backgroundColor": "var(--accent-2)", + "padding": "15px, 20px", + "&[data-state='open']": { + "animation": Var.create( + f"${{slideDown}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)", + _var_is_string=True, + ), + }, + "&[data-state='closed']": { + "animation": Var.create( + f"${{slideUp}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)", + _var_is_string=True, + ), + }, + **self.style, + } + ) + + def _get_imports(self): + return { + **super()._get_imports(), + "@emotion/react": [imports.ImportVar(tag="keyframes")], + } + + def _get_custom_code(self) -> str: + return """ +const slideDown = keyframes` +from { + height: 0; +} +to { + height: var(--radix-accordion-content-height); +} +` +const slideUp = keyframes` +from { + height: var(--radix-accordion-content-height); +} +to { + height: 0; +} +` +""" + + +# TODO: Remove this once the radix-icons PR is merged in. +class ChevronDownIcon(Component): + """A chevron down icon.""" + + library = "@radix-ui/react-icons" + + tag = "ChevronDownIcon" + + def _apply_theme(self, theme: Component): + self.style = Style( + { + "color": "var(--accent-10)", + "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)", + **self.style, + } + ) + + +accordion_root = AccordionRoot.create +accordion_item = AccordionItem.create +accordion_trigger = AccordionTrigger.create +accordion_content = AccordionContent.create +accordion_header = AccordionHeader.create +chevron_down_icon = ChevronDownIcon.create + + +def accordion(items: list[tuple[str, str]], **props) -> Component: + """High level API for the Radix accordion. + + #TODO: We need to handle taking in state here. This is just for a POC. + + + Args: + items: The items of the accordion component: list of tuples (label,panel) + **props: The properties of the component. + + Returns: + The accordion component. + """ + return accordion_root( + *[ + accordion_item( + accordion_header( + accordion_trigger( + label, + chevron_down_icon( + class_name="AccordionChevron", + ), + ), + ), + accordion_content( + panel, + ), + value=f"item-{i}", + ) + for i, (label, panel) in enumerate(items) + ], + **props, + ) diff --git a/reflex/components/radix/primitives/accordion.pyi b/reflex/components/radix/primitives/accordion.pyi new file mode 100644 index 0000000000..119220e56b --- /dev/null +++ b/reflex/components/radix/primitives/accordion.pyi @@ -0,0 +1,619 @@ +"""Stub file for reflex/components/radix/primitives/accordion.py""" +# ------------------- DO NOT EDIT ---------------------- +# This file was generated by `scripts/pyi_generator.py`! +# ------------------------------------------------------ + +from typing import Any, Dict, Literal, Optional, Union, overload +from reflex.vars import Var, BaseVar, ComputedVar +from reflex.event import EventChain, EventHandler, EventSpec +from reflex.style import Style +from typing import Literal +from reflex.components.component import Component +from reflex.components.tags import Tag +from reflex.style import Style +from reflex.utils import format, imports +from reflex.vars import Var + +LiteralAccordionType = Literal["single", "multiple"] +LiteralAccordionDir = Literal["ltr", "rtl"] +LiteralAccordionOrientation = Literal["vertical", "horizontal"] +DEFAULT_ANIMATION_DURATION = 250 + +class AccordionComponent(Component): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionComponent": + """Create the component. + + Args: + *children: The children of the component. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class AccordionRoot(AccordionComponent): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + type_: Optional[ + Union[Var[Literal["single", "multiple"]], Literal["single", "multiple"]] + ] = None, + value: Optional[Union[Var[str], str]] = None, + default_value: Optional[Union[Var[str], str]] = None, + collapsible: Optional[Union[Var[bool], bool]] = None, + disabled: Optional[Union[Var[bool], bool]] = None, + dir: Optional[Union[Var[Literal["ltr", "rtl"]], Literal["ltr", "rtl"]]] = None, + orientation: Optional[ + Union[ + Var[Literal["vertical", "horizontal"]], + Literal["vertical", "horizontal"], + ] + ] = None, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionRoot": + """Create the component. + + Args: + *children: The children of the component. + type_: The type of accordion (single or multiple). + value: The value of the item to expand. + default_value: The default value of the item to expand. + collapsible: Whether or not the accordion is collapsible. + disabled: Whether or not the accordion is disabled. + dir: The reading direction of the accordion when applicable. + orientation: The orientation of the accordion. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class AccordionItem(AccordionComponent): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + value: Optional[Union[Var[str], str]] = None, + disabled: Optional[Union[Var[bool], bool]] = None, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionItem": + """Create the component. + + Args: + *children: The children of the component. + value: A unique identifier for the item. + disabled: When true, prevents the user from interacting with the item. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class AccordionHeader(AccordionComponent): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionHeader": + """Create the component. + + Args: + *children: The children of the component. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class AccordionTrigger(AccordionComponent): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionTrigger": + """Create the component. + + Args: + *children: The children of the component. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class AccordionContent(AccordionComponent): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + as_child: Optional[Union[Var[bool], bool]] = None, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "AccordionContent": + """Create the component. + + Args: + *children: The children of the component. + as_child: Change the default rendered element for the one passed as a child. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +class ChevronDownIcon(Component): + @overload + @classmethod + def create( # type: ignore + cls, + *children, + style: Optional[Style] = None, + key: Optional[Any] = None, + id: Optional[Any] = None, + class_name: Optional[Any] = None, + autofocus: Optional[bool] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, + on_blur: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_context_menu: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_double_click: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_focus: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_down: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_enter: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_leave: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_move: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_out: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_over: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_mouse_up: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_scroll: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + on_unmount: Optional[ + Union[EventHandler, EventSpec, list, function, BaseVar] + ] = None, + **props + ) -> "ChevronDownIcon": + """Create the component. + + Args: + *children: The children of the component. + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + class_name: The class name for the component. + autofocus: Whether the component should take the focus once the page is loaded + custom_attrs: custom attribute + **props: The props of the component. + + Returns: + The component. + + Raises: + TypeError: If an invalid child is passed. + """ + ... + +accordion_root = AccordionRoot.create +accordion_item = AccordionItem.create +accordion_trigger = AccordionTrigger.create +accordion_content = AccordionContent.create +accordion_header = AccordionHeader.create +chevron_down_icon = ChevronDownIcon.create + +def accordion(items: list[tuple[str, str]], **props) -> Component: ... diff --git a/reflex/components/radix/themes/typography.py b/reflex/components/radix/themes/typography.py new file mode 100644 index 0000000000..1464e99384 --- /dev/null +++ b/reflex/components/radix/themes/typography.py @@ -0,0 +1,141 @@ +"""Components for rendering text. + +https://www.radix-ui.com/themes/docs/theme/typography +""" +from __future__ import annotations + +from typing import Literal + +from reflex.vars import Var + +from .base import ( + CommonMarginProps, + LiteralAccentColor, + LiteralVariant, + RadixThemesComponent, +) + +LiteralTextWeight = Literal["light", "regular", "medium", "bold"] +LiteralTextAlign = Literal["left", "center", "right"] +LiteralTextSize = Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"] +LiteralTextTrim = Literal["normal", "start", "end", "both"] + + +class Text(CommonMarginProps, RadixThemesComponent): + """A foundational text primitive based on the element.""" + + tag = "Text" + + # Change the default rendered element for the one passed as a child, merging their props and behavior. + as_child: Var[bool] + + # Change the default rendered element into a semantically appropriate alternative (cannot be used with asChild) + as_: Var[str] + + # Text size: "1" - "9" + size: Var[LiteralTextSize] + + # Thickness of text: "light" | "regular" | "medium" | "bold" + weight: Var[LiteralTextWeight] + + # Alignment of text in element: "left" | "center" | "right" + align: Var[LiteralTextAlign] + + # Removes the leading trim space: "normal" | "start" | "end" | "both" + trim: Var[LiteralTextTrim] + + # Overrides the accent color inherited from the Theme. + color: Var[LiteralAccentColor] + + # Whether to render the text with higher contrast color + high_contrast: Var[bool] + + +class Heading(Text): + """A semantic heading element.""" + + tag = "Heading" + + +class Blockquote(CommonMarginProps, RadixThemesComponent): + """A block level extended quotation.""" + + tag = "Blockquote" + + # Text size: "1" - "9" + size: Var[LiteralTextSize] + + # Thickness of text: "light" | "regular" | "medium" | "bold" + weight: Var[LiteralTextWeight] + + # Overrides the accent color inherited from the Theme. + color: Var[LiteralAccentColor] + + # Whether to render the text with higher contrast color + high_contrast: Var[bool] + + +class Code(Blockquote): + """Marks text to signify a short fragment of computer code.""" + + tag = "Code" + + # The visual variant to apply: "solid" | "soft" | "outline" | "ghost" + variant: Var[LiteralVariant] + + +class Em(CommonMarginProps, RadixThemesComponent): + """Marks text to stress emphasis.""" + + tag = "Em" + + +class Kbd(CommonMarginProps, RadixThemesComponent): + """Represents keyboard input or a hotkey.""" + + tag = "Kbd" + + # Text size: "1" - "9" + size: Var[LiteralTextSize] + + +LiteralLinkUnderline = Literal["auto", "hover", "always"] + + +class Link(CommonMarginProps, RadixThemesComponent): + """A semantic element for navigation between pages.""" + + tag = "Link" + + # Change the default rendered element for the one passed as a child, merging their props and behavior. + as_child: Var[bool] + + # Text size: "1" - "9" + size: Var[LiteralTextSize] + + # Thickness of text: "light" | "regular" | "medium" | "bold" + weight: Var[LiteralTextWeight] + + # Removes the leading trim space: "normal" | "start" | "end" | "both" + trim: Var[LiteralTextTrim] + + # Sets the visibility of the underline affordance: "auto" | "hover" | "always" + underline: Var[LiteralLinkUnderline] + + # Overrides the accent color inherited from the Theme. + color: Var[LiteralAccentColor] + + # Whether to render the text with higher contrast color + high_contrast: Var[bool] + + +class Quote(CommonMarginProps, RadixThemesComponent): + """A short inline quotation.""" + + tag = "Quote" + + +class Strong(CommonMarginProps, RadixThemesComponent): + """Marks text to signify strong importance.""" + + tag = "Strong" diff --git a/reflex/vars.py b/reflex/vars.py index af02eb54de..49b395ac72 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -1284,6 +1284,29 @@ def upper(self) -> Var: _var_type=str, ) + def strip(self, other: str | Var[str] = " ") -> Var: + """Strip a string var. + + Args: + other: The string to strip the var with. + + Returns: + A var with the stripped string. + + Raises: + TypeError: If the var is not a string. + """ + if not types._issubclass(self._var_type, str): + raise TypeError(f"Cannot strip non-string var {self._var_full_name}.") + + other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other + + return self._replace( + _var_name=f"{self._var_name}.replace(/^${other._var_full_name}|${other._var_full_name}$/g, '')", + _var_is_string=False, + merge_var_data=other._var_data, + ) + def split(self, other: str | Var[str] = " ") -> Var: """Split a string var into a list.