Kaynağa Gözat

add docs from reflex-web

Lendemor 1 yıl önce
ebeveyn
işleme
dbd074c33d
100 değiştirilmiş dosya ile 8518 ekleme ve 0 silme
  1. 0 0
      docs/__init__.py
  2. 214 0
      docs/api-reference/browser_javascript.md
  3. 191 0
      docs/api-reference/browser_storage.md
  4. 90 0
      docs/api-reference/cli.md
  5. 263 0
      docs/api-reference/event_triggers.md
  6. 93 0
      docs/api-reference/special_events.md
  7. 43 0
      docs/api-routes/overview.md
  8. 42 0
      docs/assets/referencing_assets.md
  9. 89 0
      docs/assets/upload_and_download_files.md
  10. 34 0
      docs/client_storage/overview.md
  11. 25 0
      docs/components/conditional_props.md
  12. 269 0
      docs/components/conditional_rendering.md
  13. 81 0
      docs/components/props.md
  14. 197 0
      docs/components/rendering_iterables.md
  15. 25 0
      docs/components/style_props.md
  16. 75 0
      docs/database/overview.md
  17. 186 0
      docs/database/queries.md
  18. 162 0
      docs/database/relationships.md
  19. 70 0
      docs/database/tables.md
  20. 0 0
      docs/datatable_tutorial/__init__.py
  21. 223 0
      docs/datatable_tutorial/add_interactivity.md
  22. 141 0
      docs/datatable_tutorial/add_styling.md
  23. 328 0
      docs/datatable_tutorial/datatable_tutorial_utils.py
  24. 108 0
      docs/datatable_tutorial/live_stream.md
  25. 87 0
      docs/datatable_tutorial/simple_table.md
  26. 175 0
      docs/events/background_events.md
  27. 90 0
      docs/events/chaining_events.md
  28. 34 0
      docs/events/event_arguments.md
  29. 41 0
      docs/events/events_overview.md
  30. 21 0
      docs/events/page_load_events.md
  31. 52 0
      docs/events/setters.md
  32. 20 0
      docs/events/special_events.md
  33. 63 0
      docs/events/yield_events.md
  34. 91 0
      docs/getting-started/configuration.md
  35. 147 0
      docs/getting-started/installation.md
  36. 226 0
      docs/getting-started/introduction.md
  37. 66 0
      docs/getting-started/project-structure.md
  38. 69 0
      docs/hosting/deploy-quick-start.md
  39. 354 0
      docs/hosting/hosting-cli-commands.md
  40. 121 0
      docs/hosting/self-hosting.md
  41. 44 0
      docs/library/chakra/datadisplay/badge.md
  42. 34 0
      docs/library/chakra/datadisplay/divider.md
  43. 68 0
      docs/library/chakra/datadisplay/list.md
  44. 41 0
      docs/library/chakra/datadisplay/stat.md
  45. 142 0
      docs/library/chakra/datadisplay/table.md
  46. 103 0
      docs/library/chakra/disclosure/accordion.md
  47. 48 0
      docs/library/chakra/disclosure/tabs.md
  48. 70 0
      docs/library/chakra/feedback/alert.md
  49. 26 0
      docs/library/chakra/feedback/circularprogress.md
  50. 24 0
      docs/library/chakra/feedback/progress.md
  51. 54 0
      docs/library/chakra/feedback/skeleton.md
  52. 38 0
      docs/library/chakra/feedback/spinner.md
  53. 375 0
      docs/library/chakra/forms/button.md
  54. 150 0
      docs/library/chakra/forms/buttongroup.md
  55. 69 0
      docs/library/chakra/forms/checkbox.md
  56. 48 0
      docs/library/chakra/forms/editable.md
  57. 110 0
      docs/library/chakra/forms/form.md
  58. 51 0
      docs/library/chakra/forms/formcontrol.md
  59. 110 0
      docs/library/chakra/forms/input.md
  60. 28 0
      docs/library/chakra/forms/numberinput.md
  61. 45 0
      docs/library/chakra/forms/pininput.md
  62. 74 0
      docs/library/chakra/forms/radiogroup.md
  63. 45 0
      docs/library/chakra/forms/rangeslider.md
  64. 86 0
      docs/library/chakra/forms/select.md
  65. 100 0
      docs/library/chakra/forms/slider.md
  66. 48 0
      docs/library/chakra/forms/switch.md
  67. 30 0
      docs/library/chakra/forms/textarea.md
  68. 27 0
      docs/library/chakra/layout/aspectratio.md
  69. 46 0
      docs/library/chakra/layout/box.md
  70. 25 0
      docs/library/chakra/layout/card.md
  71. 43 0
      docs/library/chakra/layout/center.md
  72. 20 0
      docs/library/chakra/layout/container.md
  73. 33 0
      docs/library/chakra/layout/flex.md
  74. 43 0
      docs/library/chakra/layout/grid.md
  75. 39 0
      docs/library/chakra/layout/responsivegrid.md
  76. 23 0
      docs/library/chakra/layout/spacer.md
  77. 36 0
      docs/library/chakra/layout/stack.md
  78. 27 0
      docs/library/chakra/layout/wrap.md
  79. 62 0
      docs/library/chakra/media/avatar.md
  80. 44 0
      docs/library/chakra/media/icon.md
  81. 54 0
      docs/library/chakra/media/image.md
  82. 36 0
      docs/library/chakra/navigation/breadcrumb.md
  83. 41 0
      docs/library/chakra/navigation/link.md
  84. 18 0
      docs/library/chakra/navigation/linkoverlay.md
  85. 45 0
      docs/library/chakra/overlay/alertdialog.md
  86. 70 0
      docs/library/chakra/overlay/drawer.md
  87. 31 0
      docs/library/chakra/overlay/menu.md
  88. 42 0
      docs/library/chakra/overlay/modal.md
  89. 32 0
      docs/library/chakra/overlay/popover.md
  90. 20 0
      docs/library/chakra/overlay/tooltip.md
  91. 36 0
      docs/library/chakra/typography/heading.md
  92. 20 0
      docs/library/chakra/typography/highlight.md
  93. 21 0
      docs/library/chakra/typography/span.md
  94. 27 0
      docs/library/chakra/typography/text.md
  95. 145 0
      docs/library/datadisplay/avatar.md
  96. 128 0
      docs/library/datadisplay/badge.md
  97. 140 0
      docs/library/datadisplay/callout-ll.md
  98. 96 0
      docs/library/datadisplay/callout.md
  99. 25 0
      docs/library/datadisplay/codeblock.md
  100. 356 0
      docs/library/datadisplay/data_editor.md

+ 0 - 0
docs/__init__.py


+ 214 - 0
docs/api-reference/browser_javascript.md

@@ -0,0 +1,214 @@
+```python exec
+import asyncio
+from typing import Any
+import reflex as rx
+from pcweb.pages.docs import wrapping_react
+from pcweb.pages.docs import library
+```
+
+# Browser Javascript
+
+Reflex compiles your frontend code, defined as python functions, into a Javascript web application
+that runs in the user's browser. There are instances where you may need to supply custom javascript
+code to interop with Web APIs, use certain third-party libraries, or wrap low-level functionality
+that is not exposed via Reflex's Python API.
+
+```md alert
+# Avoid Custom Javascript
+
+Custom Javascript code in your Reflex app presents a maintenance challenge, as it will be harder to debug and may be unstable across Reflex versions.
+
+Prefer to use the Python API whenever possible and file an issue if you need additional functionality that is not currently provided.
+```
+
+## Executing Script
+
+There are four ways to execute custom Javascript code into your Reflex app:
+
+* `rx.script` - Injects the script via `next/script` for efficient loading of inline and external Javascript code. Described further in the [component library]({library.other.script.path}).
+  * These components can be directly included in the body of a page, or they may
+    be passed to `rx.App(head_components=[rx.script(...)])` to be included in
+    the `<Head>` tag of all pages.
+* `rx.call_script` - An event handler that evaluates arbitrary Javascript code,
+  and optionally returns the result to another event handler.
+
+These previous two methods can work in tandem to load external scripts and then
+call functions defined within them in response to user events.
+
+The following two methods are geared towards wrapping components and are
+described with examples in the [Wrapping React]({wrapping_react.overview.path})
+section.
+
+* `_get_hooks` and `_get_custom_code` in an `rx.Component` subclass
+* `Var.create` with `_var_is_local=False`
+
+## Inline Scripts
+
+The `rx.script` component is the recommended way to load inline Javascript for greater control over
+frontend behavior.
+
+The functions and variables in the script can be accessed from backend event
+handlers or frontend event triggers via the `rx.call_script` interface.
+
+```python demo exec
+class SoundEffectState(rx.State):
+    @rx.background
+    async def delayed_play(self):
+        await asyncio.sleep(1)
+        return rx.call_script("playFromStart(button_sfx)")
+
+
+def sound_effect_demo():
+    return rx.hstack(
+        rx.script("""
+            var button_sfx = new Audio("/vintage-button-sound-effect.mp3")
+            function playFromStart (sfx) {sfx.load(); sfx.play()}"""), 
+        rx.button("Play Immediately", on_click=rx.call_script("playFromStart(button_sfx)")),
+        rx.button("Play Later", on_click=SoundEffectState.delayed_play),
+    )
+```
+
+## External Scripts
+
+External scripts can be loaded either from the `assets` directory, or from CDN URL, and then controlled
+via `rx.call_script`.
+
+```python demo
+rx.vstack(
+    rx.script(
+        src="https://cdn.jsdelivr.net/gh/scottschiller/snowstorm@snowstorm_20131208/snowstorm-min.js",
+        on_ready=rx.call_script("snowStorm.autoStart = false; snowStorm.snowColor = '#111'"),
+    ),
+    rx.button("Start Duststorm", on_click=rx.call_script("snowStorm.start()")),
+    rx.button("Toggle Duststorm", on_click=rx.call_script("snowStorm.toggleSnow()")),
+)
+```
+
+## Accessing Client Side Values
+
+The `rx.call_script` function accepts a `callback` parameter that expects an
+Event Handler with one argument which will receive the result of evaluating the
+Javascript code. This can be used to access client-side values such as the
+`window.location` or current scroll location, or any previously defined value.
+
+```python demo exec
+class WindowState(rx.State):
+    location: dict[str, str] = {}
+    scroll_position: dict[str, int] = {}
+
+    def update_location(self, location):
+        self.location = location
+
+    def update_scroll_position(self, scroll_position):
+        self.scroll_position = {
+            "x": scroll_position[0],
+            "y": scroll_position[1],
+        }
+
+    def get_client_values(self):
+        return [
+            rx.call_script(
+                "window.location",
+                callback=WindowState.update_location
+            ),
+            rx.call_script(
+                "[window.scrollX, window.scrollY]",
+                callback=WindowState.update_scroll_position,
+            ),
+        ]
+
+
+def window_state_demo():
+    return rx.vstack(
+        rx.button("Update Values", on_click=WindowState.get_client_values),
+        rx.text(f"Scroll Position: {WindowState.scroll_position.to_string()}"),
+        rx.text("window.location:"),
+        rx.text_area(value=WindowState.location.to_string(), is_read_only=True),
+        on_mount=WindowState.get_client_values,
+    )
+```
+
+```md alert
+# Allowed Callback Values
+
+The `callback` parameter may be an `EventHandler` with one argument, or a lambda with one argument that returns an `EventHandler`.
+If the callback is None, then no event is triggered.
+```
+
+## Using React Hooks
+
+To use React Hooks directly in a Reflex app, you must subclass `rx.Component`,
+typically `rx.Fragment` is used when the hook functionality has no visual
+element. The hook code is returned by the `_get_hooks` method, which is expected
+to return a `str` containing Javascript code which will be inserted into the
+page component (i.e the render function itself).
+
+For supporting code that must be defined outside of the component render
+function, use `_get_custom_code`.
+
+The following example uses `useEffect` to register global hotkeys on the
+`document` object, and then triggers an event when a specific key is pressed.
+
+```python demo exec
+class GlobalKeyState(rx.State):
+    key: str = ""
+
+    def update_key(self, key):
+        self.key = key
+
+
+class GlobalKeyWatcher(rx.Fragment):
+    # List of keys to trigger on
+    keys: rx.vars.Var[list[str]] = []
+
+    def _get_imports(self) -> rx.utils.imports.ImportDict:
+        return rx.utils.imports.merge_imports(
+            super()._get_imports(),
+            {
+                "react": {rx.utils.imports.ImportVar(tag="useEffect")}
+            },
+        )
+
+    def _get_hooks(self) -> str | None:
+        return """
+            useEffect(() => {
+                const handle_key = (_e0) => {
+                    if (%s.includes(_e0.key))
+                        %s
+                }
+                document.addEventListener("keydown", handle_key, false);
+                return () => {
+                    document.removeEventListener("keydown", handle_key, false);
+                }
+            })
+            """ % (
+                self.keys,
+                rx.utils.format.format_event_chain(self.event_triggers["on_key_down"]),
+            )
+
+    def get_event_triggers(self) -> dict[str, Any]:
+        return {
+            "on_key_down": lambda e0: [e0.key],
+        }
+
+    def render(self):
+        return ""  # No visual element, hooks only
+
+
+def global_key_demo():
+    return rx.vstack(
+        GlobalKeyWatcher.create(
+            keys=["a", "s", "d", "w"],
+            on_key_down=GlobalKeyState.update_key,
+        ),
+        rx.text("Press a, s, d or w to trigger an event"),
+        rx.heading(f"Last watched key pressed: {GlobalKeyState.key}"),
+    )
+```
+
+```md alert
+# rx.utils.format.format_event_chain?
+
+The `format_event_chain` function is used to format an event trigger defined on the component via `get_event_triggers` into a Javascript expression that can be used to actually trigger the event.
+The Javascript code should do minimal work, preferring to hand off execution to a user-supplied python `EventHandler` for processing on the backend.
+```

+ 191 - 0
docs/api-reference/browser_storage.md

@@ -0,0 +1,191 @@
+# Browser Storage
+
+## rx.Cookie
+
+Represents a state Var that is stored as a cookie in the browser. Currently only supports string values.
+
+ Parameters
+
+- `name` : The name of the cookie on the client side.
+- `path`: The cookie path. Use `/` to make the cookie accessible on all pages.
+- `max_age` : Relative max age of the cookie in seconds from when the client receives it.
+- `domain`: Domain for the cookie (e.g., `sub.domain.com` or `.allsubdomains.com`).
+- `secure`: If the cookie is only accessible through HTTPS.
+- `same_site`: Whether the cookie is sent with third-party requests. Can be one of (`True`, `False`, `None`, `lax`, `strict`).
+
+```python
+class CookieState(rx.State):
+    c1: str = rx.Cookie()
+    c2: str = rx.Cookie('c2 default')
+
+    # cookies with custom settings
+    c3: str = rx.Cookie(max_age=2)  # expires after 2 second
+    c4: str = rx.Cookie(same_site='strict')
+    c5: str = rx.Cookie(path='/foo/')  # only accessible on `/foo/`
+    c6: str = rx.Cookie(name='c6-custom-name')
+```
+
+## rx.remove_cookies
+
+Remove a cookie from the client's browser.
+
+Parameters:
+
+- `key`: The name of cookie to remove.
+
+```python
+rx.button(
+    'Remove cookie', on_click=rx.remove_cookie('key')
+)
+```
+
+This event can also be returned from an event handler:
+
+```python
+class CookieState(rx.State):
+    ...
+    def logout(self):
+        return rx.remove_cookie('auth_token')
+```
+
+## rx.LocalStorage
+
+Represents a state Var that is stored in localStorage in the browser. Currently only supports string values.
+
+Parameters
+
+- `name`: The name of the storage key on the client side.
+
+```python
+class LocalStorageState(rx.State):
+    # local storage with default settings
+    l1: str = rx.LocalStorage()
+
+    # local storage with custom settings
+    l2: str = rx.LocalStorage("l2 default")
+    l3: str = rx.LocalStorage(name="l3")
+```
+
+## rx.remove_local_storage
+
+Remove a local storage item from the client's browser.
+
+Parameters
+
+- `key`: The key to remove from local storage.
+
+```python
+rx.button(
+    'Remove Local Storage',
+    on_click=rx.remove_local_storage('key'),
+)
+```
+
+This event can also be returned from an event handler:
+
+```python
+class LocalStorageState(rx.State):
+    ...
+    def logout(self):
+        return rx.remove_local_storage('local_storage_state.l1')
+```
+
+## rx.clear_local_storage()
+
+Clear all local storage items from the client's browser. This may affect other
+apps running in the same domain or libraries within your app that use local
+storage.
+
+```python
+rx.button(
+    'Clear all Local Storage',
+    on_click=rx.clear_local_storage(),
+)
+```
+
+# Serialization Strategies
+
+If a non-trivial data structure should be stored in a `Cookie` or `LocalStorage` var it needs to
+be serialized before and after storing it. It is recommended to use `rx.Base` for the data
+which provides simple serialization helpers and works recursively in complex object structures.
+
+```python demo exec
+import reflex as rx
+
+
+class AppSettings(rx.Base):
+    theme: str = 'light'
+    sidebar_visible: bool = True
+    update_frequency: int = 60
+    error_messages: list[str] = []
+
+
+class ComplexLocalStorageState(rx.State):
+    data_raw: str = rx.LocalStorage("{}")
+    data: AppSettings = AppSettings()
+    settings_open: bool = False
+
+    def save_settings(self):
+        self.data_raw = self.data.json()
+        self.settings_open = False
+
+    def open_settings(self):
+        self.data = AppSettings.parse_raw(self.data_raw)
+        self.settings_open = True
+
+    def set_field(self, field, value):
+        setattr(self.data, field, value)
+
+
+def app_settings():
+    return rx.chakra.form(
+        rx.foreach(
+            ComplexLocalStorageState.data.error_messages,
+            rx.text,
+        ),
+        rx.chakra.form_label(
+            "Theme",
+            rx.chakra.input(
+                value=ComplexLocalStorageState.data.theme,
+                on_change=lambda v: ComplexLocalStorageState.set_field("theme", v),
+            ),
+        ),
+        rx.chakra.form_label(
+            "Sidebar Visible",
+            rx.chakra.switch(
+                is_checked=ComplexLocalStorageState.data.sidebar_visible,
+                on_change=lambda v: ComplexLocalStorageState.set_field(
+                    "sidebar_visible",
+                    v,
+                ),
+            ),
+        ),
+        rx.chakra.form_label(
+            "Update Frequency (seconds)",
+            rx.chakra.number_input(
+                value=ComplexLocalStorageState.data.update_frequency,
+                on_change=lambda v: ComplexLocalStorageState.set_field(
+                    "update_frequency",
+                    v,
+                ),
+            ),
+        ),
+        rx.button("Save", type="submit"),
+        on_submit=lambda _: ComplexLocalStorageState.save_settings(),
+    )
+
+def app_settings_example():
+    return rx.fragment(
+        rx.chakra.modal(
+            rx.chakra.modal_overlay(
+                rx.chakra.modal_content(
+                    rx.chakra.modal_header("App Settings"),
+                    rx.chakra.modal_body(app_settings()),
+                ),
+            ),
+            is_open=ComplexLocalStorageState.settings_open,
+            on_close=ComplexLocalStorageState.set_settings_open(False),
+        ),
+        rx.button("App Settings", on_click=ComplexLocalStorageState.open_settings),
+    )
+```

+ 90 - 0
docs/api-reference/cli.md

@@ -0,0 +1,90 @@
+# CLI
+
+The `reflex` command line interface (CLI) is a tool for creating and managing Reflex apps.
+
+To see a list of all available commands, run `reflex --help`.
+
+```bash
+$ reflex --help
+
+Usage: reflex [OPTIONS] COMMAND [ARGS]...
+
+  Reflex CLI to create, run, and deploy apps.
+
+Options:
+  -v, --version  Get the Reflex version.
+  --help         Show this message and exit.
+
+Commands:
+  db           Subcommands for managing the database schema.
+  demo         Run the demo app.
+  deploy       Deploy the app to the Reflex hosting service.
+  deployments  Subcommands for managing the Deployments.
+  export       Export the app to a zip file.
+  init         Initialize a new Reflex app in the current directory.
+  login        Authenticate with Reflex hosting service.
+  logout       Log out of access to Reflex hosting service.
+  run          Run the app in the current directory.
+```
+
+## Init
+
+The `reflex init` command creates a new Reflex app in the current directory.
+If an `rxconfig.py` file already exists already, it will re-initialize the app with the latest template.
+
+```bash
+$ reflex init --help
+Usage: reflex init [OPTIONS]
+
+  Initialize a new Reflex app in the current directory.
+
+Options:
+  --name APP_NAME                 The name of the app to initialize.
+  --template [demo|sidebar|blank]
+                                  The template to initialize the app with.
+  --loglevel [debug|info|warning|error|critical]
+                                  The log level to use.  [default:
+                                  LogLevel.INFO]
+  --help                          Show this message and exit.
+```
+
+## Run
+
+The `reflex run` command runs the app in the current directory.
+
+By default it runs your app in development mode.
+This means that the app will automatically reload when you make changes to the code.
+You can also run in production mode which will create an optimized build of your app.
+
+You can configure the mode, as well as other options through flags.
+
+```bash
+$ reflex run --help
+Usage: reflex run [OPTIONS]
+
+  Run the app in the current directory.
+
+Options:
+  --env [dev|prod]                The environment to run the app in.
+                                  [default: Env.DEV]
+  --frontend-only                 Execute only frontend.
+  --backend-only                  Execute only backend.
+  --frontend-port TEXT            Specify a different frontend port.
+                                  [default: 3000]
+  --backend-port TEXT             Specify a different backend port.  [default:
+                                  8000]
+  --backend-host TEXT             Specify the backend host.  [default:
+                                  0.0.0.0]
+  --loglevel [debug|info|warning|error|critical]
+                                  The log level to use.  [default:
+                                  LogLevel.INFO]
+  --help                          Show this message and exit.
+```
+
+## Export
+
+You can export your app's frontend and backend to zip files using the `reflex export` command.
+
+The frontend is a compiled NextJS app, which can be deployed to a static hosting service like Github Pages or Vercel.
+However this is just a static build, so you will need to deploy the backend separately.
+See the self-hosting guide for more information.

+ 263 - 0
docs/api-reference/event_triggers.md

@@ -0,0 +1,263 @@
+```python exec
+from datetime import datetime
+
+import reflex as rx
+
+from pcweb.templates.docpage import docdemo, h1_comp, text_comp, docpage
+
+SYNTHETIC_EVENTS = [
+    {
+        "name": "on_focus",
+        "description": "The on_focus event handler is called when the element (or some element inside of it) receives focus. For example, it’s called when the user clicks on a text input.",
+        "state": """class FocusState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self, text):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.chakra.input(value = FocusState.text, on_focus=FocusState.change_text)""",
+    },
+    {
+        "name": "on_blur",
+        "description": "The on_blur event handler is called when focus has left the element (or left some element inside of it). For example, it’s called when the user clicks outside of a focused text input.",
+        "state": """class BlurState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self, text):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.chakra.input(value = BlurState.text, on_blur=BlurState.change_text)""",
+    },
+    {
+        "name": "on_change",
+        "description": "The on_change event handler is called when the value of an element has changed. For example, it’s called when the user types into a text input each keystoke triggers the on change.",
+        "state": """class ChangeState(rx.State):
+    checked: bool = False
+
+""",
+        "example": """rx.switch(on_change=ChangeState.set_checked)""",
+    },
+    {
+        "name": "on_click",
+        "description": "The on_click event handler is called when the user clicks on an element. For example, it’s called when the user clicks on a button.",
+        "state": """class ClickState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(ClickState.text, on_click=ClickState.change_text)""",
+    },
+    {
+        "name": "on_context_menu",
+        "description": "The on_context_menu event handler is called when the user right-clicks on an element. For example, it’s called when the user right-clicks on a button.",
+        "state": """class ContextState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(ContextState.text, on_context_menu=ContextState.change_text)""",
+    },
+    {
+        "name": "on_double_click",
+        "description": "The on_double_click event handler is called when the user double-clicks on an element. For example, it’s called when the user double-clicks on a button.",
+        "state": """class DoubleClickState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(DoubleClickState.text, on_double_click=DoubleClickState.change_text)""",
+    },
+    {
+        "name": "on_mount",
+        "description": "The on_mount event handler is called after the component is rendered on the page. It is similar to a page on_load event, although it does not necessarily fire when navigating between pages.",
+        "state": """class MountState(rx.State):
+    events: list[str] = []
+
+    def on_mount(self):
+        self.events = self.events[-4:] + ["on_mount @ " + str(datetime.now())]
+""",
+        "example": """rx.vstack(rx.foreach(MountState.events, rx.text), on_mount=MountState.on_mount)""",
+    },
+    {
+        "name": "on_unmount",
+        "description": "The on_unmount event handler is called after removing the component from the page. However, on_unmount will only be called for internal navigation, not when following external links or refreshing the page.",
+        "state": """class UnmountState(rx.State):
+    events: list[str] = []
+
+    def on_unmount(self):
+        self.events = self.events[-4:] + ["on_unmount @ " + str(datetime.now())]
+""",
+        "example": """rx.vstack(rx.foreach(UnmountState.events, rx.text), on_unmount=UnmountState.on_unmount)""",
+    },
+    {
+        "name": "on_mouse_up",
+        "description": "The on_mouse_up event handler is called when the user releases a mouse button on an element. For example, it’s called when the user releases the left mouse button on a button.",
+        "state": """class MouseUpState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseUpState.text, on_mouse_up=MouseUpState.change_text)""",
+    },
+    {
+        "name": "on_mouse_down",
+        "description": "The on_mouse_down event handler is called when the user presses a mouse button on an element. For example, it’s called when the user presses the left mouse button on a button.",
+        "state": """class MouseDown(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseDown.text, on_mouse_down=MouseDown.change_text)""",
+    },
+    {
+        "name": "on_mouse_enter",
+        "description": "The on_mouse_enter event handler is called when the user’s mouse enters an element. For example, it’s called when the user’s mouse enters a button.",
+        "state": """class MouseEnter(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseEnter.text, on_mouse_enter=MouseEnter.change_text)""",
+    },
+    {
+        "name": "on_mouse_leave",
+        "description": "The on_mouse_leave event handler is called when the user’s mouse leaves an element. For example, it’s called when the user’s mouse leaves a button.",
+        "state": """class MouseLeave(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseLeave.text, on_mouse_leave=MouseLeave.change_text)""",
+    },
+    {
+        "name": "on_mouse_move",
+        "description": "The on_mouse_move event handler is called when the user moves the mouse over an element. For example, it’s called when the user moves the mouse over a button.",
+        "state": """class MouseMove(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseMove.text, on_mouse_move=MouseMove.change_text)""",
+    },
+    {
+        "name": "on_mouse_out",
+        "description": "The on_mouse_out event handler is called when the user’s mouse leaves an element. For example, it’s called when the user’s mouse leaves a button.",
+        "state": """class MouseOut(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseOut.text, on_mouse_out=MouseOut.change_text)""",
+    },
+    {
+        "name": "on_mouse_over",
+        "description": "The on_mouse_over event handler is called when the user’s mouse enters an element. For example, it’s called when the user’s mouse enters a button.",
+        "state": """class MouseOver(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.button(MouseOver.text, on_mouse_over=MouseOver.change_text)""",
+    },
+    {
+        "name": "on_scroll",
+        "description": "The on_scroll event handler is called when the user scrolls the page. For example, it’s called when the user scrolls the page down.",
+        "state": """class ScrollState(rx.State):
+    text = "Change Me!"
+
+    def change_text(self):
+        if self.text == "Change Me!":
+            self.text = "Changed!"
+        else:
+            self.text = "Change Me!"
+""",
+        "example": """rx.vstack(
+            rx.text("Scroll to make the text below change."),
+            rx.text(ScrollState.text),
+            rx.text("Scroll to make the text above change."),
+            on_scroll=ScrollState.change_text,
+            overflow = "auto",
+            height = "3em",
+            width = "100%",
+        )""",
+    },
+]
+for i in SYNTHETIC_EVENTS:
+    exec(i["state"])
+
+def component_grid():
+    events = []
+    for event in SYNTHETIC_EVENTS:
+        events.append(
+            rx.vstack(
+                h1_comp(text=event["name"]),
+                text_comp(text=event["description"]),
+                docdemo(
+                    event["example"], state=event["state"], comp=eval(event["example"])
+                ),
+                align_items="left",
+            )
+        )
+
+    return rx.box(*events)
+```
+
+# Event Triggers
+
+Components can modify the state based on user events such as clicking a button or entering text in a field.
+These events are triggered by event triggers.
+
+Event triggers are component specific and are listed in the documentation for each component.
+
+```python eval
+rx.box(
+     rx.chakra.divider(),
+    component_grid(),
+)
+```

+ 93 - 0
docs/api-reference/special_events.md

@@ -0,0 +1,93 @@
+```python exec
+import reflex as rx
+```
+
+# Special Events
+
+Reflex includes a set of built-in special events that can be utilized as event triggers
+or returned from event handlers in your applications. These events enhance interactivity and user experience.
+Below are the special events available in Reflex, along with explanations of their functionality:
+
+## rx.console_log
+
+Perform a console.log in the browser's console.
+
+```python demo
+rx.button('Log', on_click=rx.console_log('Hello World!'))
+```
+
+When triggered, this event logs a specified message to the browser's developer console.
+It's useful for debugging and monitoring the behavior of your application.
+
+## rx.redirect
+
+Redirect the user to a new path within the application.
+
+### Parameters
+
+- `path`: The destination path or URL to which the user should be redirected.
+- `external`: If set to True, the redirection will open in a new tab. Defaults to `False`.
+
+```python demo
+rx.vstack(
+    rx.button("open in tab", on_click=rx.redirect("/docs/api-reference/special-events")),
+    rx.button("open in new tab", on_click=rx.redirect('https://github.com/reflex-dev/reflex/', external=True))
+)
+```
+
+When this event is triggered, it navigates the user to a different page or location within your Reflex application.
+By default, the redirection occurs in the same tab. However, if you set the external parameter to True, the redirection
+will open in a new tab or window, providing a seamless user experience.
+
+## rx.set_clipboard
+
+Set the specified text content to the clipboard.
+
+```python demo
+rx.button('Copy "Hello World" to clipboard',on_click=rx.set_clipboard('Hello World'),)
+```
+
+This event allows you to copy a given text or content to the user's clipboard.
+It's handy when you want to provide a "Copy to Clipboard" feature in your application,
+allowing users to easily copy information to paste elsewhere.
+
+## rx.set_value
+
+Set the value of a specified reference element.
+
+```python demo
+rx.hstack(
+    rx.chakra.input(id='input1'),
+    rx.button(
+        'Erase', on_click=rx.set_value('input1', '')
+    ),
+)
+```
+
+With this event, you can modify the value of a particular HTML element, typically an input field or another form element.
+
+## rx.window_alert
+
+Create a window alert in the browser.
+
+```python demo
+rx.button('Alert', on_click=rx.window_alert('Hello World!'))
+```
+
+## rx.download
+
+Download a file at a given path.
+
+Parameters:
+
+- `url`: The URL of the file to be downloaded.
+- `data`: The data to be downloaded. Should be `str` or `bytes`, `data:` URI, `PIL.Image`, or any state Var (to be converted to JSON).
+- `filename`: The desired filename of the downloaded file.
+
+```md alert
+`url` and `data` args are mutually exclusive, and at least one of them must be provided.
+```
+
+```python demo
+rx.button("Download", on_click=rx.download(url="/reflex_banner.png", filename="different_name_logo.png"))
+```

+ 43 - 0
docs/api-routes/overview.md

