Compare commits

...

2 Commits

Author SHA1 Message Date
Lendemor
dbd074c33d add docs from reflex-web 2024-02-26 17:18:28 +01:00
Lendemor
334db18bfa move readme trads to free docs folder 2024-02-26 17:14:24 +01:00
228 changed files with 24081 additions and 4 deletions

View File

@ -3,8 +3,8 @@
```
<div align="center">
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/readme/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/readme/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
<hr>
@ -18,7 +18,7 @@
---
[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md)
[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/readme/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/readme/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/readme/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/readme/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/readme/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/readme/it/README.md) | [Español](https://github.com/reflex-dev/reflex/blob/main/readme/es/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/readme/kr/README.md)
---
## ⚙️ Installation
@ -61,7 +61,7 @@ Let's go over an example: creating an image generation UI around [DALL·E](https
&nbsp;
<div align="center">
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/dalle.gif" alt="A frontend wrapper for DALL·E, shown in the process of generating an image." width="550" />
<img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/readme/images/dalle.gif" alt="A frontend wrapper for DALL·E, shown in the process of generating an image." width="550" />
</div>
&nbsp;

0
docs/__init__.py Normal file
View File

View File

@ -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.
```

View File

@ -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
docs/api-reference/cli.md Normal file
View File

@ -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.

View File

@ -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, its 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, its 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, its 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, its 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, its 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, its 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, its 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, its 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 users mouse enters an element. For example, its called when the users 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 users mouse leaves an element. For example, its called when the users 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, its 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 users mouse leaves an element. For example, its called when the users 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 users mouse enters an element. For example, its called when the users 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, its 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(),
)
```

View File

@ -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"))
```

View File

@ -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()`.

View File

@ -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.

View File

@ -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}).

View File

@ -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)),
)
```

View File

@ -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%",
)
```

View File

@ -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
docs/components/props.md Normal file
View File

@ -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.

View File

@ -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)),
)
```

View File

@ -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
docs/database/overview.md Normal file
View File

@ -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
docs/database/queries.md Normal file
View File

@ -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()]
```

View File

@ -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
docs/database/tables.md Normal file
View File

@ -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
```

View File

View File

@ -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,
)
```

View File

@ -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,
)
```

View File

@ -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

View File

@ -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",
)
```

View File

@ -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.

View File

@ -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,
),
)
```

View File

@ -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`.

View File

@ -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.
```

View File

@ -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.

View File

@ -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
docs/events/setters.md Normal file
View File

@ -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.

View File

@ -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)
```

View File

@ -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"},
)
)
```

View File

@ -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.

View File

@ -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
```

View File

@ -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}).

View File

@ -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.

View File

@ -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
Reflexs 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).
Thats 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"
)
```

View File

@ -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 `Youre 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",
)
```

View File

@ -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
```

View File

@ -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
)
```

View File

@ -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"
)
```

View File

@ -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"
)
```

View File

@ -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%",
)
```

View File

@ -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'
)
)
```

View File

@ -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%"
)
```

View File

@ -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",
)
```

View File

@ -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%",
)
```

View File

@ -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),
)
```

View File

@ -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"],
)
```

View File

@ -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),
)
```

View File

@ -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",
),
)
```

View File

@ -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.
Heres 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.
```

View File

@ -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.
```

View File

@ -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,
)
)
```

View File

@ -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%",
)
```

View File

@ -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()),
)
```

View File

@ -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,
)
)
```

View File

@ -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()),
)
```

View File

@ -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,
)
```

View File

@ -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,
)
)
```

View File

@ -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),
),
),
),
)
```

View File

@ -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%",
)
```

View File

@ -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",
)
```

View File

@ -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%",
)
```

View File

@ -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"),
)
```

View File

@ -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.

View File

@ -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
)
```

View File

@ -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%",
)
```

View File

@ -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=`.

View File

@ -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",
)
```

View File

@ -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",
)
```

View File

@ -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%",
)
```

View File

@ -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,
)
```

View File

@ -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],
)
```

View File

@ -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%",
)
```

View File

@ -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%",
)
```

View File

@ -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",
)
```

View File

@ -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,
)
```

View File

@ -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",
)
)
```

View File

@ -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)
)
```

View File

@ -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)"
)
```

View File

@ -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)")
```

View File

@ -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),
)
```

View File

@ -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%",
)
```

View File

@ -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,
)
)
```

View File

@ -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"),
),
)
```

View File

@ -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,
),
)
```

View File

@ -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(),
),
)
```

View File

@ -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.",
)
```

View File

@ -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")
```

View File

@ -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' })
```

View File

@ -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")
)
```

View File

@ -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"),
)
```

View File

@ -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",
)
```

View File

@ -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",
)
```

View File

@ -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",
)
```

View File

@ -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",
)
```

View File

@ -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,
)
```

Some files were not shown because too many files have changed in this diff Show More