gabrieltempass / streamlit-navigation-bar

A component that allows you to place a navigation bar in your Streamlit app.
https://streamlit.io/
MIT License
112 stars 11 forks source link

Link within a layout? #1

Closed lawtj closed 5 months ago

lawtj commented 5 months ago

Checklist

Add a description

Great package, have been exploring and I think it'll do the trick for me!

One question - in my main landing page, I'd like to include links to other pages in the app. Is there a suggested workflow for this? I tried st_button(label='about page', on_click=pg.show_about) for instance, but it didn't work/didn't keep the nav bar.

gabrieltempass commented 5 months ago

Hi @lawtj, thanks for your question!

Currently there are two main ways to use st_navbar with a multipage app (MPA):

  1. The first one is when the app follows Streamlit's MPA structure. Which I believe is your case, right? If it is, you will need to call the st_navbar() function at the top of every .py file inside the pages directory, in order for the navbar to appear when you switch pages.

This approach is the more intuitive one, since it uses Streamlit's official solution for MPA. However, when you click to switch to another page, the navbar will disappear for some milliseconds and reappear. Causing a really bad user experience. And at the moment I still don't know how to get rid of this.

I know that the Streamlit team will soon release a new API for MPA. Maybe then I can make st_navbar work more seamlessly with this approach.

  1. The second way is demonstrated in this example in the documentation:

An example using a logo, an external URL, multiple pages with content, among other things:

import os
import streamlit as st
from streamlit_navigation_bar import st_navbar
import pages as pg

st.set_page_config(initial_sidebar_state="collapsed")

pages = ["Install", "User Guide", "API", "Examples", "Community", "GitHub"]
parent_dir = os.path.dirname(os.path.abspath(__file__))
logo_path = os.path.join(parent_dir, "cubes.svg")
urls = {"GitHub": "https://github.com/gabrieltempass/streamlit-navigation-bar"}
styles = {
    "nav": {
        "background-color": "royalblue",
        "justify-content": "left",
    },
    "img": {
        "padding-right": "14px",
    },
    "span": {
        "color": "white",
        "padding": "14px",
    },
    "active": {
        "color": "var(--text-color)",
        "background-color": "white",
        "font-weight": "normal",
        "padding": "14px",
    }
}

page = st_navbar(
    pages,
    logo_path=logo_path,
    urls=urls,
    styles=styles,
    options=False,
)

functions = {
    "Home": pg.show_home,
    "Install": pg.show_install,
    "User Guide": pg.show_user_guide,
    "API": pg.show_api,
    "Examples": pg.show_examples,
    "Community": pg.show_community,
}
go_to = functions.get(page)
if go_to:
    go_to()

Example 3 [App] [Source]

The major difference is that the content of each page must be inside a function, which will be called from your main .py file. For example, check how the content from the Community page is inside the show_community() function from community.py. Also, don't forget that you will have to import these functions in your main file.

As you would imagine, this approach has some downsides. Like not being able to access a specific page of your app via its URL (e.g. https://st-navbar-3.streamlit.app/community). But the navbar won't briefly disappear when switching pages, so right now I would recommend this path.

I hope that helps you!

gabrieltempass commented 4 months ago

@lawtj I created a page in the documentation to explain this in more detail:

https://github.com/gabrieltempass/streamlit-navigation-bar/wiki/Multipage