Skip to content

Más allá de lo básico: Guía completa de los botones de Streamlit

Updated on

Streamlit facilita convertir scripts de Python en aplicaciones interactivas, y los botones suelen ser la primera interacción que esperan las personas usuarias. El widget st.button puede verse minimalista, pero desbloquea flujos que van desde simples cambios hasta acciones de varios pasos. Esta guía renovada resume la API moderna, aclara malentendidos comunes y ofrece patrones comprobados para crear experiencias fiables basadas en botones.

¿Buscas un componente de analítica visual listo para usar en tus proyectos de Streamlit?

PyGWalker (opens in a new tab) incorpora una interfaz de exploración parecida a Tableau directamente en tus apps de Streamlit. Mira cómo explorar datos con PyGWalker (opens in a new tab) para verlo en acción o lee la guía de integración.

Entender st.button

Inicio rápido

En esencia, st.button renderiza un elemento clicable y devuelve True durante la ejecución del script justo después de un clic. Ese booleano suele bastar para flujos sencillos:

import streamlit as st
 
if st.button("Saludar"):
    st.write("¡Hola, Streamlit!")

Streamlit vuelve a ejecutar todo el script cada vez que un widget cambia. Por ese modelo de reinicio, asegúrate de que el trabajo dentro del bloque if sea idempotente o esté protegido con estado adicional.

Argumentos clave que debes conocer

st.button acepta varios argumentos opcionales que cubren la mayoría de necesidades de personalización:

  • key: Identificador único cuando tienes varios botones con la misma etiqueta.
  • help: Texto de ayuda que se muestra al pasar el cursor.
  • on_click: Callback que se ejecuta cuando se presiona el botón.
  • args / kwargs: Argumentos posicionales y con nombre que se envían al callback.
  • type: Elige entre los estilos "primary" y "secondary" para mantener la coherencia con el tema de Streamlit.
  • disabled: Impide que las personas interactúen con el botón.
  • use_container_width: Estira el botón al ancho del contenedor padre.
def refresh_data(verbose: bool = False, limit: int | None = None) -> None:
    st.session_state["last_result"] = load_data(limit=limit)
    if verbose:
        st.success("Datos actualizados")
 
st.button(
    "Actualizar datos",
    key="refresh",
    help="Obtén los registros más recientes de la API",
    type="primary",
    use_container_width=True,
    on_click=refresh_data,
    args=(True,),
    kwargs={"limit": 500},
)

Gestionar interacciones más allá del valor devuelto

Uso de callbacks y del estado de sesión

Los callbacks se ejecutan después de que Streamlit recopile los cambios de los widgets, por lo que son ideales para encapsular lógica y actualizar st.session_state:

import datetime as dt
import streamlit as st
 
if "last_clicked" not in st.session_state:
    st.session_state.last_clicked = None
 
 
def mark_timestamp() -> None:
    st.session_state.last_clicked = dt.datetime.now(dt.timezone.utc)
 
st.button("Registrar marca de tiempo", on_click=mark_timestamp, type="primary")
 
st.write("Último clic:", st.session_state.last_clicked or "Aún no")

Los callbacks mantienen el script principal declarativo, evitan un anidamiento profundo de if y conservan el estado entre reinicios.

Crear comportamiento de tipo interruptor

Los botones no permanecen presionados, pero puedes combinarlos con el estado de sesión para lograr interacciones tipo toggle:

import streamlit as st
 
st.session_state.setdefault("show_advanced", False)
 
if st.button("Mostrar u ocultar opciones avanzadas"):
    st.session_state.show_advanced = not st.session_state.show_advanced
 
if st.session_state.show_advanced:
    st.info("La configuración avanzada aparece aquí.")

Para controles persistentes (por ejemplo, encendido/apagado) considera widgets como st.checkbox o st.toggle, que comunican mejor el estado.

Técnicas de maquetación para botones

Streamlit organiza los elementos en el orden en que aparecen, pero sigues teniendo control del diseño mediante contenedores:

col1, col2 = st.columns(2)
with col1:
    st.button("Anterior", key="prev", type="secondary")
with col2:
    st.button("Siguiente", key="next", type="primary", use_container_width=True)
 
with st.sidebar:
    st.button("Restablecer filtros", key="reset")

Usa st.container() o st.expander() para agrupar acciones relacionadas y st.columns() para alinear botones en la misma fila sin depender de HTML crudo.

Opciones de estilo y sobreescrituras con CSS

Streamlit limita intencionalmente la personalización directa para mantener la coherencia, pero aún tienes alternativas:

  • Prefiere el preset integrado type="primary" para destacar y use_container_width=True para diseños responsivos.
  • Ajusta los colores predeterminados mediante la configuración global del tema (.streamlit/config.toml).
  • Para estilos personalizados, inyecta CSS acotado con st.markdown(..., unsafe_allow_html=True).
import streamlit as st
 
st.markdown(
    """
    <style>
    .custom-button button {
        background: linear-gradient(135deg, #005bbb, #00bcd4);
        color: white;
        border: 0;
        padding: 0.6rem 1.5rem;
        border-radius: 999px;
        transition: transform 0.1s ease-in-out;
    }
    .custom-button button:hover {
        transform: translateY(-1px);
    }
    </style>
    """,
    unsafe_allow_html=True,
)
 
with st.container():
    st.markdown('<div class="custom-button">', unsafe_allow_html=True)
    st.button("Botón degradado", key="custom")
    st.markdown("</div>", unsafe_allow_html=True)

Mantén las sobreescrituras de CSS enfocadas; grandes bloques en línea son difíciles de mantener y pueden romperse si Streamlit cambia nombres internos de clases.

Patrones prácticos

  • Revelado progresivo: combina un botón con st.session_state para mostrar entradas o texto adicional solo cuando sea necesario.
  • Pasos de procesamiento de datos: desactiva botones (disabled=True) hasta que existan requisitos previos como cargas de archivos o tokens de autenticación.
  • Flujos de descarga: usa st.download_button cuando necesites entregar archivos; reserva st.button para lógica dentro de la app.

Conclusión

Los botones sustentan muchos recorridos de usuario en Streamlit. Al combinar el valor booleano devuelto, la API de callbacks y st.session_state, puedes coordinar comportamientos complejos sin abandonar el paradigma reactivo. Apóyate en los primitivos de maquetación para la alineación, recurre al CSS solo cuando sea necesario y considera otros widgets cuando sea más claro mostrar un estado persistente. Un diseño cuidadoso de los botones mantiene tus apps de Streamlit rápidas, intuitivas y confiables.

Preguntas frecuentes

¿Cómo se crea un botón en Streamlit?

Usa st.button("Etiqueta"). La función devuelve True en la ejecución activada por el clic, así que coloca tu lógica en el bloque if correspondiente o pasa un callback con on_click.

¿Cómo se posiciona un botón en Streamlit?

Envuelve los widgets en primitivos de diseño como st.columns, st.container, st.sidebar o st.expander. Estos contenedores controlan la posición sin recurrir a HTML puro.

¿Cómo se crea un botón de opción en Streamlit?

Utiliza st.radio(label, options) para presentar opciones mutuamente excluyentes. La selección se devuelve de inmediato y puede guardarse en st.session_state para lógica posterior.

¿Cuáles son las desventajas de Streamlit?

El modelo de reinicio de scripts de Streamlit simplifica el desarrollo, pero puede resultar limitado cuando necesitas control granular del diseño, tareas en segundo plano prolongadas o personalización de estilos profunda. Aun así, el ecosistema evoluciona rápidamente: nuevos widgets, opciones de temas y utilidades de estado de sesión reducen cada vez más esas brechas.