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

Popover

rx.popover.rootrx.popover.triggerrx.popover.contentrx.popover.close

Documentación oficial

Pedido del taller

Al pulsar el botón «Comentar» bajo una publicación, abre una ventanita en ese mismo lugar para escribir un comentario breve sin salir de la página.

rx.popover es una ventanita que aparece junto a un botón al pulsarlo. A diferencia del tooltip, se abre con un clic y puede contener elementos con los que interactuar, como campos de texto o botones. Se construye con cuatro partes.

  • popover.root: envuelve todas las partes del popover.
  • popover.trigger: envuelve el botón que abre y cierra el popover.
  • popover.content: el contenido que aparece al abrirse.
  • popover.close: envuelve un botón que cierra el popover al pulsarlo.
rx.popover.root(
    rx.popover.trigger(
        rx.button("Popover"),
    ),
    rx.popover.content(
        rx.flex(
            rx.text("Simple Example"),
            rx.popover.close(
                rx.button("Close"),
            ),
            direction="column",
            spacing="3",
        ),
    ),
)

Prueba las propiedades

La posición y el tamaño van en popover.content; el modo modal, en popover.root. Cambia un valor y pulsa Open para comprobarlo.

Prueba las propiedades

text

size

side

align

modal

rx.popover.root(
    rx.popover.trigger(rx.button("Open")),
    rx.popover.content(
        rx.flex(
            rx.text("Simple Example"),
            rx.popover.close(rx.button("Close", size="1")),
            direction="column",
            spacing="3",
        ),
        size="2",
        side="bottom",
        align="center",
    ),
    modal=False,
)
size cambia a la vez el relleno interior y las esquinas. Con modal activado, mientras está abierto no se puede pulsar ni hacer scroll fuera.
PartePropiedadValoresUso
rootopenTrue / FalseDecidir la apertura desde el State (controlado). Junto con on_open_change
rootdefault_openTrue / FalseAbierto en el primer renderizado (no controlado)
rootmodalTrue / FalseBloquea la interacción exterior mientras está abierto y oculta el resto a los lectores de pantalla
rooton_open_changeEventoAl abrirse o cerrarse. Pasa el nuevo valor de apertura (bool)
contentsize"1" ~ "4"Tamaño del relleno y de las esquinas
contentside · alignNombre de posiciónLado en el que aparece y alineación (por defecto "bottom", "center")
contentside_offset · align_offsetNúmero (px)Separación con el botón y desplazamiento extra desde la alineación
contentavoid_collisions · collision_paddingbool · númeroMoverse al chocar con el borde de la pantalla y ese margen
contentsticky · hide_when_detached"partial" "always" · boolCuánto sigue pegado al hacer scroll; ocultarse si el botón queda tapado
contenton_open_auto_focus · on_close_auto_focusEventoCuando el foco entra al abrirse o vuelve al botón al cerrarse
contenton_escape_key_down · on_pointer_down_outsideEventoTecla Esc, pulsar fuera
contenton_focus_outside · on_interact_outsideEventoCuando el foco o la interacción salen fuera

trigger y close no tienen propiedades propias; solo aceptan los eventos comunes (on_click, etc.).

Un uso real: ventana de comentarios

Dentro de un popover cabe cualquier cosa. Esta es una ventana de comentarios con un campo de texto, una casilla y un botón de enviar junto al avatar. Si envuelves el botón de enviar con popover.close, la ventana se cierra en cuanto lo pulsas. El ancho se da directamente en content, como style={"width": 360}.

rx.popover.root(
    rx.popover.trigger(
        rx.button("Comment", variant="soft"),
    ),
    rx.popover.content(
        rx.flex(
            rx.avatar("2", fallback="RX", radius="full"),
            rx.box(
                rx.text_area(placeholder="Write a comment…", style={"height": 80}),
                rx.flex(
                    rx.checkbox("Send to group"),
                    rx.popover.close(rx.button("Comment", size="1")),
                    spacing="3",
                    margin_top="12px",
                    justify="between",
                ),
                flex_grow="1",
            ),
            spacing="3",
        ),
        style={"width": 360},
    ),
)

Si pones rx.inset(side="top") como primer hijo de content, puedes añadir una imagen de cabecera que llegue hasta el borde, sin el relleno superior del popover.

rx.popover.root(
    rx.popover.trigger(
        rx.button("Feedback", variant="classic"),
    ),
    rx.popover.content(
        rx.inset(
            side="top",
            background="url('https://picsum.photos/id/29/720/200') center/cover",
            height="100px",
        ),
        rx.box(
            rx.text_area(placeholder="Write a comment…", style={"height": 80}),
            rx.flex(
                rx.checkbox("Send to group"),
                rx.popover.close(rx.button("Comment", size="1")),
                spacing="3",
                margin_top="12px",
                justify="between",
            ),
            padding_top="12px",
        ),
        style={"width": 360},
    ),
)

Texto del trigger desde el State

Para usar un valor del State como texto del botón, envuélvelo una vez en rx.text, como en rx.button(rx.text(State.valor)). La documentación oficial advierte que pasarlo directamente, como en rx.button(State.valor), no funciona como se espera. Elige un idioma abajo y verás cambiar el texto del botón.

class PopoverLanguageState(rx.State):
    language: str = "EN"

    @rx.event
    def set_language(self, value: str):
        self.language = value


rx.popover.root(
    rx.popover.trigger(
        rx.button(rx.text(PopoverLanguageState.language), variant="outline"),
    ),
    rx.popover.content(
        rx.flex(
            rx.popover.close(rx.button("EN", size="1", variant="soft", on_click=PopoverLanguageState.set_language("EN"))),
            rx.popover.close(rx.button("KO", size="1", variant="soft", on_click=PopoverLanguageState.set_language("KO"))),
            rx.popover.close(rx.button("JA", size="1", variant="soft", on_click=PopoverLanguageState.set_language("JA"))),
            spacing="2",
        ),
    ),
)

Al abrirse y cerrarse: on_open_change

El on_open_change de popover.root pasa True al handler cuando se abre y False cuando se cierra.

Opened or closed: 0 times

Popover open: no

class PopoverEventState(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: ", PopoverEventState.num_opens, " times"),
    rx.text("Popover open: ", rx.cond(PopoverEventState.opened, "yes", "no")),
    rx.popover.root(
        rx.popover.trigger(
            rx.button("Popover"),
        ),
        rx.popover.content(
            rx.flex(
                rx.text("Simple Example"),
                rx.popover.close(
                    rx.button("Close"),
                ),
                direction="column",
                spacing="3",
            ),
        ),
        on_open_change=PopoverEventState.count_opens,
    ),
    direction="column",
    spacing="3",
    align="start",
)

Abrir y cerrar desde el State

Si conectas open y on_open_change a la vez, el botón del lápiz y el clic fuera funcionan como siempre, y además el código puede cerrar la ventana. Abajo, cambia el nombre y pulsa Rename: el handler guarda el valor y cierra la ventana con self.open = False. Cada vez que se abre, el campo se vuelve a rellenar con el nombre actual.

Untitled

class PopoverControlState(rx.State):
    open: bool = False
    name: str = "Untitled"
    draft: str = ""

    @rx.event
    def set_open(self, value: bool):
        self.open = value
        if value:
            self.draft = self.name

    @rx.event
    def set_draft(self, value: str):
        self.draft = value

    @rx.event
    def rename(self):
        self.name = self.draft.strip() or "Untitled"
        self.open = False


rx.flex(
    rx.heading(PopoverControlState.name, size="4"),
    rx.popover.root(
        rx.popover.trigger(rx.icon_button(rx.icon("pencil"), variant="soft", size="1", aria_label="Rename")),
        rx.popover.content(
            rx.flex(
                rx.input(value=PopoverControlState.draft, on_change=PopoverControlState.set_draft),
                rx.button("Rename", size="1", on_click=PopoverControlState.rename),
                spacing="2",
            ),
        ),
        open=PopoverControlState.open,
        on_open_change=PopoverControlState.set_open,
    ),
    align="center",
    spacing="3",
)

Completar el pedido

Una ventanita de comentarios que se abre desde el botón «Comentar» bajo la publicación. side="top" hace que se abra hacia arriba y align="start" la alinea con el borde izquierdo del botón.

Shipping is now free over $30.

rx.card(
    rx.text("Shipping is now free over $30.", size="2"),
    rx.popover.root(
        rx.popover.trigger(rx.button(rx.icon("message-circle"), "Comment", variant="ghost", size="1", margin_top="8px")),
        rx.popover.content(
            rx.flex(
                rx.text_area(placeholder="Write a comment…", rows="3"),
                rx.flex(
                    rx.popover.close(rx.button("Cancel", size="1", variant="soft", color_scheme="gray")),
                    rx.popover.close(rx.button("Post", size="1")),
                    spacing="2",
                    justify="end",
                ),
                direction="column",
                spacing="2",
            ),
            side="top",
            align="start",
            width="300px",
        ),
    ),
    max_width="360px",
)

Notas del taller

  • Se construye con cuatro partes: root · trigger · content · close. Se abre al pulsar trigger y se cierra con close o pulsando fuera.

  • Posición y tamaño en content (side, align, side_offset, size); el modo modal en root (modal).

  • Para usar un valor del State como texto del botón trigger, envuélvelo en rx.text.

  • on_open_change pasa el nuevo valor de apertura (bool). Si lo controlas con open, el handler puede cerrar la ventana.

← Anterior

Superposiciones · Tooltip

Siguiente →

Superposiciones · Hover Card

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