R

ReflexKR

Documentación de Reflex

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

El taller de componentes: los 100 componentes de Reflex
Superposiciones

Alert Dialog

rx.alert_dialog.rootrx.alert_dialog.triggerrx.alert_dialog.contentrx.alert_dialog.titlerx.alert_dialog.descriptionrx.alert_dialog.actionrx.alert_dialog.cancel

Documentació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",
        ),
    ),
)

Prueba las propiedades

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",
    ),
)
Si la acción es peligrosa, el botón de ejecutar va en red y el de cancelar en gris soft. Los botones suelen ir al extremo derecho (justify="end").
PartePropiedadValoresUso
rootopenTrue / FalseDecidir la apertura desde el State (controlado)
rootdefault_openTrue / FalseAbierto en el primer renderizado (no controlado)
rooton_open_changeEventoAl abrirse o cerrarse. Pasa el nuevo valor de apertura (bool)
contentsize"1" ~ "4"Tamaño del relleno y de las esquinas
contentforce_mountTrue / FalseMantenerlo en el DOM aunque esté cerrado (para animaciones)
contenton_open_auto_focus · on_close_auto_focusEventoCuando el foco entra en la ventana al abrirse o vuelve al trigger al cerrarse
contenton_escape_key_downEventoAl 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.

Color y alineación a la derecha

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},
    ),
)

Al abrirse y cerrarse: on_open_change

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

Abrir y cerrar desde el State

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

Enviar un formulario

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

Completar el pedido

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

← Anterior

Superposiciones · Dialog

Siguiente →

Superposiciones · Drawer

Recibe avisos de nuevas lecciones

Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.

Datos: tu correo electrónico · Finalidad: avisos de nuevas lecciones o de la publicación de este curso · Conservación: hasta que pidas que lo borremos. No lo usamos para nada más ni lo compartimos. Responde a cualquier aviso y lo borraremos enseguida.

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.

Se muestra como texto plano, sin enlaces ni formato.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex