diff --git a/reflex/__init__.py b/reflex/__init__.py
index 52b59f571..956576ccf 100644
--- a/reflex/__init__.py
+++ b/reflex/__init__.py
@@ -4,6 +4,7 @@ Anything imported here will be available in the default Reflex import as `rx.*`.
To signal to typecheckers that something should be reexported,
we use the Flask "import name as name" syntax.
"""
+
from __future__ import annotations
import importlib
@@ -107,6 +108,9 @@ _ALL_COMPONENTS = [
"EditorOptions",
"icon",
"markdown",
+ "list_item",
+ "unordered_list",
+ "ordered_list",
]
_MAPPING = {
diff --git a/reflex/__init__.pyi b/reflex/__init__.pyi
index 977bcc698..8f66aeb85 100644
--- a/reflex/__init__.pyi
+++ b/reflex/__init__.pyi
@@ -90,6 +90,9 @@ from reflex.components import EditorButtonList as EditorButtonList
from reflex.components import EditorOptions as EditorOptions
from reflex.components import icon as icon
from reflex.components import markdown as markdown
+from reflex.components import list_item as list_item
+from reflex.components import unordered_list as unordered_list
+from reflex.components import ordered_list as ordered_list
from reflex.components.component import Component as Component
from reflex.components.component import NoSSRComponent as NoSSRComponent
from reflex.components.component import memo as memo
diff --git a/reflex/components/radix/themes/layout/__init__.py b/reflex/components/radix/themes/layout/__init__.py
index c6201f30a..ccc0b6f4c 100644
--- a/reflex/components/radix/themes/layout/__init__.py
+++ b/reflex/components/radix/themes/layout/__init__.py
@@ -5,6 +5,7 @@ from .center import Center
from .container import Container
from .flex import Flex
from .grid import Grid
+from .list import ListItem, OrderedList, UnorderedList
from .section import Section
from .spacer import Spacer
from .stack import HStack, Stack, VStack
@@ -19,6 +20,9 @@ spacer = Spacer.create
stack = Stack.create
hstack = HStack.create
vstack = VStack.create
+list_item = ListItem.create
+ordered_list = OrderedList.create
+unordered_list = UnorderedList.create
__all__ = [
"box",
@@ -31,4 +35,7 @@ __all__ = [
"stack",
"hstack",
"vstack",
+ "list_item",
+ "ordered_list",
+ "unordered_list",
]
diff --git a/reflex/components/radix/themes/layout/list.py b/reflex/components/radix/themes/layout/list.py
new file mode 100644
index 000000000..69c95acbe
--- /dev/null
+++ b/reflex/components/radix/themes/layout/list.py
@@ -0,0 +1,154 @@
+"""List components."""
+
+from types import SimpleNamespace
+from typing import Iterable, Literal, Optional, Union
+
+from reflex.components.component import Component
+from reflex.components.core.foreach import Foreach
+from reflex.components.el.elements.typography import Li
+from reflex.style import Style
+from reflex.vars import Var
+
+from .base import LayoutComponent
+from .flex import Flex
+
+# from reflex.vars import Var
+
+# from reflex.components.radix.themes.layout import LayoutComponent
+
+LiteralListStyleTypeUnordered = Literal[
+ "none",
+ "disc",
+ "circle",
+ "square",
+]
+
+LiteralListStyleTypeOrdered = Literal[
+ "none",
+ "decimal",
+ "decimal-leading-zero",
+ "lower-roman",
+ "upper-roman",
+ "lower-greek",
+ "lower-latin",
+ "upper-latin",
+ "armenian",
+ "georgian",
+ "lower-alpha",
+ "upper-alpha",
+ "hiragana",
+ "katakana",
+]
+
+
+class BaseList(Flex, LayoutComponent):
+ """Base class for ordered and unordered lists."""
+
+ @classmethod
+ def create(
+ cls,
+ *children,
+ items: Optional[Union[Var[Iterable], Iterable]] = None,
+ list_style_type: str = "",
+ **props,
+ ):
+ """Create a list component.
+
+ Args:
+ *children: The children of the component.
+ items: A list of items to add to the list.
+ list_style_type: The style of the list.
+ **props: The properties of the component.
+
+ Returns:
+ The list component.
+ """
+ if not children and items is not None:
+ if isinstance(items, Var):
+ children = [Foreach.create(items, ListItem.create)]
+ else:
+ children = [ListItem.create(item) for item in items]
+ props["list_style_type"] = list_style_type
+ props["direction"] = "column"
+ style = props.setdefault("style", {})
+ style["list_style_position"] = "outside"
+ if "gap" in props:
+ style["gap"] = props["gap"]
+ return super().create(*children, **props)
+
+ def _apply_theme(self, theme: Component):
+ self.style = Style(
+ {
+ "direction": "column",
+ "list_style_position": "outside",
+ **self.style,
+ }
+ )
+
+
+class UnorderedList(BaseList):
+ """Display an unordered list."""
+
+ @classmethod
+ def create(
+ cls,
+ *children,
+ items: Optional[Var[Iterable]] = None,
+ list_style_type: LiteralListStyleTypeUnordered = "disc",
+ **props,
+ ):
+ """Create a unordered list component.
+
+ Args:
+ *children: The children of the component.
+ items: A list of items to add to the list.
+ list_style_type: The style of the list.
+ **props: The properties of the component.
+
+ Returns:
+ The list component.
+ """
+ return super().create(
+ *children, items=items, list_style_type=list_style_type, **props
+ )
+
+
+class OrderedList(BaseList):
+ """Display an ordered list."""
+
+ @classmethod
+ def create(
+ cls,
+ *children,
+ items: Optional[Var[Iterable]] = None,
+ list_style_type: LiteralListStyleTypeOrdered = "decimal",
+ **props,
+ ):
+ """Create an ordered list component.
+
+ Args:
+ *children: The children of the component.
+ items: A list of items to add to the list.
+ list_style_type: The style of the list.
+ **props: The properties of the component.
+
+ Returns:
+ The list component.
+ """
+ return super().create(
+ *children, items=items, list_style_type=list_style_type, **props
+ )
+
+
+class ListItem(Li):
+ """Display an item of an ordered or unordered list."""
+
+ ...
+
+
+class List(SimpleNamespace):
+ """List components."""
+
+ item = ListItem.create
+ ordered = OrderedList.create
+ unordered = UnorderedList.create
diff --git a/reflex/components/radix/themes/layout/list.pyi b/reflex/components/radix/themes/layout/list.pyi
new file mode 100644
index 000000000..708cf8fca
--- /dev/null
+++ b/reflex/components/radix/themes/layout/list.pyi
@@ -0,0 +1,1065 @@
+"""Stub file for reflex/components/radix/themes/layout/list.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 types import SimpleNamespace
+from typing import Iterable, Literal, Optional, Union
+from reflex.components.component import Component
+from reflex.components.core.foreach import Foreach
+from reflex.components.el.elements.typography import Li
+from reflex.style import Style
+from reflex.vars import Var
+from .base import LayoutComponent
+from .flex import Flex
+
+LiteralListStyleTypeUnordered = Literal["none", "disc", "circle", "square"]
+LiteralListStyleTypeOrdered = Literal[
+ "none",
+ "decimal",
+ "decimal-leading-zero",
+ "lower-roman",
+ "upper-roman",
+ "lower-greek",
+ "lower-latin",
+ "upper-latin",
+ "armenian",
+ "georgian",
+ "lower-alpha",
+ "upper-alpha",
+ "hiragana",
+ "katakana",
+]
+
+class BaseList(Flex, LayoutComponent):
+ @overload
+ @classmethod
+ def create( # type: ignore
+ cls,
+ *children,
+ items: Optional[Union[Union[Var[Iterable], Iterable], Iterable]] = None,
+ list_style_type: Optional[str] = "",
+ as_child: Optional[Union[Var[bool], bool]] = None,
+ display: Optional[
+ Union[
+ Var[Literal["none", "inline-flex", "flex"]],
+ Literal["none", "inline-flex", "flex"],
+ ]
+ ] = None,
+ direction: Optional[
+ Union[
+ Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+ Literal["row", "column", "row-reverse", "column-reverse"],
+ ]
+ ] = None,
+ align: Optional[
+ Union[
+ Var[Literal["start", "center", "end", "baseline", "stretch"]],
+ Literal["start", "center", "end", "baseline", "stretch"],
+ ]
+ ] = None,
+ justify: Optional[
+ Union[
+ Var[Literal["start", "center", "end", "between"]],
+ Literal["start", "center", "end", "between"],
+ ]
+ ] = None,
+ wrap: Optional[
+ Union[
+ Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+ Literal["nowrap", "wrap", "wrap-reverse"],
+ ]
+ ] = None,
+ gap: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ access_key: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ auto_capitalize: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ content_editable: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ context_menu: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+ draggable: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ enter_key_hint: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ hidden: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ input_mode: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ item_prop: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+ role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+ slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+ spell_check: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ tab_index: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ title: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ translate: Optional[
+ Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+ ] = None,
+ p: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ px: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ py: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ pt: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ pr: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ pb: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ pl: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+ grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+ m: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ mx: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ my: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ mt: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ mr: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ mb: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ ml: Optional[
+ Union[
+ Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+ Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ ]
+ ] = None,
+ style: Optional[Style] = None,
+ key: Optional[Any] = None,
+ id: Optional[Any] = None,
+ class_name: Optional[Any] = None,
+ autofocus: Optional[bool] = None,
+ _rename_props: Optional[Dict[str, str]] = 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
+ ) -> "BaseList":
+ """Create a list component.
+
+ Args:
+ *children: The children of the component.
+ items: A list of items to add to the list.
+ list_style_type: The style of the list.
+ as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+ display: How to display the element: "none" | "inline-flex" | "flex"
+ direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+ align: Alignment of children along the main axis: "start" | "center" | "end" | "baseline" | "stretch"
+ justify: Alignment of children along the cross axis: "start" | "center" | "end" | "between"
+ wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+ gap: Gap between children: "0" - "9"
+ access_key: Provides a hint for generating a keyboard shortcut for the current element.
+ auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+ content_editable: Indicates whether the element's content is editable.
+ context_menu: Defines the ID of a