diff --git a/demo/demo/demo.py b/demo/demo/demo.py index d884642..1443d37 100644 --- a/demo/demo/demo.py +++ b/demo/demo/demo.py @@ -3,65 +3,65 @@ import reflex as rx import reflex_ui as ui - +from .simple_icon import simple_icon_demo class State(rx.State): seed: int = 0 def index() -> rx.Component: - # Welcome Page (Index) return rx.el.div( - ui.tooltip( - ui.button( - ui.icon("SmileIcon"), - "Click me", - on_click=rx.toast.success( - "You are cool :)", - position="top-center", + # Left: Column of UI components + rx.el.div( + ui.tooltip( + ui.button( + ui.icon("SmileIcon"), + "Click me", + on_click=rx.toast.success( + "You are cool :)", + position="top-center", + ), ), + content="Seriously, click me", ), - content="Seriously, click me", - ), - ui.checkbox( - label="Click me", - on_checked_change=lambda value: rx.toast.success(f"Value: {value}"), - ), - ui.slider( - value=State.seed, - on_value_change=State.set_seed, - on_value_committed=lambda value: rx.toast.success(f"Value: {value}"), - class_name="max-w-xs", - ), - ui.gradient_profile( - seed=State.seed, - class_name="size-10", - ), - ui.switch( - on_checked_change=lambda value: rx.toast.success(f"Value: {value}"), + ui.checkbox( + label="Click me", + on_checked_change=lambda value: rx.toast.success(f"Value: {value}"), + ), + ui.slider( + value=State.seed, + on_value_change=State.set_seed, + on_value_committed=lambda value: rx.toast.success(f"Value: {value}"), + class_name="max-w-xs", + ), + ui.gradient_profile( + seed=State.seed, + class_name="size-10", + ), + ui.switch( + on_checked_change=lambda value: rx.toast.success(f"Value: {value}"), + ), + ui.select( + items=[f"Item {i}" for i in range(1, 11)], + name="select", + default_value="Select an item", + on_value_change=lambda value: rx.toast.success(f"Value: {value}"), + on_open_change=lambda value: rx.toast.success(f"Open: {value}"), + ), + class_name="flex flex-col gap-y-6 justify-center items-center", ), - ui.select( - items=[ - "Item 1", - "Item 2", - "Item 3", - "Item 4", - "Item 5", - "Item 6", - "Item 7", - "Item 8", - "Item 9", - "Item 10", - ], - name="select", - default_value="Select an item", - on_value_change=lambda value: rx.toast.success(f"Value: {value}"), - on_open_change=lambda value: rx.toast.success(f"Open: {value}"), + + # Right: Icon demo + rx.el.div( + simple_icon_demo(), + class_name="flex justify-center items-center", ), + + # Theme switcher (floating top-right) ui.theme_switcher(class_name="absolute top-4 right-4"), - class_name=ui.cn( - "flex flex-col gap-6 items-center justify-center h-screen", "bg-secondary-1" - ), + + # Parent container: center everything horizontally & vertically + class_name="flex flex-row gap-16 justify-center items-center h-screen bg-secondary-1 relative", ) diff --git a/demo/demo/simple_icon.py b/demo/demo/simple_icon.py new file mode 100644 index 0000000..b104bb8 --- /dev/null +++ b/demo/demo/simple_icon.py @@ -0,0 +1,41 @@ +import reflex as rx +import reflex_ui as ui + +def simple_icon_demo(): + icons = [ + "SiGithub", + "SiPytorch", + "SiPython", + "SiReact", + "SiDell", + "SiOkta", + "SiOpenai", + "SiDatabricks", + "SiDocker", + "SiLinux", + "SiVercel", + "SiNetlify" + ] + + # Define the pyramid shape (row lengths) + row_counts = [1, 2, 3, 4, 5, 4, 3, 2, 1] + + # Track the index in the icons list + index = 0 + rows = [] + + for count in row_counts: + row_icons = icons[index:index+count] + index += count + + rows.append( + rx.el.div( + *[ui.simple_icon(icon, size=48) for icon in row_icons], + class_name="flex justify-center gap-3 py-1" + ) + ) + + return rx.el.div( + *rows, + class_name="w-full h-screen flex flex-col items-center justify-center" + ) diff --git a/reflex_ui/__init__.py b/reflex_ui/__init__.py index 845dda8..f89268a 100644 --- a/reflex_ui/__init__.py +++ b/reflex_ui/__init__.py @@ -38,6 +38,7 @@ **_REFLEX_UI_MAPPING, "components": ["base"], "components.icons.hugeicon": ["hi", "icon"], + "components.icons.simple_icon": ["simple_icon"], "components.icons.others": ["spinner"], "utils.twmerge": ["cn"], } diff --git a/reflex_ui/__init__.pyi b/reflex_ui/__init__.pyi index 6d15ed9..27e0419 100644 --- a/reflex_ui/__init__.pyi +++ b/reflex_ui/__init__.pyi @@ -35,6 +35,7 @@ from .components.base.toggle_group import toggle_group from .components.base.tooltip import tooltip from .components.icons.hugeicon import hi, icon from .components.icons.others import spinner +from .components.icons.simple_icon import simple_icon from .utils.twmerge import cn _REFLEX_UI_MAPPING = { @@ -72,6 +73,7 @@ _SUBMOD_ATTRS = { **_REFLEX_UI_MAPPING, "components": ["base"], "components.icons.hugeicon": ["hi", "icon"], + "components.icons.simple_icon": ["simple_icon"], "components.icons.others": ["spinner"], "utils.twmerge": ["cn"], } @@ -101,6 +103,7 @@ __all__ = [ "preview_card", "scroll_area", "select", + "simple_icon", "skeleton", "slider", "spinner", diff --git a/reflex_ui/components/base/context_menu.pyi b/reflex_ui/components/base/context_menu.pyi index ef4f59a..2cb3e96 100644 --- a/reflex_ui/components/base/context_menu.pyi +++ b/reflex_ui/components/base/context_menu.pyi @@ -590,8 +590,8 @@ class ContextMenuRadioGroup(ContextMenuBaseComponent): on_scroll_end: EventType[()] | None = None, on_unmount: EventType[()] | None = None, on_value_change: EventType[()] - | EventType[str | int] - | EventType[str | int, dict] + | EventType[int | str] + | EventType[int | str, dict] | None = None, **props, ) -> ContextMenuRadioGroup: diff --git a/reflex_ui/components/base/menu.pyi b/reflex_ui/components/base/menu.pyi index 6ff476f..91bfc90 100644 --- a/reflex_ui/components/base/menu.pyi +++ b/reflex_ui/components/base/menu.pyi @@ -610,8 +610,8 @@ class MenuRadioGroup(MenuBaseComponent): on_scroll_end: EventType[()] | None = None, on_unmount: EventType[()] | None = None, on_value_change: EventType[()] - | EventType[str | int] - | EventType[str | int, dict] + | EventType[int | str] + | EventType[int | str, dict] | None = None, **props, ) -> MenuRadioGroup: diff --git a/reflex_ui/components/icons/hugeicon.pyi b/reflex_ui/components/icons/hugeicon.pyi index ddd00a5..4e95618 100644 --- a/reflex_ui/components/icons/hugeicon.pyi +++ b/reflex_ui/components/icons/hugeicon.pyi @@ -71,6 +71,7 @@ class HugeIcon(CoreComponent): Returns: The created component. + """ hi = icon = HugeIcon.create diff --git a/reflex_ui/components/icons/simple_icon.py b/reflex_ui/components/icons/simple_icon.py new file mode 100644 index 0000000..5a19688 --- /dev/null +++ b/reflex_ui/components/icons/simple_icon.py @@ -0,0 +1,42 @@ +"""Simple Icon component wrapper for @icons-pack/react-simple-icons.""" + +import reflex as rx +from reflex.utils.imports import ImportVar + + +class SimpleIcon(rx.Component): + """Simple Icon component wrapper for @icons-pack/react-simple-icons.""" + + library = "@icons-pack/react-simple-icons" + + tag = "SiReact" + + color: rx.Var[str] + size: rx.Var[int | str] + + @classmethod + def create(cls, icon_name: str, **props): + """Create a SimpleIcon component. + + Args: + icon_name: The icon component name (e.g., "SiReact", "SiGithub", "SiPython") + **props: Additional props like size, color + + Returns: + The component instance. + """ + instance = super().create(**props) + instance.tag = icon_name + return instance + + def add_imports(self): + """Add the specific icon import.""" + return { + self.library: ImportVar( + tag=self.tag, + is_default=False, + ) + } + + +simple_icon = SimpleIcon.create diff --git a/reflex_ui/components/icons/simple_icon.pyi b/reflex_ui/components/icons/simple_icon.pyi new file mode 100644 index 0000000..540d1d3 --- /dev/null +++ b/reflex_ui/components/icons/simple_icon.pyi @@ -0,0 +1,67 @@ +"""Stub file for reflex_ui/components/icons/simple_icon.py""" + +# ------------------- DO NOT EDIT ---------------------- +# This file was generated by `reflex/utils/pyi_generator.py`! +# ------------------------------------------------------ +from collections.abc import Mapping, Sequence +from typing import Any + +import reflex as rx +from reflex.components.core.breakpoints import Breakpoints +from reflex.event import EventType, PointerEventInfo +from reflex.vars.base import Var + +class SimpleIcon(rx.Component): + @classmethod + def create( + cls, + *children, + color: Var[str] | str | None = None, + size: Var[int | str] | int | str | None = None, + style: Sequence[Mapping[str, Any]] + | Mapping[str, Any] + | Var[Mapping[str, Any]] + | Breakpoints + | None = None, + key: Any | None = None, + id: Any | None = None, + ref: Var | None = None, + class_name: Any | None = None, + custom_attrs: dict[str, Var | Any] | None = None, + on_blur: EventType[()] | None = None, + on_click: EventType[()] | EventType[PointerEventInfo] | None = None, + on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None, + on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None, + on_focus: EventType[()] | None = None, + on_mount: EventType[()] | None = None, + on_mouse_down: EventType[()] | None = None, + on_mouse_enter: EventType[()] | None = None, + on_mouse_leave: EventType[()] | None = None, + on_mouse_move: EventType[()] | None = None, + on_mouse_out: EventType[()] | None = None, + on_mouse_over: EventType[()] | None = None, + on_mouse_up: EventType[()] | None = None, + on_scroll: EventType[()] | None = None, + on_scroll_end: EventType[()] | None = None, + on_unmount: EventType[()] | None = None, + **props, + ) -> SimpleIcon: + """Create a SimpleIcon component. + + Args: + icon_name: The icon component name (e.g., "SiReact", "SiGithub", "SiPython") + style: The style of the component. + key: A unique key for the component. + id: The id for the component. + ref: The Var to pass as the ref to the component. + class_name: The class name for the component. + custom_attrs: custom attribute + **props: Additional props like size, color + + Returns: + The component instance. + """ + + def add_imports(self): ... + +simple_icon = SimpleIcon.create