@@ -0,0 +1,43 @@
+```python exec
+import reflex as rx
+```
+
+# Backend API Routes
+
+In addition to your frontend app, Reflex also uses a FastAPI backend to serve your app.
+
+To add additional endpoints to the backend API, you can use `app.add_api_route` and add a route that returns JSON.
+
+```python
+async def api_test(item_id: int):
+    return \{"my_result": item_id}
+
+app = rx.App()
+app.api.add_api_route("/items/\{item_id}", api_test)
+```
+
+Now you can access the endpoint at `localhost:8000/items/23` and get the result.
+
+This is useful for creating a backend API that can be used for purposes other than your Reflex app.
+
+## Reserved Routes
+
+Some routes on the backend are reserved for the runtime of Reflex, and should not be overriden unless you know what you are doing.
+
+## Ping
+
+`localhost:8000/ping/`: You can use this route to check the health of the backend.
+
+The expected return is `"pong"`.
+
+## Event
+
+`localhost:8000/_event`: the frontend will use this route to notify the backend that an event occurred.
+
+```md alert error
+# Overriding this route will break the event communication
+```
+
+## Upload
+
+`localhost:8000/_upload`: This route is used for the upload of file when using `rx.upload()`.

+ 42 - 0
docs/assets/referencing_assets.md

@@ -0,0 +1,42 @@
+```python exec
+import reflex as rx
+```
+
+# Assets
+
+Static files such as images and stylesheets can be placed in `"assets/"` folder of the project. These files can be referenced within your app.
+
+```md alert
+# Assets are copied during the build process.
+
+Any files placed within the `assets/` folder at runtime will not be available to the app
+when running in production mode. The `assets/` folder should only be used for static files.
+```
+
+## Referencing Assets
+
+To reference an image in the `"assets/"` simply pass the relative path as a prop.
+
+For example, you can store your logo in your assets folder:
+
+```bash
+assets
+└── Reflex.svg
+```
+
+Then you can display it using a `rx.image` component:
+
+```python demo
+rx.image(src="/Reflex.svg", width="5em")
+```
+
+```md alert
+Always prefix the asset path with a forward slash `/` to reference the asset from the root of the project,
+or it may not display correctly on non-root pages.
+```
+
+## Favicon
+
+The favicon is the small icon that appears in the browser tab.
+
+You can add a `"favicon.ico"` file to the `"assets/"` folder to change the favicon.

+ 89 - 0
docs/assets/upload_and_download_files.md

