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
Renderizado dinámico

Auto Scroll

Pedido del taller

Crea una ventana de chat de atención al cliente. Cuando llegue un mensaje nuevo debe bajar hasta el final, pero si el usuario ha subido para leer la conversación anterior, no debe arrastrarlo hacia abajo.

rx.auto_scroll es una caja (div) que se desplaza sola hasta abajo cuando se añade contenido nuevo. Se usa con contenido que se va acumulando por abajo, como chats, logs o feeds, para tener siempre a la vista lo más reciente. No hace falta escribir código para gestionar la posición del scroll.

Initial message
class AutoScrollBasicState(rx.State):
    messages: list[str] = ["Initial message"]
    count: int = 1

    @rx.event
    def add_message(self):
        self.count += 1
        self.messages = (self.messages + [f"New message #{self.count}"])[-50:]


rx.vstack(
    rx.auto_scroll(
        rx.foreach(
            AutoScrollBasicState.messages,
            lambda message: rx.box(
                message,
                padding="0.5em",
                border_bottom=f"1px solid {rx.color('gray', 4)}",
                width="100%",
            ),
        ),
        height="200px",
        width="300px",
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="8px",
    ),
    rx.button("Add Message", on_click=AutoScrollBasicState.add_message),
    width="300px",
    align_items="center",
)

Cada vez que pulsas Add Message se añade un mensaje, y cuando la caja empieza a desbordarse baja sola para que se vea el mensaje nuevo.

Prueba las propiedades

rx.auto_scroll se basa en rx.el.div, así que acepta todas las propiedades y estilos de un div. Como es una caja con scroll, lo más importante es height. La caja de abajo contiene veinte líneas y desde el principio se ve la última (Line 20). Aunque reduzcas la altura para que se desborde, sigue mostrando la parte de abajo.

Prueba las propiedades

Line 1

Line 2

Line 3

Line 4

Line 5

Line 6

Line 7

Line 8

Line 9

Line 10

Line 11

Line 12

Line 13

Line 14

Line 15

Line 16

Line 17

Line 18

Line 19

Line 20

height

padding

radius

rx.auto_scroll(
    *[rx.text("Line " + str(i), size="2") for i in range(1, 21)],
    height="160px",
    padding="8px",
    border_radius="8px",
    border=f"1px solid {rx.color('gray', 6)}",
    width="260px",
)
Por defecto lleva overflow="auto", así que el contenido que supera la altura se desplaza dentro de la caja.
PropiedadValoresPor defectoUso
heightLongitud CSSNingunoAltura de la caja con scroll. Sin ella, crece con el contenido y no aparece scroll
widthLongitud CSSNingunoAncho
overflowValor CSS"auto"Qué hacer con el contenido que desborda. Por defecto, scroll
padding, border, border_radiusValor CSSNingunoRelleno interior, borde, esquinas
idCadenaAutomáticoSi no das uno, se asigna automáticamente un id único
Resto de propiedades de divtitle, role, on_click …Igual que rx.el.div

Cuándo usarlo

  • Chat: la ventana de conversación muestra siempre los mensajes más recientes.
  • Visor de logs: baja con cada nueva línea de log.
  • Feed: muestra lo nuevo en una lista que se actualiza continuamente.

Cómo funciona

Cuando se añade contenido, solo baja hasta el final en estos dos casos:

  1. Cuando el usuario ya está cerca del final (a menos de 50 píxeles)
  2. Cuando antes no había barra de scroll y el contenido nuevo la hace aparecer

Por eso, si el usuario ha subido para leer contenido anterior, no lo arrastra a la fuerza hacia abajo. Sube en la caja de logs de abajo y pulsa Add 10: la posición se mantiene. Vuelve a bajar del todo y púlsalo de nuevo: ahora sí baja.

import random


class AutoScrollLogState(rx.State):
    lines: list[str] = []
    count: int = 0

    @rx.event
    def add(self, n: int):
        levels = ["INFO", "INFO", "INFO", "WARN", "ERROR"]
        new = []
        for _ in range(n):
            self.count += 1
            new.append(f"{self.count:04d} {random.choice(levels)} request handled")
        self.lines = (self.lines + new)[-100:]

    @rx.event
    def clear(self):
        self.lines = []
        self.count = 0


rx.vstack(
    rx.auto_scroll(
        rx.foreach(AutoScrollLogState.lines, lambda line: rx.text(line, size="1", font_family="var(--code-font-family)")),
        height="160px",
        width="100%",
        padding="8px 10px",
        background=rx.color("gray", 2),
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="8px",
    ),
    rx.hstack(
        rx.button("Add 1", on_click=AutoScrollLogState.add(1), size="1"),
        rx.button("Add 10", on_click=AutoScrollLogState.add(10), size="1", variant="soft"),
        rx.button("Clear", on_click=AutoScrollLogState.clear, size="1", variant="soft", color_scheme="gray"),
    ),
    width="100%",
    max_width="420px",
)

Completar el pedido

Se da display="flex" y flex_direction="column" a rx.auto_scroll para apilar los bocadillos en vertical, y rx.cond cambia la alineación y el color según quién envía. Al mandar un mensaje se añaden el tuyo y la respuesta, y la ventana baja con ellos. Si has subido para leer, se queda donde está.

Hi! Ask me about your order.
class AutoScrollChatState(rx.State):
    messages: list[dict[str, str]] = [{"who": "bot", "text": "Hi! Ask me about your order."}]

    @rx.event
    def send(self, form_data: dict):
        text = form_data.get("text", "").strip()[:200]
        if not text:
            return
        reply = {"who": "bot", "text": f"Got it: {text}"}
        self.messages = (self.messages + [{"who": "me", "text": text}, reply])[-40:]


rx.vstack(
    rx.auto_scroll(
        rx.foreach(
            AutoScrollChatState.messages,
            lambda m: rx.flex(
                rx.box(
                    m["text"],
                    padding="6px 10px",
                    border_radius="12px",
                    max_width="80%",
                    background=rx.cond(m["who"] == "me", rx.color("indigo", 9), rx.color("gray", 4)),
                    color=rx.cond(m["who"] == "me", "white", rx.color("gray", 12)),
                ),
                justify=rx.cond(m["who"] == "me", "end", "start"),
                width="100%",
            ),
        ),
        display="flex",
        flex_direction="column",
        gap="6px",
        height="240px",
        width="100%",
        padding="10px",
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="10px",
    ),
    rx.form(
        rx.hstack(
            rx.input(name="text", placeholder="Type a message", flex="1", auto_complete=False),
            rx.button(rx.icon("send", size=16), type="submit", aria_label="Send"),
            width="100%",
        ),
        on_submit=AutoScrollChatState.send,
        reset_on_submit=True,
        width="100%",
    ),
    width="100%",
    max_width="360px",
)

Notas del taller

  • rx.auto_scroll(...) es un div que baja hasta el final cuando aparece contenido nuevo.

  • Dale siempre height. overflow="auto" ya viene por defecto.

  • Solo baja si estás cerca del final (50px) o si aparece por primera vez la barra de scroll.

  • No arrastra hacia abajo a quien ha subido para leer. Ideal para chats, logs y feeds.

← Anterior

Renderizado dinámico · Foreach

Siguiente →

Multimedia · Image

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