streamlit-elements

repository·main·Indexed 21 days ago

https://github.com/okld/streamlit-elements

A Streamlit component for building advanced, interactive dashboards using Material UI widgets, Monaco editors, Nivo charts, and draggable/resizable layouts. It provides modules for MUI components, HTML objects, a grid-based dashboard system, and utilities for synchronizing session state with element events via sync() and lazy() callbacks.

Tokens
2.3K
Snippets
7
Records
8
Agent score
25%

What's inside streamlit-elements

  1. Display elements using the elements() frame

    main

    All elements must be rendered within an elements() context manager. The elements() function takes a unique key as a parameter which cannot be reused by another frame or Streamlit widget.

    Creating elements with children

    You can add children to an element by passing them as arguments or by using a with statement.

    from streamlit_elements import elements, mui, html
    
    with elements("my_frame"):
        # Single child
        mui.Typography("Hello world")
    
        # Multiple children as arguments
        mui.Button(
            mui.icon.EmojiPeople,
            mui.icon.DoubleArrow,
            "Button with multiple children"
        )
    
        # Multiple children using 'with' statement
        with mui.Button:
            mui.icon.EmojiPeople()
            mui.icon.DoubleArrow()
            mui.Typography("Button with multiple children")
    
        # Nested children
        with mui.Paper:
            with mui.Typography:
                html.p("Hello world")
                html.p("Goodbye world")
    from streamlit_elements import elements, mui, html
    
    with elements("my_frame"):
        mui.Typography("Hello world")
    
        mui.Button(
            mui.icon.EmojiPeople,
            mui.icon.DoubleArrow,
            "Button with multiple children"
        )
    
        with mui.Button:
            mui.icon.EmojiPeople()
            mui.icon.DoubleArrow()
            mui.Typography("Button with multiple children")
    
        with mui.Paper:
            with mui.Typography:
                html.p("Hello world")
                html.p("Goodbye world")
  2. Handle callbacks and synchronize state

    main

    Retrieve element data manually

    You can define a function to handle events (like onChange) and update st.session_state manually.

    Synchronize with sync()

    Use sync("key") to automatically store event data into a session state item. If an event passes multiple parameters, use sync("param1", "param2"). To ignore the first parameter but keep others, use sync(None, "param2").

    Defer reloads with lazy()

    To prevent the entire Streamlit app from reloading on every single input (e.g., every keystroke in a text field), wrap your callback with lazy(). This defers the execution until a non-lazy callback is triggered.

    import streamlit as st
    from streamlit_elements import elements, mui, sync, lazy
    
    with elements("callbacks"):
        if "my_event" not in st.session_state:
            st.session_state.my_event = None
    
        # 1. Manual callback
        def handle_change(event):
            st.session_state.my_text = event.target.value
    
        mui.TextField(label="Manual", onChange=handle_change)
    
        # 2. Using sync()
        mui.TextField(label="Sync", onChange=sync("my_event"))
    
        # 3. Using lazy() to avoid constant reloads
        # This will only sync when a non-lazy callback (like a button) is clicked
        mui.TextField(label="Lazy Sync", onChange=lazy(sync("my_event")))
        mui.Button("Update", onClick=sync())
    import streamlit as st
    from streamlit_elements import elements, mui, sync, lazy
    
    with elements("callbacks"):
        if "my_event" not in st.session_state:
            st.session_state.my_event = None
    
        def handle_change(event):
            st.session_state.my_text = event.target.value
    
        mui.TextField(label="Manual", onChange=handle_change)
    
        mui.TextField(label="Sync", onChange=sync("my_event"))
    
        mui.TextField(label="Lazy Sync", onChange=lazy(sync("my_event")))
        mui.Button("Update", onClick=sync())
  3. Build a draggable and resizable dashboard

    main

    Use the dashboard module to create a grid-based layout where items can be moved or resized.

    1. Define a layout using dashboard.Item(id, x, y, w, h, **props).
    2. Wrap your elements in a dashboard.Grid(layout, **props).
    3. Use the key property on elements to link them to the layout items.
    4. Use onLayoutChange to capture updated layout positions.
    from streamlit_elements import elements, dashboard, mui
    
    layout = [
        dashboard.Item("item1", 0, 0, 2, 2),
        dashboard.Item("item2", 2, 0, 2, 2, isDraggable=False),
        dashboard.Item("item3", 0, 2, 1, 1, isResizable=False),
    ]
    
    with elements("dash"):
        with dashboard.Grid(layout):
            mui.Paper("Item 1", key="item1")
            mui.Paper("Item 2 (Static)", key="item2")
            mui.Paper("Item 3 (Fixed Size)", key="item3")
  4. Use Hotkeys and Intervals

    main

    The event module allows you to trigger callbacks based on keyboard or time-based events.

    • event.Hotkey(sequence, callback, bindInputs=False, overrideDefault=False): Triggers when a key sequence is pressed.
      • bindInputs=True: Allows the hotkey to work even when a text field has focus.
      • overrideDefault=True: Overrides default browser/app hotkeys (e.g., ctrl+f).
    • event.Interval(seconds, callback): Triggers a callback every $n$ seconds.

    Note: These trigger a full Streamlit app rerun.

    from streamlit_elements import elements, event
    
    with elements("events"):
        def my_callback():
            print("Triggered!")
    
        # Hotkey
        event.Hotkey("g", my_callback)
        
        # Interval (every 1 second)
        event.Interval(1, my_callback)
    from streamlit_elements import elements, event
    
    with elements("events"):
        def my_callback():
            print("Triggered!")
    
        event.Hotkey("g", my_callback)
        event.Interval(1, my_callback)
  5. Add properties and custom CSS to elements

    main

    Adding properties

    Elements accept properties via named parameters. If a parameter name is a Python keyword (like in), append an underscore (e.g., in_=True).

    Applying custom CSS

    • Material UI elements: Use the sx property for styling.
    • Other elements (like HTML): Use the css property (based on Emotion).
    from streamlit_elements import elements, mui, html
    
    with elements("styling"):
        # Using properties and sx for MUI
        with mui.Paper(elevation=3, variant="outlined", square=True):
            mui.TextField(
                label="My text input",
                defaultValue="Type here",
                variant="outlined",
            )
    
        # Using sx for MUI Box
        mui.Box(
            "Some text in a styled box",
            sx={
                "bgcolor": "background.paper",
                "boxShadow": 1,
                "borderRadius": 2,
                "p": 2,
                "minWidth": 300,
            }
        )
    
        # Using css for HTML elements
        html.div(
            "This has a hotpink background",
            css={
                "backgroundColor": "hotpink",
                "&:hover": {
                    "color": "lightgreen"
                }
            }
        )
    from streamlit_elements import elements, mui, html
    
    with elements("styling"):
        with mui.Paper(elevation=3, variant="outlined", square=True):
            mui.TextField(
                label="My text input",
                defaultValue="Type here",
                variant="outlined",
            )
    
        mui.Box(
            "Some text in a styled box",
            sx={
                "bgcolor": "background.paper",
                "boxShadow": 1,
                "borderRadius": 2,
                "p": 2,
                "minWidth": 300,
            }
        )
    
        html.div(
            "This has a hotpink background",
            css={
                "backgroundColor": "hotpink",
                "&:hover": {
                    "color": "lightgreen"
                }
            }
        )
  6. Use Monaco Editor and Nivo Charts

    main

    Monaco Editor

    Embed a code editor or diff editor using editor.Monaco or editor.MonacoDiff.

    Nivo Charts

    Access 45+ data visualization components via nivo. Components like nivo.Radar accept data, keys, and various styling/layout parameters.

    from streamlit_elements import elements, editor, nivo, mui
    
    with elements("third_party"):
        # Monaco Editor
        editor.Monaco(height=300, defaultValue="Hello World")
    
        # Nivo Radar Chart
        nivo.Radar(
            data=[{"taste": "fruity", "val": 93}, {"taste": "bitter", "val": 61}],
            keys=["val"],
            indexBy="taste"
        )
    from streamlit_elements import elements, editor, nivo, mui
    
    with elements("third_party"):
        editor.Monaco(height=300, defaultValue="Hello World")
    
        nivo.Radar(
            data=[{"taste": "fruity", "val": 93}, {"taste": "bitter", "val": 61}],
            keys=["val"],
            indexBy="taste"
        )
  7. Available elements and objects in streamlit-elements

    main

    Streamlit Elements provides several modules and objects to compose your application:

    • elements: Create a frame where elements will be displayed. Elements will not render outside this frame, and native Streamlit widgets will not render inside it.
    • dashboard: Build a draggable and resizable dashboard.
    • mui: Material UI (MUI) widgets and icons.
    • html: HTML objects.
    • editor: Monaco code and diff editor.
    • nivo: Nivo chart library.
    • media: Media player.
    • sync: Callback to synchronize Streamlit's session state with elements events data.
    • lazy: Defer a callback call until another non-lazy callback is called.