@@ -0,0 +1,89 @@
+```python exec
+import reflex as rx
+from pcweb.pages.docs import library
+from pcweb.pages.docs import api_reference
+```
+
+# Files
+
+In addition to any assets you ship with your app, many web app will often need to receive or send files, whether you want to share medias, allow user to import their data, or export some backend data.
+
+In this section, we will cover all you need to know for manipulating files in Reflex.
+
+## Download
+
+If you want to let the users of your app download files from your server to their computer, Reflex offer you two way.
+
+### With a regular link
+
+For some basic usage, simply providing the path to your resource in a `rx.link` will work, and clicking the link will download or display the resource.
+
+```python demo
+rx.link("Download", href="/reflex_banner.png")
+```
+
+### With `rx.download` event
+
+Using the `rx.download` event will always prompt the browser to download the file, even if it could be displayed in the browser.
+
+The `rx.download` event also allows the download to be triggered from another backend event handler.
+
+```python demo
+rx.button(
+    "Download", 
+    on_click=rx.download(url="/reflex_banner.png"),
+)
+```
+
+`rx.download` lets you specify a name for the file that will be downloaded, if you want it to be different from the name on the server side.
+
+```python demo
+rx.button(
+    "Download and Rename", 
+    on_click=rx.download(
+        url="/reflex_banner.png", 
+        filename="different_name_logo.png"
+    ),
+)
+```
+
+If the data to download is not already available at a known URL, pass the `data` directly to the `rx.download` event from the backend.
+
+```python demo exec
+import random
+
+class DownloadState(rx.State):
+    def download_random_data(self):
+        return rx.download(
+            data=",".join([str(random.randint(0, 100)) for _ in range(10)]),
+            filename="random_numbers.csv"
+        )
+
+def download_random_data_button():
+    return rx.button(
+        "Download random numbers",
+        on_click=DownloadState.download_random_data
+    )
+```
+
+The `data` arg accepts `str` or `bytes` data, a `data:` URI, `PIL.Image`, or any state Var. If the Var is not already a string, it will be converted to a string using `JSON.stringify`. This allows complex state structures to be offered as JSON downloads.
+
+Reference page for `rx.download` [here]({api_reference.special_events.path}#rx.download).
+
+## Upload
+
+Uploading files to your server let your users interact with your app in a different way than just filling forms to provide data.
+
+The component `rx.upload` let your users upload files on the server.
+
+Here is a basic example of how it is used:
+
+```python
+def index():
+    return rx.fragment(
+        rx.upload(rx.text("Upload files"), rx.icon(tag="upload")),
+        rx.button(on_submit=State.<your_upload_handler>)
+    )
+```
+
+For detailed information, see the reference page of the component [here]({library.forms.upload.path}).

+ 34 - 0
docs/client_storage/overview.md

@@ -0,0 +1,34 @@
+```python exec
+import reflex as rx
+```
+
+# Client-storage
+
+You can use the browser's local storage to persist state between sessions.
+This allows user preferences, authentication cookies, other bits of information
+to be stored on the client and accessed from different browser tabs.
+
+A client-side storage var looks and acts like a normal `str` var, except the
+default value is either `rx.Cookie` or `rx.LocalStorage` depending on where the
+value should be stored.  The key name will be based on the var name, but this
+can be overridden by passing `name="my_custom_name"` as a keyword argument.
+
+For more information see [Browser Storage](/docs/api-reference/browser/).
+
+Try entering some values in the text boxes below and then load the page in a separate
+tab or check the storage section of browser devtools to see the values saved in the browser.
+
+```python demo exec
+class ClientStorageState(rx.State):
+    my_cookie: str = rx.Cookie("")
+    my_local_storage: str = rx.LocalStorage("")
+    custom_cookie: str = rx.Cookie(name="CustomNamedCookie", max_age=3600)
+
+
+def client_storage_example():
+    return rx.vstack(
+        rx.hstack(rx.text("my_cookie"), rx.chakra.input(value=ClientStorageState.my_cookie, on_change=ClientStorageState.set_my_cookie)),
+        rx.hstack(rx.text("my_local_storage"), rx.chakra.input(value=ClientStorageState.my_local_storage, on_change=ClientStorageState.set_my_local_storage)),
+        rx.hstack(rx.text("custom_cookie"), rx.chakra.input(value=ClientStorageState.custom_cookie, on_change=ClientStorageState.set_custom_cookie)),
+    )
+```

+ 25 - 0
docs/components/conditional_props.md

@@ -0,0 +1,25 @@
+```python exec
+import reflex as rx
+```
+
+# Conditional Props
+
+Sometimes you want to set a prop based on a condition. You can use the `rx.cond` function to do this.
+
+```python demo exec
+class PropCondState(rx.State):
+
+    value: list[int]
+    
+    def set_end(self, value: int):
+        self.value = value
+
+
+def cond_prop():
+    return rx.slider(
+        default_value=[50],
+        on_value_commit=PropCondState.set_end,
+        color_scheme=rx.cond(PropCondState.value[0] > 50, "green", "pink"),
+        width="100%",
+    )
+```

+ 269 - 0
docs/components/conditional_rendering.md

@@ -0,0 +1,269 @@
+```python exec
+import reflex as rx
+
+from pcweb.pages.docs import vars, library
+```
+
+# Conditional Rendering
+
+We use the `cond` component to conditionally render components. The `cond` component acts in a similar way to a conditional (ternary) operator in python, acting in a similar fashion to an `if-else` statement.
+
+```md alert
+Check out the API reference for [cond docs]({library.layout.cond.path}).
+```
+
+```python eval
+rx.box(height="2em")
+```
+
+Here is a simple example to show how by checking the value of the state var `show` we can render either `blue` text or `red` text.
+
+The first argument to the `cond` component is the condition we are checking. Here the condition is the value of the state var boolean `show`.
+
+If `show` is `True` then the 2nd argument to the `cond` component is rendered, in this case that is `rx.text("Text 1", color="blue")`.
+
+If `show` is `False` then the 3rd argument to the `cond` component is rendered, in this case that is `rx.text("Text 2", color="red")`.
+
+```python demo exec
+class CondSimpleState(rx.State):
+    show: bool = True
+
+    def change(self):
+        self.show = not (self.show)
+
+
+def cond_simple_example():
+    return rx.vstack(
+        rx.button("Toggle", on_click=CondSimpleState.change),
+        rx.cond(
+            CondSimpleState.show,
+            rx.text("Text 1", color="blue"),
+            rx.text("Text 2", color="red"),
+        ),
+    )
+```
+
+## Var Operations (negation)
+
+You can use var operations with the `cond` component. To learn more generally about var operators check out [these docs]({vars.var_operations.path}). The logical operator `~` can be used to negate a condition. In this example we show that by negating the condition `~CondNegativeState.show` within the cond, we then render the `rx.text("Text 1", color="blue")` component when the state var `show` is negative.
+
+```python demo exec
+class CondNegativeState(rx.State):
+    show: bool = True
+
+    def change(self):
+        self.show = not (self.show)
+
+
+def cond_negative_example():
+    return rx.vstack(
+        rx.text(f"Value of state var show: {CondNegativeState.show}"),
+        rx.button("Toggle", on_click=CondNegativeState.change),
+        rx.cond(
+            CondNegativeState.show,
+            rx.text("Text 1", color="blue"),
+            rx.text("Text 2", color="red"),
+        ),
+        rx.cond(
+            ~CondNegativeState.show,
+            rx.text("Text 1", color="blue"),
+            rx.text("Text 2", color="red"),
+        ),
+    )
+```
+
+## Multiple Conditions
+
+It is also possible to make up complex conditions using the `logical or` (|) and `logical and` (&) operators.
+
+Here we have an example using the var operators `>=`, `<=`, `&`. We define a condition that if a person has an age between 18 and 65, including those ages, they are able to work, otherwise they cannot.
+
+We could equally use the operator `|` to represent a `logical or` in one of our conditions.
+
+```python demo exec
+import random
+
+class CondComplexState(rx.State):
+    age: int = 19
+
+    def change(self):
+        self.age = random.randint(0, 100)
+
+
+def cond_complex_example():
+    return rx.vstack(
+        rx.button("Toggle", on_click=CondComplexState.change),
+        rx.text(f"Age: {CondComplexState.age}"),
+        rx.cond(
+            (CondComplexState.age >= 18) & (CondComplexState.age <=65),
+            rx.text("You can work!", color="green"),
+            rx.text("You cannot work!", color="red"),
+        ),
+    )
+
+```
+
+## Reusing Cond
+
+We can also reuse a `cond` component several times by defining it within a function that returns a `cond`.
+
+In this example we define the function `render_item`. This function takes in an `item`, uses the `cond` to check if the item `is_packed`. If it is packed it returns the `item_name` with a `✔` next to it, and if not then it just returns the `item_name`.
+
+```python demo exec
+class ToDoListItem(rx.Base):
+    item_name: str
+    is_packed: bool
+
+class CondRepeatState(rx.State):
+    to_do_list: list[ToDoListItem] = [
+        ToDoListItem(item_name="Space suit", is_packed=True), 
+        ToDoListItem(item_name="Helmet", is_packed=True),
+        ToDoListItem(item_name="Back Pack", is_packed=False),
+        ]
+
+
+def render_item(item: [str, bool]):
+    return rx.cond(
+        item.is_packed, 
+        rx.chakra.list_item(item.item_name + ' ✔'),
+        rx.chakra.list_item(item.item_name),
+        )
+
+def packing_list():
+    return rx.vstack(
+        rx.text("Sammy's Packing List"),
+        rx.chakra.list(rx.foreach(CondRepeatState.to_do_list, render_item)),
+    )
+
+```
+
+## Nested Conditional
+
+We can also nest `cond` components within each other to create more complex logic. In python we can have an `if` statement that then has several `elif` statements before finishing with an `else`. This is also possible in reflex using nested `cond` components. In this example we check whether a number is positive, negative or zero.
+
+Here is the python logic using `if` statements:
+
+```python
+number = 0
+
+if number > 0:
+    print("Positive number")
+
+elif number == 0:
+    print('Zero')
+else:
+    print('Negative number')
+```
+
+This reflex code that is logically identical:
+
+```python demo exec
+import random
+
+
+class NestedState(rx.State):
+    
+    num: int = 0
+
+    def change(self):
+        self.num = random.randint(-10, 10)
+
+
+def cond_nested_example():
+    return rx.vstack(
+        rx.button("Toggle", on_click=NestedState.change),
+        rx.cond(
+            NestedState.num > 0,
+            rx.text(f"{NestedState.num} is Positive!", color="orange"),
+            rx.cond(
+                NestedState.num == 0,
+                rx.text(f"{NestedState.num} is Zero!", color="blue"),
+                rx.text(f"{NestedState.num} is Negative!", color="red"),
+            )
+        ),
+    )
+
+```
+
+Here is a more advanced example where we have three numbers and we are checking which of the three is the largest. If any two of them are equal then we return that `Some of the numbers are equal!`.
+
+The reflex code that follows is logically identical to doing the following in python:
+
+```python
+a = 8
+b = 10
+c = 2
+
+if((a>b and a>c) and (a != b and a != c)): 
+ print(a, " is the largest!") 
+elif((b>a and b>c) and (b != a and b != c)): 
+ print(b, " is the largest!") 
+elif((c>a and c>b) and (c != a and c != b)): 
+ print(c, " is the largest!") 
+else: 
+ print("Some of the numbers are equal!") 
+```
+
+```python demo exec
+import random
+
+
+class CNS(rx.State):
+    # CNS: CondNestedState
+    a: int = 8
+    b: int = 10
+    c: int = 2
+    
+
+    def change(self):
+        self.a = random.randint(0, 10)
+        self.b = random.randint(0, 10)
+        self.c = random.randint(0, 10)
+
+
+def cond_nested_example_2():
+    return rx.vstack(
+        rx.button("Toggle", on_click=CNS.change),
+        rx.text(f"a: {CNS.a}, b: {CNS.b}, c: {CNS.c}"),
+        rx.cond(
+            ((CNS.a > CNS.b) & (CNS.a > CNS.c)) & ((CNS.a != CNS.b) & (CNS.a != CNS.c)),
+            rx.text(f"{CNS.a} is the largest!", color="green"),
+            rx.cond(
+                ((CNS.b > CNS.a) & (CNS.b > CNS.c)) & ((CNS.b != CNS.a) & (CNS.b != CNS.c)),
+                rx.text(f"{CNS.b} is the largest!", color="orange"),
+                rx.cond(
+                    ((CNS.c > CNS.a) & (CNS.c > CNS.b)) & ((CNS.c != CNS.a) & (CNS.c != CNS.b)),
+                    rx.text(f"{CNS.c} is the largest!", color="blue"),
+                    rx.text("Some of the numbers are equal!", color="red"),
+                ),
+            ),
+        ),
+    )
+
+```
+
+## Cond used as a style prop
+
+`Cond` can also be used to show and hide content in your reflex app. In this example, we have no third argument to the `cond` operator which means that nothing is rendered if the condition is false.
+
+```python demo exec
+class CondStyleState(rx.State):
+    show: bool = False
+    img_url: str = "/preview.png"
+    def change(self):
+        self.show = not (self.show)
+
+
+def cond_style_example():
+    return rx.vstack(
+        rx.button("Toggle", on_click=CondStyleState.change),
+        rx.cond(
+            CondStyleState.show,
+            rx.image(
+                src=CondStyleState.img_url,
+                height="25em",
+                width="25em",
+            ),
+        ),
+    )
+```

+ 81 - 0
docs/components/props.md

@@ -0,0 +1,81 @@
+```python exec
+from pcweb.pages.docs.library import library
+from pcweb.pages.docs import state, vars
+import reflex as rx
+```
+
+# Props
+
+Props modify the behavior and appearance of a component. They are passed in as keyword arguments to the component function.
+
+## Component Props
+
+Each component has props that are specific to that component. For example, the `rx.avatar` component has a fallback prop that sets the `fallback` of the avatar.
+
+```python demo
+rx.avatar(
+    fallback="JD"
+)
+```
+
+Check the docs for the component you are using to see what props are available.
+
+```md alert success
+# Reflex has a wide selection of [built-in components]({library.path}) to get you started quickly.
+```
+
+## HTML Props
+
+Components support many standard HTML properties as props. For example: the HTML [id]({"https://www.w3schools.com/html/html_id.asp"}) property is exposed directly as the prop `id`. The HTML [className]({"https://www.w3schools.com/jsref/prop_html_classname.asp"}) property is exposed as the prop `class_name` (note the Pythonic snake_casing!).
+
+```python demo
+rx.box(
+    "Hello World",
+    id="box-id",
+    class_name=["class-name-1", "class-name-2",],
+)
+```
+
+## Binding Props to State
+
+Reflex apps can have a [State]({state.overview.path}) that stores all variables that can change when the app is running, as well as the event handlers that can change those variables.
+
+State may be modified in response to things like user input like clicking a button, or in response to events like loading a page.
+
+State vars can be bound to component props, so that the UI always reflects the current state of the app.
+
+```md alert warning
+Optional: Learn all about [State]({state.overview.path}) first.
+```
+
+You can set the value of a prop to a [state var]({vars.base_vars.path}) to make the component update when the var changes.
+
+Try clicking the badge below to change its color.
+
+```python demo exec
+class PropExampleState(rx.State):
+    text: str = "Hello World"
+    color: str = "red"
+
+    def flip_color(self):
+        if self.color == "red":
+            self.color = "blue"
+        else:
+            self.color = "red"
+
+
+def index():
+    return rx.badge(
+        PropExampleState.text,
+        color_scheme=PropExampleState.color,
+        on_click=PropExampleState.flip_color,
+        font_size="1.5em",
+        _hover={
+            "cursor": "pointer",
+        }
+    )
+```
+
+In this example, the `color_scheme` prop is bound to the `color` state var.
+
+When the `flip_color` event handler is called, the `color` var is updated, and the `color_scheme` prop is updated to match.

+ 197 - 0
docs/components/rendering_iterables.md

@@ -0,0 +1,197 @@
+```python exec
+import reflex as rx
+
+from pcweb.pages.docs import vars
+```
+
+# Rendering Iterables
+
+You will often want to display multiple similar components from a collection of data. The `rx.foreach` component takes an `iterable` (list, tuple or dict) and a `function` that renders each item in the list. This is useful for dynamically rendering a list of items defined in a state.
+
+In this first simple example we iterate through a `list` of colors and render the name of the color and use this color as the background for that `rx.box`. As we can see we have a function `colored_box` that we pass to the `rx.foreach` component. This function renders each item from the `list` that we have defined as a state var `color`.
+
+```python demo exec
+class IterState(rx.State):
+    color: list[str] = [
+        "red",
+        "green",
+        "blue",
+        "yellow",
+        "orange",
+        "purple",
+    ]
+
+
+def colored_box(color: str):
+    return rx.box(rx.text(color), background_color=color)
+
+
+def simple_foreach():
+    return rx.chakra.responsive_grid(
+        rx.foreach(IterState.color, colored_box),
+        columns=[2, 4, 6],
+    )
+
+```
+
+```md alert warning
+# The type signature of the functions does not matter to the `foreach` component. It's the type annotation on the `state var` that determines what operations are available (e.g. when nesting).
+```
+
+## Enumeration
+
+The function can also take an index as a second argument, meaning that we can enumerate through data as shown in the example below.
+
+```python demo exec
+class IterIndexState(rx.State):
+    color: list[str] = [
+        "red",
+        "green",
+        "blue",
+        "yellow",
+        "orange",
+        "purple",
+    ]
+
+
+def enumerate_foreach():
+    return rx.chakra.responsive_grid(
+        rx.foreach(
+            IterIndexState.color,
+            lambda color, index: rx.box(rx.text(index), bg=color)
+        ),
+        columns=[2, 4, 6],
+    )
+
+```
+
+## Dictionary
+
+We can iterate through a `dict` data structure using a `foreach`. When the dict is passed through to the function that renders each item, it is presented as a list of key-value pairs `[("sky", "blue"), ("balloon", "red"), ("grass", "green")]`.
+
+```python demo exec
+class SimpleDictIterState(rx.State):
+    color_chart: dict[str, str] = {
+        "sky": "blue",
+        "balloon": "red",
+        "grass": "green",
+    }
+
+
+def display_color(color: list):
+    # color is presented as a list key-value pairs [("sky", "blue"), ("balloon", "red"), ("grass", "green")]
+    return rx.box(rx.text(color[0]), bg=color[1], padding_x="1.5em")
+
+
+def dict_foreach():
+    return rx.chakra.responsive_grid(
+        rx.foreach(
+            SimpleDictIterState.color_chart,
+            display_color,
+        ),
+        columns=[2, 4, 6],
+    )
+
+```
+
+## Nested examples
+
+`rx.foreach` can be used with nested state vars. Here we use nested `foreach` components to render the nested state vars. The `rx.foreach(project["technologies"], get_badge)` inside of the `project_item` function, renders the `dict` values which are of type `list`. The `rx.box(rx.foreach(NestedStateFE.projects, project_item))` inside of the `projects_example` function renders each `dict` inside of the overall state var `projects`.
+
+```python demo exec
+class NestedStateFE(rx.State):
+    projects: list[dict[str, list]] = [
+        {
+            "technologies": ["Next.js", "Prisma", "Tailwind", "Google Cloud", "Docker", "MySQL"]
+        },
+        {
+            "technologies": ["Python", "Flask", "Google Cloud", "Docker"]
+        }
+    ]
+
+def get_badge(technology: str) -> rx.Component:
+    return rx.chakra.badge(technology, variant="subtle", color_scheme="green")
+
+def project_item(project: dict) -> rx.Component:
+    return rx.box(
+        rx.hstack(            
+            rx.foreach(project["technologies"], get_badge)
+        ),
+    )
+
+def projects_example() -> rx.Component:
+    return rx.box(rx.foreach(NestedStateFE.projects, project_item))
+```
+
+If you want an example where not all of the values in the dict are the same type then check out the example on [var operations using foreach]({vars.var_operations.path}).
+
+Here is a further example of how to use `foreach` with a nested data structure.
+
+```python demo exec
+class NestedDictIterState(rx.State):
+    color_chart: dict[str, list[str]] = {
+        "purple": ["red", "blue"],
+        "orange": ["yellow", "red"],
+        "green": ["blue", "yellow"],
+    }
+
+
+def display_colors(color: list[str, list[str]]):
+    
+    return rx.vstack(
+        rx.text(color[0], color=color[0]),
+        rx.hstack(
+            rx.foreach(
+                color[1],
+                lambda x: rx.box(
+                    rx.text(x, color="black"), bg=x
+                ),
+            )
+        ),
+    )
+
+
+def nested_dict_foreach():
+    return rx.chakra.responsive_grid(
+        rx.foreach(
+            NestedDictIterState.color_chart,
+            display_colors,
+        ),
+        columns=[2, 4, 6],
+    )
+
+```
+
+## Foreach with Cond
+
+We can also use `foreach` with the `cond` component.
+
+In this example we define the function `render_item`. This function takes in an `item`, uses the `cond` to check if the item `is_packed`. If it is packed it returns the `item_name` with a `✔` next to it, and if not then it just returns the `item_name`. We use the `foreach` to iterate over all of the items in the `to_do_list` using the `render_item` function.
+
+```python demo exec
+class ToDoListItem(rx.Base):
+    item_name: str
+    is_packed: bool
+
+class ForeachCondState(rx.State):
+    to_do_list: list[ToDoListItem] = [
+        ToDoListItem(item_name="Space suit", is_packed=True), 
+        ToDoListItem(item_name="Helmet", is_packed=True),
+        ToDoListItem(item_name="Back Pack", is_packed=False),
+        ]
+
+
+def render_item(item: [str, bool]):
+    return rx.cond(
+        item.is_packed, 
+        rx.chakra.list_item(item.item_name + ' ✔'),
+        rx.chakra.list_item(item.item_name),
+        )
+
+def packing_list():
+    return rx.vstack(
+        rx.text("Sammy's Packing List"),
+        rx.chakra.list(rx.foreach(ForeachCondState.to_do_list, render_item)),
+    )
+
+```

+ 25 - 0
docs/components/style_props.md

@@ -0,0 +1,25 @@
+```python exec
+from pcweb.pages.docs import styling
+import reflex as rx
+```
+
+# Style Props
+
+In addition to component-specific props, most built-in components support a full range of style props. You can use any CSS property to style a component.
+
+```python demo
+rx.button(
+    "Fancy Button",
+    border_radius="1em",
+    box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
+    background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
+    box_sizing="border-box",
+    color="white",
+    opacity= 1,
+    _hover={
+        "opacity": .5,
+    }
+)
+```
+
+See the [styling docs]({styling.overview.path}) to learn more about customizing the appearance of your app.

+ 75 - 0
docs/database/overview.md

@@ -0,0 +1,75 @@
+# Database
+
+Reflex uses [sqlmodel](https://sqlmodel.tiangolo.com) to provide a built-in ORM wrapping SQLAlchemy.
+
+The examples on this page refer specifically to how Reflex uses various tools to
+expose an integrated database interface.  Only basic use cases will be covered
+below, but you can refer to the
+[sqlmodel tutorial](https://sqlmodel.tiangolo.com/tutorial/select/)
+for more examples and information, just replace `SQLModel` with `rx.Model` and
+`Session(engine)` with `rx.session()`
+
+For advanced use cases, please see the
+[SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/orm/quickstart.html) (v1.4).
+
+## Connecting
+
+Reflex provides a built-in SQLite database for storing and retrieving data.
+
+You can connect to your own SQL compatible database by modifying the
+`rxconfig.py` file with your database url.
+
+```python
+config = rx.Config(
+    app_name="my_app",
+    db_url="sqlite:///reflex.db",
+)
+```
+
+For more examples of database URLs that can be used, see the [SQLAlchemy
+docs](https://docs.sqlalchemy.org/en/14/core/engines.html#backend-specific-urls).
+Be sure to install the appropriate DBAPI driver for the database you intend to
+use.
+
+## Tables
+
+To create a table make a class that inherits from `rx.Model` with and specify
+that it is a table.
+
+```python
+class User(rx.Model, table=True):
+    username: str
+    email: str
+    password: str   
+```
+
+## Migrations
+
+Reflex leverages [alembic](https://alembic.sqlalchemy.org/en/latest/)
+to manage database schema changes.
+
+Before the database feature can be used in a new app you must call `reflex db init`
+to initialize alembic and create a migration script with the current schema.
+
+After making changes to the schema, use
+`reflex db makemigrations --message 'something changed'`
+to generate a script in the `alembic/versions` directory that will update the
+database schema. It is recommended that scripts be inspected before applying
+them.
+
+The `reflex db migrate` command is used to apply migration scripts to bring the
+database up to date. During app startup, if Reflex detects that the current
+database schema is not up to date, a warning will be displayed on the console.
+
+## Queries
+
+To query the database you can create a `rx.session()`
+which handles opening and closing the database connection.
+
+You can use normal SQLAlchemy queries to query the database.
+
+```python
+with rx.session() as session:
+    session.add(User(username="test", email="admin@pynecone.io", password="admin"))
+    session.commit()
+```

+ 186 - 0
docs/database/queries.md

@@ -0,0 +1,186 @@
+# Queries
+
+Queries are used to retrieve data from a database.
+
+A query is a request for information from a database table or combination of
+tables. A query can be used to retrieve data from a single table or multiple
+tables. A query can also be used to insert, update, or delete data from a table.
+
+## Session
+
+To execute a query you must first create a `rx.session`. You can use the session
+to query the database using SQLModel or SQLAlchemy syntax.
+
+The `rx.session` statement will automatically close the session when the code
+block is finished. **If `session.commit()` is not called, the changes will be
+rolled back and not persisted to the database.** The code can also explicitly
+rollback without closing the session via `session.rollback()`.
+
+The following example shows how to create a session and query the database.
+First we create a table called `User`.
+
+```python
+class User(rx.Model, table=True):
+    username: str
+    email: str
+```
+
+### Select
+
+Then we create a session and query the User table.
+
+```python
+class QueryUser(rx.State):
+    name: str
+    users: list[User]
+
+    def get_users(self):
+        with rx.session() as session:
+            self.users = session.exec(
+                User.select.where(
+                    User.username.contains(self.name)).all())
+```
+
+The `get_users` method will query the database for all users that contain the
+value of the state var `name`.
+
+On older python versions, the `.select` attribute on model objects does not work, but
+you may use `sqlmodel.select(User)` instead.
+
+### Insert
+
+Similarly, the `session.add()` method to add a new record to the
+database or persist an existing object.
+
+```python
+class AddUser(rx.State):
+    username: str
+    email: str
+    
+    def add_user(self):
+        with rx.session() as session:
+            session.add(User(username=self.username, email=self.email))
+            session.commit()
+```
+
+### Update
+
+To update the user, first query the database for the object, make the desired
+modifications, `.add` the object to the session and finally call `.commit()`.
+
+```python
+class ChangeEmail(rx.State):
+    username: str
+    email: str
+
+    def modify_user(self):
+        with rx.session() as session:
+            user = session.exec(User.select.where(
+                (User.username == self.username).first()))
+            user.email = self.email
+            session.add(user)
+            session.commit()
+```
+
+### Delete
+
+To delete a user, first query the database for the object, then call
+`.delete()` on the session and finally call `.commit()`.
+
+```python
+class RemoveUser(rx.State):
+    username: str
+
+    def delete_user(self):
+        with rx.session() as session:
+            user = session.exec(User.select.where(
+                User.username == self.username).first())
+            session.delete(user)
+            session.commit()
+```
+
+## ORM Object Lifecycle
+
+The objects returned by queries are bound to the session that created them, and cannot generally
+be used outside that session. After adding or updating an object, not all fields are automatically
+updated, so accessing certain attributes may trigger additional queries to refresh the object.
+
+To avoid this, the `session.refresh()` method can be used to update the object explicitly and
+ensure all fields are up to date before exiting the session.
+
+```python
+class AddUserForm(rx.State):
+    user: User | None = None
+    
+    def add_user(self, form_data: dict[str, str]):
+        with rx.session() as session:
+            self.user = User(**form_data)
+            session.add(self.user)
+            session.commit()
+            session.refresh(self.user)
+```
+
+Now the `self.user` object will have a correct reference to the autogenerated
+primary key, `id`, even though this was not provided when the object was created
+from the form data.
+
+If `self.user` needs to be modified or used in another query in a new session,
+it must be added to the session. Adding an object to a session does not
+necessarily create the object, but rather associates it with a session where it
+may either be created or updated accordingly.
+
+```python
+class AddUserForm(rx.State):
+    ...
+    
+    def update_user(self, form_data: dict[str, str]):
+        if self.user is None:
+            return
+        with rx.session() as session:
+            self.user.set(**form_data)
+            session.add(self.user)
+            session.commit()
+            session.refresh(self.user)
+```
+
+If an ORM object will be referenced and accessed outside of a session, you
+should call `.refresh()` on it to avoid stale object exceptions.
+
+## Using SQL Directly
+
+Avoiding SQL is one of the main benefits of using an ORM, but sometimes it is
+necessary for particularly complex queries, or when using database-specific
+features.
+
+SQLModel exposes the `session.execute()` method that can be used to execute raw
+SQL strings.  If parameter binding is needed, the query may be wrapped in
+[`sqlalchemy.text`](https://docs.sqlalchemy.org/en/14/core/sqlelement.html#sqlalchemy.sql.expression.text),
+which allows colon-prefix names to be used as placeholders.
+
+```md alert
+Never use string formatting to construct SQL queries, as this may lead to SQL injection vulnerabilities in the app.
+```
+
+```python
+import sqlalchemy
+
+import reflex as rx
+
+
+class State(rx.State):
+    def insert_user_raw(self, username, email):
+        with rx.session() as session:
+            session.execute(
+                sqlalchemy.text(
+                    "INSERT INTO user (username, email) "
+                    "VALUES (:username, :email)"
+                ),
+                \{"username": username, "email": email},
+            )
+            session.commit()
+
+    @rx.var
+    def raw_user_tuples(self) -> list[list]:
+        with rx.session() as session:
+            return [list(row) for row in session.execute("SELECT * FROM user").all()]
+```

+ 162 - 0
docs/database/relationships.md

@@ -0,0 +1,162 @@
+# Relationships
+
+Foreign key relationships are used to link two tables together. For example,
+the `Post` model may have a field, `user_id`, with a foreign key of `user.id`,
+referencing a `User` model. This would allow us to automatically query the `Post` objects
+associated with a user, or find the `User` object associated with a `Post`.
+
+To establish bidirectional relationships a model must correctly set the
+`back_populates` keyword argument on the `Relationship` to the relationship
+attribute in the _other_ model.
+
+## Foreign Key Relationships
+
+To create a relationship, first add a field to the model that references the
+primary key of the related table, then add a `sqlmodel.Relationship` attribute
+which can be used to access the related objects.
+
+Defining relationships like this requires the use of `sqlmodel` objects as
+seen in the example.
+
+```python
+from typing import List, Optional
+
+import sqlmodel
+
+import reflex as rx
+
+
+class Post(rx.Model, table=True):
+    title: str
+    body: str
+    user_id: int = sqlmodel.Field(foreign_key="user.id")
+
+    user: Optional["User"] = sqlmodel.Relationship(back_populates="posts")
+    flags: Optional[List["Flag"]] = sqlmodel.Relationship(back_populates="post")
+
+
+class User(rx.Model, table=True):
+    username: str
+    email: str
+
+    posts: List[Post] = sqlmodel.Relationship(back_populates="user")
+    flags: List["Flag"] = sqlmodel.Relationship(back_populates="user")
+
+
+class Flag(rx.Model, table=True):
+    post_id: int = sqlmodel.Field(foreign_key="post.id")
+    user_id: int = sqlmodel.Field(foreign_key="user.id")
+    message: str
+
+    post: Optional[Post] = sqlmodel.Relationship(back_populates="flags")
+    user: Optional[User] = sqlmodel.Relationship(back_populates="flags")
+```
+
+See the [SQLModel Relationship Docs](https://sqlmodel.tiangolo.com/tutorial/relationship-attributes/define-relationships-attributes/) for more details.
+
+## Querying Relationships
+
+### Inserting Linked Objects
+
+The following example assumes that the flagging user is stored in the state as a
+`User` instance and that the post `id` is provided in the data submitted in the
+form.
+
+```python
+class FlagPostForm(rx.State):
+    user: User
+
+    def flag_post(self, form_data: dict[str, str]):
+        with rx.session() as session:
+            post = session.get(Post, int(form_data.pop("post_id")))
+            flag = Flag(message=form_data.pop("message"), post=post, user=self.user)
+            session.add(flag)
+            session.commit()
+```
+
+### How are Relationships Dereferenced?
+
+By default, the relationship attributes are in **lazy loading** or `"select"`
+mode, which generates a query _on access_ to the relationship attribute. Lazy
+loading is generally fine for single object lookups and manipulation, but can be
+inefficient when accessing many linked objects for serialization purposes.
+
+There are several alternative loading mechanisms available that can be set on
+the relationship object or when performing the query.
+
+* "joined" or `joinload` - generates a single query to load all related objects
+  at once.
+* "subquery" or `subqueryload` - generates a single query to load all related
+  objects at once, but uses a subquery to do the join, instead of a join in the
+  main query.
+* "selectin" or `selectinload` - emits a second (or more) SELECT statement which
+  assembles the primary key identifiers of the parent objects into an IN clause,
+  so that all members of related collections / scalar references are loaded at
+  once by primary key
+
+There are also non-loading mechanisms, "raise" and "noload" which are used to
+specifically avoid loading a relationship.
+
+Each loading method comes with tradeoffs and some are better suited for different
+data access patterns.
+See [SQLAlchemy: Relationship Loading Techniques](https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html)
+for more detail.
+
+### Querying Linked Objects
+
+To query the `Post` table and include all `User` and `Flag` objects up front,
+the `.options` interface will be used to specify `selectinload` for the required
+relationships. Using this method, the linked objects will be available for
+rendering in frontend code without additional steps.
+
+```python
+import sqlalchemy
+
+
+class PostState(rx.State):
+    posts: List[Post]
+
+    def load_posts(self):
+        with rx.session() as session:
+            self.posts = session.exec(
+                Post.select
+                .options(
+                    sqlalchemy.orm.selectinload(Post.user),
+                    sqlalchemy.orm.selectinload(Post.flags).options(
+                        sqlalchemy.orm.selectinload(Flag.user),
+                    ),
+                )
+                .limit(15)
+            ).all()
+```
+
+The loading methods create new query objects and thus may be linked if the
+relationship itself has other relationships that need to be loaded. In this
+example, since `Flag` references `User`, the `Flag.user` relationship must be
+chain loaded from the `Post.flags` relationship.
+
+### Specifying the Loading Mechanism on the Relationship
+
+Alternatively, the loading mechanism can be specified on the relationship by
+passing `sa_relationship_kwargs=\{"lazy": method}` to `sqlmodel.Relationship`,
+which will use the given loading mechanism in all queries by default.
+
+```python
+from typing import List, Optional
+
+import sqlmodel
+
+import reflex as rx
+
+
+class Post(rx.Model, table=True):
+    ...
+    user: Optional["User"] = sqlmodel.Relationship(
+        back_populates="posts",
+        sa_relationship_kwargs=\{"lazy": "selectin"},
+    )
+    flags: Optional[List["Flag"]] = sqlmodel.Relationship(
+        back_populates="post",
+        sa_relationship_kwargs=\{"lazy": "selectin"},
+    )
+```

+ 70 - 0
docs/database/tables.md

@@ -0,0 +1,70 @@
+# Tables
+
+Tables are database objects that contain all the data in a database.
+
+In tables, data is logically organized in a row-and-column format similar to a
+spreadsheet. Each row represents a unique record, and each column represents a
+field in the record.
+
+## Creating a Table
+
+To create a table make a class that inherits from `rx.Model`.
+
+The following example shows how to create a table called `User`.
+
+```python
+class User(rx.Model, table=True):
+    username: str
+    email: str
+```
+
+The `table=True` argument tells Reflex to create a table in the database for
+this class.
+
+### Primary Key
+
+By default, Reflex will create a primary key column called `id` for each table.
+
+However, if an `rx.Model` defines a different field with `primary_key=True`, then the
+default `id` field will not be created. A table may also redefine `id` as needed.
+
+It is not currently possible to create a table without a primary key.
+
+## Advanced Column Types
+
+SQLModel automatically maps basic python types to SQLAlchemy column types, but
+for more advanced use cases, it is possible to define the column type using
+`sqlalchemy` directly. For example, we can add a last updated timestamp to the
+post example as a proper `DateTime` field with timezone.
+
+```python
+import datetime
+
+import sqlmodel
+import sqlalchemy
+
+class Post(rx.Model, table=True):
+    ...
+    update_ts: datetime.datetime = sqlmodel.Field(
+        default=None,
+        sa_column=sqlalchemy.Column(
+            "update_ts",
+            sqlalchemy.DateTime(timezone=True),
+            server_default=sqlalchemy.func.now(),
+        ),
+    )
+```
+
+To make the `Post` model more usable on the frontend, a `dict` method may be provided
+that converts any fields to a JSON serializable value. In this case, the dict method is
+overriding the default `datetime` serializer to strip off the microsecond part.
+
+```python
+class Post(rx.Model, table=True):
+    ...
+
+    def dict(self, *args, **kwargs) -> dict:
+        d = super().dict(*args, **kwargs)
+        d["update_ts"] = self.update_ts.replace(microsecond=0).isoformat()
+        return d
+```

+ 0 - 0
docs/datatable_tutorial/__init__.py


+ 223 - 0
docs/datatable_tutorial/add_interactivity.md

@@ -0,0 +1,223 @@
+```python exec
+import reflex as rx
+from docs.datatable_tutorial.datatable_tutorial_utils import DataTableState, DataTableState2
+```
+
+# Adding Interactivity to our DataTable
+
+Now we will add interactivity to our datatable. We do this using event handlers and event triggers.
+
+The first example implements a handler for the `on_cell_clicked` event trigger, which is called when the user clicks on a cell of the data editor. The event trigger receives the coordinates of the cell.
+
+```python
+class DataTableState(rx.State):
+    clicked_cell: str = "Cell clicked: "
+
+    ...
+
+
+    def get_clicked_data(self, pos: tuple[int, int]) -> str:
+        self.clicked_cell = f"Cell clicked: \{pos}"
+        
+```
+
+The state has a var called `clicked_cell` that will store a message about which cell was clicked. We define an event handler `get_clicked_data` that updates the value of the `clicked_cell` var when it is called. In essence, we have clicked on a cell, called the `on_cell_clicked` event trigger which calls the `get_clicked_data` event handler, which updates the `clicked_cell` var.
+
+```python demo
+rx.text(DataTableState.clicked_cell)
+```
+
+```python demo
+rx.data_editor(
+    columns=DataTableState.cols,
+    data=DataTableState.data,
+    on_cell_clicked=DataTableState.get_clicked_data,
+)
+```
+
+The event handler `on_cell_context_menu` can be used in the same way as `on_cell_clicked`, except here the event trigger is called when the user right clicks, i.e. when the cell should show a context menu.
+
+## Editing cells
+
+Another important type of interactivity we will showcase is how to edit cells. Here we use the `on_cell_edited` event trigger to update the data based on what the user entered.
+
+```python
+class DataTableState(rx.State):
+    clicked_cell: str = "Cell clicked: "
+    edited_cell: str = "Cell edited: "
+
+    ...
+
+
+    def get_clicked_data(self, pos) -> str:
+        self.clicked_cell = f"Cell clicked: \{pos}"
+
+    def get_edited_data(self, pos, val) -> str:
+        col, row = pos
+        self.data[row][col] = val["data"]
+        self.edited_cell = f"Cell edited: \{pos}, Cell value: \{val["data"]}"
+        
+```
+
+The `on_cell_edited` event trigger is called when the user modifies the content of a cell. It receives the coordinates of the cell and the modified content. We pass these into the `get_edited_data` event handler and use them to update the `data` state var at the appropriate position. We then update the `edited_cell` var value.
+
+```python demo
+rx.text(DataTableState.edited_cell)
+```
+
+```python demo
+rx.data_editor(
+    columns=DataTableState.cols,
+    data=DataTableState.data,
+    on_cell_clicked=DataTableState.get_clicked_data,
+    on_cell_edited=DataTableState.get_edited_data,
+)
+```
+
+## Group Header
+
+We can define group headers which are headers that encompass a group of columns. We define these in the `columns` using the `group` property such as `"group": "Data"`. The `columns` would now be defined as below. Only the `Title` does not fall under a group header, all the rest fall under the `Data` group header.
+
+```python
+class DataTableState2(rx.State):
+    """The app state."""
+
+    ...
+
+    cols: list[dict] = [
+        {\"title": "Title", "type": "str"},
+        {
+            "title": "Name",
+            "type": "str",
+            "group": "Data",
+            "width": 300,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "group": "Data",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "group": "Data",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "group": "Data",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "group": "Data",
+            "width": 200,
+        },
+    ]
+
+    ...
+```
+
+The table now has a header as below.
+
+```python demo
+rx.data_editor(
+    columns=DataTableState2.cols,
+    data=DataTableState2.data,
+    on_cell_clicked=DataTableState2.get_clicked_data,
+    on_cell_edited=DataTableState2.get_edited_data,
+)
+```
+
+There are several event triggers we can apply to the group header.
+
+```python
+class DataTableState2(rx.State):
+    """The app state."""
+
+    right_clicked_group_header : str = "Group header right clicked: "
+
+    ...
+
+    def get_group_header_right_click(self, index, val):
+        self.right_clicked_group_header = f"Group header right clicked at index: \{index}, Group header value: \{val['group']}"
+
+```
+
+```python demo
+rx.text(DataTableState2.right_clicked_group_header)
+```
+
+```python demo
+rx.data_editor(
+    columns=DataTableState2.cols,
+    data=DataTableState2.data,
+    on_cell_clicked=DataTableState2.get_clicked_data,
+    on_cell_edited=DataTableState2.get_edited_data,
+    on_group_header_context_menu=DataTableState2.get_group_header_right_click,
+)
+```
+
+In this example we use the `on_group_header_context_menu` event trigger which is called when the user right-clicks on a group header. It returns the `index` and the `data` of the group header. We can also use the `on_group_header_clicked` and `on_group_header_renamed` event triggers which are called when the user left-clicks on a group header and when a user renames a group header respectively.
+
+## More Event Triggers
+
+There are several other event triggers that are worth exploring. The `on_item_hovered` event trigger is called whenever the user hovers over an item in the datatable. The `on_delete` event trigger is called when the user deletes a cell from the datatable.
+
+The final event trigger to check out is `on_column_resize`. `on_column_resize` allows us to respond to the user dragging the handle between columns. The event trigger returns the `col` we are adjusting and the new `width` we have defined. The `col` that is returned is a dictionary for example: `\{'title': 'Name', 'type': 'str', 'group': 'Data', 'width': 198, 'pos': 1}`. We then index into `self.cols` defined in our state and change the `width` of that column using this code: `self.cols[col['pos']]['width'] = width`.
+
+```python
+class DataTableState2(rx.State):
+    """The app state."""
+
+    ...
+
+    item_hovered: str = "Item Hovered: "
+    deleted: str = "Deleted: "
+
+    ...
+
+
+    def get_item_hovered(self, pos) -> str:
+        self.item_hovered = f"Item Hovered type: \{pos['kind']}, Location: \{pos['location']}"
+        
+    def get_deleted_item(self, selection):
+        self.deleted = f"Deleted cell: \{selection['current']['cell']}"
+
+    def column_resize(self, col, width):
+        self.cols[col['pos']]['width'] = width 
+```
+
+```python demo
+rx.text(DataTableState2.item_hovered)
+```
+
+```python demo
+rx.text(DataTableState2.deleted)
+```
+
+```python demo
+rx.data_editor(
+    columns=DataTableState2.cols,
+    data=DataTableState2.data,
+    on_cell_clicked=DataTableState2.get_clicked_data,
+    on_cell_edited=DataTableState2.get_edited_data,
+    on_group_header_context_menu=DataTableState2.get_group_header_right_click,
+    on_item_hovered=DataTableState2.get_item_hovered,
+    on_delete=DataTableState2.get_deleted_item,
+    on_column_resize=DataTableState2.column_resize,
+)
+```

+ 141 - 0
docs/datatable_tutorial/add_styling.md

@@ -0,0 +1,141 @@
+```python exec
+import reflex as rx
+from docs.datatable_tutorial.datatable_tutorial_utils import DataTableState, DataTableState2
+from pcweb.pages.docs import library
+```
+
+# DataTable Styling
+
+There are props that we can explore to ensure the datatable is shaped correctly and reacts in the way we expect. We can set `on_paste` to `True`, which allows us to paste directly into a cell. We can use `draw_focus_ring` to draw a ring around the cells when selected, this defaults to `True` so can be turned off if we do not want it. The `rows` prop can be used to hard code the number of rows that we show.
+
+`freeze_columns` is used to keep a certain number of the left hand columns frozen when scrolling horizontally. `group_header_height` and `header_height` define the height of the group header and the individual headers respectively. `max_column_width` and `min_column_width` define how large or small the columns are allowed to be with the manual column resizing. We can also define the `row_height` to make the rows more nicely spaced.
+
+We can add `row_markers`, which appear on the furthest left side of the table. They can take values of `'none', 'number', 'checkbox', 'both', 'clickable-number'`. We can set `smooth_scroll_x` and `smooth_scroll_y`, which allows us to smoothly scroll along the columns and rows.
+
+By default there is a `vertical_border` between the columns, we can turn it off by setting this prop to `False`. We can define how many columns a user can select at a time by setting the `column_select` prop. It can take values of `"none", "single", "multi"`.
+
+We can allow `overscroll_x`, which allows users to scroll past the limit of the actual horizontal content. There is an equivalent `overscroll_y`.
+
+Check out [these docs]({library.datadisplay.data_editor.path}) for more information on these props.
+
+```python demo
+rx.data_editor(
+    columns=DataTableState2.cols,
+    data=DataTableState2.data,
+
+    #rows=4,
+    on_paste=True,
+    draw_focus_ring=False,
+    freeze_columns=2,
+    group_header_height=50,
+    header_height=60,
+    max_column_width=300,
+    min_column_width=100,
+    row_height=50,
+    row_markers='clickable-number',
+    smooth_scroll_x=True,
+    vertical_border=False,
+    column_select="multi",
+    overscroll_x=100,
+
+
+    on_cell_clicked=DataTableState2.get_clicked_data,
+    on_cell_edited=DataTableState2.get_edited_data,
+    on_group_header_context_menu=DataTableState2.get_group_header_right_click,
+    on_item_hovered=DataTableState2.get_item_hovered,
+    on_delete=DataTableState2.get_deleted_item,
+    on_column_resize=DataTableState2.column_resize,
+)
+```
+
+## Theming
+
+Lastly there is a `theme` prop that allows us to pass in all color and font information for the data table.
+
+```python
+darkTheme = {
+    "accentColor": "#8c96ff",
+    "accentLight": "rgba(202, 206, 255, 0.253)",
+    "textDark": "#ffffff",
+    "textMedium": "#b8b8b8",
+    "textLight": "#a0a0a0",
+    "textBubble": "#ffffff",
+    "bgIconHeader": "#b8b8b8",
+    "fgIconHeader": "#000000",
+    "textHeader": "#a1a1a1",
+    "textHeaderSelected": "#000000",
+    "bgCell": "#16161b",
+    "bgCellMedium": "#202027",
+    "bgHeader": "#212121",
+    "bgHeaderHasFocus": "#474747",
+    "bgHeaderHovered": "#404040",
+    "bgBubble": "#212121",
+    "bgBubbleSelected": "#000000",
+    "bgSearchResult": "#423c24",
+    "borderColor": "rgba(225,225,225,0.2)",
+    "drilldownBorder": "rgba(225,225,225,0.4)",
+    "linkColor": "#4F5DFF",
+    "headerFontStyle": "bold 14px",
+    "baseFontStyle": "13px",
+    "fontFamily": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
+}
+```
+
+```python exec
+darkTheme = {
+    "accentColor": "#8c96ff",
+    "accentLight": "rgba(202, 206, 255, 0.253)",
+    "textDark": "#ffffff",
+    "textMedium": "#b8b8b8",
+    "textLight": "#a0a0a0",
+    "textBubble": "#ffffff",
+    "bgIconHeader": "#b8b8b8",
+    "fgIconHeader": "#000000",
+    "textHeader": "#a1a1a1",
+    "textHeaderSelected": "#000000",
+    "bgCell": "#16161b",
+    "bgCellMedium": "#202027",
+    "bgHeader": "#212121",
+    "bgHeaderHasFocus": "#474747",
+    "bgHeaderHovered": "#404040",
+    "bgBubble": "#212121",
+    "bgBubbleSelected": "#000000",
+    "bgSearchResult": "#423c24",
+    "borderColor": "rgba(225,225,225,0.2)",
+    "drilldownBorder": "rgba(225,225,225,0.4)",
+    "linkColor": "#4F5DFF",
+    "headerFontStyle": "bold 14px",
+    "baseFontStyle": "13px",
+    "fontFamily": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
+}
+```
+
+```python demo
+rx.data_editor(
+    columns=DataTableState2.cols,
+    data=DataTableState2.data,
+
+    on_paste=True,
+    draw_focus_ring=False,
+    freeze_columns=2,
+    group_header_height=50,
+    header_height=60,
+    max_column_width=300,
+    min_column_width=100,
+    row_height=50,
+    row_markers='clickable-number',
+    smooth_scroll_x=True,
+    vertical_border=False,
+    column_select="multi",
+    overscroll_x=100,
+    theme=darkTheme,
+
+
+    on_cell_clicked=DataTableState2.get_clicked_data,
+    on_cell_edited=DataTableState2.get_edited_data,
+    on_group_header_context_menu=DataTableState2.get_group_header_right_click,
+    on_item_hovered=DataTableState2.get_item_hovered,
+    on_delete=DataTableState2.get_deleted_item,
+    on_column_resize=DataTableState2.column_resize,
+)
+```

+ 328 - 0
docs/datatable_tutorial/datatable_tutorial_utils.py

@@ -0,0 +1,328 @@
+import asyncio
+from typing import Any
+
+import httpx
+
+import reflex as rx
+
+
+class DataTableState(rx.State):
+    """The app state."""
+
+    clicked_cell: str = "Cell clicked: "
+    edited_cell: str = "Cell edited: "
+
+    cols: list[dict] = [
+        {"title": "Title", "type": "str"},
+        {
+            "title": "Name",
+            "type": "str",
+            "width": 300,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "width": 200,
+        },
+    ]
+
+    data = [
+        [
+            "1",
+            "Harry James Potter",
+            "31 July 1980",
+            True,
+            "Gryffindor",
+            "11'  Holly  phoenix feather",
+            "Stag",
+            "Half-blood",
+        ],
+        [
+            "2",
+            "Ronald Bilius Weasley",
+            "1 March 1980",
+            True,
+            "Gryffindor",
+            "12' Ash unicorn tail hair",
+            "Jack Russell terrier",
+            "Pure-blood",
+        ],
+        [
+            "3",
+            "Hermione Jean Granger",
+            "19 September, 1979",
+            True,
+            "Gryffindor",
+            "10¾'  vine wood dragon heartstring",
+            "Otter",
+            "Muggle-born",
+        ],
+        [
+            "4",
+            "Albus Percival Wulfric Brian Dumbledore",
+            "Late August 1881",
+            True,
+            "Gryffindor",
+            "15' Elder Thestral tail hair core",
+            "Phoenix",
+            "Half-blood",
+        ],
+        [
+            "5",
+            "Rubeus Hagrid",
+            "6 December 1928",
+            False,
+            "Gryffindor",
+            "16'  Oak unknown core",
+            "None",
+            "Part-Human (Half-giant)",
+        ],
+        [
+            "6",
+            "Fred Weasley",
+            "1 April, 1978",
+            True,
+            "Gryffindor",
+            "Unknown",
+            "Unknown",
+            "Pure-blood",
+        ],
+        [
+            "7",
+            "George Weasley",
+            "1 April, 1978",
+            True,
+            "Gryffindor",
+            "Unknown",
+            "Unknown",
+            "Pure-blood",
+        ],
+    ]
+
+    def get_clicked_data(self, pos) -> str:
+        self.clicked_cell = f"Cell clicked: {pos}"
+
+    def get_edited_data(self, pos, val) -> str:
+        col, row = pos
+        self.data[row][col] = val["data"]
+        self.edited_cell = f"Cell edited: {pos}, Cell value: {val['data']}"
+
+
+class DataTableState2(rx.State):
+    """The app state."""
+
+    clicked_cell: str = "Cell clicked: "
+    edited_cell: str = "Cell edited: "
+    right_clicked_group_header: str = "Group header right clicked: "
+    item_hovered: str = "Item Hovered: "
+    deleted: str = "Deleted: "
+
+    cols: list[dict] = [
+        {
+            "title": "Title",
+            "type": "str",
+            "width": 100,
+        },
+        {
+            "title": "Name",
+            "type": "str",
+            "group": "Data",
+            "width": 200,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "group": "Data",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "group": "Data",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "group": "Data",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "group": "Data",
+            "width": 200,
+        },
+    ]
+
+    data = [
+        [
+            "1",
+            "Harry James Potter",
+            "31 July 1980",
+            True,
+            "Gryffindor",
+            "11'  Holly  phoenix feather",
+            "Stag",
+            "Half-blood",
+        ],
+        [
+            "2",
+            "Ronald Bilius Weasley",
+            "1 March 1980",
+            True,
+            "Gryffindor",
+            "12' Ash unicorn tail hair",
+            "Jack Russell terrier",
+            "Pure-blood",
+        ],
+        [
+            "3",
+            "Hermione Jean Granger",
+            "19 September, 1979",
+            True,
+            "Gryffindor",
+            "10¾'  vine wood dragon heartstring",
+            "Otter",
+            "Muggle-born",
+        ],
+        [
+            "4",
+            "Albus Percival Wulfric Brian Dumbledore",
+            "Late August 1881",
+            True,
+            "Gryffindor",
+            "15' Elder Thestral tail hair core",
+            "Phoenix",
+            "Half-blood",
+        ],
+        [
+            "5",
+            "Rubeus Hagrid",
+            "6 December 1928",
+            False,
+            "Gryffindor",
+            "16'  Oak unknown core",
+            "None",
+            "Part-Human (Half-giant)",
+        ],
+        [
+            "6",
+            "Fred Weasley",
+            "1 April, 1978",
+            True,
+            "Gryffindor",
+            "Unknown",
+            "Unknown",
+            "Pure-blood",
+        ],
+        [
+            "7",
+            "George Weasley",
+            "1 April, 1978",
+            True,
+            "Gryffindor",
+            "Unknown",
+            "Unknown",
+            "Pure-blood",
+        ],
+    ]
+
+    def get_clicked_data(self, pos) -> str:
+        self.clicked_cell = f"Cell clicked: {pos}"
+
+    def get_edited_data(self, pos, val) -> str:
+        col, row = pos
+        self.data[row][col] = val["data"]
+        self.edited_cell = f"Cell edited: {pos}, Cell value: {val['data']}"
+
+    def get_group_header_right_click(self, index, val):
+        self.right_clicked_group_header = f"Group header right clicked at index: {index}, Group header value: {val['group']}"
+
+    def get_item_hovered(self, pos) -> str:
+        self.item_hovered = (
+            f"Item Hovered type: {pos['kind']}, Location: {pos['location']}"
+        )
+
+    def get_deleted_item(self, selection):
+        self.deleted = f"Deleted cell: {selection['current']['cell']}"
+
+    def column_resize(self, col, width):
+        self.cols[col["pos"]]["width"] = width
+
+
+class DataTableLiveState(rx.State):
+    "The app state."
+
+    running: bool = False
+    table_data: list[dict[str, Any]] = []
+    rate: int = 0.4
+    columns: list[dict[str, str]] = [
+        {
+            "title": "id",
+            "id": "v1",
+            "type": "int",
+            "width": 100,
+        },
+        {
+            "title": "advice",
+            "id": "v2",
+            "type": "str",
+            "width": 750,
+        },
+    ]
+
+    @rx.background
+    async def live_stream(self):
+        while True:
+            await asyncio.sleep(1 / self.rate)
+            if not self.running:
+                break
+
+            async with self:
+                if len(self.table_data) > 50:
+                    self.table_data.pop(0)
+
+                res = httpx.get("https://api.adviceslip.com/advice")
+                data = res.json()
+                self.table_data.append(
+                    {"v1": data["slip"]["id"], "v2": data["slip"]["advice"]}
+                )
+
+    def toggle_pause(self):
+        self.running = not self.running
+        if self.running:
+            return DataTableLiveState.live_stream

+ 108 - 0
docs/datatable_tutorial/live_stream.md

@@ -0,0 +1,108 @@
+```python exec
+import reflex as rx
+from docs.datatable_tutorial.datatable_tutorial_utils import DataTableLiveState
+
+darkTheme = {
+    "accentColor": "#8c96ff",
+    "accentLight": "rgba(202, 206, 255, 0.253)",
+    "textDark": "#ffffff",
+    "textMedium": "#b8b8b8",
+    "textLight": "#a0a0a0",
+    "textBubble": "#ffffff",
+    "bgIconHeader": "#b8b8b8",
+    "fgIconHeader": "#000000",
+    "textHeader": "#a1a1a1",
+    "textHeaderSelected": "#000000",
+    "bgCell": "#16161b",
+    "bgCellMedium": "#202027",
+    "bgHeader": "#212121",
+    "bgHeaderHasFocus": "#474747",
+    "bgHeaderHovered": "#404040",
+    "bgBubble": "#212121",
+    "bgBubbleSelected": "#000000",
+    "bgSearchResult": "#423c24",
+    "borderColor": "rgba(225,225,225,0.2)",
+    "drilldownBorder": "rgba(225,225,225,0.4)",
+    "linkColor": "#4F5DFF",
+    "headerFontStyle": "bold 14px",
+    "baseFontStyle": "13px",
+    "fontFamily": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
+}
+```
+
+# Live Streaming example
+
+Lastly let's add in an API so we can live stream data into our datatable.
+
+Here we use a [Background Task](https://reflex.dev/docs/advanced-guide/background-tasks) to stream the data into the table without blocking UI interactivity. We call an advice API using `httpx` and then append that data to the `self.table_data` state var. We also create a button that allows us to start and pause the streaming of the data by changing the value of the boolean state var `running` using the event handler `toggle_pause`. If the `running` state var is set to `True` we stream the API data, when it is set to `False` we break out of the `while` loop and end the background event.
+
+```python
+class DataTableLiveState(BaseState):
+    "The app state."
+
+    running: bool = False
+    table_data: list[dict[str, Any]] = []
+    rate: int = 0.4
+    columns: list[dict[str, str]] = [
+        {
+            "title": "id", 
+            "id": "v1", 
+            "type": "int",
+            "width": 100,
+        },
+        {
+            "title": "advice", 
+            "id": "v2", 
+            "type": "str",
+            "width": 750,
+        },
+    
+    ]
+
+    @rx.background
+    async def live_stream(self):
+        while True:
+            await asyncio.sleep(1 / self.rate)
+            if not self.running:
+                break
+
+            async with self:
+                if len(self.table_data) > 50:
+                    self.table_data.pop(0)
+
+                res = httpx.get('https://api.adviceslip.com/advice')
+                data = res.json()
+                self.table_data.append(\{"v1": data["slip"]["id"], "v2": data["slip"]["advice"]})
+
+
+    def toggle_pause(self):
+        self.running = not self.running
+        if self.running:
+            return DataTableLiveState.live_stream
+```
+
+```python demo
+rx.vstack(
+    rx.stack(
+        rx.cond(
+            ~DataTableLiveState.running,
+            rx.button("Start", on_click=DataTableLiveState.toggle_pause, color_scheme='green'),
+            rx.button("Pause", on_click=DataTableLiveState.toggle_pause, color_scheme='red'),
+        ),
+    ),
+    rx.data_editor(
+        columns=DataTableLiveState.columns,
+        data=DataTableLiveState.table_data,
+        draw_focus_ring=True,
+        row_height=50,
+        smooth_scroll_x=True,
+        smooth_scroll_y=True,
+        column_select="single",
+        # style
+        theme=darkTheme,
+        ),
+    overflow_x="auto",
+    width="100%",
+    height="30vh",
+)
+```

+ 87 - 0
docs/datatable_tutorial/simple_table.md

@@ -0,0 +1,87 @@
+```python exec
+import reflex as rx
+from docs.datatable_tutorial.datatable_tutorial_utils import DataTableState, DataTableState2
+from pcweb.pages.docs import library
+```
+
+# Data Table (Editable) Tutorial
+
+```md alert info
+#There is another [datatable component]({library.datadisplay.datatable.path}), which is only used for displaying data and does not support user interactivity or editing.
+```
+
+```python eval
+rx.box(height="2em")
+```
+
+We need to start by defining our columns that describe the shape of our data. The column var should be typed as a `list` of `dict` (`list[dict]`), where each item describes the attributes of a single column in the table.
+
+Each column dict recognizes the keys below:
+
+1. `title`: The text to display in the header of the column
+2. `id`: An id for the column, if not defined, will default to a lower case of title
+3. `width`: The width of the column (in pixels)
+4. `type`: The type of the columns, default to "str"
+
+Below we define `DataTableState` with columns definitions in the `cols` var, and data about Harry Potter characters in the `data` var..
+
+```python
+class DataTableState(rx.State):
+    """The app state."""
+    cols: list[dict] = [
+        {\"title": "Title", "type": "str"},
+        {
+            "title": "Name",
+            "type": "str",
+            "width": 300,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "width": 200,
+        },
+    ]
+    data = [
+        ["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "11'  Holly  phoenix feather", "Stag", "Half-blood"],
+        ["2", "Ronald Bilius Weasley", "1 March 1980", True,"Gryffindor", "12' Ash unicorn tail hair", "Jack Russell terrier", "Pure-blood"],
+        ["3", "Hermione Jean Granger", "19 September, 1979", True, "Gryffindor", "10¾'  vine wood dragon heartstring", "Otter", "Muggle-born"], 
+        ["4", "Albus Percival Wulfric Brian Dumbledore", "Late August 1881", True, "Gryffindor", "15' Elder Thestral tail hair core", "Phoenix", "Half-blood"], 
+        ["5", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "16'  Oak unknown core", "None", "Part-Human (Half-giant)"], 
+        ["6", "Fred Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"], 
+        ["7", "George Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"],
+    ]
+```
+
+We then define a basic table by passing the previously defined state vars as props `columns` and `data` to the `rx.data_editor()` component,
+
+```python demo
+rx.data_editor(
+    columns=DataTableState.cols,
+    data=DataTableState.data,
+)
+```
+
+This is enough to display the data, but there is no way to interact with it. On the next page we will explore how to add interactivity to our datatable.

+ 175 - 0
docs/events/background_events.md

@@ -0,0 +1,175 @@
+```python exec
+import reflex as rx
+from pcweb import constants, styles
+```
+
+# Background Tasks
+
+A background task is a special type of `EventHandler` that may run
+concurrently with other `EventHandler` functions. This enables long-running
+tasks to execute without blocking UI interactivity.
+
+A background task is defined by decorating an async `State` method with
+`@rx.background`.
+
+Whenever a background task needs to interact with the state, **it must enter an
+`async with self` context block** which refreshes the state and takes an
+exclusive lock to prevent other tasks or event handlers from modifying it
+concurrently.  Because other `EventHandler` functions may modify state while the
+task is running, **outside of the context block, Vars accessed by the background
+task may be _stale_**. Attempting to modify the state from a background task
+outside of the context block will raise an `ImmutableStateError` exception.
+
+In the following example, the `my_task` event handler is decorated with
+`@rx.background` and increments the `counter` variable every half second, as
+long as certain conditions are met. While it is running, the UI remains
+interactive and continues to process events normally.
+
+```python demo exec
+import asyncio
+import reflex as rx
+
+
+class MyTaskState(rx.State):
+    counter: int = 0
+    max_counter: int = 10
+    running: bool = False
+    _n_tasks: int = 0
+
+    @rx.background
+    async def my_task(self):
+        async with self:
+            # The latest state values are always available inside the context
+            if self._n_tasks > 0:
+                # only allow 1 concurrent task
+                return
+            
+            # State mutation is only allowed inside context block
+            self._n_tasks += 1
+
+        while True:
+            async with self:
+                # Check for stopping conditions inside context
+                if self.counter >= self.max_counter:
+                    self.running = False
+                if not self.running:
+                    self._n_tasks -= 1
+                    return
+
+                self.counter += 1
+
+            # Await long operations outside the context to avoid blocking UI
+            await asyncio.sleep(0.5)
+
+    def toggle_running(self):
+        self.running = not self.running
+        if self.running:
+            return MyTaskState.my_task
+
+    def clear_counter(self):
+        self.counter = 0
+
+
+def background_task_example():
+    return rx.hstack(
+        rx.heading(MyTaskState.counter, " /"),
+        rx.chakra.number_input(
+            value=MyTaskState.max_counter,
+            on_change=MyTaskState.set_max_counter,
+            width="8em",
+        ),
+        rx.button(
+            rx.cond(~MyTaskState.running, "Start", "Stop"),
+            on_click=MyTaskState.toggle_running,
+        ),
+        rx.button(
+            "Reset",
+            on_click=MyTaskState.clear_counter,
+        ),
+    )
+```
+
+## Task Lifecycle
+
+When a background task is triggered, it starts immediately, saving a reference to
+the task in `app.background_tasks`. When the task completes, it is removed from
+the set.
+
+Multiple instances of the same background task may run concurrently, and the
+framework makes no attempt to avoid duplicate tasks from starting.
+
+It is up to the developer to ensure that duplicate tasks are not created under
+the circumstances that are undesirable. In the example above, the `_n_tasks`
+backend var is used to control whether `my_task` will enter the increment loop,
+or exit early.
+
+## Background Task Limitations
+
+Background tasks mostly work like normal `EventHandler` methods, with certain exceptions:
+
+* Background tasks must be `async` functions.
+* Background tasks cannot modify the state outside of an `async with self` context block.
+* Background tasks may read the state outside of an `async with self` context block, but the value may be stale.
+* Background tasks may not be directly called from other event handlers or background tasks. Instead use `yield` or `return` to trigger the background task.
+
+## Low-level API
+
+The `@rx.background` decorator is a convenience wrapper around the lower-level
+`App.modify_state` async contextmanager. If more control over task lifecycle is
+needed, arbitrary async tasks may safely manipulate the state using an
+`async with app.modify_state(token) as state` context block. In this case the
+`token` for a state is retrieved from `state.get_token()` and identifies a
+single instance of the state (i.e. the state for an individual browser tab).
+
+Care must be taken to **never directly modify the state outside of the
+`modify_state` contextmanager**. If the code that creates the task passes a
+direct reference to the state instance, this can introduce subtle bugs or not
+work at all (if redis is used for state storage).
+
+The following example creates an arbitrary `asyncio.Task` to fetch data and then
+uses the low-level API to safely update the state and send the changes to the
+frontend.
+
+```python demo exec
+import asyncio
+import httpx
+import reflex as rx
+
+my_tasks = set()
+
+
+async def _fetch_data(app, token):
+    async with httpx.AsyncClient() as client:
+        response = await client.get("https://api.github.com/zen")
+    async with app.modify_state(token) as state:
+        substate = state.get_substate(
+            LowLevelState.get_full_name().split("."),
+        )
+        substate.result = response.text
+
+
+class LowLevelState(rx.State):
+    result: str = ""
+
+    def fetch_data(self):
+        task = asyncio.create_task(
+            _fetch_data(
+                app=rx.utils.prerequisites.get_app().app,
+                token=self.get_token(),
+            ),
+        )
+
+        # Always save a reference to your tasks until they are done
+        my_tasks.add(task)
+        task.add_done_callback(my_tasks.discard)
+
+
+def low_level_example():
+    return rx.vstack(
+        rx.text(LowLevelState.result),
+        rx.button(
+            "Fetch Data",
+            on_click=LowLevelState.fetch_data,
+        ),
+    )
+```

+ 90 - 0
docs/events/chaining_events.md

@@ -0,0 +1,90 @@
+```python exec
+import reflex as rx
+```
+
+# Chaining events
+
+## Calling Event Handlers From Event Handlers
+
+You can call other event handlers from event handlers to keep your code modular. Just use the `self.call_handler` syntax to run another event handler. As always, you can yield within your function to send incremental updates to the frontend.
+
+```python demo exec
+import asyncio
+
+class CallHandlerState(rx.State):
+    count: int = 0
+    progress: int = 0
+
+    async def run(self):
+        # Reset the count.
+        self.set_progress(0)
+        yield
+
+        # Count to 10 while showing progress.
+        for i in range(10):
+            # Wait and increment.
+            await asyncio.sleep(0.5)
+            self.count += 1
+
+            # Update the progress.
+            self.set_progress(i + 1)
+
+            # Yield to send the update.
+            yield
+
+
+def call_handler_example():
+    return rx.vstack(
+        rx.badge(CallHandlerState.count, font_size="1.5em", color_scheme="green"),
+        rx.progress(value=CallHandlerState.progress, max=10, width="100%"),
+        rx.button("Run", on_click=CallHandlerState.run),
+    )
+```
+
+## Returning Events From Event Handlers
+
+So far, we have only seen events that are triggered by components. However, an event handler can also return events.
+
+In Reflex, event handlers run synchronously, so only one event handler can run at a time, and the events in the queue will be blocked until the current event handler finishes.The difference between returning an event and calling an event handler is that returning an event will send the event to the frontend and unblock the queue.
+
+```md alert
+Be sure to use the class name `State` (or any substate) rather than `self` when returning events.
+```
+
+Try entering an integer in the input below then clicking out.
+
+```python demo exec
+class CollatzState(rx.State):
+    count: int = 0
+
+    def start_collatz(self, count: str):
+        """Run the collatz conjecture on the given number."""
+        self.count = abs(int(count))
+        return CollatzState.run_step
+
+    async def run_step(self):
+        """Run a single step of the collatz conjecture."""
+
+        while self.count > 1:
+            await asyncio.sleep(0.5)
+
+            if self.count % 2 == 0:
+                # If the number is even, divide by 2.
+                self.count /= 2
+            else:
+                # If the number is odd, multiply by 3 and add 1.
+                self.count = self.count * 3 + 1
+            yield
+
+
+def collatz_example():
+    return rx.vstack(
+        rx.badge(CollatzState.count, font_size="1.5em", color_scheme="green"),
+        rx.chakra.input(on_blur=CollatzState.start_collatz),
+    )
+
+```
+
+In this example, we run the [Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture) on a number entered by the user.
+
+When the `on_blur` event is triggered, the event handler `start_collatz` is called. It sets the initial count, then calls `run_step` which runs until the count reaches `1`.

+ 34 - 0
docs/events/event_arguments.md

@@ -0,0 +1,34 @@
+```python exec
+import reflex as rx
+```
+
+# Event Arguments
+
+In some use cases, you want to pass additional arguments to your event handlers. To do this you can bind an event trigger to a lambda, which can call your event handler with the arguments you want.
+
+Try typing a color in an input below and clicking away from it to change the color of the input.
+
+```python demo exec
+class ArgState(rx.State):
+    colors: list[str] = ["rgba(222,44,12)", "white", "#007ac2"]
+
+    def change_color(self, color: str, index: int):
+        self.colors[index] = color
+
+def event_arguments_example():
+    return rx.hstack(
+        rx.chakra.input(default_value=ArgState.colors[0], on_blur=lambda c: ArgState.change_color(c, 0), bg=ArgState.colors[0]),
+        rx.chakra.input(default_value=ArgState.colors[1], on_blur=lambda c: ArgState.change_color(c, 1), bg=ArgState.colors[1]),
+        rx.chakra.input(default_value=ArgState.colors[2], on_blur=lambda c: ArgState.change_color(c, 2), bg=ArgState.colors[2]),
+    )
+
+```
+
+In this case, in we want to pass two arguments to the event handler `change_color`, the color and the index of the color to change.
+
+The `on_blur` event trigger passes the text of the input as an argument to the lambda, and the lambda calls the `change_color` event handler with the text and the index of the input.
+
+```md alert warning
+# Event Handler Parameters should provide type annotations.
+Like state vars, be sure to provide the right type annotations for the parameters in an event handler.
+```

+ 41 - 0
docs/events/events_overview.md

@@ -0,0 +1,41 @@
+```python exec
+import reflex as rx
+
+from pcweb.pages.docs.library import library
+```
+
+# Events Overview
+
+Events are how we modify the state and make the app interactive.
+
+Event triggers are component props that create an event to be sent to an event handler.
+Each component supports a set of events triggers. They are described in each [component's documentation]({library.path}) in the event trigger section.
+
+Lets take a look at an example below. Try mousing over the heading to change the word.
+
+```python demo exec
+class WordCycleState(rx.State):
+    # The words to cycle through.
+    text: list[str] = ["Welcome", "to", "Reflex", "!"]
+
+    # The index of the current word.
+    index: int = 0
+
+    def next_word(self):
+        self.index = (self.index + 1) % len(self.text)
+
+    @rx.var
+    def get_text(self) -> str:
+        return self.text[self.index]
+
+def event_triggers_example():
+    return rx.heading(
+        WordCycleState.get_text,
+        on_mouse_over=WordCycleState.next_word,
+        color="green",
+    )
+
+```
+
+In this example, the heading component has the event trigger, `on_mouse_over`.
+Whenever the user hovers over the heading, the `next_word` handler will be called to cycle the word. Once the handler returns, the UI will be updated to reflect the new state.

+ 21 - 0
docs/events/page_load_events.md

@@ -0,0 +1,21 @@
+```python exec
+import reflex as rx
+```
+
+# Page Load Events
+
+You can also specify a function to run when the page loads. This can be useful for fetching data once vs on every render or state change.
+In this example, we fetch data when the page loads:
+
+```python
+class State(rx.State):
+    data: Dict[str, Any]
+
+    def get_data(self):
+        # Fetch data
+        self.data = fetch_data()
+
+@rx.page(on_load=State.get_data)
+def index():
+    return rx.text('A Beautiful App')
+```

+ 52 - 0
docs/events/setters.md

@@ -0,0 +1,52 @@
+```python exec
+import reflex as rx
+```
+
+# Setters
+
+Every base var has a built-in event handler to set it's value for convenience, called `set_VARNAME`.
+
+Say you wanted to change the value of the select component. You could write your own event handler to do this:
+
+```python demo exec
+
+options: list[str] = ["1", "2", "3", "4"]
+class SetterState1(rx.State):
+    selected: str = "1"
+
+    def change(self, value):
+        self.selected = value
+
+
+def code_setter():
+    return rx.vstack(
+        rx.badge(SetterState1.selected, color_scheme="green"),
+        rx.select(
+            options,
+            on_change= lambda value: SetterState1.change(value),
+        )
+    )
+
+```
+
+Or you could could use a built-in setter for conciseness.
+
+```python demo exec
+
+options: list[str] = ["1", "2", "3", "4"]
+class SetterState2(rx.State):
+    selected: str = "1"
+
+def code_setter_2():
+    return rx.vstack(
+        rx.badge(SetterState2.selected, color_scheme="green"),
+        rx.select(
+            options,
+            on_change= SetterState2.set_selected,
+        )
+    )
+```
+
+In this example, the setter for `selected` is `set_selected`. Both of these examples are equivalent.
+
+Setters are a great way to make your code more concise. But if you want to do something more complicated, you can always write your own function in the state.

+ 20 - 0
docs/events/special_events.md

@@ -0,0 +1,20 @@
+```python exec
+import reflex as rx
+
+from pcweb.pages.docs import api_reference
+```
+
+# Special Events
+
+Reflex also has built-in special events can be found in the [reference]({api_reference.special_events.path}).
+
+For example, an event handler can trigger an alert on the browser.
+
+```python demo exec
+class SpecialEventsState(rx.State):
+    def alert(self):
+        return rx.window_alert("Hello World!")
+
+def special_events_example():
+    return rx.button("Alert", on_click=SpecialEventsState.alert)
+```

+ 63 - 0
docs/events/yield_events.md

@@ -0,0 +1,63 @@
+```python exec
+import reflex as rx
+
+```
+
+# Yielding Multiple Updates
+
+A regular event handler will send a `StateUpdate` when it has finished running. This works fine for basic event, but sometimes we need more complex logic. To update the UI multiple times in an event handler, we can `yield` when we want to send an update.
+
+To do so, we can use the Python keyword `yield`. For every yield inside the function, a `StateUpdate` will be sent to the frontend with the changes up to this point in the execution of the event handler.
+
+```python demo exec
+
+import asyncio
+
+class MultiUpdateState(rx.State):
+    count: int = 0
+
+    async def timed_update(self):
+        for i in range(5):
+            await asyncio.sleep(0.5)
+            self.count += 1
+            yield
+
+
+def multi_update():
+    return rx.vstack(
+    rx.text(MultiUpdateState.count),
+    rx.button("Start", on_click=MultiUpdateState.timed_update)
+)
+
+```
+
+Here is another example of yielding multiple updates with a loading icon.
+
+```python demo exec
+
+import asyncio
+
+class ProgressExampleState(rx.State):
+    count: int = 0
+    show_progress: bool = False
+
+    async def increment(self):
+        self.show_progress = True
+        yield
+        # Think really hard.
+        await asyncio.sleep(0.5)
+        self.count += 1
+        self.show_progress = False
+
+def progress_example():
+    return rx.cond(
+        ProgressExampleState.show_progress,
+        rx.chakra.circular_progress(is_indeterminate=True),
+        rx.heading(
+            ProgressExampleState.count,
+            on_click=ProgressExampleState.increment,
+            _hover={"cursor": "pointer"},
+        )
+    )
+
+```

+ 91 - 0
docs/getting-started/configuration.md

@@ -0,0 +1,91 @@
+```python exec
+config_api_ref_url = "/docs/api-reference/config"
+cli_api_ref_url = "/docs/api-reference/cli"
+```
+
+# Configuration
+
+Reflex apps can be configured using a configuration file, environment variables, and command line arguments.
+
+## Configuration File
+
+Running `reflex init` will create an `rxconfig.py` file in your root directory.
+You can pass keyword arguments to the `Config` class to configure your app.
+
+For example:
+
+```python
+# rxconfig.py
+import reflex as rx
+
+config = rx.Config(
+    app_name="my_app_name",
+    # Connect to your own database.
+    db_url="postgresql://user:password@localhost:5432/my_db",
+    # Change the frontend port.
+    frontend_port=3001,
+)
+```
+
+See the [config reference]({config_api_ref_url}) for all the parameters available.
+
+## Environment Variables
+
+You can override the configuration file by setting environment variables.
+For example, to override the `frontend_port` setting, you can set the `FRONTEND_PORT` environment variable.
+
+```bash
+FRONTEND_PORT=3001 reflex run
+```
+
+## Command Line Arguments
+
+Finally, you can override the configuration file and environment variables by passing command line arguments to `reflex run`.
+
+```bash
+reflex run --frontend-port 3001
+```
+
+See the [CLI reference]({cli_api_ref_url}) for all the arguments available.
+
+## Anonymous Usage Statistics
+
+Reflex collects completely anonymous telemetry data about general usage.
+Participation in this anonymous program is optional, and you may opt-out if you'd not like to share any information.
+
+### What's Being Collected
+
+Telemetry allows us to understand how Reflex is used, what features are most important, and how we can improve the product.
+
+The following information is collected:
+
+* Operating system
+* CPU count
+* Memoryd
+* Python version
+* Reflex version
+
+### How to Opt-Out
+
+To disable telemetry, set `telemetry_enabled=False` in your `rxconfig.py` file.
+
+```python
+config = rx.Config(
+    app_name="hello",
+    telemetry_enabled=False,
+)
+```
+
+Alternatively, you can set the `TELEMETRY_ENABLED` environment variable to `False`.
+
+## Customizable App Data Directory
+
+The `REFLEX_DIR` environment variable can be set, which allows users to set the location where Reflex writes helper tools like Bun and NodeJS.
+
+By default we use Platform specific directories:
+
+On windows, `C:/Users/<username>/AppData/Local/reflex` is used.
+
+On macOS, `~/Library/Application Support/reflex` is used.
+
+On linux, `~/.local/share/reflex` is used.

+ 147 - 0
docs/getting-started/installation.md

@@ -0,0 +1,147 @@
+```python exec
+from pcweb import constants
+import reflex as rx
+app_name = "my_app_name"
+default_url = "http://localhost:3000"
+```
+
+# Installation
+
+Reflex requires Python 3.8+.
+
+## Virtual Environment
+
+We **highly recommend** creating a virtual environment for your project.
+
+[venv]({constants.VENV_URL}) is the standard option. [conda]({constants.CONDA_URL}) and [poetry]({constants.POETRY_URL}) are some alternatives.
+
+## Install on macOS/Linux
+
+We will go with [venv]({constants.VENV_URL}) here.
+
+
+### Prerequisites
+macOS (Apple Silicon) users should install [Rosetta 2](https://support.apple.com/en-us/HT211861). Run this command:
+    
+`/usr/sbin/softwareupdate --install-rosetta --agree-to-license`
+
+
+### Create the project directory 
+
+Replace `{app_name}` with your project name. Switch to the new directory.
+
+```bash
+mkdir {app_name}
+cd {app_name}
+```
+
+### Setup virtual environment
+
+```bash
+python3 -m venv .venv
+source .venv/bin/activate
+```
+
+```md alert warning
+# Error `No module named venv`
+
+While Python typically ships with `venv` it is not installed by default on some systems.
+If so, please install it manually. E.g. on Ubuntu Linux, run `sudo apt-get install python3-venv`.
+```
+
+### Install Reflex package
+
+Reflex is available as a [pip](constants.PIP_URL) package.
+
+```bash
+pip install reflex
+```
+
+```md alert warning
+# Error `command not found: pip`
+
+While Python typically ships with `pip` as the standard package management tool, it is not installed by default on some systems.
+You may need to install it manually. E.g. on Ubuntu Linux, run `apt-get install python3-pip`
+```
+
+### Initialize the project
+
+```bash
+reflex init
+```
+
+```md alert warning
+# Error `command not found: reflex`
+If you install Reflex with no virtual environment and get this error it means your `PATH` cannot find the reflex package. 
+A virtual environment should solve this problem, or you can try running `python3 -m` before the reflex command.
+```
+
+
+## Install on Windows
+
+### Prerequisites
+For Windows users, we recommend using [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/about) for optimal performance.
+
+WSL users should refer to instructions for Linux above.
+
+For the rest of this section we will work with native Windows (non-WSL).
+
+We will go with [venv]({constants.VENV_URL}) here, for virtual environments.
+
+### Create a new project directory
+
+```bash
+mkdir {app_name}
+cd {app_name}
+```
+
+### Setup virtual environment
+
+```bash
+py -3 -m venv .venv
+.venv\\Scripts\\activate
+```
+
+### Install Reflex package
+
+```bash
+pip install reflex
+```
+
+### Initialize the project
+
+```bash
+reflex init
+```
+
+```md alert warning
+# Error `command not found: reflex`
+
+The Reflex framework includes the `reflex` command line (CLI) tool. Using a virtual environment is highly recommended for a seamless experience (see below).",
+```
+
+## Run the App
+
+Run it in development mode:
+
+```bash
+reflex run
+```
+
+Your app runs at [http://localhost:3000](http://localhost:3000).
+
+Reflex prints logs to the terminal. To increase log verbosity to help with debugging, use the `--loglevel` flag:
+
+```bash
+reflex run --loglevel debug
+```
+
+Reflex will *hot reload* any code changes in real time when running in development mode. Your code edits will show up on [http://localhost:3000](http://localhost:3000) automatically.
+
+## (Optional) Run the demo app
+
+The demo app showcases some of Reflex's features.
+
+```bash
+reflex demo
+```

+ 226 - 0
docs/getting-started/introduction.md

@@ -0,0 +1,226 @@
+```python exec
+import reflex as rx
+from pcweb import constants, styles
+from pcweb.templates.docpage import doccode
+from pcweb.pages.docs import tutorial
+from pcweb.pages.docs import getting_started
+from pcweb.pages.docs import wrapping_react
+from pcweb.pages.docs.library import library
+from pcweb.pages.docs import vars
+```
+
+<!-- TODO how do we consistently rename page title? -->
+# Introduction
+
+**Reflex** is an open-source framework for quickly building beautiful, interactive web applications in **pure Python**.
+
+## Goals
+
+```md section
+# Pure Python
+Use Python for everything. Don't worry about learning a new language.
+
+# Easy to Learn
+Build and share your first app in minutes. No web development experience required.
+
+# Full Flexibility
+Remain as flexible as traditional web frameworks. Reflex is easy to use, yet allows for advanced use cases.
+
+Build anything from small data science apps to large, multi-page websites. **This entire site was built and deployed with Reflex!**
+
+# Batteries Included
+No need to reach for a bunch of different tools. Reflex handles the user interface, server-side logic, and deployment of your app.
+```
+
+## An example: Make it count
+
+Here, we go over a simple counter app that lets the user count up or down.
+
+<!-- TODO use radix components, to allow more concise styling - e.g. all them props -->
+
+
+
+```python exec
+class CounterExampleState(rx.State):
+    count: int = 0
+
+    def increment(self):
+        self.count += 1
+
+    def decrement(self):
+        self.count -= 1
+
+```
+
+
+```python demo box
+rx.hstack(
+    rx.button(
+        "Decrement",
+        color_scheme="ruby",
+        on_click=CounterExampleState.decrement,
+    ),
+    rx.heading(CounterExampleState.count, font_size="2em"),
+    rx.button(
+        "Increment",
+        color_scheme="grass",
+        on_click=CounterExampleState.increment,
+    ),
+    spacing="4",
+)
+```
+
+Here is the full code for this example:
+
+```python
+import reflex as rx
+
+
+class State(rx.State):
+    count: int = 0
+
+    def increment(self):
+        self.count += 1
+
+    def decrement(self):
+        self.count -= 1
+
+def index():
+    return rx.hstack(
+        rx.button(
+            "Decrement",
+            color_scheme="ruby",
+            on_click=State.decrement,
+        ),
+        rx.heading(State.count, font_size="2em"),
+        rx.button(
+            "Increment",
+            color_scheme="grass",
+            on_click=State.increment,
+        ),
+        spacing="4",
+    )
+
+
+app = rx.App()
+app.add_page(index)
+```
+
+
+## The Structure of a Reflex App
+
+Let's break this example down.
+
+### Import
+
+```python
+import reflex as rx
+```
+
+We begin by importing the `reflex` package (aliased to `rx`). We reference Reflex objects as `rx.*` by convention.
+
+### State
+
+```python
+class State(rx.State):
+    count: int = 0
+```
+
+The state defines all the variables (called **[vars]({vars.base_vars.path})**) in an app that can change, as well as the functions (called **[event_handlers](#event-handlers)**) that change them.
+
+Here our state has a single var, `count`, which holds the current value of the counter. We initialize it to `0`.
+
+### Event Handlers
+
+```python
+def increment(self):
+    self.count += 1
+
+def decrement(self):
+    self.count -= 1
+```
+
+Within the state, we define functions, called **event handlers**, that change the state vars.
+
+Event handlers are the only way that we can modify the state in Reflex.
+They can be called in response to user actions, such as clicking a button or typing in a text box.
+These actions are called **events**.
+
+Our counter app has two event handlers, `increment` and `decrement`.
+
+### User Interface (UI)
+
+```python
+def index():
+    return rx.hstack(
+        rx.button(
+            "Decrement",
+            color_scheme="ruby",
+            on_click=State.decrement,
+        ),
+        rx.heading(State.count, font_size="2em"),
+        rx.button(
+            "Increment",
+            color_scheme="grass",
+            on_click=State.increment,
+        ),
+        spacing="4",
+    )
+```
+
+This function defines the app's user interface.
+
+We use different components such as `rx.hstack`, `rx.button`, and `rx.heading` to build the frontend. Components can be nested to create complex layouts, and can be styled using the full power of CSS.
+
+Reflex comes with [50+ built-in components]({library.path}) to help you get started.
+We are actively adding more components. Also, it's easy to [wrap your own React components]({wrapping_react.overview.path}).
+
+```python
+rx.heading(State.count, font_size="2em"),
+```
+
+Components can reference the app's state vars.
+The `rx.heading` component displays the current value of the counter by referencing `State.count`.
+All components that reference state will reactively update whenever the state changes.
+
+```python
+rx.button(
+    "Decrement",
+    color_scheme="ruby",
+    on_click=State.decrement,
+),
+```
+
+Components interact with the state by binding events triggers to event handlers.
+For example, `on_click` is an event that is triggered when a user clicks a component.
+
+The first button in our app binds its `on_click` event to the `State.decrement` event handler.  Similarly the second button binds `on_click` to `State.increment`.
+
+In other words, the sequence goes like this:
+
+* User clicks "increment" on the UI.
+* `on_click` event is triggered.
+* Event handler `State.increment` is called.
+* `State.count` is incremented.
+* UI updates to reflect the new value of `State.count`.
+
+### Add pages
+
+Next we define our app and add the counter component to the base route.
+
+```python
+app = rx.App()
+app.add_page(index)
+```
+
+## Next Steps
+
+🎉 And that's it!
+
+We've created a simple, yet fully interactive web app in pure Python.
+
+By continuing with our documentation, you will learn how to building awesome apps with Reflex.
+
+For a glimpse of the possibilities, check out these resources:
+
+* For a more real-world example, check out the [tutorial]({tutorial.intro.path}).

+ 66 - 0
docs/getting-started/project-structure.md

@@ -0,0 +1,66 @@
+# Project Structure
+
+## Directory Structure
+
+```python exec
+app_name = "hello"
+```
+
+Let's create a new app called `{app_name}`
+
+```bash
+mkdir {app_name}
+cd {app_name}
+reflex init
+```
+
+This will create a directory structure like this:
+
+```bash
+{app_name}
+├── .web
+├── assets
+├── {app_name}
+│   ├── __init__.py
+│   └── {app_name}.py
+└── rxconfig.py
+```
+
+Let's go over each of these directories and files.
+
+## .web
+
+This is where the compiled Javascript files will be stored. You will never need to touch this directory, but it can be useful for debugging.
+
+Each Reflex page will compile to a corresponding `.js` file in the `.web/pages` directory.
+
+## Assets
+
+The `assets` directory is where you can store any static assets you want to be publicly available. This includes images, fonts, and other files.
+
+For example, if you save an image to `assets/image.png` you can display it from your app like this:
+
+```python
+rx.image(src="image.png")
+```
+
+## Main Project
+
+Initializing your project creates a directory with the same name as your app. This is where you will write your app's logic.
+
+Reflex generates a default app within the `{app_name}/{app_name}.py` file. You can modify this file to customize your app.
+
+## Configuration
+
+The `rxconfig.py` file can be used to configure your app. By default it looks something like this:
+
+```python
+import reflex as rx
+
+
+config = rx.Config(
+    app_name="{app_name}",
+)
+```
+
+We will discuss configuration in more detail in the next section.

+ 69 - 0
docs/hosting/deploy-quick-start.md

@@ -0,0 +1,69 @@
+# Reflex Hosting Service
+
+```python exec
+import reflex as rx
+from pcweb import constants
+from pcweb.pages import docs
+from pcweb.templates.docpage import doccmdoutput
+```
+
+So far, we have been running our apps locally on our own machines.
+But what if we want to share our apps with the world? This is where
+the hosting service comes in.
+
+## Quick Start
+
+Reflex’s hosting service makes it easy to deploy your apps without worrying about configuring the infrastructure.
+
+### Prerequisites
+
+1. Hosting service requires `reflex>=0.3.2`.
+2. This tutorial assumes you have successfully `reflex init` and `reflex run` your app.
+3. Also make sure you have a `requirements.txt` file at the top level app directory that contains all your python dependencies!
+
+### Authentication
+
+First, create an account or log into it using the following command.
+
+```bash
+reflex login
+```
+
+You will be redirected to your browser where you can authenticate through Github or Gmail.
+
+### Deployment
+
+Once you have successfully authenticated, you can start deploying your apps.
+
+Navigate to the project directory that you want to deploy and type the following command:
+
+```bash
+reflex deploy
+```
+
+The command is by default interactive. It asks you a few questions for information required for the deployment.
+
+**Name**: choose a name for the deployed app. This name will be part of the deployed app URL, i.e. `<app-name>.reflex.run`. The name should only contain domain name safe characters: no slashes, no underscores. Domain names are case insensitive. To avoid confusion, the name you choose here is also case insensitive. If you enter letters in upper cases, we automatically convert them to lower cases.
+
+**Regions**: enter the region code here or press `Enter` to accept the default. The default code `sjc` stands for San Jose, California in the US west coast. Check the list of supported regions at [reflex deployments regions](#reflex-deployments-regions).
+
+**Envs**: `Envs` are environment variables. You might not have used them at all in your app. In that case, press `Enter` to skip. More on the environment variables in the later section [Environment Variables](#environment-variables).
+
+That’s it! You should receive some feedback on the progress of your deployment and in a few minutes your app should be up. 🎉
+
+```md alert info
+Once your code is uploaded, the hosting service will start the deployment. After a complete upload, exiting from the command **does not** affect the deployment process. The command prints a message when you can safely close it without affecting the deployment.
+```
+
+## See it in Action
+
+Below is a video of deploying the [AI chat app]({docs.tutorial.intro.path}) to our hosting service.
+
+```python eval
+rx.center(
+    rx.video(url="https://www.youtube.com/embed/pf3FKE26hx4"),
+    rx.box(height="3em"),
+    width="100%",
+    padding_y="2em"
+)
+```

+ 354 - 0
docs/hosting/hosting-cli-commands.md

@@ -0,0 +1,354 @@
+# Reflex Hosting Service CLI Commands
+
+```python exec
+import reflex as rx
+from pcweb import constants
+from pcweb.templates.docpage import doccmdoutput
+```
+
+## Concepts
+
+### Requirements
+
+To be able to deploy your app, we ask that you prepare a `requirements.txt` file containing all the required Python packages for it. The hosting service runs a `pip install` command based on this file to prepare the instances that run your app. We recommend that  you use a Python virtual environment when starting a new app, and only install the necessary packages. This reduces the preparation time installing no more packages than needed, and your app is deployed faster. There are a lot of resources online on Python virtual environment tools and how to capture the packages in a `requirements.txt` file.
+
+### Environment Variables
+
+When deploying to Reflex's hosting service, the command prompt asks if you want to add any environment variables. These are encrypted and safely stored. We recommend that backend API keys or secrets are entered as `envs`. Make sure to enter the `envs` without any quotation marks.
+
+The environment variables are key value pairs. We do not show the values of them in any CLI commands, only their names (or keys). However, if your app intentionally prints the values of these variables, the logs returned still contain the printed values. At the moment, the logs are not censored for anything resembling secrets. Only the app owner and Reflex team admins can access these logs.
+
+You access the values of `envs` by referencing `os.environ` with their names as keys in your app's backend. For example, if you set an env `ASYNC_DB_URL`, you are able to access it by `os.environ["ASYNC_DB_URL"]`. Some Python libraries automatically look for certain environment variables. For example, `OPENAI_API_KEY` for the `openai` python client. The `boto3` client credentials can be configured by setting `AWS_ACCESS_KEY_ID`,`AWS_SECRET_ACCESS_KEY`. This information is typically available in the documentation of the Python packages you use.
+
+### Updating Deployment
+
+To redeploy or update your app, navigate to the project directory and type `reflex deploy` again. This command communicates with the hosting service to automatically detects your existing app by the same name. This time the deploy command overwrites the app. You should see a prompt similar to `Overwrite deployment [ app-name ] ...`. This operation is a complete overwrite and not an incremental update.
+
+## CLI Command Reference
+
+All the `reflex` commands come with a help manual. The help manual lists additional command options that may be useful. You type `--help` to see the help manual. Some commands are organized under a `subcommands` series. Here is an example below. Note that the help manual may look different depending on the version of `reflex` or the `reflex-hosting-cli`.
+
+```python eval
+doccmdoutput(
+    command="reflex deployments --help",
+    output="""Usage: reflex deployments [OPTIONS] COMMAND [ARGS]...
+
+  Subcommands for managing the Deployments.
+
+Options:
+  --help  Show this message and exit.
+
+Commands:
+  build-logs  Get the build logs for a deployment.
+  delete      Delete a hosted instance.
+  list        List all the hosted deployments of the authenticated user.
+  logs        Get the logs for a deployment.
+  regions     List all the regions of the hosting service.
+  status      Check the status of a deployment.
+"""
+)
+```
+
+### Authentication Commands
+
+#### reflex login
+
+When you type the `reflex login` command for the very first time, it opens the hosting service login page in your browser. We authenticate users through OAuth. At the moment the supported OAuth providers are Github and Gmail. You should be able to revoke such authorization on your Github and Google account settings page. We do not log into your Github or Gmail account. OAuth authorization provides us your email address and in case of Github your username handle. We use those to create an account for you. The email used in the original account creation is used to identify you as a user. If you have authenticated using different emails, those create separate accounts. To switch to another account, first log out using the `reflex logout` command. More details on the logout command are in [reflex logout](#reflex-logout) section.
+
+```python eval
+doccmdoutput(
+    command="reflex login",
+    output="""Opening https://control-plane.reflex.run ...
+Successfully logged in.
+""",
+)
+```
+
+After authentication, the browser redirects to the original hosting service login page. It shows that you have logged in. Now you can return to the terminal where you type the login command. It should print a message such as `Successfully logged in`.
+
+Your access token is cached locally in the reflex support directory. For subsequent login commands, the cached token is validated first. If the token is still valid, the CLI command simply shows `You’re already logged in`. If the token is expired or simply not valid for any reason, the login command tries to open your browser again for web based authentication.
+
+#### reflex logout
+
+When you successfully authenticate with the hosting service, there is information cached in two different places: a file containing the access token in the reflex support directory, and cookies in your browser. The cookies include the access token, a refresh token, some unix epochs indicating when the access token expires. The logout command removes the cached information from these places.
+
+### Deployment Commands
+
+#### reflex deploy
+
+This is the command to deploy a reflex app from its top level app directory. This directory contains a `rxconfig.py` where you run `reflex init` and `reflex run`.
+
+A `requirements.txt` file is required. The deploy command checks the content of this file against the top level packages installed in your current Python environment. If the command detects new packages in your Python environment, or newer versions of the same packages, it prints the difference and asks if you would like to update your `requirements.txt`. Make sure you double check the suggested updates. This functionality is added in more recent versions of the hosting CLI package `reflex-hosting-cli>=0.1.3`.
+
+```python eval
+doccmdoutput(
+    command="reflex deploy",
+    output="""Info: The requirements.txt may need to be updated.
+--- requirements.txt
++++ new_requirements.txt
+@@ -1,3 +1,3 @@
+-reflex>=0.2.0
+-openai==0.28
++openai==0.28.0
++reflex==0.3.8
+
+Would you like to update requirements.txt based on the changes above? [y/n]: y
+
+Choose a name for your deployed app (https://<picked-name>.reflex.run)
+Enter to use default. (webui-gray-sun): demo-chat
+Region to deploy to. See regions: https://bit.ly/46Qr3mF
+Enter to use default. (sjc): lax
+Environment variables for your production App ...
+ * env-1 name (enter to skip): OPENAI_API_KEY
+   env-1 value: sk-*********************
+ * env-2 name (enter to skip):
+Finished adding envs.
+──────────────── Compiling production app and preparing for export. ────────────────
+Zipping Backend: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 12/12 0:00:00
+Uploading Backend code and sending request ...
+Backend deployment will start shortly.
+──────────────── Compiling production app and preparing for export. ────────────────
+Compiling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 9/9 0:00:00
+Creating Production Build:  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 9/9 0:00:07
+Zipping Frontend: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 20/20 0:00:00
+Uploading Frontend code and sending request ...
+Frontend deployment will start shortly.
+───────────────────────────── Deploying production app. ────────────────────────────
+Deployment will start shortly: https://demo-chat.reflex.run
+Closing this command now will not affect your deployment.
+Waiting for server to report progress ...
+2024-01-12 12:24:54.188271 PST | Updating frontend...
+2024-01-12 12:24:55.074264 PST | Frontend updated!
+2024-01-12 12:24:55.137679 PST | Deploy success (frontend)
+2024-01-12 12:24:59.722384 PST | Updating backend...
+2024-01-12 12:25:01.006386 PST | Building backend image...
+2024-01-12 12:26:03.672379 PST | Deploying backend image...
+2024-01-12 12:26:21.017946 PST | Backend updated!
+2024-01-12 12:26:21.018003 PST | Deploy success (backend)
+Waiting for the new deployment to come up
+Your site [ demo-chat ] at ['lax'] is up: https://demo-chat.reflex.run
+""",
+)
+```
+
+The deploy command is by default interactive. To deploy without interaction, add `--no-interactive` and set the relevant command options as deployment settings. Type `reflex deploy --help` to see the help manual for explanations on each option. The deploy sequences are the same, whether the deploy command is interactive or not.
+
+```bash
+reflex deploy --no-interactive -k todo -r sjc -r sea --env OPENAI_API_KEY=YOU-KEY-NO-EXTRA-QUOTES --env DB_URL=YOUR-EXTERNAL-DB-URI --env KEY3=THATS-ALOTOF-KEYS
+```
+
+#### reflex deployments list
+
+List all your deployments.
+
+```python eval
+doccmdoutput(
+    command="reflex deployments list",
+    output="""key                           regions  app_name              reflex_version       cpus     memory_mb  url                                         envs
+----------------------------  -------  --------------------  ----------------  -------   -----------  ------------------------------------------  ---------
+webui-navy-star               ['sjc']  webui                 0.3.7                   1          1024  https://webui-navy-star.reflex.run          ['OPENAI_API_KEY']
+chatroom-teal-ocean           ['ewr']  chatroom              0.3.2                   1          1024  https://chatroom-teal-ocean.reflex.run      []
+sales-navy-moon               ['phx']  sales                 0.3.4                   1          1024  https://sales-navy-moon.reflex.run          []
+simple-background-tasks       ['yul']  lorem_stream          0.3.7                   1          1024  https://simple-background-tasks.reflex.run  []
+snakegame                     ['sjc']  snakegame             0.3.3                   1          1024  https://snakegame.reflex.run                []
+basic-crud-navy-apple         ['dfw']  basic_crud            0.3.8                   1          1024  https://basic-crud-navy-apple.reflex.run    []
+""",
+)
+```
+
+#### reflex deployments status `app-name`
+
+Get the status of a specific app, including backend and frontend.
+
+```python eval
+doccmdoutput(
+    command="reflex deployments status clock-gray-piano",
+    output="""Getting status for [ clock-gray-piano ] ...
+
+backend_url                                reachable    updated_at
+-----------------------------------------  -----------  ------------
+https://rxh-prod-clock-gray-piano.fly.dev  False        N/A
+
+
+frontend_url                               reachable    updated_at
+-----------------------------------------  -----------  -----------------------
+https://clock-gray-piano.reflex.run        True         2023-10-13 15:23:07 PDT
+""",
+)
+```
+
+#### reflex deployments logs `app-name`
+
+Get the logs from a specific deployment.
+
+The returned logs are the messages printed to console. If you have `print` statements in your code, they show up in these logs. By default, the logs command return the latest 100 lines of logs and continue to stream any new lines.
+
+We have added more options to this command including `from` and `to` timestamps and the limit on how many lines of logs to fetch. Accepted timestamp formats include the ISO 8601 format, unix epoch and relative timestamp. A relative timestamp is some time units ago from `now`. The units are `d (day), h (hour), m (minute), s (second)`. For example, `--from 3d --to 4h` queries from 3 days ago up to 4 hours ago. For the exact syntax in the version of CLI you use, refer to the help manual.
+
+```python eval
+doccmdoutput(
+    command="reflex deployments logs todo",
+    output="""Note: there is a few seconds delay for logs to be available.
+2023-10-13 22:18:39.696028 | rxh-dev-todo | info | Pulling container image registry.fly.io/rxh-dev-todo:depot-1697235471
+2023-10-13 22:18:41.462929 | rxh-dev-todo | info | Pulling container image registry.fly.io/rxh-dev-todo@sha256:60b7b531e99e037f2fb496b3e05893ee28f93a454ee618bda89a531a547c4002
+2023-10-13 22:18:45.963840 | rxh-dev-todo | info | Successfully prepared image registry.fly.io/rxh-dev-todo@sha256:60b7b531e99e037f2fb496b3e05893ee28f93a454ee618bda89a531a547c4002 (4.500906837s)
+2023-10-13 22:18:46.134860 | rxh-dev-todo | info | Successfully prepared image registry.fly.io/rxh-dev-todo:depot-1697235471 (6.438815793s)
+2023-10-13 22:18:46.210583 | rxh-dev-todo | info | Configuring firecracker
+2023-10-13 22:18:46.434645 | rxh-dev-todo | info | [    0.042971] Spectre V2 : WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!
+2023-10-13 22:18:46.477693 | rxh-dev-todo | info | [    0.054250] PCI: Fatal: No config space access function found
+2023-10-13 22:18:46.664016 | rxh-dev-todo | info | Configuring firecracker
+""",
+)
+```
+
+#### reflex deployments build-logs `app-name`
+
+Get the logs of the hosting service deploying the app.
+
+```python eval
+doccmdoutput(
+    command="reflex deployments build-logs webcam-demo",
+    output="""Note: there is a few seconds delay for logs to be available.
+2024-01-08 11:02:46.109785 PST | fly-controller-prod | #8 extracting sha256:bd9ddc54bea929a22b334e73e026d4136e5b73f5cc29942896c72e4ece69b13d 0.0s done | None | None
+2024-01-08 11:02:46.109811 PST | fly-controller-prod | #8 DONE 5.3s | None | None
+2024-01-08 11:02:46.109834 PST | fly-controller-prod |  | None | None
+2024-01-08 11:02:46.109859 PST | fly-controller-prod | #8 [1/4] FROM public.ecr.aws/p3v4g4o2/reflex-hosting-base:v0.1.8-py3.11@sha256:9e8569507f349d78d41a86e1eb29a15ebc9dece487816875bbc874f69dcf7ecf | None | None
+...
+...
+2024-01-08 11:02:50.913748 PST | fly-controller-prod | #11 [4/4] RUN . /home/reflexuser/venv/bin/activate && pip install --no-color --no-cache-dir -q -r /home/reflexuser/app/requirements.txt reflex==0.3.4 | None | None
+...
+...
+2024-01-08 11:03:07.430922 PST | fly-controller-prod | #12 pushing layer sha256:d9212ef47485c9f363f105a05657936394354038a5ae5ce03c6025f7f8d2d425 3.5s done | None | None
+2024-01-08 11:03:07.881471 PST | fly-controller-prod | #12 pushing layer sha256:ee46d14ae1959b0cacda828e5c4c1debe32c9c4c5139fb670cde66975a70c019 3.9s done | None | None
+...
+2024-01-08 11:03:13.943166 PST | fly-controller-prod | Built backend image | None | None
+2024-01-08 11:03:13.943174 PST | fly-controller-prod | Deploying backend image... | None | None
+2024-01-08 11:03:13.943311 PST | fly-controller-prod | Running sys_run | None | None
+...
+2024-01-08 11:03:31.005887 PST | fly-controller-prod | Checking for valid image digest to be deployed to machines... | None | None
+2024-01-08 11:03:31.005893 PST | fly-controller-prod | Running sys_run | None | None
+2024-01-08 11:03:32.411762 PST | fly-controller-prod | Backend updated! | None | None
+2024-01-08 11:03:32.481276 PST | fly-controller-prod | Deploy success (backend) | None | None
+""",
+)
+```
+
+The hosting service prints log messages when preparing and deploying your app. These log messages are called build logs. Build logs are useful in troubleshooting deploy failures. For example, if there is a package `numpz==1.26.3` (supposed to be `numpy`) in the `requirements.txt`, hosting service will be unable to install it. That package does not exist. We expect to find a few lines in the build logs indicating that the `pip install` command fails.
+
+#### reflex deployments delete `app-name`
+
+Delete a specific deployment.
+
+### Public Commands
+
+These commands do not require authentication.
+
+#### reflex deployments regions
+
+List all the valid regions to select for a deployment.
+
+```python eval
+rx.table.root(
+    rx.table.header(
+        rx.table.row(
+            rx.table.column_header_cell("Region Code"),
+            rx.table.column_header_cell("Region"),
+        ),
+    ),
+    rx.table.body(
+        rx.table.row(
+            rx.table.row_header_cell("alt"),
+            rx.table.cell("Atlanta, Georgia (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("bog"),
+            rx.table.cell("Bogotá, Colombia"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("bos"),
+            rx.table.cell("Boston, Massachusetts (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("cdg"),
+            rx.table.cell("Paris, France"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("den"),
+            rx.table.cell("Denver, Colorado (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("dfw"),
+            rx.table.cell("Dallas, Texas (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("eze"),
+            rx.table.cell("Ezeiza, Argentina"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("fra"),
+            rx.table.cell("Frankfurt, Germany"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("hkg"),
+            rx.table.cell("Hong Kong, Hong Kong"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("iad"),
+            rx.table.cell("Ashburn, Virginia (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("lax"),
+            rx.table.cell("Los Angeles, California (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("lhr"),
+            rx.table.cell("London, United Kingdom"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("mad"),
+            rx.table.cell("Madrid, Spain"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("mia"),
+            rx.table.cell("Miami, Florida (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("ord"),
+            rx.table.cell("Chicago, Illinois (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("scl"),
+            rx.table.cell("Santiago, Chile"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("sea"),
+            rx.table.cell("Seattle, Washington (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("sin"),
+            rx.table.cell("Singapore, Singapore"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("sjc"),
+            rx.table.cell("San Jose, California (US)"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("syd"),
+            rx.table.cell("Sydney, Australia"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("waw"),
+            rx.table.cell("Warsaw, Poland"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("yul"),
+            rx.table.cell("Montréal, Canada"),
+        ),
+        rx.table.row(
+            rx.table.row_header_cell("yyz"),
+            rx.table.cell("Toronto, Canada"),
+        ),
+    ),
+    variant="surface",
+)
+```

+ 121 - 0
docs/hosting/self-hosting.md

@@ -0,0 +1,121 @@
+```python exec
+import reflex as rx
+
+from pcweb.pages.docs import getting_started
+```
+
+# Self Hosting
+
+When available, we recommend using `reflex deploy`, but you can also host your
+apps yourself in the meantime.
+
+Clone your code to a server and install the [requirements]({getting_started.installation.path}).
+
+## API URL
+
+Edit your `rxconfig.py` file and set `api_url` to the publicly accessible IP
+address or hostname of your server, with the port `:8000` at the end. Setting
+this correctly is essential for the frontend to interact with the backend state.
+
+For example if your server is at `app.example.com`, your config would look like this:
+
+```python
+config = rx.Config(
+    app_name="your_app_name",
+    api_url="http://app.example.com:8000",
+)
+```
+
+It is also possible to set the environment variable `API_URL` at run time or
+export time to retain the default for local development.
+
+## Production Mode
+
+Then run your app in production mode:
+
+```bash
+reflex run --env prod
+```
+
+Production mode creates an optimized build of your app.  By default, the static
+frontend of the app (HTML, Javascript, CSS) will be exposed on port `3000` and
+the backend (event handlers) will be listening on port `8000`.
+
+```md alert warning
+# Reverse Proxy and Websockets
+Because the backend uses websockets, some reverse proxy servers, like [nginx](https://nginx.org/en/docs/http/websocket.html) or [apache](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#protoupgrade), must be configured to pass the `Upgrade` header to allow backend connectivity.
+```
+
+## Exporting a Static Build
+
+Exporting a static build of the frontend allows the app to be served using a
+static hosting provider, like Netlify or Github Pages. Be sure `api_url` is set
+to an accessible backend URL when the frontend is exported.
+
+```bash
+API_URL=http://app.example.com:8000 reflex export
+```
+
+This will create a `frontend.zip` file with your app's minified HTML,
+Javascript, and CSS build that can be uploaded to your static hosting service.
+
+It also creates a `backend.zip` file with your app's backend python code to
+upload to your server and run.
+
+You can export only the frontend or backend by passing in the `--frontend-only`
+or `--backend-only` flags.
+
+It is also possible to export the components without zipping. To do
+this, use the `--no-zip` parameter. This provides the frontend in the
+`.web/_static/` directory and the backend can be found in the root directory of
+the project.
+
+## Reflex Container Service
+
+Another option is to run your Reflex service in a container. For this
+purpose, a `Dockerfile` and additional documentation is available in the Reflex
+project in the directory `docker-example`.
+
+For the build of the container image it is necessary to edit the `rxconfig.py`
+and the add the `requirements.txt`
+to your project folder. The following changes are necessary in `rxconfig.py`:
+
+```python
+config = rx.Config(
+    app_name="app",
+    api_url="http://app.example.com:8000",
+)
+```
+
+Notice that the `api_url` should be set to the externally accessible hostname or
+IP, as the client browser must be able to connect to it directly to establish
+interactivity.
+
+You can find the `requirements.txt` in the `docker-example` folder of the
+project too.
+
+The project structure should looks like this:
+
+```bash
+hello
+├── .web
+├── assets
+├── hello
+│   ├── __init__.py
+│   └── hello.py
+├── rxconfig.py
+├── Dockerfile
+└── requirements.txt
+```
+
+After all changes have been made, the container image can now be created as follows.
+
+```bash
+docker build -t reflex-project:latest .
+```
+
+Finally, you can start your Reflex container service as follows.
+
+```bash
+docker run -d -p 3000:3000 -p 8000:8000 --name app reflex-project:latest
+```

+ 44 - 0
docs/library/chakra/datadisplay/badge.md

@@ -0,0 +1,44 @@
+---
+components:
+    - rx.chakra.Badge
+---
+
+```python exec
+import reflex as rx
+```
+
+# Badge
+
+Badges are used to highlight an item's status for quick recognition.
+
+There are 3 variants of badges: `solid`, `subtle`, and `outline`.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.badge("Example", variant="solid", color_scheme="green"),
+    rx.chakra.badge("Example", variant="subtle", color_scheme="green"),
+    rx.chakra.badge("Example", variant="outline", color_scheme="green"),
+)
+```
+
+Color schemes are an easy way to change the color of a badge.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.badge("Example", variant="subtle", color_scheme="green"),
+    rx.chakra.badge("Example", variant="subtle", color_scheme="red"),
+    rx.chakra.badge("Example", variant="subtle", color_scheme="yellow"),
+)
+```
+
+You can also customize the badge through traditional style args.
+
+```python demo
+rx.chakra.badge(
+    "Custom Badge", 
+    bg="#90EE90",
+    color="#3B7A57",
+    border_color="#29AB87",
+    border_width=2
+)
+```

+ 34 - 0
docs/library/chakra/datadisplay/divider.md

@@ -0,0 +1,34 @@
+---
+components:
+    - rx.chakra.Divider
+---
+
+```python exec
+import reflex as rx
+```
+
+# Divider
+
+Dividers are a quick built in way to separate sections of content.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.text("Example"),
+    rx.chakra.divider(border_color="black"),
+    rx.chakra.text("Example"),
+    rx.chakra.divider(variant="dashed", border_color="black"),
+    width="100%",
+)
+```
+
+If the vertical orientation is used, make sure that the parent component is assigned a height.
+
+```python demo
+rx.chakra.center(
+    rx.chakra.divider(
+        orientation="vertical", 
+        border_color = "black"
+    ), 
+    height = "4em"
+)
+```

+ 68 - 0
docs/library/chakra/datadisplay/list.md

@@ -0,0 +1,68 @@
+---
+components:
+    - rx.chakra.List
+    - rx.chakra.ListItem
+    - rx.chakra.UnorderedList
+    - rx.chakra.OrderedList
+---
+
+```python exec
+import reflex as rx
+```
+
+# List
+
+There are three types of lists: regular lists, ordered, unordered.
+
+The shorthand syntax used to create a list is by passing in a list of items.
+These items can be components or Python primitives.
+
+```python demo
+rx.chakra.list(
+    items=["Example 1", "Example 2", "Example 3"],
+    spacing=".25em"
+)
+```
+
+The examples below have the explicit syntax of list and list_items.
+Regular lists are used to display a list of items.
+They have no bullet points or numbers and stack the list items vertically.
+
+```python demo
+rx.chakra.list(
+    rx.chakra.list_item("Example 1"),
+    rx.chakra.list_item("Example 2"),
+    rx.chakra.list_item("Example 3"),
+)
+```
+
+Unordered have bullet points to display the list items.
+
+```python demo
+rx.chakra.unordered_list(
+    rx.chakra.list_item("Example 1"),
+    rx.chakra.list_item("Example 2"),
+    rx.chakra.list_item("Example 3"),
+)
+```
+
+Ordered lists have numbers to display the list items.
+
+```python demo
+rx.chakra.ordered_list(
+    rx.chakra.list_item("Example 1"),
+    rx.chakra.list_item("Example 2"),
+    rx.chakra.list_item("Example 3"),
+)
+```
+
+Lists can also be used with icons.
+
+```python demo
+rx.chakra.list(
+    rx.chakra.list_item(rx.chakra.icon(tag="check_circle", color = "green"), "Allowed"),
+    rx.chakra.list_item(rx.chakra.icon(tag="not_allowed", color = "red"), "Not"),
+    rx.chakra.list_item(rx.chakra.icon(tag="settings", color = "grey"), "Settings"),
+    spacing = ".25em"
+)
+```

+ 41 - 0
docs/library/chakra/datadisplay/stat.md

@@ -0,0 +1,41 @@
+---
+components:
+    - rx.chakra.Stat
+    - rx.chakra.StatLabel
+    - rx.chakra.StatNumber
+    - rx.chakra.StatHelpText
+    - rx.chakra.StatArrow
+    - rx.chakra.StatGroup
+---
+
+```python exec
+import reflex as rx
+```
+
+# Stat
+
+The stat component is a great way to visualize statistics in a clean and concise way.
+
+```python demo
+rx.chakra.stat(
+    rx.chakra.stat_label("Example Price"),
+    rx.chakra.stat_number("$25"),
+    rx.chakra.stat_help_text("The price of the item."),
+)
+```
+
+Example of a stats in a group with arrow.
+
+```python demo
+rx.chakra.stat_group(
+        rx.chakra.stat(
+            rx.chakra.stat_number("$250"),
+            rx.chakra.stat_help_text("%50", rx.chakra.stat_arrow(type_="increase")),
+        ),
+        rx.chakra.stat(
+            rx.chakra.stat_number("£100"),
+            rx.chakra.stat_help_text("%50", rx.chakra.stat_arrow(type_="decrease")),
+        ),
+        width="100%",
+)
+```

+ 142 - 0
docs/library/chakra/datadisplay/table.md

@@ -0,0 +1,142 @@
+---
+components:
+    - rx.chakra.Table
+    - rx.chakra.TableCaption
+    - rx.chakra.Thead
+    - rx.chakra.Tbody
+    - rx.chakra.Tfoot
+    - rx.chakra.Tr
+    - rx.chakra.Th
+    - rx.chakra.Td
+    - rx.chakra.TableContainer
+---
+
+```python exec
+import reflex as rx
+```
+
+# Table
+
+Tables are used to organize and display data efficiently.
+The table component differs from the `data_table`` component in that it is not meant to display large amounts of data.
+It is meant to display data in a more organized way.
+
+Tables can be created with a shorthand syntax or by explicitly creating the table components.
+The shorthand syntax is great for simple tables, but if you need more control over the table you can use the explicit syntax.
+
+Let's start with the shorthand syntax.
+The shorthand syntax has `headers`, `rows`, and `footers` props.
+
+```python demo
+rx.chakra.table_container(
+    rx.chakra.table(
+        headers=["Name", "Age", "Location"],
+        rows=[
+            ("John", 30, "New York"),
+            ("Jane", 31, "San Francisco"),
+            ("Joe", 32, "Los Angeles")
+        ],
+        footers=["Footer 1", "Footer 2", "Footer 3"],
+        variant='striped'
+    )
+)
+```
+
+Let's create a simple table explicitly. In this example we will make a table with 2 columns: `Name` and `Age`.
+
+```python demo
+rx.chakra.table(
+    rx.chakra.thead(
+        rx.chakra.tr(
+            rx.chakra.th("Name"),
+            rx.chakra.th("Age"),
+        )
+    ),
+    rx.chakra.tbody(
+        rx.chakra.tr(
+            rx.chakra.td("John"),
+            rx.chakra.td(30),
+        )
+    ),
+)
+```
+
+In the examples we will be using this data to display in a table.
+
+```python exec
+columns = ["Name", "Age", "Location"]
+data = [
+    ["John", 30, "New York"],
+    ["Jane", 25, "San Francisco"],
+]
+footer = ["Footer 1", "Footer 2", "Footer 3"]
+```
+
+```python
+columns = ["Name", "Age", "Location"]
+data = [
+    ["John", 30, "New York"],
+    ["Jane", 25, "San Francisco"],
+]
+footer = ["Footer 1", "Footer 2", "Footer 3"]
+```
+
+Now lets create a table with the data we created.
+
+```python eval
+rx.chakra.center(
+    rx.chakra.table_container(
+        rx.chakra.table(
+            rx.chakra.table_caption("Example Table"),
+            rx.chakra.thead(
+                rx.chakra.tr(
+                    *[rx.chakra.th(column) for column in columns]
+                )
+            ),
+            rx.chakra.tbody(
+                *[rx.chakra.tr(*[rx.chakra.td(item) for item in row]) for row in data]
+            ),
+            rx.chakra.tfoot(
+                rx.chakra.tr(
+                    *[rx.chakra.th(item) for item in footer]
+                )
+            ),
+        )
+    )
+)
+```
+
+Tables can also be styled with the variant and color_scheme arguments.
+
+```python demo
+rx.chakra.table_container(
+    rx.chakra.table(
+        rx.chakra.thead(
+        rx.chakra.tr(
+            rx.chakra.th("Name"),
+            rx.chakra.th("Age"),
+            rx.chakra.th("Location"),
+            )
+        ),
+        rx.chakra.tbody(
+            rx.chakra.tr(
+                rx.chakra.td("John"),
+                rx.chakra.td(30),
+                rx.chakra.td("New York"),
+            ),
+            rx.chakra.tr(
+                rx.chakra.td("Jane"), 
+                rx.chakra.td(31),
+                rx.chakra.td("San Francisco"),
+            ),
+            rx.chakra.tr(
+                rx.chakra.td("Joe"),
+                rx.chakra.td(32),
+                rx.chakra.td("Los Angeles"),
+            )
+        ),
+        variant='striped',
+        color_scheme='teal'
+    )
+)
+```

+ 103 - 0
docs/library/chakra/disclosure/accordion.md

@@ -0,0 +1,103 @@
+---
+components:
+    - rx.chakra.Accordion
+    - rx.chakra.AccordionItem
+    - rx.chakra.AccordionButton
+    - rx.chakra.AccordionPanel
+    - rx.chakra.AccordionIcon
+---
+
+```python exec
+import reflex as rx
+```
+
+# Accordion
+
+Accordions allow you to hide and show content in a container under a header.
+
+Accordion consist of an outer accordion component and inner accordion items.
+Each item has a optional button and panel. The button is used to toggle the panel's visibility.
+
+```python demo
+rx.chakra.accordion(
+    rx.chakra.accordion_item(
+        rx.chakra.accordion_button(
+            rx.chakra.heading("Example"),
+            rx.chakra.accordion_icon(),
+        ),
+        rx.chakra.accordion_panel(
+            rx.chakra.text("This is an example of an accordion component.")
+        )
+    ),
+    allow_toggle = True,
+    width = "100%"
+)
+```
+
+An accordion can have multiple items.
+
+```python demo
+rx.chakra.accordion(
+    rx.chakra.accordion_item(
+        rx.chakra.accordion_button(
+            rx.chakra.heading("Example 1"),
+            rx.chakra.accordion_icon(),
+        ),
+        rx.chakra.accordion_panel(
+            rx.chakra.text("This is an example of an accordion component.")
+        ),
+    ),
+    rx.chakra.accordion_item(
+        rx.chakra.accordion_button(
+            rx.chakra.heading("Example 2"),
+            rx.chakra.accordion_icon(),
+        ),
+        rx.chakra.accordion_panel(
+            rx.chakra.text("This is an example of an accordion component.")
+        ),
+    ),
+    allow_multiple = True,
+    bg="black",
+    color="white",
+    width = "100%"
+)
+```
+
+You can create multilevel accordions by nesting accordions within the outer accordion panel.
+
+```python demo
+rx.chakra.accordion(
+    rx.chakra.accordion_item(
+        rx.chakra.accordion_button(
+            rx.chakra.accordion_icon(),
+            rx.chakra.heading("Outer"),
+            
+        ),
+        rx.chakra.accordion_panel(
+            rx.chakra.accordion(
+            rx.chakra.accordion_item(
+                rx.chakra.accordion_button(
+                    rx.chakra.accordion_icon(),
+                    rx.chakra.heading("Inner"),    
+                ),
+                rx.chakra.accordion_panel(
+                    rx.chakra.badge("Inner Panel", variant="solid", color_scheme="green"),
+                )
+            )
+            ),
+        )  
+    ),
+    width = "100%"
+)
+```
+
+You can also create an accordion using the shorthand syntax.
+Pass a list of tuples to the `items` prop.
+Each tuple should contain a label and a panel.
+
+```python demo
+rx.chakra.accordion(
+   items=[("Label 1", rx.chakra.center("Panel 1")), ("Label 2", rx.chakra.center("Panel 2"))],
+   width="100%"
+)
+```

+ 48 - 0
docs/library/chakra/disclosure/tabs.md

@@ -0,0 +1,48 @@
+---
+components:
+    - rx.chakra.Tabs
+    - rx.chakra.TabList
+    - rx.chakra.Tab
+    - rx.chakra.TabPanel
+    - rx.chakra.TabPanels
+---
+
+```python exec
+import reflex as rx
+```
+
+# Tabs
+
+Tab components allow you display content in multiple pages within a container.
+These page are organized by a tab list and the corresponding tab panel can take in children components if needed.
+
+```python demo
+rx.chakra.tabs(
+    rx.chakra.tab_list(
+        rx.chakra.tab("Tab 1"),
+        rx.chakra.tab("Tab 2"),
+        rx.chakra.tab("Tab 3"),
+    ),
+    rx.chakra.tab_panels(
+        rx.chakra.tab_panel(rx.chakra.text("Text from tab 1.")),
+        rx.chakra.tab_panel(rx.chakra.checkbox("Text from tab 2.")),
+        rx.chakra.tab_panel(rx.chakra.button("Text from tab 3.", color="black")),
+    ),
+    bg="black",
+    color="white",
+    shadow="lg",
+)
+```
+
+You can create a tab component using the shorthand syntax.
+Pass a list of tuples to the `items` prop.
+Each tuple should contain a label and a panel.
+
+```python demo
+rx.chakra.tabs(
+    items = [("Tab 1", rx.chakra.text("Text from tab 1.")), ("Tab 2", rx.chakra.checkbox("Text from tab 2.")), ("Tab 3", rx.chakra.button("Text from tab 3.", color="black"))],
+    bg="black",
+    color="white",
+    shadow="lg",
+)
+```

+ 70 - 0
docs/library/chakra/feedback/alert.md

@@ -0,0 +1,70 @@
+---
+components:
+    - rx.chakra.Alert
+    - rx.chakra.AlertIcon
+    - rx.chakra.AlertTitle
+    - rx.chakra.AlertDescription
+---
+
+```python exec
+import reflex as rx
+```
+
+# Alert
+
+Alerts are used to communicate a state that affects a system, feature or page.
+An example of the different alert statuses is shown below.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Error Reflex version is out of date."),
+        status="error",
+    ),
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Warning Reflex version is out of date."),
+        status="warning",
+    ),
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Reflex version is up to date."),
+        status="success",
+    ),
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Reflex version is 0.1.32."),
+        status="info",
+    ),
+    width="100%",
+)
+```
+
+Along with different status types, alerts can also have different style variants and an optional description.
+By default the variant is 'subtle'.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Reflex version is up to date."),
+        rx.chakra.alert_description("No need to update."),
+        status="success",
+        variant="subtle",
+    ),
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Reflex version is up to date."),
+        status="success",
+        variant="solid",
+    ),
+    rx.chakra.alert(
+        rx.chakra.alert_icon(),
+        rx.chakra.alert_title("Reflex version is up to date."),
+        status="success",
+        variant="top-accent",
+    ),
+    width="100%",
+)
+```

+ 26 - 0
docs/library/chakra/feedback/circularprogress.md

@@ -0,0 +1,26 @@
+---
+components:
+    - rx.chakra.CircularProgress
+    - rx.chakra.CircularProgressLabel
+---
+
+```python exec
+import reflex as rx
+```
+
+# CircularProgress
+
+The CircularProgress component is used to indicate the progress for determinate and indeterminate processes.
+Determinate progress: fills the circular track with color, as the indicator moves from 0 to 360 degrees.
+Indeterminate progress: grows and shrinks the indicator while moving along the circular track.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.circular_progress(value=0),
+    rx.chakra.circular_progress(value=25),
+    rx.chakra.circular_progress(rx.chakra.circular_progress_label(50), value=50),
+    rx.chakra.circular_progress(value=75),
+    rx.chakra.circular_progress(value=100),
+    rx.chakra.circular_progress(is_indeterminate=True),
+)
+```

+ 24 - 0
docs/library/chakra/feedback/progress.md

@@ -0,0 +1,24 @@
+---
+components:
+    - rx.chakra.Progress
+---
+
+```python exec
+import reflex as rx
+```
+
+# Progress
+
+Progress is used to display the progress status for a task that takes a long time or consists of several steps.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.progress(value=0, width="100%"),
+    rx.chakra.progress(value=50, width="100%"),
+    rx.chakra.progress(value=75, width="100%"),
+    rx.chakra.progress(value=100, width="100%"),
+    rx.chakra.progress(is_indeterminate=True, width="100%"),
+    spacing="1em",
+    min_width=["10em", "20em"],
+)
+```

+ 54 - 0
docs/library/chakra/feedback/skeleton.md

@@ -0,0 +1,54 @@
+---
+components:
+    - rx.chakra.Skeleton
+    - rx.chakra.SkeletonCircle
+    - rx.chakra.SkeletonText
+---
+
+```python exec
+import reflex as rx
+```
+
+# Skeleton
+
+Skeleton is used to display the loading state of some components.
+
+```python demo
+rx.chakra.stack(
+    rx.chakra.skeleton(height="10px", speed=1.5),
+    rx.chakra.skeleton(height="15px", speed=1.5),
+    rx.chakra.skeleton(height="20px", speed=1.5),
+    width="50%",
+)
+```
+
+Along with the basic skeleton box there are also a skeleton circle and text for ease of use.
+
+```python demo
+rx.chakra.stack(
+    rx.chakra.skeleton_circle(size="30px"),
+    rx.chakra.skeleton_text(no_of_lines=8),
+    width="50%",
+)
+```
+
+Another feature of skeleton is the ability to animate colors.
+We provide the args start_color and end_color to animate the color of the skeleton component(s).
+
+```python demo
+rx.chakra.stack(
+    rx.chakra.skeleton_text(
+        no_of_lines=5, start_color="pink.500", end_color="orange.500"
+    ),
+    width="50%",
+)
+```
+
+You can prevent the skeleton from loading by using the `is_loaded` prop.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.skeleton(rx.chakra.text("Text is already loaded."), is_loaded=True),
+    rx.chakra.skeleton(rx.chakra.text("Text is already loaded."), is_loaded=False),
+)
+```

+ 38 - 0
docs/library/chakra/feedback/spinner.md

@@ -0,0 +1,38 @@
+---
+components:
+    - rx.chakra.Spinner
+---
+
+```python exec
+import reflex as rx
+```
+
+# Spinner
+
+Spinners provide a visual cue that an event is either processing, awaiting a course of change or a result.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.spinner(color="red", size="xs"),
+    rx.chakra.spinner(color="orange", size="sm"),
+    rx.chakra.spinner(color="green", size="md"),
+    rx.chakra.spinner(color="blue", size="lg"),
+    rx.chakra.spinner(color="purple", size="xl"),
+)
+```
+
+Along with the color you can style further with props such as speed, empty color, and thickness.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.spinner(color="lightgreen", thickness=1, speed="1s", size="xl"),
+    rx.chakra.spinner(color="lightgreen", thickness=5, speed="1.5s", size="xl"),
+    rx.chakra.spinner(
+        color="lightgreen",
+        thickness=10,
+        speed="2s",
+        empty_color="red",
+        size="xl",
+    ),
+)
+```

+ 375 - 0
docs/library/chakra/forms/button.md

@@ -0,0 +1,375 @@
+---
+components:
+    - rx.chakra.Button
+    - rx.chakra.IconButton
+---
+
+```python exec
+import reflex as rx
+from pcweb.templates.docpage import docdemo
+
+
+basic_button = """rx.chakra.button("Click Me!")
+"""
+button_style = """rx.chakra.button_group(
+    rx.chakra.button("Example", bg="lightblue", color="black", size = 'sm'),
+    rx.chakra.button("Example", bg="orange", color="white", size = 'md'),
+    rx.chakra.button("Example", color_scheme="red", size = 'lg'),
+    space = "1em",
+)
+"""
+button_visual_states = """rx.chakra.button_group(
+    rx.chakra.button("Example", bg="lightgreen", color="black", is_loading = True),
+    rx.chakra.button("Example", bg="lightgreen", color="black", is_disabled = True),
+    rx.chakra.button("Example", bg="lightgreen", color="black", is_active = True),
+    space = '1em',
+)
+"""
+
+button_group_example = """rx.chakra.button_group(
+    rx.chakra.button(rx.chakra.icon(tag="minus"), color_scheme="red"),
+    rx.chakra.button(rx.chakra.icon(tag="add"), color_scheme="green"),
+    is_attached=True,
+)
+"""
+
+button_state = """class ButtonState(rx.State):
+    count: int = 0
+
+    def increment(self):
+        self.count += 1
+
+    def decrement(self):
+        self.count -= 1
+"""
+exec(button_state)
+button_state_example = """rx.chakra.hstack(
+    rx.chakra.button(
+        "Decrement",
+        bg="#fef2f2",
+        color="#b91c1c",
+        border_radius="lg",
+        on_click=ButtonState.decrement,
+    ),
+    rx.chakra.heading(ButtonState.count, font_size="2em", padding_x="0.5em"),
+    rx.chakra.button(
+        "Increment",
+        bg="#ecfdf5",
+        color="#047857",
+        border_radius="lg",
+        on_click=ButtonState.increment,
+    ),
+)
+"""
+
+
+button_state_code = f"""
+import reflex as rx
+
+{button_state}
+
+def index():
+    return {button_state_example}
+
+app = rx.chakra.App()
+app.add_page(index)"""
+
+button_state2 = """class ExampleButtonState(rx.State):
+    text_value: str = "Random value"
+"""
+exec(button_state2)
+
+button_state2_render_code = """rx.chakra.vstack(
+ rx.chakra.text(ExampleButtonState.text_value),
+        rx.chakra.button(
+            "Change Value",
+            on_click=ExampleButtonState.set_text_value("Modified value"))
+    )
+"""
+
+button_state2_code = f"""
+import reflex as rx
+
+{button_state2}
+
+def index():
+    return {button_state2_render_code}
+
+app = rx.chakra.App()
+app.add_page(index)"""
+
+
+button_sizes = (
+"""rx.chakra.button_group(
+        rx.chakra.button(
+        'Example', bg='lightblue', color='black', size='sm'
+        ),
+        rx.chakra.button(
+            'Example', bg='orange', color='white', size='md'
+        ),
+        rx.chakra.button('Example', color_scheme='red', size='lg'),
+)
+"""  
+)
+
+button_colors = (
+"""rx.chakra.button_group(
+        rx.chakra.button('White Alpha', color_scheme='whiteAlpha', min_width='unset'),
+        rx.chakra.button('Black Alpha', color_scheme='blackAlpha', min_width='unset'),
+        rx.chakra.button('Gray', color_scheme='gray', min_width='unset'),
+        rx.chakra.button('Red', color_scheme='red', min_width='unset'),
+        rx.chakra.button('Orange', color_scheme='orange', min_width='unset'),
+        rx.chakra.button('Yellow', color_scheme='yellow', min_width='unset'),
+        rx.chakra.button('Green', color_scheme='green', min_width='unset'),
+        rx.chakra.button('Teal', color_scheme='teal', min_width='unset'),
+        rx.chakra.button('Blue', color_scheme='blue', min_width='unset'),
+        rx.chakra.button('Cyan', color_scheme='cyan', min_width='unset'),
+        rx.chakra.button('Purple', color_scheme='purple', min_width='unset'),
+        rx.chakra.button('Pink', color_scheme='pink', min_width='unset'),
+        rx.chakra.button('LinkedIn', color_scheme='linkedin', min_width='unset'),
+        rx.chakra.button('Facebook', color_scheme='facebook', min_width='unset'),
+        rx.chakra.button('Messenger', color_scheme='messenger', min_width='unset'),
+        rx.chakra.button('WhatsApp', color_scheme='whatsapp', min_width='unset'),
+        rx.chakra.button('Twitter', color_scheme='twitter', min_width='unset'),
+        rx.chakra.button('Telegram', color_scheme='telegram', min_width='unset'),
+        width='100%',
+)
+
+""" 
+)
+
+button_colors_render_code = (
+"""rx.chakra.button_group(
+        rx.chakra.button('White Alpha', color_scheme='whiteAlpha'),
+        rx.chakra.button('Black Alpha', color_scheme='blackAlpha'),
+        rx.chakra.button('Gray', color_scheme='gray'),
+        rx.chakra.button('Red', color_scheme='red'),
+        rx.chakra.button('Orange', color_scheme='orange'),
+        rx.chakra.button('Yellow', color_scheme='yellow'),
+        rx.chakra.button('Green', color_scheme='green'),
+        rx.chakra.button('Teal', color_scheme='teal'),
+        rx.chakra.button('Blue', color_scheme='blue'),
+        rx.chakra.button('Cyan', color_scheme='cyan'),
+        rx.chakra.button('Purple', color_scheme='purple'),
+        rx.chakra.button('Pink', color_scheme='pink'),
+        rx.chakra.button('LinkedIn', color_scheme='linkedin'),
+        rx.chakra.button('Facebook', color_scheme='facebook'),
+        rx.chakra.button('Messenger', color_scheme='messenger'),
+        rx.chakra.button('WhatsApp', color_scheme='whatsapp'),
+        rx.chakra.button('Twitter', color_scheme='twitter'),
+        rx.chakra.button('Telegram', color_scheme='telegram'),
+)
+
+""" 
+)
+
+button_variants = (
+"""rx.chakra.button_group(
+        rx.chakra.button('Ghost Button', variant='ghost'),
+        rx.chakra.button('Outline Button', variant='outline'),
+        rx.chakra.button('Solid Button', variant='solid'),
+        rx.chakra.button('Link Button', variant='link'),
+        rx.chakra.button('Unstyled Button', variant='unstyled'),
+    )
+"""  
+
+)
+
+button_disable = (
+"""rx.chakra.button('Inactive button', is_disabled=True)"""  
+)
+  
+loading_states = (
+"""rx.chakra.button(
+            'Random button',
+            is_loading=True,
+            loading_text='Loading...',
+            spinner_placement='start'
+    )
+"""  
+)
+
+stack_buttons_vertical = (
+"""rx.chakra.stack(
+        rx.chakra.button('Button 1'),
+        rx.chakra.button('Button 2'),
+        rx.chakra.button('Button 3'),
+        direction='column',
+)
+
+"""  
+)
+
+stack_buttons_horizontal = (
+"""rx.chakra.stack(
+        rx.chakra.button('Button 1'),
+        rx.chakra.button('Button 2'),
+        rx.chakra.button('Button 3'),
+        direction='row',
+)
+"""  
+)
+
+button_group = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+            variant='outline',
+         is_attached=True,
+        )
+"""  
+
+)
+
+```
+
+# Button
+
+Buttons are essential elements in your application's user interface that users can click to trigger events.
+This documentation will help you understand how to use button components effectively in your Reflex application.
+
+## Basic Usage
+
+A basic button component is created using the `rx.chakra.button` method:
+
+```python eval
+docdemo(basic_button)
+```
+
+## Button Sizing
+
+You can change the size of a button by setting the size prop to one of the following
+values: `xs`,`sm`,`md`, or `lg`.
+
+```python eval
+docdemo(button_sizes)
+```
+
+## Button colors
+
+Customize the appearance of buttons by adjusting their color scheme through the color_scheme prop.
+You have the flexibility to choose from a range of color scales provided by your design
+system, such as whiteAlpha, blackAlpha, gray, red, blue, or even utilize your own custom color scale.
+
+```python demo box
+eval(button_colors)
+```
+
+```python
+{button_colors_render_code.strip()}
+```
+
+## Button Variants
+
+You can customize the visual style of your buttons using the variant prop. Here are the available button variants:
+
+- `ghost`: A button with a transparent background and visible text.
+- `outline`: A button with no background color but with a border.
+- `solid`: The default button style with a solid background color.
+- `link`: A button that resembles a text link.
+- `unstyled`: A button with no specific styling.
+
+```python eval
+docdemo(button_variants)
+```
+
+## Disabling Buttons
+
+Make buttons inactive by setting the `is_disabled` prop to `True`.
+
+```python eval
+docdemo(button_disable)
+```
+
+## Handling Loading States
+
+To indicate a loading state for a button after it's clicked, you can use the following properties:
+
+- `is_loading`: Set this property to `True` to display a loading spinner.
+- `loading_text`: Optionally, you can provide loading text to display alongside the spinner.
+- `spinner_placement`: You can specify the placement of the spinner element, which is 'start' by default.
+
+```python eval
+docdemo(loading_states)
+```
+
+## Handling Click Events
+
+You can define what happens when a button is clicked using the `on_click` event argument.
+For example, to change a value in your application state when a button is clicked:
+
+```python demo box
+eval(button_state2_render_code)
+```
+
+```python
+{button_state2_code.strip()}
+```
+
+In the code above, The value of `text_value` is changed through the `set_text_value` event handler upon clicking the button.
+Reflex provides a default setter event_handler for every base var which can be accessed by prefixing the base var with the `set_` keyword.
+
+Here’s another example that creates two buttons to increase and decrease a count value:
+
+```python demo box
+eval(button_state_example)
+```
+
+```python
+{button_state_code.strip()}
+```
+
+In this example, we have a `ButtonState` state class that maintains a count base var.
+When the "Increment" button is clicked, it triggers the `ButtonState.increment` event handler, and when the "Decrement"
+button is clicked, it triggers the `ButtonState.decrement` event handler.
+
+## Special Events and Server-Side Actions
+
+Buttons in Reflex can trigger special events and server-side actions,
+allowing you to create dynamic and interactive user experiences.
+You can bind these events to buttons using the `on_click` prop.
+For a comprehensive list of
+available special events and server-side actions, please refer to the
+[Special Events Documentation](/docs/api-reference/special-events) for detailed information and usage examples.
+
+## Grouping Buttons
+
+In your Reflex application, you can group buttons effectively using the `Stack` component and
+the `ButtonGroup` component. Each of these options offers unique capabilities to help you structure
+and style your buttons.
+
+## Using the `Stack` Component
+
+The `Stack` component allows you to stack buttons both vertically and horizontally, providing a flexible
+layout for your button arrangements.
+
+## Stack Buttons Vertically
+
+```python eval
+docdemo(stack_buttons_vertical)
+```
+
+## Stack Buttons Horizontally
+
+```python eval
+docdemo(stack_buttons_horizontal)
+```
+
+With the `stack` component, you can easily create both vertical and horizontal button arrangements.
+
+## Using the `rx.chakra.button_group` Component
+
+The `ButtonGroup` component is designed specifically for grouping buttons. It allows you to:
+
+- Set the `size` and `variant` of all buttons within it.
+- Add `spacing` between the buttons.
+- Flush the buttons together by removing the border radius of their children as needed.
+
+```python eval
+docdemo(button_group)
+```
+
+```md alert
+# The `ButtonGroup` component stacks buttons horizontally, whereas the `Stack` component allows stacking buttons both vertically and horizontally.
+```

+ 150 - 0
docs/library/chakra/forms/buttongroup.md

@@ -0,0 +1,150 @@
+---
+components:
+    - rx.chakra.ButtonGroup
+---
+
+```python exec
+import reflex as rx
+from pcweb.templates.docpage import docdemo
+
+
+basic_button_group = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+        )
+"""
+)
+
+button_group_attached = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+            is_attached=True,
+        )
+
+"""  
+)
+
+button_group_variant = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+            variant='ghost',
+        )
+
+"""  
+)
+
+button_group_sizes = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Large Button', size='lg'),
+            rx.chakra.button('Medium Button', size='md'),
+            rx.chakra.button('Small Button', size='sm'),
+        )
+
+"""  
+)
+
+button_group_disable = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+            is_disabled=True,
+        )
+
+"""  
+)
+
+button_group_spacing = (
+"""rx.chakra.button_group(
+            rx.chakra.button('Option 1'),
+            rx.chakra.button('Option 2'),
+            rx.chakra.button('Option 3'),
+            spacing=8,
+        )
+
+"""  
+
+)
+```
+
+# Button Group
+
+The `rx.chakra.button_group` component allows you to create a group of buttons that are visually connected and styled together.
+This is commonly used to group related actions or options in your application's user interface.
+
+## Basic Usage
+
+Here's an example of how to use the `rx.chakra.button_group` component to create a simple group of buttons:
+
+```python eval
+docdemo(basic_button_group)
+```
+
+In this example, a button group is created with three buttons. The buttons are visually connected, and there
+is a default spacing of `2` pixels between them.
+
+## Adjusting ButtonGroup Properties
+
+You can customize the appearance and behavior of the `rx.chakra.button_group` component by adjusting
+its properties. For instance, you can set `is_attached` prop to `True` to make the buttons
+appear flushed together:
+
+```python eval
+docdemo(button_group_attached)
+```
+
+In this example, the `is_attached` property is set to `True`, resulting in the buttons having a seamless appearance.
+
+## ButtonGroup Variants
+
+Just like the `button` component, you can customize the visual style of your buttons using the `variant` prop.
+This will apply to all buttons in the group.
+
+```python eval
+docdemo(button_group_variant)
+```
+
+In this example, the `variant` prop is set to `ghost`, applying the variant style to all buttons in the group.
+
+## ButtonGroup Sizes
+
+Similarly, you can adjust the size of buttons within a button group using the `size` prop.
+This prop allows you to choose from different size options, affecting all buttons within the group.
+
+```python eval
+docdemo(button_group_sizes)
+```
+
+In this example, the `size` prop is used to set the size of all buttons within the group, with options such as `"lg"` (large), `"md"` (medium), and `"sm"` (small).
+
+## Disabling ButtonGroup
+
+You can also disable all the buttons within a button group by setting the `is_disabled` prop to `True`:
+
+```python eval
+docdemo(button_group_disable)
+```
+
+In this case, all the buttons within the group will be disabled and unclickable.
+
+## Customizing Spacing
+
+The `spacing` prop allows you to control the gap between buttons within the group. Here's an example of setting a custom spacing of `8` pixels:
+
+```python eval
+docdemo(button_group_spacing)
+```
+
+By setting `spacing` to `8`, the buttons will have a larger gap between them.
+
+```md alert info
+- You can nest other components or elements within the button group to create more complex layouts.
+- Button groups are a useful way to visually organize related actions or options in your application, providing a consistent and cohesive user interface.
+- Experiment with different combinations of props to achieve the desired styling and behavior for your button groups in Reflex-based applications.
+```

+ 69 - 0
docs/library/chakra/forms/checkbox.md

@@ -0,0 +1,69 @@
+---
+components:
+    - rx.chakra.Checkbox
+---
+
+# Checkbox
+
+A checkbox is a common way to toggle boolean value.
+The checkbox component can be used on its own or in a group.
+
+```python exec
+import reflex as rx
+```
+
+```python demo
+rx.chakra.checkbox("Check Me!")
+```
+
+Checkboxes can range in size and styles.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.checkbox("Example", color_scheme="green", size="sm"),
+    rx.chakra.checkbox("Example", color_scheme="blue", size="sm"),
+    rx.chakra.checkbox("Example", color_scheme="yellow", size="md"),
+    rx.chakra.checkbox("Example", color_scheme="orange", size="md"),
+    rx.chakra.checkbox("Example", color_scheme="red", size="lg"),
+)
+```
+
+Checkboxes can also have different visual states.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.checkbox(
+        "Example", color_scheme="green", size="lg", is_invalid=True
+    ),
+    rx.chakra.checkbox(
+        "Example", color_scheme="green", size="lg", is_disabled=True
+    ),
+)
+```
+
+Checkboxes can be hooked up to a state using the `on_change` prop.
+
+```python demo exec
+import reflex as rx
+
+
+class CheckboxState(rx.State):
+    checked: bool = False
+
+    def toggle(self):
+        self.checked = not self.checked
+
+
+def checkbox_state_example():
+    return rx.chakra.hstack(
+        rx.cond(
+            CheckboxState.checked,
+            rx.chakra.text("Checked", color="green"),
+            rx.chakra.text("Unchecked", color="red"),
+        ),
+        rx.chakra.checkbox(
+            "Example",
+            on_change=CheckboxState.set_checked,
+        )
+    )
+```

+ 48 - 0
docs/library/chakra/forms/editable.md

@@ -0,0 +1,48 @@
+---
+components:
+    - rx.chakra.Editable
+    - rx.chakra.EditablePreview
+    - rx.chakra.EditableInput
+    - rx.chakra.EditableTextarea
+---
+
+```python exec
+import reflex as rx
+```
+
+# Editable
+
+Editable is used for inline renaming of some text.
+It appears as normal UI text but transforms into a text input field when the user clicks on or focuses it.
+
+```python demo exec
+class EditableState(rx.State):
+    example_input: str
+    example_textarea: str
+    example_state: str
+
+    def set_uppertext(self, example_state: str):
+        self.example_state = example_state.upper()
+
+
+def editable_example():
+    return rx.chakra.editable(
+        rx.chakra.editable_preview(),
+        rx.chakra.editable_input(),
+        placeholder="An input example...",
+        on_submit=EditableState.set_uppertext,
+        width="100%",
+    )
+```
+
+Another variant of editable can be made with a textarea instead of an input.
+
+```python demo
+rx.chakra.editable(
+    rx.chakra.editable_preview(),
+    rx.chakra.editable_textarea(),
+    placeholder="A textarea example...",
+    on_submit=EditableState.set_example_textarea,
+    width="100%",
+)
+```

+ 110 - 0
docs/library/chakra/forms/form.md

@@ -0,0 +1,110 @@
+---
+components:
+    - rx.chakra.Form
+---
+
+```python exec
+import reflex as rx
+```
+
+# Form
+
+Forms are used to collect user input. The `rx.chakra.form` component is used to group inputs and submit them together.
+
+The form component's children can be form controls such as `rx.chakra.input`, `rx.chakra.checkbox`, or `rx.chakra.switch`. The controls should have an `name` attribute that is used to identify the control in the form data. The `on_submit` event trigger submits the form data as a dictionary to the `handle_submit` event handler.
+
+The form is submitted when the user clicks the submit button or presses enter on the form controls.
+
+```python demo exec
+class FormState(rx.State):
+    form_data: dict = {}
+
+    def handle_submit(self, form_data: dict):
+        """Handle the form submit."""
+        self.form_data = form_data
+
+
+def form_example():
+    return rx.chakra.vstack(
+        rx.chakra.form(
+            rx.chakra.vstack(
+                rx.chakra.input(placeholder="First Name", name="first_name"),
+                rx.chakra.input(placeholder="Last Name", name="last_name"),
+                rx.chakra.hstack(
+                    rx.chakra.checkbox("Checked", name="check"),
+                    rx.chakra.switch("Switched", name="switch"),
+                ),
+                rx.chakra.button("Submit", type_="submit"),
+            ),
+            on_submit=FormState.handle_submit,
+            reset_on_submit=True,
+        ),
+        rx.chakra.divider(),
+        rx.chakra.heading("Results"),
+        rx.chakra.text(FormState.form_data.to_string()),
+    )
+```
+
+```md alert warning
+# When using the form you must include a button or input with `type_='submit'`.
+```
+
+## Dynamic Forms
+
+Forms can be dynamically created by iterating through state vars using `rx.foreach`.
+
+This example allows the user to add new fields to the form prior to submit, and all
+fields will be included in the form data passed to the `handle_submit` function.
+
+```python demo exec
+class DynamicFormState(rx.State):
+    form_data: dict = {}
+    form_fields: list[str] = ["first_name", "last_name", "email"]
+
+    @rx.cached_var
+    def form_field_placeholders(self) -> list[str]:
+        return [
+            " ".join(w.capitalize() for w in field.split("_"))
+            for field in self.form_fields
+        ]
+
+    def add_field(self, form_data: dict):
+        new_field = form_data.get("new_field")
+        if not new_field:
+            return
+        field_name = new_field.strip().lower().replace(" ", "_")
+        self.form_fields.append(field_name)
+
+    def handle_submit(self, form_data: dict):
+        self.form_data = form_data
+
+
+def dynamic_form():
+    return rx.chakra.vstack(
+        rx.chakra.form(
+            rx.chakra.vstack(
+                rx.foreach(
+                    DynamicFormState.form_fields,
+                    lambda field, idx: rx.chakra.input(
+                        placeholder=DynamicFormState.form_field_placeholders[idx],
+                        name=field,
+                    ),
+                ),
+                rx.chakra.button("Submit", type_="submit"),
+            ),
+            on_submit=DynamicFormState.handle_submit,
+            reset_on_submit=True,
+        ),
+        rx.chakra.form(
+            rx.chakra.hstack(
+                rx.chakra.input(placeholder="New Field", name="new_field"),
+                rx.chakra.button("+", type_="submit"),
+            ),
+            on_submit=DynamicFormState.add_field,
+            reset_on_submit=True,
+        ),
+        rx.chakra.divider(),
+        rx.chakra.heading("Results"),
+        rx.chakra.text(DynamicFormState.form_data.to_string()),
+    )
+```

+ 51 - 0
docs/library/chakra/forms/formcontrol.md

@@ -0,0 +1,51 @@
+---
+components:
+    - rx.chakra.FormControl
+    - rx.chakra.FormLabel
+    - rx.chakra.FormErrorMessage
+    - rx.chakra.FormHelperText
+---
+
+# Form Control
+
+Form control provides context such as filled/focused/error/required for form inputs.
+
+```python exec
+import reflex as rx
+```
+
+```python demo
+rx.chakra.form_control(
+    rx.chakra.form_label("First Name", html_for="email"),
+    rx.chakra.checkbox("Example"),
+    rx.chakra.form_helper_text("This is a help text"),
+    is_required=True,
+)
+```
+
+The example below shows a form error when then name length is 3 or less.
+
+```python demo exec
+import reflex as rx
+
+class FormErrorState(rx.State):
+    name: str
+
+    @rx.var
+    def is_error(self) -> bool:
+         return len(self.name) <= 3
+
+def form_state_example():
+    return rx.chakra.vstack(
+        rx.chakra.form_control(
+            rx.chakra.input(placeholder="name", on_blur=FormErrorState.set_name),
+            rx.cond(
+                FormErrorState.is_error,
+                rx.chakra.form_error_message("Name should be more than four characters"),
+                rx.chakra.form_helper_text("Enter name"),
+            ),
+            is_invalid=FormErrorState.is_error,
+            is_required=True,
+        )
+    )
+```

+ 110 - 0
docs/library/chakra/forms/input.md

@@ -0,0 +1,110 @@
+---
+components:
+    - rx.chakra.Input
+---
+
+```python exec
+import reflex as rx
+from pcweb.pages.docs import library
+```
+
+# Input
+
+The input component is used to receive text input from the user.
+
+```python demo exec
+class InputState(rx.State):
+    text: str = "Type something..."
+
+def basic_input_example():
+    return rx.chakra.vstack(
+        rx.chakra.text(InputState.text, color_scheme="green"),
+        rx.chakra.input(value=InputState.text, on_change=InputState.set_text)
+    )
+```
+
+"Behind the scene, the input component is implemented using debounced input to avoid sending individual state updates per character to the backend while the user is still typing.
+This allows a state var to directly control the `value` prop from the backend without the user experiencing input lag.
+For advanced use cases, you can tune the debounce delay by setting the `debounce_timeout` when creating the Input component.
+You can find examples of how it is used in the [DebouncedInput]({library.forms.debounce.path}) component.
+
+```python demo exec
+class ClearInputState(rx.State):
+    text: str
+
+    def clear_text(self):
+        self.text = ""
+
+
+def clear_input_example():
+    return rx.chakra.vstack(
+        rx.chakra.text(ClearInputState.text),
+        rx.chakra.input(
+            on_change=ClearInputState.set_text,
+            value=ClearInputState.text,
+        ),
+        rx.chakra.button("Clear", on_click=ClearInputState.clear_text),
+    )
+```
+
+The input component can also use the `on_blur` event handler to only change the state when the user clicks away from the input.
+This is useful for performance reasons, as the state will only be updated when the user is done typing.
+
+```python demo exec
+class InputBlurState(rx.State):
+    text: str = "Type something..."
+
+    def set_text(self, text: str):
+        self.text = text.upper()
+
+
+def input_blur_example():
+    return rx.chakra.vstack(
+        rx.chakra.text(InputBlurState.text),
+        rx.chakra.input(placeholder="Type something...", on_blur=InputBlurState.set_text)
+    )
+```
+
+You can change the type of input by using the `type_` prop.
+For example you can create a password input or a date picker.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.input(type_="password"),
+    rx.chakra.input(type_="date"),
+)
+```
+
+We also provide a `rx.chakra.password` component as a shorthand for the password input.
+
+```python demo
+rx.chakra.password()
+```
+
+You can also use forms in combination with inputs.
+This is useful for collecting multiple values with a single event handler and automatically supporting `Enter` key submit functionality that desktop users expect.
+
+```python demo exec
+class InputFormState(rx.State):
+    form_data: dict = {}
+
+    def handle_submit(self, form_data: dict):
+        """Handle the form submit."""
+        self.form_data = form_data
+    
+def input_form_example():
+    return rx.chakra.vstack(
+        rx.chakra.form(
+            rx.chakra.vstack(
+                rx.chakra.input(placeholder="First Name", id="first_name"),
+                rx.chakra.input(placeholder="Last Name", id="last_name"),
+                rx.chakra.button("Submit", type_="submit"),
+            ),
+            on_submit=InputFormState.handle_submit,
+        ),
+        rx.chakra.divider(),
+        rx.chakra.heading("Results"),
+        rx.chakra.text(InputFormState.form_data.to_string()),
+    )
+```
+

