Skip to content

streamlit-calendar does not render consistently when placed inside st.tabs after navigation #58

@ByronLeeeee

Description

@ByronLeeeee

Describe the bug
The streamlit-calendar component renders correctly when its tab is the first one active upon initial page load of a view containing st.tabs. However, if I navigate away from this view (e.g., to a dashboard page) and then navigate back to the view containing the tabs, the calendar often fails to render when its tab is subsequently selected (if it wasn't the first active tab on that re-navigation). The space for the calendar appears to be reserved, but the calendar UI itself is not visible.

Interestingly, if the tab containing the calendar is the very first tab in the st.tabs definition, it tends to render more reliably even after re-navigation to the parent view. This was also confirmed by making the calendar's tab the first one in the list, which then allowed it to render correctly upon re-entry to the page.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Streamlit app with at least two "pages" or views managed by st.session_state (e.g., a "Dashboard" view and a "Case Detail" view).

  2. The "Case Detail" view uses st.tabs to organize content. Place the streamlit_calendar.calendar() component inside one of these tabs (e.g., a "Calendar" tab). Ensure this tab is NOT the first tab in the st.tabs list.

    # In Case Detail view's render function
    # (Assuming this code is within the context of rendering a specific case detail page)
    # import streamlit as st
    # from streamlit_calendar import calendar # Ensure this import is present
    # from datetime import datetime
    
    # case_id_example = 1 # Example case ID for unique key generation
    
    tab_titles = ["Info", "Documents", "Calendar Tab", "Settings"] # "Calendar Tab" is not first
    info_tab, docs_tab, calendar_tab_ui, settings_tab = st.tabs(tab_titles)
    
    with calendar_tab_ui:
        st.subheader("Case Calendar in Tab")
        events_data = [
            {"title": "Test Event in Tab", "start": datetime.now().isoformat(), "color": "green"}
        ]
        calendar_options = {"initialView": "dayGridMonth", "locale": "zh-cn"}
        # Using a unique key, for example, based on a case ID
        calendar_widget_key = f"case_calendar_in_tab_{case_id_example}"
        
        # Placeholder for where calendar_manager would be used to fetch real events
        # For reproduction, static events_data is sufficient.
        
        calendar(events=events_data, options=calendar_options, key=calendar_widget_key)
  3. Scenario 1 (Initial Load - Calendar Tab is first):

    • Modify tab_titles so "Calendar Tab" is the first tab: tab_titles = ["Calendar Tab", "Info", ...]
    • Navigate directly to the "Case Detail" view (or refresh if already there).
    • Result: The calendar renders correctly within its tab.
  4. Scenario 2 (Re-navigation - Calendar Tab is not first):

    • Set tab_titles so "Calendar Tab" is NOT the first tab (e.g., tab_titles = ["Info", "Calendar Tab", ...]).
    • Start the app on the "Dashboard" view.
    • Navigate from the "Dashboard" view to the "Case Detail" view. (The "Info" tab will likely be active by default).
    • Click to switch to the "Calendar Tab".
    • Result: The calendar component often fails to render. The subheader "Case Calendar in Tab" might appear, but the calendar UI itself is blank. No JavaScript errors are immediately obvious in the browser console.
  5. Scenario 3 (Key Change Observation - Temporary Workaround):

    • If the key of the calendar() component is forced to change every time the "Case Detail" view is entered or the "Calendar Tab" is (assumed to be) activated (e.g., by appending a uuid.uuid4() to the key string), the calendar does render correctly. However, this leads to other issues like rapid page refreshes if the key changes during interactions within the tab, making it an unsuitable permanent solution. This behavior suggests the component might need a "fresh" initialization sequence when its tab becomes active after a parent view re-render or navigation event.

Expected behavior
The streamlit-calendar component should render reliably inside an st.tabs container, regardless of whether its tab is initially active or if the user navigates to the parent view and then back to the tab. The component should initialize or re-initialize its JavaScript frontend correctly when its containing tab becomes visible.

Desktop:

  • OS: Windows 11
  • Browser: Chrome
  • Streamlit Version: 1.45.1
  • streamlit-calendar Version: streamlit-calendar-1.3.1

Additional context
The issue seems related to the component's JavaScript initialization lifecycle or state management when contained within Streamlit's tabbed interface, particularly when the tab is not immediately active upon the parent view's rendering. The fact that making the calendar's tab the first tab (ensuring it's rendered and visible on initial load of the st.tabs container) improves reliability, or that forcing a key change (which forces a complete re-instantiation by Streamlit) makes it render, points towards this.

Thank you for this excellent component! Any guidance on best practices for using it within st.tabs, or potential workarounds that don't involve constant key changes, would be greatly appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions