El taller de componentes: los 100 componentes de Reflex
·
Resumen del curso
Diseño
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Tipografía
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Formularios
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Visualización de datos
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Mostrar y ocultar
·
Tabs
·
Accordion
·
Segmented Control
Superposiciones
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Renderizado dinámico
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Multimedia
·
Image
·
Audio
·
Video
Tablas y cuadrículas de datos
·
Table
·
Data Table
·
Data Editor
Gráficos
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Piezas de gráficos
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Otras bibliotecas de gráficos
·
Plotly
·
Pyplot
Elementos HTML
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Otras herramientas
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.alert_dialog.rootrx.alert_dialog.triggerrx.alert_dialog.contentrx.alert_dialog.titlerx.alert_dialog.descriptionrx.alert_dialog.actionrx.alert_dialog.cancelDocumentación oficial
Pedido del taller
Al pulsar el botón de papelera de la lista de proyectos, no borres nada todavía: abre una ventana que pregunte una vez más si de verdad se quiere borrar.
rx.alert_dialog es una ventana de confirmación que detiene el flujo del usuario para pedirle una respuesta. A diferencia del Dialog normal, no se cierra al pulsar fuera, así que el usuario tiene que elegir entre «cancelar» y «ejecutar» (la tecla Esc cuenta como cancelar). Va delante de acciones difíciles de deshacer, como borrar algo o retirar permisos.
alert_dialog.root: envuelve todas las partes.alert_dialog.trigger: envuelve el elemento que abre la ventana al pulsarlo.alert_dialog.content: el contenido de la ventana.alert_dialog.title: el título de la ventana. Los lectores de pantalla lo leen al abrirse.alert_dialog.description: una explicación adicional (opcional). Se lee junto con el título al abrirse.alert_dialog.action: envuelve el botón de ejecutar. Al pulsarlo, la ventana se cierra.alert_dialog.cancel: envuelve el botón de cancelar. Al pulsarlo, la ventana se cierra. Haz que se distinga a simple vista del botón de ejecutar.rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.button("Revoke access"),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Revoke access"),
rx.alert_dialog.description(
"Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel"),
),
rx.alert_dialog.action(
rx.button("Revoke access"),
),
spacing="3",
),
),
)El relleno de la ventana se fija con size de content, y la colocación de los botones con justify del rx.flex que los envuelve. Da al botón de ejecutar un color acorde con la gravedad de la acción.
Prueba las propiedades
title
action
color
size
justify
rx.alert_dialog.root(
rx.alert_dialog.trigger(rx.button("Delete", color_scheme="red")),
rx.alert_dialog.content(
rx.alert_dialog.title("Delete this file?"),
rx.alert_dialog.description("This action cannot be undone.", size="2"),
rx.flex(
rx.alert_dialog.cancel(rx.button("Cancel", variant="soft", color_scheme="gray")),
rx.alert_dialog.action(rx.button("Delete", color_scheme="red")),
spacing="3",
margin_top="16px",
justify="end",
),
size="3",
max_width="450px",
),
)| Parte | Propiedad | Valores | Uso |
|---|---|---|---|
root | open | True / False | Decidir la apertura desde el State (controlado) |
root | default_open | True / False | Abierto en el primer renderizado (no controlado) |
root | on_open_change | Evento | Al abrirse o cerrarse. Pasa el nuevo valor de apertura (bool) |
content | size | "1" ~ "4" | Tamaño del relleno y de las esquinas |
content | force_mount | True / False | Mantenerlo en el DOM aunque esté cerrado (para animaciones) |
content | on_open_auto_focus · on_close_auto_focus | Evento | Cuando el foco entra en la ventana al abrirse o vuelve al trigger al cerrarse |
content | on_escape_key_down | Evento | Al pulsar la tecla Esc |
trigger, title, description, action y cancel solo tienen los eventos comunes. Los eventos de «pulsar fuera» que tenía el content de Dialog no existen aquí, porque pulsar fuera no cierra la ventana.
El botón de ejecutar y el trigger van en rojo, el de cancelar pierde fuerza en gris soft, y los dos botones se agrupan a la derecha con justify="end". El ancho de la ventana se reduce con style={"max_width": 450}.
rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.button("Revoke access", color_scheme="red"),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Revoke access"),
rx.alert_dialog.description(
"Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
size="2",
),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel", variant="soft", color_scheme="gray"),
),
rx.alert_dialog.action(
rx.button("Revoke access", color_scheme="red", variant="solid"),
),
spacing="3",
margin_top="16px",
justify="end",
),
style={"max_width": 450},
),
)Si con rx.inset llevas una tabla hasta los bordes laterales de la ventana, se ve de un vistazo qué se va a borrar.
rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.button("Delete Users", color_scheme="red"),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Delete Users"),
rx.alert_dialog.description(
"Are you sure you want to delete these users? This action is permanent and cannot be undone.",
size="2",
),
rx.inset(
rx.table.root(
rx.table.header(
rx.table.row(
rx.table.column_header_cell("Full Name"),
rx.table.column_header_cell("Email"),
rx.table.column_header_cell("Group"),
),
),
rx.table.body(
rx.table.row(
rx.table.row_header_cell("Danilo Rosa"),
rx.table.cell("danilo@example.com"),
rx.table.cell("Developer"),
),
rx.table.row(
rx.table.row_header_cell("Zahra Ambessa"),
rx.table.cell("zahra@example.com"),
rx.table.cell("Admin"),
),
),
),
side="x",
margin_top="24px",
margin_bottom="24px",
),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel", variant="soft", color_scheme="gray"),
),
rx.alert_dialog.action(
rx.button("Delete users", color_scheme="red"),
),
spacing="3",
justify="end",
),
style={"max_width": 500},
),
)El on_open_change de alert_dialog.root pasa True cuando se abre y False cuando se cierra.
Opened or closed: 0 times
Alert dialog open: no
class AlertDialogEventState(rx.State):
num_opens: int = 0
opened: bool = False
@rx.event
def count_opens(self, value: bool):
self.opened = value
self.num_opens += 1
rx.flex(
rx.text("Opened or closed: ", AlertDialogEventState.num_opens, " times"),
rx.text("Alert dialog open: ", rx.cond(AlertDialogEventState.opened, "yes", "no")),
rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.button("Revoke access", color_scheme="red"),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Revoke access"),
rx.alert_dialog.description(
"Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
size="2",
),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel", variant="soft", color_scheme="gray"),
),
rx.alert_dialog.action(
rx.button("Revoke access", color_scheme="red", variant="solid"),
),
spacing="3",
margin_top="16px",
justify="end",
),
style={"max_width": 450},
),
on_open_change=AlertDialogEventState.count_opens,
),
direction="column",
spacing="3",
align="start",
)Si conectas un valor del State a open, puedes abrir la ventana sin alert_dialog.trigger, con un botón que está fuera de ella. Los botones de cancelar y ejecutar de dentro también cierran la ventana invirtiendo el valor con el mismo handler. Para que el State se entere también cuando se cierra con Esc, conecta además on_open_change.
El ejemplo de la documentación oficial invierte el valor con self.opened = ~self.opened, pero en Python ~ convierte un bool en un entero (-1, -2). Aquí usamos not self.opened.
class AlertDialogControlState(rx.State):
opened: bool = False
@rx.event
def dialog_open(self):
self.opened = not self.opened
@rx.event
def set_opened(self, value: bool):
self.opened = value
rx.box(
rx.alert_dialog.root(
rx.alert_dialog.content(
rx.alert_dialog.title("Revoke access"),
rx.alert_dialog.description(
"Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel", on_click=AlertDialogControlState.dialog_open),
),
rx.alert_dialog.action(
rx.button("Revoke access", on_click=AlertDialogControlState.dialog_open),
),
spacing="3",
),
),
open=AlertDialogControlState.opened,
on_open_change=AlertDialogControlState.set_opened,
),
rx.button("Button to Open the Dialog", on_click=AlertDialogControlState.dialog_open),
)Igual que en Dialog, puedes meter un rx.form. Si envuelves el botón de envío en alert_dialog.action, la ventana se cierra al enviar. El guardado real en la base de datos es igual que el código de la página Dialog.
class AlertDialogFormState(rx.State):
current_user: dict[str, str] = {}
@rx.event
def add_user(self, form_data: dict):
self.current_user = form_data
# Here you would save the user to a database (see the Database course).
return rx.toast.info(
f"User {form_data.get('name', '')} has been added.", position="bottom-right"
)
rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.button(rx.icon("plus", size=26), rx.text("Add User", size="4")),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Add New User"),
rx.alert_dialog.description("Fill the form with the user's info"),
rx.form(
rx.flex(
rx.input(placeholder="User Name", name="name"),
rx.input(placeholder="user@reflex.dev", name="email"),
rx.flex(
rx.alert_dialog.cancel(
rx.button("Cancel", variant="soft", color_scheme="gray"),
),
rx.alert_dialog.action(
rx.button("Submit", type="submit"),
),
spacing="3",
justify="end",
),
direction="column",
spacing="4",
),
on_submit=AlertDialogFormState.add_user,
reset_on_submit=False,
),
max_width="450px",
),
)Cada elemento de la lista recibe su botón de papelera y su ventana de confirmación. El on_click del botón de ejecutar recibe el nombre que hay que borrar, y el handler lo quita de la lista y muestra un aviso. Si se pulsa cancelar o Esc, no pasa nada.
Website
Mobile app
Newsletter
class AlertDialogProjectState(rx.State):
projects: list[str] = ["Website", "Mobile app", "Newsletter"]
@rx.event
def delete_project(self, name: str):
self.projects = [p for p in self.projects if p != name]
return rx.toast.success(f"Deleted {name}")
@rx.event
def restore(self):
self.projects = ["Website", "Mobile app", "Newsletter"]
rx.vstack(
rx.foreach(
AlertDialogProjectState.projects,
lambda name: rx.flex(
rx.text(name),
rx.spacer(),
rx.alert_dialog.root(
rx.alert_dialog.trigger(
rx.icon_button(rx.icon("trash-2"), color_scheme="red", variant="ghost", aria_label="Delete"),
),
rx.alert_dialog.content(
rx.alert_dialog.title("Delete project?"),
rx.alert_dialog.description(
"The project ", rx.text.strong(name), " and all its files will be deleted.",
size="2",
),
rx.flex(
rx.alert_dialog.cancel(rx.button("Cancel", variant="soft", color_scheme="gray")),
rx.alert_dialog.action(
rx.button("Delete", color_scheme="red", on_click=AlertDialogProjectState.delete_project(name)),
),
spacing="3",
margin_top="16px",
justify="end",
),
max_width="420px",
),
),
width="100%",
align="center",
padding="6px 10px",
border=f"1px solid {rx.color('gray', 5)}",
border_radius="6px",
),
),
rx.button("Restore all", size="1", variant="soft", on_click=AlertDialogProjectState.restore),
width="100%",
max_width="360px",
)Notas del taller
root · trigger · content · title · description · action · cancel. No se cierra al pulsar fuera.
Tanto action como cancel cierran la ventana. Lo que hay que hacer de verdad se conecta al on_click del botón dentro de action.
Distingue el botón de ejecutar con un color acorde a la gravedad (red para borrar) y el de cancelar con gris soft.
Si lo controlas con open, conecta también on_open_change para que el cierre con Esc vuelva al State.
Si la acción se puede deshacer, en lugar de una ventana de confirmación considera ejecutarla y mostrar un aviso (Toast) con «Deshacer».
Recibe avisos de nuevas lecciones
Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.
R
ReflexKR
Aprende Python y Reflex haciendo. Todos los ejemplos se ejecutaron y verificaron en Reflex 0.10.0.
ReflexKR es gratis y sin banners publicitarios. Si te ayudó, puedes apoyarlo con un café. ☕ Invítanos un café
Aviso de afiliados© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Preguntas y respuestas
Pregunta lo que quieras sobre esta lección. Aquí se reúnen las preguntas de todas las versiones de idioma de esta página.