+ 28 - 0
docs/library/chakra/forms/numberinput.md

@@ -0,0 +1,28 @@
+---
+components:
+    - rx.chakra.NumberInput
+    - rx.chakra.NumberInputField
+    - rx.chakra.NumberInputStepper
+    - rx.chakra.NumberIncrementStepper
+    - rx.chakra.NumberDecrementStepper
+---
+
+```python exec
+import reflex as rx
+```
+
+# NumberInput
+
+The NumberInput component is similar to the Input component, but it has controls for incrementing or decrementing numeric values.
+
+```python demo exec
+class NumberInputState(rx.State):
+    number: int
+
+
+def number_input_example():
+    return rx.chakra.number_input(
+        value=NumberInputState.number,
+        on_change=NumberInputState.set_number,
+    )
+```

+ 45 - 0
docs/library/chakra/forms/pininput.md

@@ -0,0 +1,45 @@
+---
+components:
+    - rx.chakra.PinInput
+---
+
+```python exec
+import reflex as rx
+```
+
+# PinInput
+
+The PinInput component is similar to the Input component, but it is optimized for entering sequences of digits
+
+```python demo exec
+class PinInputState(rx.State):
+    pin: str
+
+
+def basic_pininput_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(PinInputState.pin),
+        rx.chakra.box(
+            rx.chakra.pin_input(
+                length=4,
+                on_change=PinInputState.set_pin,
+                mask=True,
+            ),
+        ),
+    )
+```
+
+The PinInput component can also be customized as seen below.
+
+```python demo
+rx.chakra.center(
+    rx.chakra.pin_input(
+        rx.chakra.pin_input_field(color="red"),
+        rx.chakra.pin_input_field(border_color="green"),
+        rx.chakra.pin_input_field(shadow="md"),
+        rx.chakra.pin_input_field(color="blue"),
+        rx.chakra.pin_input_field(border_radius="md"),
+        on_change=PinInputState.set_pin,
+    )
+)
+```

