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.drawer.rootrx.drawer.triggerrx.drawer.overlayrx.drawer.portalrx.drawer.contentrx.drawer.closeDocumentación oficial
Pedido del taller
En la pantalla de la tienda en el móvil, al pulsar el botón «Filtros», haz que suba un panel desde abajo para elegir el orden y las condiciones de stock.
rx.drawer es un panel que entra deslizándose desde un borde de la pantalla. Sirve para sacar un momento contenido grande, como un menú lateral o un panel de selección que sube desde abajo. También se puede cerrar arrastrándolo con el dedo o el ratón. Reflex construye este componente con la librería Vaul.
drawer.root: envuelve todas las partes. Aquí van la dirección (direction) y el estado de apertura.drawer.trigger: envuelve el elemento que abre el drawer al pulsarlo.drawer.overlay: la capa semitransparente que cubre el fondo mientras está abierto.drawer.portal: dibuja el contenido en la capa más externa de la página para que ningún otro elemento lo tape.drawer.content: el panel que entra.drawer.close: envuelve un elemento que cierra el drawer al pulsarlo.Por defecto, drawer.content se coloca cubriendo toda la pantalla (position: fixed, los cuatro lados a 0). Por eso el tamaño del panel se fija liberando el lado opuesto con "auto" y dando el ancho o el alto a mano. Para un panel que sale por la izquierda, da right="auto" y un width.
rx.drawer.root(
rx.drawer.trigger(rx.button("Open Drawer")),
rx.drawer.overlay(z_index="5"),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.close(rx.box(rx.button("Close"))),
align_items="start",
direction="column",
),
top="auto",
right="auto",
height="100%",
width="20em",
padding="2em",
background_color=rx.color("gray", 2),
)
),
direction="left",
)Cambia el ancho y el color de un panel que sale por la derecha (direction="right", left="auto"). Si desactivas modal, con el drawer abierto se puede pulsar y hacer scroll en el fondo.
Prueba las propiedades
title
width
color
modal
rx.drawer.root(
rx.drawer.trigger(rx.button("Open panel")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.title("Settings"),
rx.drawer.description("Drag it to the right or press Esc to close."),
rx.drawer.close(rx.button("Close", size="1")),
direction="column",
align_items="start",
spacing="3",
),
left="auto",
height="100%",
width="20em",
padding="2em",
background_color=rx.color("gray", 3),
),
),
direction="right",
modal=True,
)| Propiedad (root) | Valores | Por defecto | Uso |
|---|---|---|---|
direction | "top" "bottom" "left" "right" | "bottom" | Dirección por la que entra. También decide hacia dónde se arrastra para cerrar |
open · default_open | True / False | - | Decidir la apertura desde el State (controlado) · abierto al principio |
modal | True / False | True | Con False, se puede pulsar y hacer scroll fuera mientras está abierto |
dismissible | True / False | - | Con False, no se cierra arrastrando, pulsando fuera ni con Esc (se usa junto con open) |
handle_only | True / False | - | Con True, solo se puede arrastrar desde drawer.handle |
snap_points | Lista de números entre 0 y 1 o de "px" | - | Alturas en las que se detiene (solo valores Python, no valores del State) |
fade_from_index | Entero | Último punto | A partir de qué punto de parada se oscurece el fondo |
close_threshold | 0~1 | - | Cuánto hay que arrastrar para que se cierre |
scroll_lock_timeout | Milisegundos | 500 | Tiempo que se bloquea el arrastre tras hacer scroll dentro del panel |
should_scale_background | True / False | - | Efecto de encoger un poco el fondo (requiere vaul-drawer-wrapper) |
prevent_scroll_restoration | True / False | True | Evitar que se restaure la posición de scroll al cerrarse |
on_open_change | Evento | - | Al abrirse o cerrarse. Pasa el nuevo valor de apertura (bool) |
on_animation_end | Evento | - | Al terminar la animación de apertura o cierre. Pasa el valor de apertura de ese momento |
drawer.content tiene los eventos on_open_auto_focus, on_close_auto_focus, on_escape_key_down, on_pointer_down_outside y on_interact_outside. Las demás partes apenas aceptan as_child.
Cada direction pega el panel a un lado distinto, así que hay que liberar el lado opuesto con "auto". Los paneles que salen por arriba o por abajo fijan el alto en lugar del ancho. Como los cuatro drawers se construyen igual, los agrupamos en una pequeña función.
def drawer_edge_demo(side: str, **position):
return rx.drawer.root(
rx.drawer.trigger(rx.button(side, variant="soft")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.title(f"From the {side}"),
rx.drawer.close(rx.button("Close", size="1")),
direction="column",
align_items="start",
spacing="3",
),
padding="2em",
background_color=rx.color("gray", 2),
**position,
),
),
direction=side,
)
rx.flex(
drawer_edge_demo("left", right="auto", width="16em"),
drawer_edge_demo("right", left="auto", width="16em"),
drawer_edge_demo("top", bottom="auto", height="30%"),
drawer_edge_demo("bottom", top="auto", height="30%"),
spacing="3",
wrap="wrap",
)No aparecen en la lista de partes de la documentación oficial, pero en 0.10 también existen drawer.title, drawer.description y drawer.handle. Los lectores de pantalla leen el título y la descripción, y el asa dibuja una barra arrastrable en la parte superior del panel. Con handle_only=True solo se puede arrastrar desde el asa, así es más difícil cerrarlo sin querer al pulsar los botones de dentro.
rx.drawer.root(
rx.drawer.trigger(rx.button("Open sheet")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.handle(),
rx.drawer.title("Share this page"),
rx.drawer.description("Drag the handle down to close the sheet."),
rx.flex(
rx.button(rx.icon("link"), "Copy link", variant="soft"),
rx.button(rx.icon("mail"), "Email", variant="soft"),
spacing="3",
),
direction="column",
spacing="3",
width="100%",
),
top="auto",
height="auto",
padding="1.5em",
background_color=rx.color("gray", 2),
border_radius="12px 12px 0 0",
),
),
handle_only=True,
)Si conectas un valor del State a open, el código puede cerrar el drawer al pulsar un enlace. Conecta también on_open_change para que los cambios de apertura hechos con el botón trigger, el botón Close o la tecla Esc vuelvan al State. Como es modal=False, se puede hacer scroll en la página con el drawer abierto, y al pulsar un enlace el drawer se cierra y lleva a esa sección.
class DrawerSidebarState(rx.State):
is_open: bool = False
@rx.event
def set_is_open(self, value: bool):
self.is_open = value
@rx.event
def close_drawer(self):
self.is_open = False
rx.vstack(
rx.drawer.root(
rx.drawer.trigger(rx.button("Open Drawer")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.close(rx.button("Close")),
rx.link("Section 1", href="#drawer-section-1", on_click=DrawerSidebarState.close_drawer),
rx.link("Section 2", href="#drawer-section-2", on_click=DrawerSidebarState.close_drawer),
align_items="start",
direction="column",
spacing="3",
),
right="auto",
height="100%",
width="16em",
padding="2em",
background_color=rx.color("grass", 4),
),
),
open=DrawerSidebarState.is_open,
on_open_change=DrawerSidebarState.set_is_open,
direction="left",
modal=False,
),
rx.section(rx.heading("Section 1", size="5"), id="drawer-section-1", height="160px", padding="1em 0"),
rx.section(rx.heading("Section 2", size="5"), id="drawer-section-2", height="160px", padding="1em 0"),
)Un panel de filtros que sube desde abajo. Lo que se elige con los interruptores y los botones de radio entra al momento en el State, y al pulsar «Show results» el handler baja el panel con self.open = False. Si se cierra arrastrándolo hacia abajo, los valores se conservan igual.
Sort: Newest
class DrawerFilterState(rx.State):
open: bool = False
in_stock: bool = False
sort: str = "Newest"
@rx.event
def set_open(self, value: bool):
self.open = value
@rx.event
def set_in_stock(self, value: bool):
self.in_stock = value
@rx.event
def set_sort(self, value: str):
self.sort = value
@rx.event
def apply(self):
self.open = False
rx.flex(
rx.text("Sort: ", DrawerFilterState.sort, rx.cond(DrawerFilterState.in_stock, " · in stock only", ""), size="2"),
rx.drawer.root(
rx.drawer.trigger(rx.button(rx.icon("sliders-horizontal"), "Filters", variant="outline")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.handle(),
rx.drawer.title("Filters"),
rx.flex(rx.switch(checked=DrawerFilterState.in_stock, on_change=DrawerFilterState.set_in_stock),
rx.text("In stock only", size="2"), spacing="2", align="center"),
rx.radio(["Newest", "Price: low", "Price: high"], value=DrawerFilterState.sort,
on_change=DrawerFilterState.set_sort, direction="row"),
rx.button("Show results", on_click=DrawerFilterState.apply, width="100%"),
direction="column",
spacing="4",
width="100%",
max_width="480px",
margin="0 auto",
),
top="auto",
height="auto",
padding="1.5em",
background_color=rx.color("gray", 2),
border_radius="12px 12px 0 0",
),
),
open=DrawerFilterState.open,
on_open_change=DrawerFilterState.set_open,
direction="bottom",
),
spacing="3",
align="center",
wrap="wrap",
)Notas del taller
root(direction) > trigger · overlay · portal > content > close. La dirección por defecto es bottom.
content se coloca cubriendo toda la pantalla, así que libera el lado opuesto con "auto" y fija width o height.
Si lo controlas con open + on_open_change, el handler de un enlace o un botón puede cerrar el drawer.
modal=False permite usar el fondo con el drawer abierto, y handle_only=True solo deja arrastrar desde el asa.
snap_points se fija al compilar, así que no admite valores del State.
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.