+ 74 - 0
docs/library/chakra/forms/radiogroup.md

@@ -0,0 +1,74 @@
+---
+components:
+    - rx.chakra.RadioGroup
+    - rx.chakra.Radio
+---
+
+```python exec
+import reflex as rx
+```
+
+# Radio
+
+Radios are used when only one choice may be selected in a series of options.
+
+```python demo exec
+from typing import List
+options: List[str] = ["Option 1", "Option 2", "Option 3"]
+
+class RadioState(rx.State):
+    text: str = "No Selection"
+
+
+def basic_radio_example():
+    return rx.chakra.vstack(
+        rx.chakra.badge(RadioState.text, color_scheme="green"),
+        rx.chakra.radio_group(
+            options,
+            on_change=RadioState.set_text,
+        ),
+    )
+```
+
+The `default_value` and `default_checked` arguments can be used to set the default value of the radio group.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.radio_group(
+        options,
+        default_value="Option 2",
+        default_checked=True,
+    ),
+)
+```
+
+A hstack with the `spacing` argument can be used to set the spacing between the radio buttons.
+
+```python demo
+rx.chakra.radio_group(
+    rx.chakra.radio_group(
+        rx.chakra.hstack(
+            rx.foreach(
+                options,
+                lambda option: rx.chakra.radio(option),
+            ),
+        spacing="2em",
+        ),
+    ),
+)
+```
+
+A vstack can be used to stack the radio buttons vertically.
+
+```python demo
+rx.chakra.radio_group(
+    rx.chakra.radio_group(
+        rx.chakra.vstack(
+            rx.foreach(
+                options,
+                lambda option: rx.chakra.radio(option),
+            ),
+        ),
+    ),
+)
+```

+ 45 - 0
docs/library/chakra/forms/rangeslider.md

@@ -0,0 +1,45 @@
+---
+components:
+    - rx.chakra.RangeSlider
+    - rx.chakra.RangeSliderTrack
+    - rx.chakra.RangeSliderFilledTrack
+    - rx.chakra.RangeSliderThumb
+---
+
+```python exec
+import reflex as rx
+```
+
+# RangeSlider
+
+The range slider is used to allow users to make selections from a range of values.
+
+```python demo exec
+from typing import List
+
+class RangeSliderState(rx.State):
+    value: List[int] = [0, 100]
+
+
+def range_slider_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(f"{RangeSliderState.value[0]} : {RangeSliderState.value[1]}"),
+        rx.chakra.range_slider(
+            on_change_end=RangeSliderState.set_value
+        ),
+        width="100%",
+    )
+```
+
+If you want to trigger state change on every slider movement, you can use the `on_change` event handler.
+This is not recommended for performance reasons and should only be used if you need to perform an event on every slider movement.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.heading(f"{RangeSliderState.value[0]} : {RangeSliderState.value[1]}"),
+    rx.chakra.range_slider(
+        on_change=RangeSliderState.set_value
+    ),
+    width="100%",
+)
+```

+ 86 - 0
docs/library/chakra/forms/select.md

@@ -0,0 +1,86 @@
+---
+components:
+    - rx.chakra.Select
+---
+
+```python exec
+import reflex as rx
+```
+
+# Select
+
+The Select component is used to create a list of options, which allows a user to select one or more options from it.
+
+```python demo exec
+from typing import List
+options: List[str] = ["Option 1", "Option 2", "Option 3"]
+
+class SelectState(rx.State):
+    option: str = "No selection yet."
+
+
+def basic_select_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(SelectState.option),
+        rx.chakra.select(
+            options,
+            placeholder="Select an example.",
+            on_change=SelectState.set_option,
+            color_schemes="twitter",
+        ),
+    )
+```
+
+Select can also have multiple options selected at once.
+
+```python demo exec
+from typing import List
+options: List[str] = ["Option 1", "Option 2", "Option 3"]
+
+class MultiSelectState(rx.State):
+    option: List[str] = []
+
+
+def multiselect_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(MultiSelectState.option),
+        rx.chakra.select(
+            options, 
+            placeholder="Select examples", 
+            is_multi=True,
+            on_change=MultiSelectState.set_option,
+            close_menu_on_select=False,
+            color_schemes="twitter",
+        ),
+    )
+```
+
+The component can also be customized and styled as seen in the next examples.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.select(options, placeholder="Select an example.", size="xs"),
+    rx.chakra.select(options, placeholder="Select an example.", size="sm"),
+    rx.chakra.select(options, placeholder="Select an example.", size="md"),
+    rx.chakra.select(options, placeholder="Select an example.", size="lg"),
+)
+```
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.select(options, placeholder="Select an example.", variant="outline"),
+    rx.chakra.select(options, placeholder="Select an example.", variant="filled"),
+    rx.chakra.select(options, placeholder="Select an example.", variant="flushed"),
+    rx.chakra.select(options, placeholder="Select an example.", variant="unstyled"),
+)
+```
+
+```python demo
+rx.chakra.select(
+    options,
+    placeholder="Select an example.",
+    color="white",
+    bg="#68D391",
+    border_color="#38A169",
+)
+```

+ 100 - 0
docs/library/chakra/forms/slider.md

@@ -0,0 +1,100 @@
+---
+components:
+    - rx.chakra.Slider
+    - rx.chakra.SliderTrack
+    - rx.chakra.SliderFilledTrack
+    - rx.chakra.SliderThumb
+    - rx.chakra.SliderMark
+---
+
+```python exec
+import reflex as rx
+```
+
+# Slider
+
+The Slider is used to allow users to make selections from a range of values.
+
+```python demo exec
+class SliderState(rx.State):
+    value: int = 50
+
+
+def slider_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(SliderState.value),
+        rx.chakra.slider(
+            on_change=SliderState.set_value
+        ),
+        width="100%",
+    )
+```
+
+You can also combine all three event handlers: `on_change`, `on_change_start`, and `on_change_end`.
+
+```python demo exec
+class SliderCombo(rx.State):
+    value: int = 50
+    color: str = "black"
+
+    def set_start(self, value):
+        self.color = "#68D391" 
+
+    def set_end(self, value):
+        self.color = "#F56565" 
+
+
+def slider_combo_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(SliderCombo.value, color=SliderCombo.color),
+        rx.chakra.slider(
+            on_change_start=SliderCombo.set_start,
+            on_change=SliderCombo.set_value,
+            on_change_end=SliderCombo.set_end,
+        ),
+        width="100%",
+    )
+```
+
+You can also customize the appearance of the slider by passing in custom components for the track and thumb.
+
+```python demo exec
+class SliderManual(rx.State):
+    value: int = 50
+
+    def set_end(self, value: int):
+        self.value = value
+
+
+def slider_manual_example():
+    return rx.chakra.vstack( 
+        rx.chakra.heading(f"Weather is {SliderManual.value} degrees"),
+        rx.chakra.slider(
+            rx.chakra.slider_track(
+                rx.chakra.slider_filled_track(bg="tomato"),
+                bg='red.100'
+            ),
+            rx.chakra.slider_thumb(
+                rx.chakra.icon(tag="sun", color="white"),
+                box_size="1.5em",
+                bg="tomato",
+            ),
+            on_change_end=SliderManual.set_end,
+        ),
+        width="100%",
+    )
+```
+
+If you want to trigger state change on every slider movement, you can use the `on_change` event handler.
+
+For performance reasons, you may want to trigger state change only when the user releases the slider by using the `on_change_end` event handler, but if you need perform an event on every slider movement, you can use the `on_change` event handler.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.heading(SliderState.value),
+    rx.chakra.slider(
+        on_change=SliderState.set_value
+    ),
+    width="100%",
+)
+```

+ 48 - 0
docs/library/chakra/forms/switch.md

@@ -0,0 +1,48 @@
+---
+components:
+    - rx.chakra.Switch
+---
+
+```python exec
+import reflex as rx
+```
+
+# Switch
+
+The Switch component is used as an alternative for the Checkbox component.
+You can switch between enabled or disabled states.
+
+```python demo exec
+class SwitchState1(rx.State):
+    checked: bool = False
+    is_checked: bool = "Switch off!"
+
+    def change_check(self, checked: bool):
+        self.checked = checked
+        if self.checked:
+            self.is_checked = "Switch on!"
+        else:
+            self.is_checked = "Switch off!"
+
+
+def switch_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(SwitchState1.is_checked),
+        rx.chakra.switch(
+            is_checked=SwitchState1.checked, on_change=SwitchState1.change_check
+        ),
+    )
+```
+
+You can also change the color scheme of the Switch component by passing the `color_scheme` argument.
+The default color scheme is blue.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.switch(color_scheme="red"),
+    rx.chakra.switch(color_scheme="green"),
+    rx.chakra.switch(color_scheme="yellow"),
+    rx.chakra.switch(color_scheme="blue"),
+    rx.chakra.switch(color_scheme="purple"),
+)
+```

+ 30 - 0
docs/library/chakra/forms/textarea.md

@@ -0,0 +1,30 @@
+---
+components:
+    - rx.chakra.TextArea
+---
+
+```python exec
+import reflex as rx
+from pcweb.pages.docs import library
+```
+
+# Textarea
+
+The TextArea component allows you to easily create multi-line text inputs.
+
+```python demo exec
+class TextareaState(rx.State):
+    text: str = "Hello World!"
+
+def textarea_example():
+    return rx.chakra.vstack(
+        rx.chakra.heading(TextareaState.text),
+        rx.chakra.text_area(value=TextareaState.text, on_change=TextareaState.set_text)
+    )
+```
+
+Alternatively, you can use the `on_blur` event handler to only update the state when the user clicks away.
+
+Similar to the Input component, the TextArea is also implemented using debounced input when it is fully controlled.
+You can tune the debounce delay by setting the `debounce_timeout` prop.
+You can find examples of how it is used in the [DebouncedInput]({library.forms.debounce.path}) component.

+ 27 - 0
docs/library/chakra/layout/aspectratio.md

@@ -0,0 +1,27 @@
+---
+components:
+    - rx.chakra.AspectRatio
+---
+
+# Aspect Ratio
+
+```python exec
+import reflex as rx
+```
+
+Preserve the ratio of the components contained within a region.
+
+```python demo
+rx.chakra.box(element="iframe", src="https://bit.ly/naruto-sage", border_color="red")
+```
+
+```python demo
+rx.chakra.aspect_ratio(
+    rx.chakra.box(
+        element="iframe",
+        src="https://bit.ly/naruto-sage",
+        border_color="red"
+    ),
+    ratio=4/3
+)
+```

+ 46 - 0
docs/library/chakra/layout/box.md

@@ -0,0 +1,46 @@
+---
+components:
+    - rx.chakra.Box
+---
+
+# Box
+
+```python exec
+import reflex as rx
+```
+
+Box is a generic container component that can be used to group other components.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.box("Example", bg="yellow", border_radius="sm", width="20%"),
+    rx.chakra.box("Example", bg="orange", border_radius="md", width="40%"),
+    rx.chakra.box("Example", bg="red", border_radius="md", width="60%"),
+    rx.chakra.box("Example", bg="lightblue", border_radius="lg", width="80%"),
+    rx.chakra.box("Example", bg="lightgreen", border_radius="xl", width="100%"),
+    width="100%",
+)
+```
+
+Below is an example of how a box component can contain other components.
+
+```python demo
+rx.chakra.box(
+    rx.chakra.button("Click Me"),
+    bg="lightgreen",
+    border_radius="15px",
+    border_color="green",
+    border_width="thick",
+    padding=5,
+)
+```
+
+Box can also compose videos and iframe elements.
+
+```python demo
+rx.chakra.box(
+    element= "iframe",
+    src="https://www.youtube.com/embed/9bZkp7q19f0",
+    width = "100%",
+)
+```

+ 25 - 0
docs/library/chakra/layout/card.md

@@ -0,0 +1,25 @@
+---
+components:
+    - rx.chakra.Card
+    - rx.chakra.CardHeader
+    - rx.chakra.CardBody
+    - rx.chakra.CardFooter
+---
+
+```python exec
+import reflex as rx
+```
+
+# Card
+
+Card is a flexible component used to group and display content in a clear and concise format.
+
+```python demo
+rx.chakra.card(
+    rx.chakra.text("Body of the Card Component"), 
+    header=rx.chakra.heading("Header", size="lg"), 
+    footer=rx.chakra.heading("Footer",size="sm"),
+)
+```
+
+You can pass a header with `header=` and/or a footer with `footer=`.

+ 43 - 0
docs/library/chakra/layout/center.md

@@ -0,0 +1,43 @@
+---
+components:
+    - rx.chakra.Center
+    - rx.chakra.Circle
+    - rx.chakra.Square
+---
+
+# Center
+
+```python exec
+import reflex as rx
+```
+
+Center, Square, and Circle are components that center its children within itself.
+
+```python demo
+rx.chakra.center(
+    rx.chakra.text("Hello World!"),
+    border_radius="15px",
+    border_width="thick",
+    width="50%",
+)
+```
+
+Below are examples of circle and square.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.square(
+        rx.chakra.vstack(rx.chakra.text("Square")),
+        border_width="thick",
+        border_color="purple",
+        padding="1em",
+    ),
+    rx.chakra.circle(
+        rx.chakra.vstack(rx.chakra.text("Circle")),
+        border_width="thick",
+        border_color="orange",
+        padding="1em",
+    ),
+    spacing="2em",
+)
+```

+ 20 - 0
docs/library/chakra/layout/container.md

@@ -0,0 +1,20 @@
+---
+components:
+    - rx.chakra.Container
+---
+
+# Container
+
+```python exec
+import reflex as rx
+```
+
+Containers are used to constrain a content's width to the current breakpoint, while keeping it fluid.
+
+```python demo
+rx.chakra.container(
+    rx.chakra.box("Example", bg="blue", color="white", width="50%"),
+    center_content=True,
+    bg="lightblue",
+)
+```

+ 33 - 0
docs/library/chakra/layout/flex.md

@@ -0,0 +1,33 @@
+---
+components:
+    - rx.chakra.Flex
+---
+
+# Flex
+
+```python exec
+import reflex as rx
+```
+
+Flexbox is a layout model that allows elements to align and distribute space within a container. Using flexible widths and heights, elements can be aligned to fill a space or distribute space between elements, which makes it a great tool to use for responsive design systems.
+
+```python demo
+rx.chakra.flex(
+    rx.chakra.center("Center", bg="lightblue"),
+    rx.chakra.square("Square", bg="lightgreen", padding=10),
+    rx.chakra.box("Box", bg="salmon", width="150px"),
+)
+```
+
+Combining flex with spacer allows for stackable and responsive components.
+
+```python demo
+rx.chakra.flex(
+    rx.chakra.center("Center", bg="lightblue"),
+    rx.chakra.spacer(),
+    rx.chakra.square("Square", bg="lightgreen", padding=10),
+    rx.chakra.spacer(),
+    rx.chakra.box("Box", bg="salmon", width="150px"),
+    width = "100%",
+)
+```

+ 43 - 0
docs/library/chakra/layout/grid.md

@@ -0,0 +1,43 @@
+---
+components:
+    - rx.chakra.Grid
+    - rx.chakra.GridItem
+---
+
+# Grid
+
+```python exec
+import reflex as rx
+```
+
+A primitive useful for grid layouts. Grid is Box with display, grid and it comes with helpful style shorthand. It renders a div element.
+
+```python demo
+rx.chakra.grid(
+    rx.chakra.grid_item(row_span=1, col_span=1, bg="lightgreen"),
+    rx.chakra.grid_item(row_span=1, col_span=1, bg="lightblue"),
+    rx.chakra.grid_item(row_span=1, col_span=1, bg="purple"),
+    rx.chakra.grid_item(row_span=1, col_span=1, bg="orange"),
+    rx.chakra.grid_item(row_span=1, col_span=1, bg="yellow"),
+    template_columns="repeat(5, 1fr)",
+    h="10em",
+    width="100%",
+    gap=4,
+)
+```
+
+In some layouts, you may need certain grid items to span specific amount of columns or rows instead of an even distribution. To achieve this, you need to pass the col_span prop to the GridItem component to span across columns and also pass the row_span component to span across rows. You also need to specify the template_columns and template_rows.
+
+```python demo
+rx.chakra.grid(
+    rx.chakra.grid_item(row_span=2, col_span=1, bg="lightblue"),
+    rx.chakra.grid_item(col_span=2, bg="lightgreen"),
+    rx.chakra.grid_item(col_span=2, bg="yellow"),
+    rx.chakra.grid_item(col_span=4, bg="orange"),
+    template_rows="repeat(2, 1fr)",
+    template_columns="repeat(5, 1fr)",
+    h="200px",
+    width="100%",
+    gap=4,
+)
+```

+ 39 - 0
docs/library/chakra/layout/responsivegrid.md

@@ -0,0 +1,39 @@
+---
+components:
+    - rx.chakra.ResponsiveGrid
+---
+
+# Responsive Grid
+
+```python exec
+import reflex as rx
+```
+
+ResponsiveGrid provides a friendly interface to create responsive grid layouts with ease. SimpleGrid composes Box so you can pass all the Box props and css grid props with addition to the ones below.
+
+Specify a fixed number of columns for the grid layout.
+
+```python demo
+rx.chakra.responsive_grid(
+    rx.chakra.box(height="5em", width="5em", bg="lightgreen"),
+    rx.chakra.box(height="5em", width="5em", bg="lightblue"),
+    rx.chakra.box(height="5em", width="5em", bg="purple"),
+    rx.chakra.box(height="5em", width="5em", bg="tomato"),
+    rx.chakra.box(height="5em", width="5em", bg="orange"),
+    rx.chakra.box(height="5em", width="5em", bg="yellow"),
+    columns=[3],
+    spacing="4",
+)
+```
+
+```python demo
+rx.chakra.responsive_grid(
+    rx.chakra.box(height="5em", width="5em", bg="lightgreen"),
+    rx.chakra.box(height="5em", width="5em", bg="lightblue"),
+    rx.chakra.box(height="5em", width="5em", bg="purple"),
+    rx.chakra.box(height="5em", width="5em", bg="tomato"),
+    rx.chakra.box(height="5em", width="5em", bg="orange"),
+    rx.chakra.box(height="5em", width="5em", bg="yellow"),
+    columns=[1, 2, 3, 4, 5, 6],
+)
+```

+ 23 - 0
docs/library/chakra/layout/spacer.md

@@ -0,0 +1,23 @@
+---
+components:
+    - rx.chakra.Spacer
+---
+
+# Spacer
+
+```python exec
+import reflex as rx
+```
+
+Creates an adjustable, empty space that can be used to tune the spacing between child elements within Flex.
+
+```python demo
+rx.chakra.flex(
+    rx.chakra.center(rx.chakra.text("Example"), bg="lightblue"),
+    rx.chakra.spacer(),
+    rx.chakra.center(rx.chakra.text("Example"), bg="lightgreen"),
+    rx.chakra.spacer(),
+    rx.chakra.center(rx.chakra.text("Example"), bg="salmon"),
+    width="100%",
+)
+```

+ 36 - 0
docs/library/chakra/layout/stack.md

@@ -0,0 +1,36 @@
+---
+components:
+    - rx.chakra.Stack
+    - rx.chakra.Hstack
+    - rx.chakra.Vstack
+---
+
+# Stack
+
+```python exec
+import reflex as rx
+```
+
+Below are two examples the different types of stack components vstack and hstack for ordering items on a page.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.box("Example", bg="red", border_radius="md", width="10%"),
+    rx.chakra.box("Example", bg="orange", border_radius="md", width="10%"),
+    rx.chakra.box("Example", bg="yellow", border_radius="md", width="10%"),
+    rx.chakra.box("Example", bg="lightblue", border_radius="md", width="10%"),
+    rx.chakra.box("Example", bg="lightgreen", border_radius="md", width="60%"),
+    width="100%",
+)
+```
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.box("Example", bg="red", border_radius="md", width="20%"),
+    rx.chakra.box("Example", bg="orange", border_radius="md", width="40%"),
+    rx.chakra.box("Example", bg="yellow", border_radius="md", width="60%"),
+    rx.chakra.box("Example", bg="lightblue", border_radius="md", width="80%"),
+    rx.chakra.box("Example", bg="lightgreen", border_radius="md", width="100%"),
+    width="100%",
+)
+```

+ 27 - 0
docs/library/chakra/layout/wrap.md

@@ -0,0 +1,27 @@
+---
+components:
+    - rx.chakra.Wrap
+    - rx.chakra.WrapItem
+---
+
+# Wrap
+
+```python exec
+import reflex as rx
+```
+
+Wrap is a layout component that adds a defined space between its children.
+
+It wraps its children automatically if there isn't enough space to fit any more in the same row. Think of it as a smarter flex-wrap with spacing support.
+
+```python demo
+rx.chakra.wrap(
+    rx.chakra.wrap_item(rx.chakra.box("Example", bg="lightgreen", w="100px", h="80px")),
+    rx.chakra.wrap_item(rx.chakra.box("Example", bg="lightblue", w="200px", h="80px")),
+    rx.chakra.wrap_item(rx.chakra.box("Example", bg="red", w="300px", h="80px")),
+    rx.chakra.wrap_item(rx.chakra.box("Example", bg="orange", w="400px", h="80px")),
+    width="100%",
+    spacing="2em",
+    align="center",
+)
+```

+ 62 - 0
docs/library/chakra/media/avatar.md

@@ -0,0 +1,62 @@
+---
+components:
+    - rx.chakra.Avatar
+    - rx.chakra.AvatarBadge
+    - rx.chakra.AvatarGroup
+---
+
+```python exec
+import reflex as rx
+```
+
+# Avatar
+
+The Avatar component is used to represent a user, and displays the profile picture, initials or fallback icon.
+
+```python demo
+rx.chakra.hstack(
+    rx.chakra.avatar(size="sm"),
+    rx.chakra.avatar(name="Barack Obama", size="md"),
+    rx.chakra.avatar(name="Donald Trump", size="lg"),
+    rx.chakra.avatar(name="Joe Biden", size="xl"),
+)
+```
+
+Avatar components can be grouped into avatar groups for easier display.
+
+```python demo
+rx.chakra.avatar_group(
+    rx.chakra.avatar(name="Barack Obama"),
+    rx.chakra.avatar(name="Donald Trump"),
+    rx.chakra.avatar(name="Joe Biden"),
+)
+```
+
+Badges can also be applied to show elements about the avatar such as activity.
+
+```python demo
+rx.chakra.avatar_group(
+    rx.chakra.avatar(
+        rx.chakra.avatar_badge(
+            box_size="1.25em", bg="green.500", border_color="green.500"
+        ),
+        name="Barack Obama",
+    ),
+    rx.chakra.avatar(
+        rx.chakra.avatar_badge(
+            box_size="1.25em", bg="yellow.500", border_color="red.500"
+        ),
+        name="Donald Trump",
+    ),
+)
+```
+
+If there are too many avatar to display a limit can be set using the `max_` prop.
+
+```python demo
+rx.chakra.avatar_group(
+    *([rx.chakra.avatar(name="Barack Obama")] * 5),
+    size="md",
+    max_=3,
+)
+```

+ 44 - 0
docs/library/chakra/media/icon.md

@@ -0,0 +1,44 @@
+---
+components:
+    - rx.chakra.Icon
+---
+
+```python exec
+import reflex as rx
+from reflex.components.media.icon import ICON_LIST
+```
+
+# Icon
+
+The Icon component is used to display an icon from a library of icons.
+
+```python demo
+rx.chakra.icon(tag="calendar")
+```
+
+Use the tag prop to specify the icon to display.
+
+```md alert success
+Below is a list of all available icons.
+```
+
+```python eval
+rx.chakra.box(
+    rx.chakra.divider(),
+    rx.chakra.responsive_grid(
+        *[
+            rx.chakra.vstack(
+                rx.chakra.icon(tag=icon),
+                rx.chakra.text(icon),
+                bg="white",
+                border="1px solid #EAEAEA",
+                border_radius="0.5em",
+                padding=".75em",
+            )
+            for icon in ICON_LIST
+        ],
+        columns=[2, 2, 3, 3, 4],
+        spacing="1em",
+    )
+)
+```

+ 54 - 0
docs/library/chakra/media/image.md

@@ -0,0 +1,54 @@
+---
+components:
+    - rx.chakra.Image
+---
+
+```python exec
+import reflex as rx
+```
+
+# Image
+
+The Image component can display an image given a `src` path as an argument.
+This could either be a local path from the assets folder or an external link.
+
+```python demo
+rx.chakra.image(src="/reflex_banner.png", width="100px", height="auto")
+```
+
+Image composes a box and can be styled simlarly.
+
+```python demo
+rx.chakra.image(
+    src="/reflex_banner.png",
+    width="100px",
+    height="auto",
+    border_radius="15px 50px",
+    border="5px solid #555",
+    box_shadow="lg",
+)
+```
+
+You can also pass a `PIL` image object as the `src`.
+
+```python demo box
+rx.chakra.vstack(
+    rx.chakra.image(src="https://picsum.photos/id/1/200/300", alt="An Unsplash Image")
+)
+```
+
+```python
+from PIL import Image
+import requests
+
+
+class ImageState(rx.State):
+    url = f"https://picsum.photos/id/1/200/300"
+    image = Image.open(requests.get(url, stream=True).raw)
+
+
+def image_pil_example():
+    return rx.chakra.vstack(
+        rx.chakra.image(src=ImageState.image)
+    )
+```

+ 36 - 0
docs/library/chakra/navigation/breadcrumb.md

@@ -0,0 +1,36 @@
+---
+components:
+    - rx.chakra.Breadcrumb
+    - rx.chakra.BreadcrumbItem
+    - rx.chakra.BreadcrumbLink
+---
+
+```python exec
+import reflex as rx
+```
+
+# Breadcrumb
+
+Breadcrumbs, or a breadcrumb navigation, can help enhance how users navigate to previous page levels of a website.
+
+This is userful for websites with a lot of pages.
+
+```python demo
+rx.chakra.breadcrumb(
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Home", href="#")),
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Docs", href="#")),
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Breadcrumb", href="#")),
+)
+```
+
+The separator prop can be used to change the default separator.
+
+```python demo
+rx.chakra.breadcrumb(
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Home", href="#")),
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Docs", href="#")),
+    rx.chakra.breadcrumb_item(rx.chakra.breadcrumb_link("Breadcrumb", href="#")),
+    separator=">",
+    color="rgb(107,99,246)"
+)
+```

+ 41 - 0
docs/library/chakra/navigation/link.md

@@ -0,0 +1,41 @@
+---
+components:
+    - rx.chakra.Link
+---
+
+```python exec
+import reflex as rx
+```
+
+# Link
+
+Links are accessible elements used primarily for navigation.
+
+```python demo
+rx.chakra.link("Example", href="https://reflex.dev", color="rgb(107,99,246)")
+```
+
+You can also provide local links to other pages in your project without writing the full url.
+
+```python demo
+rx.chakra.link("Example", href="/docs/library", color="rgb(107,99,246)")
+```
+
+The link component can be used to wrap other components to make them link to other pages.
+
+```python demo
+rx.chakra.link(rx.chakra.button("Example"), href="https://reflex.dev", color="rgb(107,99,246)", button=True)
+```
+
+You can also create anchors to link to specific parts of a page using the id prop.
+
+```python demo
+rx.chakra.box("Example", id="example")
+```
+
+To reference an anchor, you can use the href prop of the link component.
+The `href` should be in the format of the page you want to link to followed by a `#` and the `id` of the anchor.
+
+```python demo
+rx.chakra.link("Example", href="/docs/library/navigation/link#example", color="rgb(107,99,246)")
+```

+ 18 - 0
docs/library/chakra/navigation/linkoverlay.md

@@ -0,0 +1,18 @@
+---
+components:
+    - rx.chakra.LinkOverlay
+---
+
+```python exec
+import reflex as rx
+```
+
+# LinkOverlay
+
+Link overlay provides a semantic way to wrap elements (cards, blog post, articles, etc.) in a link.
+
+```python
+rx.chakra.link_overlay(
+    rx.chakra.box("Example", bg="black", color="white", font_size=30),
+)
+```

+ 45 - 0
docs/library/chakra/overlay/alertdialog.md

@@ -0,0 +1,45 @@
+---
+components:
+    - rx.chakra.AlertDialog
+    - rx.chakra.AlertDialogOverlay
+    - rx.chakra.AlertDialogContent
+    - rx.chakra.AlertDialogHeader
+    - rx.chakra.AlertDialogBody
+    - rx.chakra.AlertDialogFooter
+---
+
+```python exec
+import reflex as rx
+```
+
+# AlertDialog
+
+AlertDialog component is used to interrupt the user with a mandatory confirmation or event.
+The component will appear in front of the page prompting the user to conplete an event.
+
+```python demo exec
+class AlertDialogState(rx.State):
+    show: bool = False
+
+    def change(self):
+        self.show = not (self.show)
+
+
+def alertdialog_example():
+    return rx.chakra.vstack(
+        rx.chakra.button("Show Alert Dialog", on_click=AlertDialogState.change),
+        rx.chakra.alert_dialog(
+            rx.chakra.alert_dialog_overlay(
+                rx.chakra.alert_dialog_content(
+                    rx.chakra.alert_dialog_header("Confirm"),
+                    rx.chakra.alert_dialog_body("Do you want to confirm example?"),
+                    rx.chakra.alert_dialog_footer(
+                        rx.chakra.button("Close", on_click=AlertDialogState.change)
+                    ),
+                )
+            ),
+            is_open=AlertDialogState.show,
+        ),
+        width="100%",
+    )
+```

+ 70 - 0
docs/library/chakra/overlay/drawer.md

@@ -0,0 +1,70 @@
+---
+components:
+    - rx.chakra.Drawer
+    - rx.chakra.DrawerOverlay
+    - rx.chakra.DrawerContent
+    - rx.chakra.DrawerHeader
+    - rx.chakra.DrawerBody
+    - rx.chakra.DrawerFooter
+---
+
+```python exec
+import reflex as rx
+```
+
+# Drawer
+
+The Drawer component is a panel that slides out from the edge of the screen.
+It can be useful when you need users to complete a task or view some details without leaving the current page.
+
+```python demo exec
+class DrawerState(rx.State):
+    show_right: bool = False
+    show_top: bool = False
+
+    def top(self):
+        self.show_top = not (self.show_top)
+
+    def right(self):
+        self.show_right = not (self.show_right)
+
+def drawer_example():
+    return rx.chakra.vstack(
+        rx.chakra.button("Show Right Drawer", on_click=DrawerState.right),
+        rx.chakra.drawer(
+            rx.chakra.drawer_overlay(
+                rx.chakra.drawer_content(
+                    rx.chakra.drawer_header("Confirm"),
+                    rx.chakra.drawer_body("Do you want to confirm example?"),
+                    rx.chakra.drawer_footer(
+                        rx.chakra.button("Close", on_click=DrawerState.right)
+                    ),
+                    bg = "rgba(0, 0, 0, 0.3)"
+                )
+            ),
+            is_open=DrawerState.show_right,
+        )
+    )
+```
+
+Drawer can display from the top, bottom, left, or right.
+By defualt it displays to the right as seen above
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.button("Show Top Drawer", on_click=DrawerState.top),
+    rx.chakra.drawer(
+        rx.chakra.drawer_overlay(
+            rx.chakra.drawer_content(
+                rx.chakra.drawer_header("Confirm"),
+                rx.chakra.drawer_body("Do you want to confirm example?"),
+                rx.chakra.drawer_footer(
+                    rx.chakra.button("Close", on_click=DrawerState.top)
+                ),
+            )
+        ),
+        placement="top",
+        is_open=DrawerState.show_top,
+    )
+)
+```

+ 31 - 0
docs/library/chakra/overlay/menu.md

@@ -0,0 +1,31 @@
+---
+components:
+    - rx.chakra.Menu
+    - rx.chakra.MenuButton
+    - rx.chakra.MenuList
+    - rx.chakra.MenuItem
+    - rx.chakra.MenuDivider
+    - rx.chakra.MenuGroup
+    - rx.chakra.MenuOptionGroup
+    - rx.chakra.MenuItemOption
+---
+
+```python exec
+import reflex as rx
+```
+
+# Menu
+
+An accessible dropdown menu for the common dropdown menu button design pattern.
+
+```python demo
+rx.chakra.menu(
+    rx.chakra.menu_button("Menu"),
+    rx.chakra.menu_list(
+        rx.chakra.menu_item("Example"),
+        rx.chakra.menu_divider(),
+        rx.chakra.menu_item("Example"),
+        rx.chakra.menu_item("Example"),
+    ),
+)
+```

+ 42 - 0
docs/library/chakra/overlay/modal.md

@@ -0,0 +1,42 @@
+---
+components:
+    - rx.chakra.Modal
+    - rx.chakra.ModalOverlay
+    - rx.chakra.ModalContent
+    - rx.chakra.ModalHeader
+    - rx.chakra.ModalBody
+    - rx.chakra.ModalFooter
+---
+
+```python exec
+import reflex as rx
+```
+
+# Modal
+
+A modal dialog is a window overlaid on either the primary window or another dialog window.
+Content behind a modal dialog is inert, meaning that users cannot interact with it.
+
+```python demo exec
+class ModalState(rx.State):
+    show: bool = False
+
+    def change(self):
+        self.show = not (self.show)
+
+
+def modal_example():
+    return rx.chakra.vstack(
+    rx.chakra.button("Confirm", on_click=ModalState.change),
+    rx.chakra.modal(
+        rx.chakra.modal_overlay(
+            rx.chakra.modal_content(
+                rx.chakra.modal_header("Confirm"),
+                rx.chakra.modal_body("Do you want to confirm example?"),
+                rx.chakra.modal_footer(rx.chakra.button("Close", on_click=ModalState.change)),
+            )
+        ),
+        is_open=ModalState.show,
+    ),
+)
+```

+ 32 - 0
docs/library/chakra/overlay/popover.md

@@ -0,0 +1,32 @@
+---
+components:
+    - rx.chakra.Popover
+    - rx.chakra.PopoverTrigger
+    - rx.chakra.PopoverContent
+    - rx.chakra.PopoverHeader
+    - rx.chakra.PopoverBody
+    - rx.chakra.PopoverFooter
+    - rx.chakra.PopoverArrow
+    - rx.chakra.PopoverAnchor
+---
+
+```python exec
+import reflex as rx
+```
+
+# Popover
+
+Popover is a non-modal dialog that floats around a trigger.
+It is used to display contextual information to the user, and should be paired with a clickable trigger element.
+
+```python demo
+rx.chakra.popover(
+    rx.chakra.popover_trigger(rx.chakra.button("Popover Example")),
+    rx.chakra.popover_content(
+        rx.chakra.popover_header("Confirm"),
+        rx.chakra.popover_body("Do you want to confirm example?"),
+        rx.chakra.popover_footer(rx.chakra.text("Footer text.")),
+        rx.chakra.popover_close_button(),
+    ),
+)
+```

+ 20 - 0
docs/library/chakra/overlay/tooltip.md

@@ -0,0 +1,20 @@
+---
+components:
+    - rx.chakra.Tooltip
+---
+
+```python exec
+import reflex as rx
+```
+
+# Tooltip
+
+A tooltip is a brief, informative message that appears when a user interacts with an element.
+Tooltips are usually initiated in one of two ways: through a mouse-hover gesture or through a keyboard-hover gesture.
+
+```python demo
+rx.chakra.tooltip(
+    rx.chakra.text("Example", font_size=30),
+    label="Tooltip helper.",
+)
+```

+ 36 - 0
docs/library/chakra/typography/heading.md

@@ -0,0 +1,36 @@
+---
+components:
+    - rx.chakra.Heading
+---
+
+```python exec
+import reflex as rx
+```
+
+# Heading
+
+The Heading component takes in a string and displays it as a heading.
+
+```python demo
+rx.chakra.heading("Hello World!")
+```
+
+The size can be changed using the `size` prop.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.heading("Hello World!", size= "sm", color="red"),
+    rx.chakra.heading("Hello World!", size= "md", color="blue"),
+    rx.chakra.heading("Hello World!", size= "lg", color="green"),
+    rx.chakra.heading("Hello World!", size= "xl", color="blue"),
+    rx.chakra.heading("Hello World!", size= "2xl", color="red"),
+    rx.chakra.heading("Hello World!", size= "3xl", color="blue"),
+    rx.chakra.heading("Hello World!", size= "4xl", color="green"),
+)
+```
+
+It can also be styled using regular CSS styles.
+
+```python demo
+rx.chakra.heading("Hello World!", font_size="2em")
+```

+ 20 - 0
docs/library/chakra/typography/highlight.md

@@ -0,0 +1,20 @@
+---
+components:
+    - rx.chakra.Highlight
+---
+
+```python exec
+import reflex as rx
+```
+
+# Highlight
+
+The highlight component take in a string and display some of the words as highlighted text.
+
+The words to highlight can be selected using the `query` prop.
+
+You can also customize how the hightlight will be rendered with the `styles` prop.
+
+```python demo
+rx.chakra.highlight("Hello World, we have some highlight", query=['World','some'], styles={ 'px': '2', 'py': '1', 'rounded': 'full', 'bg': 'grey' })
+```

+ 21 - 0
docs/library/chakra/typography/span.md

@@ -0,0 +1,21 @@
+---
+components:
+    - rx.chakra.span
+---
+
+```python exec
+import reflex as rx
+```
+
+# Span
+
+The span component can be used to style inline text without creating a new line.
+
+```python demo
+rx.chakra.box(
+    "Write some ",
+    rx.chakra.span("stylized ", color="red"),    
+    rx.chakra.span("text ", color="blue"),
+    rx.chakra.span("using spans.", font_weight="bold")
+)
+```

+ 27 - 0
docs/library/chakra/typography/text.md

@@ -0,0 +1,27 @@
+---
+components:
+    - rx.chakra.Text
+---
+
+```python exec
+import reflex as rx
+```
+
+# Text
+
+The text component displays a paragraph of text.
+
+```python demo
+rx.chakra.text("Hello World!", font_size="2em")
+```
+
+The text element can be visually modified using the `as_` prop.
+
+```python demo
+rx.chakra.vstack(
+    rx.chakra.text("Hello World!", as_="i"),
+    rx.chakra.text("Hello World!", as_="s"),
+    rx.chakra.text("Hello World!", as_="mark"),
+    rx.chakra.text("Hello World!", as_="sub"),
+)
+```

+ 145 - 0
docs/library/datadisplay/avatar.md

@@ -0,0 +1,145 @@
+---
+components:
+    - rx.radix.avatar
+Avatar: |
+    lambda **props: rx.hstack(rx.avatar(src="/logo.jpg", **props), rx.avatar(fallback="RX", **props), spacing="3")
+---
+# Avatar
+
+```python exec
+import reflex as rx
+from pcweb.templates.docpage import style_grid
+```
+
+The Avatar component is used to represent a user, and display their profile pictures or fallback texts such as initials.
+
+## Basic Example
+
+To create an avatar component with an image, pass the image URL as the `src` prop.
+
+```python demo
+rx.avatar(src="/logo.jpg")
+```
+
+To display a text such as initials, set the `fallback` prop without passing the `src` prop.
+
+```python demo
+rx.avatar(fallback="RX")
+```
+
+## Styling
+
+```python eval
+style_grid(component_used=rx.avatar, component_used_str="rx.avatar", variants=["solid", "soft"], fallback="RX")
+```
+
+### Size
+
+The `size` prop controls the size and spacing of the avatar. The acceptable size is from `"1"` to `"9"`, with `"3"` being the default.
+
+```python demo
+rx.flex(
+    rx.avatar(src="/logo.jpg", fallback="RX", size="1"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="2"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="3"),
+    rx.avatar(src="/logo.jpg", fallback="RX"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="4"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="5"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="6"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="7"),
+    rx.avatar(src="/logo.jpg", fallback="RX", size="8"),
+    spacing="1",
+)
+```
+
+### Variant
+
+The `variant` prop controls the visual style of the avatar fallback text. The variant can be `"solid"` or `"soft"`. The default is `"soft"`.
+
+```python demo
+rx.flex(
+    rx.avatar(fallback="RX", variant="solid"),
+    rx.avatar(fallback="RX", variant="soft"),
+    rx.avatar(fallback="RX"),
+    spacing="2",
+)
+```
+
+### Color Scheme
+
+The `color_scheme` prop sets a specific color to the fallback text, ignoring the global theme.
+
+```python demo
+rx.flex(
+    rx.avatar(fallback="RX", color_scheme="indigo"),
+    rx.avatar(fallback="RX", color_scheme="cyan"),
+    rx.avatar(fallback="RX", color_scheme="orange"),
+    rx.avatar(fallback="RX", color_scheme="crimson"),
+    spacing="2",
+)
+```
+
+### High Contrast
+
+The `high_contrast` prop increases color contrast of the fallback text with the background.
+
+```python demo
+rx.grid(
+    rx.avatar(fallback="RX", variant="solid"),
+    rx.avatar(fallback="RX", variant="solid", high_contrast=True),
+    rx.avatar(fallback="RX", variant="soft"),
+    rx.avatar(fallback="RX", variant="soft", high_contrast=True),
+    rows="2",
+    spacing="2",
+    flow="column",
+)
+```
+
+### Radius
+
+The `radius` prop sets specific radius value, ignoring the global theme. It can take values `"none" | "small" | "medium" | "large" | "full"`.
+
+```python demo
+rx.grid(
+    rx.avatar(src="/logo.jpg", fallback="RX", radius="none"),
+    rx.avatar(fallback="RX", radius="none"),
+    rx.avatar(src="/logo.jpg", fallback="RX", radius="small"),
+    rx.avatar(fallback="RX", radius="small"),
+    rx.avatar(src="/logo.jpg", fallback="RX", radius="medium"),
+    rx.avatar(fallback="RX", radius="medium"),
+    rx.avatar(src="/logo.jpg", fallback="RX", radius="large"),
+    rx.avatar(fallback="RX", radius="large"),
+    rx.avatar(src="/logo.jpg", fallback="RX", radius="full"),
+    rx.avatar(fallback="RX", radius="full"),
+    rows="2",
+    spacing="2",
+    flow="column",
+)
+```
+
+### Fallback
+
+The `fallback` prop indicates the rendered text when the `src` cannot be loaded.
+
+```python demo
+rx.flex(
+    rx.avatar(fallback="RX"),
+    rx.avatar(fallback="PC"),
+    spacing="2",
+)
+```
+
+## Final Example
+
+As part of a user profile page, the Avatar component is used to display the user's profile picture, with the fallback text showing the user's initials. Text components displays the user's full name and username handle and a Button component shows the edit profile button.
+
+```python demo
+rx.flex(
+    rx.avatar(src="/logo.jpg", fallback="RU", size="9"),
+    rx.text("Reflex User", weight="bold", size="4"),
+    rx.text("@reflexuser", color_scheme="gray"),
+    rx.button("Edit Profile", color_scheme="indigo", variant="solid"),
+    direction="column",
+    spacing="1",
+)
+```

+ 128 - 0
docs/library/datadisplay/badge.md

@@ -0,0 +1,128 @@
+---
+components:
+    - rx.radix.badge
+
+Badge: |
+    lambda **props: rx.badge("Basic Badge", **props)
+---
+# Badge
+
+```python exec
+import reflex as rx
+from pcweb.templates.docpage import style_grid
+```
+
+Badges are used to highlight an item's status for quick recognition.
+
+## Basic Example
+
+To create a badge component with only text inside, pass the text as an argument.
+
+```python demo
+rx.badge("New")
+```
+
+## Styling
+
+```python eval
+style_grid(component_used=rx.badge, component_used_str="rx.badge", variants=["solid", "soft", "surface", "outline"], components_passed="England!",)
+```
+
+### Size
+
+The `size` prop controls the size and padding of a badge. It can take values of `"1" | "2"`, with default being `"1"`.
+
+```python demo
+rx.flex(
+    rx.badge("New"),
+    rx.badge("New", size="1"),
+    rx.badge("New", size="2"),
+    align="center",
+    spacing="2",
+)
+```
+
+### Variant
+
+The `variant` prop controls the visual style of the badge. The supported variant types are `"solid" | "soft" | "surface" | "outline"`. The variant default is `"soft"`.
+
+```python demo
+rx.flex(
+    rx.badge("New", variant="solid"),
+    rx.badge("New", variant="soft"),
+    rx.badge("New"),
+    rx.badge("New", variant="surface"),
+    rx.badge("New", variant="outline"),
+    spacing="2",
+)
+```
+
+### Color Scheme
+
+The `color_scheme` prop sets a specific color, ignoring the global theme.
+
+```python demo
+rx.flex(
+    rx.badge("New", color_scheme="indigo"),
+    rx.badge("New", color_scheme="cyan"),
+    rx.badge("New", color_scheme="orange"),
+    rx.badge("New", color_scheme="crimson"),
+    spacing="2",
+)
+```
+
+### High Contrast
+
+The `high_contrast` prop increases color contrast of the fallback text with the background.
+
+```python demo
+rx.flex(
+    rx.flex(
+        rx.badge("New", variant="solid"),
+        rx.badge("New", variant="soft"),
+        rx.badge("New", variant="surface"),
+        rx.badge("New", variant="outline"),
+        spacing="2",
+    ),
+    rx.flex(
+        rx.badge("New", variant="solid", high_contrast=True),
+        rx.badge("New", variant="soft", high_contrast=True),
+        rx.badge("New", variant="surface", high_contrast=True),
+        rx.badge("New", variant="outline", high_contrast=True),
+        spacing="2",
+    ),
+    direction="column",
+    spacing="2",
+)
+```
+
+### Radius
+
+The `radius` prop sets specific radius value, ignoring the global theme. It can take values `"none" | "small" | "medium" | "large" | "full"`.
+
+```python demo
+rx.flex(
+    rx.badge("New", radius="none"),
+    rx.badge("New", radius="small"),
+    rx.badge("New", radius="medium"),
+    rx.badge("New", radius="large"),
+    rx.badge("New", radius="full"),
+    spacing="3",
+)
+```
+
+## Final Example
+
+A badge may contain more complex elements within it. This example uses a `flex` component to align an icon and the text correctly, using the `gap` prop to
+ensure a comfortable spacing between the two.
+
+```python demo
+rx.badge(
+    rx.flex(
+        rx.icon(tag="arrow_up"),
+        rx.text("8.8%"),
+        spacing="1",
+    ),
+    color_scheme="grass",
+)
+```

+ 140 - 0
docs/library/datadisplay/callout-ll.md

@@ -0,0 +1,140 @@
+---
+components:
+    - rx.radix.callout.root
+    - rx.radix.callout.icon
+    - rx.radix.callout.text
+---
+
+
+```python exec
+import reflex as rx
+```
+
+# Callout
+
+A `callout` is a short message to attract user's attention.
+
+```python demo
+rx.callout.root(
+    rx.callout.icon(rx.icon(tag="info")),
+    rx.callout.text("You will need admin privileges to install and access this application."),
+)
+```
+
+The `callout` component is made up of a `callout.root`, which groups `callout.icon` and `callout.text` parts. This component is based on the `div` element and supports common margin props.
+
+The `callout.icon` provides width and height for the `icon` associated with the `callout`. This component is based on the `div` element. See the [**icon** component for all icons that are available.](/docs/library/radix/datadisplay/icon)
+
+The `callout.text` renders the callout text. This component is based on the `p` element.
+
+## As alert
+
+```python demo
+rx.callout.root(
+    rx.callout.icon(rx.icon(tag="alert_triangle")),
+    rx.callout.text("Access denied. Please contact the network administrator to view this page."),
+    color_scheme="red",
+    role="alert",
+)
+```
+
+## Style
+
+### Size
+
+Use the `size` prop to control the size.
+
+```python demo
+rx.flex(
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        size="3",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        size="2",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        size="1",
+    ),
+    direction="column",
+    spacing="3",
+    align="start",
+)
+```
+
+### Variant
+
+Use the `variant` prop to control the visual style. It is set to `soft` by default.
+
+```python demo
+rx.flex(
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        variant="soft",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        variant="surface",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        variant="outline",
+    ),
+    direction="column",
+    spacing="3",
+)
+```
+
+### Color
+
+Use the `color_scheme` prop to assign a specific color, ignoring the global theme.
+
+```python demo
+rx.flex(
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        color_scheme="blue",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        color_scheme="green",
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        color_scheme="red",
+    ),
+    direction="column",
+    spacing="3",
+)
+```
+
+### High Contrast
+
+Use the `high_contrast` prop to add additional contrast.
+
+```python demo
+rx.flex(
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+    ),
+    rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        high_contrast=True,
+    ),
+    direction="column",
+    spacing="3",
+)
+```

+ 96 - 0
docs/library/datadisplay/callout.md

@@ -0,0 +1,96 @@
+---
+components:
+    - rx.radix.callout
+    - rx.radix.callout.root
+    - rx.radix.callout.icon
+    - rx.radix.callout.text
+
+Callout: |
+    lambda **props: rx.callout("Basic Callout", icon="search", **props)
+
+CalloutRoot: |
+    lambda **props: rx.callout.root(
+        rx.callout.icon(rx.icon(tag="info")),
+        rx.callout.text("You will need admin privileges to install and access this application."),
+        **props
+    )
+---
+
+
+```python exec
+import reflex as rx
+```
+
+# Callout
+
+A `callout` is a short message to attract user's attention.
+
+```python demo
+rx.callout("You will need admin privileges to install and access this application.", icon="info")
+```
+
+The `icon` prop allows an icon to be passed to the `callout` component. See the [**icon** component for all icons that are available.](/docs/library/radix/datadisplay/icon)
+
+## As alert
+
+```python demo
+rx.callout("Access denied. Please contact the network administrator to view this page.", icon="alert_triangle", color_scheme="red", role="alert")
+```
+
+## Style
+
+### Size
+
+Use the `size` prop to control the size.
+
+```python demo
+rx.flex(
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", size="3",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", size="2",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", size="1",),
+    direction="column",
+    spacing="3",
+    align="start",
+)
+```
+
+### Variant
+
+Use the `variant` prop to control the visual style. It is set to `soft` by default.
+
+```python demo
+rx.flex(
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", variant="soft",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", variant="surface",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", variant="outline",),
+    direction="column",
+    spacing="3",
+)
+```
+
+### Color
+
+Use the `color_scheme` prop to assign a specific color, ignoring the global theme.
+
+```python demo
+rx.flex(
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", color_scheme="blue",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", color_scheme="green",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", color_scheme="red",),
+    direction="column",
+    spacing="3",
+)
+```
+
+### High Contrast
+
+Use the `high_contrast` prop to add additional contrast.
+
+```python demo
+rx.flex(
+    rx.callout("You will need admin privileges to install and access this application.", icon="info",),
+    rx.callout("You will need admin privileges to install and access this application.", icon="info", high_contrast=True,),
+    direction="column",
+    spacing="3",
+)
+```

+ 25 - 0
docs/library/datadisplay/codeblock.md

@@ -0,0 +1,25 @@
+---
+components:
+    - rx.code_block
+---
+
+```python exec
+import reflex as rx
+```
+
+# CodeBlock
+
+The CodeBlock component can be used to display code easily within a website.
+Put in a multiline string with the correct spacing and specify and language to show the desired code.
+
+```python demo
+rx.code_block(
+    """def fib(n):
+    if n <= 1:
+        return n
+    else:
+        return(fib(n-1) + fib(n-2))""",
+    language="python",
+    show_line_numbers=True,
+)
+```

+ 356 - 0
docs/library/datadisplay/data_editor.md

@@ -0,0 +1,356 @@
+---
+components:
+    - rx.data_editor
+---
+
+# Data Editor
+
+A datagrid editor based on [Glide Data Grid](https://grid.glideapps.com/)
+
+```python exec
+import reflex as rx
+from pcweb.pages.docs import library
+from typing import Any
+
+columns: list[dict[str, str]] = [
+    {
+        "title":"Code",
+        "type": "str",
+    },
+    {
+        "title":"Value",
+        "type": "int",
+    }, 
+    {
+        "title":"Activated",
+        "type": "bool",
+    },
+]
+data: list[list[Any]] = [
+    ["A", 1, True],
+    ["B", 2, False],
+    ["C", 3, False],
+    ["D", 4, True],
+    ["E", 5, True],
+    ["F", 6, False],
+]
+
+```
+
+This component is introduced as an alternative to the [datatable]({library.datadisplay.datatable.path}) to support editing the displayed data.
+
+## Columns
+
+The columns definition should be a `list` of `dict`, each `dict` describing the associated columns.
+Property of a column dict:
+
+- `title`: The text to display in the header of the column.
+- `id`: An id for the column, if not defined, will default to a lower case of `title`
+- `width`: The width of the column.
+- `type`: The type of the columns, default to `"str"`.
+
+## Data
+
+The `data` props of `rx.data_editor` accept a `list` of `list`, where each `list` represent a row of data to display in the table.
+
+## Simple Example
+
+Here is a basic example of using the data_editor representing data with no interaction and no styling. Below we define the `columns` and the `data` which are taken in by the `rx.data_editor` component. When we define the `columns` we must define a `title` and a `type` for each column we create. The columns in the `data` must then match the defined `type` or errors will be thrown.
+
+```python demo box
+rx.data_editor(
+    columns=columns,
+    data=data,
+)
+```
+
+```python
+columns: list[dict[str, str]] = [
+    {
+        "title":"Code",
+        "type": "str",
+    },
+    {
+        "title":"Value",
+        "type": "int",
+    }, 
+    {
+        "title":"Activated",
+        "type": "bool",
+    },
+]
+data: list[list[Any]] = [
+    ["A", 1, True],
+    ["B", 2, False],
+    ["C", 3, False],
+    ["D", 4, True],
+    ["E", 5, True],
+    ["F", 6, False],
+]
+```
+
+```python
+rx.data_editor(
+    columns=columns,
+    data=data,
+)
+```
+
+## Interactive Example
+
+```python exec
+class DataEditorState_HP(rx.State):
+
+    clicked_data: str = "Cell clicked: "
+    cols: list[Any] = [
+        {"title": "Title", "type": "str"},
+        {
+            "title": "Name",
+            "type": "str",
+            "group": "Data",
+            "width": 300,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "id": "date",
+            "group": "Data",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "group": "Data",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+            "id": "date",
+            "group": "Data",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "id": "date",
+            "group": "Data",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+            "id": "date",
+            "group": "Data",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "id": "date",
+            "group": "Data",
+            "width": 200,
+        }
+    ]
+
+    data = [
+        ["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "11'  Holly  phoenix feather", "Stag", "Half-blood"],
+        ["2", "Ronald Bilius Weasley", "1 March 1980", True,"Gryffindor", "12' Ash unicorn tail hair", "Jack Russell terrier", "Pure-blood"],
+        ["3", "Hermione Jean Granger", "19 September, 1979", True, "Gryffindor", "10¾'  vine wood dragon heartstring", "Otter", "Muggle-born"], 
+        ["4", "Albus Percival Wulfric Brian Dumbledore", "Late August 1881", True, "Gryffindor", "15' Elder Thestral tail hair core", "Phoenix", "Half-blood"], 
+        ["5", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "16'  Oak unknown core", "None", "Part-Human (Half-giant)"], 
+        ["6", "Fred Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"], 
+    ]
+
+    def click_cell(self, pos):
+        col, row = pos
+        yield self.get_clicked_data(pos)
+        
+
+    def get_clicked_data(self, pos) -> str:
+        self.clicked_data = f"Cell clicked: {pos}"
+        
+```
+
+Here we define a State, as shown below, that allows us to print the location of the cell as a heading when we click on it, using the `on_cell_clicked` `event trigger`. Check out all the other `event triggers` that you can use with datatable at the bottom of this page. We also define a `group` with a label `Data`. This groups all the columns with this `group` label under a larger group `Data` as seen in the table below.
+
+```python demo box
+rx.heading(DataEditorState_HP.clicked_data)
+```
+
+```python demo box
+rx.data_editor(
+    columns=DataEditorState_HP.cols,
+    data=DataEditorState_HP.data,
+    on_cell_clicked=DataEditorState_HP.click_cell,
+)
+```
+
+```python
+class DataEditorState_HP(rx.State):
+    
+    clicked_data: str = "Cell clicked: "
+
+    cols: list[Any] = [
+        {
+            "title": "Title", 
+            "type": "str"
+        },
+        {
+            "title": "Name",
+            "type": "str",
+            "group": "Data",
+            "width": 300,
+        },
+        {
+            "title": "Birth",
+            "type": "str",
+            "group": "Data",
+            "width": 150,
+        },
+        {
+            "title": "Human",
+            "type": "bool",
+            "group": "Data",
+            "width": 80,
+        },
+        {
+            "title": "House",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Wand",
+            "type": "str",
+            "group": "Data",
+            "width": 250,
+        },
+        {
+            "title": "Patronus",
+            "type": "str",
+            "group": "Data",
+        },
+        {
+            "title": "Blood status",
+            "type": "str",
+            "group": "Data",
+            "width": 200,
+        }
+    ]
+
+    data = [
+        ["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "11'  Holly  phoenix feather", "Stag", "Half-blood"],
+        ["2", "Ronald Bilius Weasley", "1 March 1980", True,"Gryffindor", "12' Ash unicorn tail hair", "Jack Russell terrier", "Pure-blood"],
+        ["3", "Hermione Jean Granger", "19 September, 1979", True, "Gryffindor", "10¾'  vine wood dragon heartstring", "Otter", "Muggle-born"], 
+        ["4", "Albus Percival Wulfric Brian Dumbledore", "Late August 1881", True, "Gryffindor", "15' Elder Thestral tail hair core", "Phoenix", "Half-blood"], 
+        ["5", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "16'  Oak unknown core", "None", "Part-Human (Half-giant)"], 
+        ["6", "Fred Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"], 
+    ]
+
+
+    def click_cell(self, pos):
+        col, row = pos
+        yield self.get_clicked_data(pos)
+        
+
+    def get_clicked_data(self, pos) -> str:
+        self.clicked_data = f"Cell clicked: \{pos}"
+```
+
+```python
+rx.data_editor(
+    columns=DataEditorState_HP.cols,
+    data=DataEditorState_HP.data,
+    on_cell_clicked=DataEditorState_HP.click_cell,
+)
+```
+
+## Styling Example
+
+Now let's style our datatable to make it look more aesthetic and easier to use. We must first import `DataEditorTheme` and then we can start setting our style props as seen below in `dark_theme`.
+
+We then set these themes using `theme=DataEditorTheme(**dark_theme)`. On top of the styling we can also set some `props` to make some other aesthetic changes to our datatable. We have set the `row_height` to equal `50` so that the content is easier to read. We have also made the `smooth_scroll_x` and `smooth_scroll_y` equal `True` so that we can smoothly scroll along the columns and rows. Finally, we added `column_select=single`, where column select can take any of the following values `none`, `single` or `multiple`.
+
+```python exec
+from reflex.components.datadisplay.dataeditor import DataEditorTheme
+dark_theme = {
+    "accentColor": "#8c96ff",
+    "accentLight": "rgba(202, 206, 255, 0.253)",
+    "textDark": "#ffffff",
+    "textMedium": "#b8b8b8",
+    "textLight": "#a0a0a0",
+    "textBubble": "#ffffff",
+    "bgIconHeader": "#b8b8b8",
+    "fgIconHeader": "#000000",
+    "textHeader": "#a1a1a1",
+    "textHeaderSelected": "#000000",
+    "bgCell": "#16161b",
+    "bgCellMedium": "#202027",
+    "bgHeader": "#212121",
+    "bgHeaderHasFocus": "#474747",
+    "bgHeaderHovered": "#404040",
+    "bgBubble": "#212121",
+    "bgBubbleSelected": "#000000",
+    "bgSearchResult": "#423c24",
+    "borderColor": "rgba(225,225,225,0.2)",
+    "drilldownBorder": "rgba(225,225,225,0.4)",
+    "linkColor": "#4F5DFF",
+    "headerFontStyle": "bold 14px",
+    "baseFontStyle": "13px",
+    "fontFamily": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
+}
+```
+
+```python demo box
+rx.data_editor(
+    columns=DataEditorState_HP.cols,
+    data=DataEditorState_HP.data,
+    row_height=80,
+    smooth_scroll_x=True,
+    smooth_scroll_y=True,
+    column_select="single",
+    theme=DataEditorTheme(**dark_theme),
+    height="30vh",
+)
+```
+
+```python
+from reflex.components.datadisplay.dataeditor import DataEditorTheme
+dark_theme_snake_case = {
+    "accent_color": "#8c96ff",
+    "accent_light": "rgba(202, 206, 255, 0.253)",
+    "text_dark": "#ffffff",
+    "text_medium": "#b8b8b8",
+    "text_light": "#a0a0a0",
+    "text_bubble": "#ffffff",
+    "bg_icon_header": "#b8b8b8",
+    "fg_icon_header": "#000000",
+    "text_header": "#a1a1a1",
+    "text_header_selected": "#000000",
+    "bg_cell": "#16161b",
+    "bg_cell_medium": "#202027",
+    "bg_header": "#212121",
+    "bg_header_has_focus": "#474747",
+    "bg_header_hovered": "#404040",
+    "bg_bubble": "#212121",
+    "bg_bubble_selected": "#000000",
+    "bg_search_result": "#423c24",
+    "border_color": "rgba(225,225,225,0.2)",
+    "drilldown_border": "rgba(225,225,225,0.4)",
+    "link_color": "#4F5DFF",
+    "header_font_style": "bold 14px",
+    "base_font_style": "13px",
+    "font_family": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
+}
+```
+
+```python
+rx.data_editor(
+    columns=DataEditorState_HP.cols,
+    data=DataEditorState_HP.data,
+    row_height=80,
+    smooth_scroll_x=True,
+    smooth_scroll_y=True,
+    column_select="single",
+    theme=DataEditorTheme(**dark_theme),
+    height="30vh",
+)
+```

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor