{"id":13738708,"url":"https://github.com/okld/streamlit-elements","last_synced_at":"2025-05-15T06:13:22.932Z","repository":{"id":46138113,"uuid":"358417820","full_name":"okld/streamlit-elements","owner":"okld","description":"Create a draggable and resizable dashboard in Streamlit, featuring Material UI widgets, Monaco editor (Visual Studio Code), Nivo charts, and more!","archived":false,"fork":false,"pushed_at":"2023-09-01T10:19:48.000Z","size":12535,"stargazers_count":824,"open_issues_count":32,"forks_count":91,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-08T17:44:46.136Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/okld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-04-15T23:20:11.000Z","updated_at":"2025-05-08T09:03:49.000Z","dependencies_parsed_at":"2024-01-07T21:03:00.403Z","dependency_job_id":"db26b2ba-2b11-4708-99ba-03c942cedf45","html_url":"https://github.com/okld/streamlit-elements","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okld%2Fstreamlit-elements","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okld%2Fstreamlit-elements/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okld%2Fstreamlit-elements/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okld%2Fstreamlit-elements/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/okld","download_url":"https://codeload.github.com/okld/streamlit-elements/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254283267,"owners_count":22045141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T03:02:34.075Z","updated_at":"2025-05-15T06:13:22.914Z","avatar_url":"https://github.com/okld.png","language":"TypeScript","readme":"✨ Streamlit Elements \u0026nbsp; [![GitHub][github_badge]][github_link] [![PyPI][pypi_badge]][pypi_link]\n=====================\n\nCreate a draggable and resizable dashboard in Streamlit, featuring Material UI widgets, Monaco editor (Visual Studio Code), Nivo charts, and more!\n\nDemo\n----\n\n[![Open in Streamlit][share_badge]][share_link]\n\n[![Preview][share_video]][share_link]\n\n[share_badge]: https://static.streamlit.io/badges/streamlit_badge_black_white.svg\n[share_link]: https://share.streamlit.io/okld/streamlit-gallery/main?p=elements\n[share_video]: https://github.com/okld/streamlit-elements/raw/main/demo.gif\n\n[github_badge]: https://badgen.net/badge/icon/GitHub?icon=github\u0026color=black\u0026label\n[github_link]: https://github.com/okld/streamlit-elements\n\n[pypi_badge]: https://badgen.net/pypi/v/streamlit-elements?icon=pypi\u0026color=black\u0026label\n[pypi_link]: https://pypi.org/project/streamlit-elements\n\n\nGetting started\n---------------\n\n### 1. Introduction\n\nStreamlit Elements is a component that gives you the tools to compose beautiful applications with Material UI widgets, Monaco, Nivo charts, and more.\nIt also includes a feature to create draggable and resizable dashboards.\n\n#### Installation\n\n```sh\npip install streamlit-elements==0.1.*\n```\n\n**Caution**: It is recommended to pin the version to `0.1.*`. Future versions might introduce breaking API changes.\n\n#### Available elements and objects\n\nHere is a list of elements and objects you can import in your app:\n\nElement   | Description\n:--------:|:-----------\nelements  | Create a frame where elements will be displayed.\ndashboard | Build a draggable and resizable dashboard.\nmui       | Material UI (MUI) widgets and icons.\nhtml      | HTML objects.\neditor    | Monaco code and diff editor that powers Visual Studio Code.\nnivo      | Nivo chart library.\nmedia     | Media player.\nsync      | Callback to synchronize Streamlit's session state with elements events data.\nlazy      | Defer a callback call until another non-lazy callback is called.\n\n#### Caution\n\n- A few Material UI widgets may not work as expected (ie. modal dialogs and snackbars).\n- Using many element frames can significantly impact your app's performance. Try to gather elements in few frames at most.\n\n---\n\n### 2. Display elements\n\n#### 2.1. Create an element with a child\n\n```python\n# First, import the elements you need\n\nfrom streamlit_elements import elements, mui, html\n\n# Create a frame where Elements widgets will be displayed.\n#\n# Elements widgets will not render outside of this frame.\n# Native Streamlit widgets will not render inside this frame.\n#\n# elements() takes a key as parameter.\n# This key can't be reused by another frame or Streamlit widget.\n\nwith elements(\"new_element\"):\n\n    # Let's create a Typography element with \"Hello world\" as children.\n    # The first step is to check Typography's documentation on MUI:\n    # https://mui.com/components/typography/\n    #\n    # Here is how you would write it in React JSX:\n    #\n    # \u003cTypography\u003e\n    #   Hello world\n    # \u003c/Typography\u003e\n\n    mui.Typography(\"Hello world\")\n```\n- MUI Typography: https://mui.com/components/typography/\n\n---\n\n#### 2.2. Create an element with multiple children\n\n```python\nwith elements(\"multiple_children\"):\n\n    # You have access to Material UI icons using: mui.icon.IconNameHere\n    #\n    # Multiple children can be added in a single element.\n    #\n    # \u003cButton\u003e\n    #   \u003cEmojiPeople /\u003e\n    #   \u003cDoubleArrow /\u003e\n    #   Hello world\n    # \u003c/Button\u003e\n\n    mui.Button(\n        mui.icon.EmojiPeople,\n        mui.icon.DoubleArrow,\n        \"Button with multiple children\"\n    )\n\n    # You can also add children to an element using a 'with' statement.\n    #\n    # \u003cButton\u003e\n    #   \u003cEmojiPeople /\u003e\n    #   \u003cDoubleArrow /\u003e\n    #   \u003cTypography\u003e\n    #     Hello world\n    #   \u003c/Typography\u003e\n    # \u003c/Button\u003e\n\n    with mui.Button:\n        mui.icon.EmojiPeople()\n        mui.icon.DoubleArrow()\n        mui.Typography(\"Button with multiple children\")\n```\n- MUI button: https://mui.com/components/buttons/\n- MUI icons: https://mui.com/components/material-icons/\n\n---\n\n#### 2.3. Create an element with nested children\n\n```python\nwith elements(\"nested_children\"):\n\n    # You can nest children using multiple 'with' statements.\n    #\n    # \u003cPaper\u003e\n    #   \u003cTypography\u003e\n    #     \u003cp\u003eHello world\u003c/p\u003e\n    #     \u003cp\u003eGoodbye world\u003c/p\u003e\n    #   \u003c/Typography\u003e\n    # \u003c/Paper\u003e\n\n    with mui.Paper:\n        with mui.Typography:\n            html.p(\"Hello world\")\n            html.p(\"Goodbye world\")\n```\n- MUI paper: https://mui.com/components/paper/\n\n---\n\n#### 2.4. Add properties to an element\n\n```python\nwith elements(\"properties\"):\n\n    # You can add properties to elements with named parameters.\n    #\n    # To find all available parameters for a given element, you can\n    # refer to its related documentation on mui.com for MUI widgets,\n    # on https://microsoft.github.io/monaco-editor/ for Monaco editor,\n    # and so on.\n    #\n    # \u003cPaper elevation={3} variant=\"outlined\" square\u003e\n    #   \u003cTextField label=\"My text input\" defaultValue=\"Type here\" variant=\"outlined\" /\u003e\n    # \u003c/Paper\u003e\n\n    with mui.Paper(elevation=3, variant=\"outlined\", square=True):\n        mui.TextField(\n            label=\"My text input\",\n            defaultValue=\"Type here\",\n            variant=\"outlined\",\n        )\n\n    # If you must pass a parameter which is also a Python keyword, you can append an\n    # underscore to avoid a syntax error.\n    #\n    # \u003cCollapse in /\u003e\n\n    mui.Collapse(in_=True)\n\n    # mui.collapse(in=True)\n    # \u003e Syntax error: 'in' is a Python keyword:\n```\n- MUI text field: https://mui.com/components/text-fields/\n\n---\n\n#### 2.5. Apply custom CSS styles\n\n##### 2.5.1. Material UI elements\n\n```python\nwith elements(\"style_mui_sx\"):\n\n    # For Material UI elements, use the 'sx' property.\n    #\n    # \u003cBox\n    #   sx={{\n    #     bgcolor: 'background.paper',\n    #     boxShadow: 1,\n    #     borderRadius: 2,\n    #     p: 2,\n    #     minWidth: 300,\n    #   }}\n    # \u003e\n    #   Some text in a styled box\n    # \u003c/Box\u003e\n\n    mui.Box(\n        \"Some text in a styled box\",\n        sx={\n            \"bgcolor\": \"background.paper\",\n            \"boxShadow\": 1,\n            \"borderRadius\": 2,\n            \"p\": 2,\n            \"minWidth\": 300,\n        }\n    )\n```\n- MUI's **sx** property: https://mui.com/system/the-sx-prop/\n\n##### 2.5.2. Other elements\n\n```python\nwith elements(\"style_elements_css\"):\n\n    # For any other element, use the 'css' property.\n    #\n    # \u003cdiv\n    #   css={{\n    #     backgroundColor: 'hotpink',\n    #     '\u0026:hover': {\n    #         color: 'lightgreen'\n    #     }\n    #   }}\n    # \u003e\n    #   This has a hotpink background\n    # \u003c/div\u003e\n\n    html.div(\n        \"This has a hotpink background\",\n        css={\n            \"backgroundColor\": \"hotpink\",\n            \"\u0026:hover\": {\n                \"color\": \"lightgreen\"\n            }\n        }\n    )\n```\n- Emotion's **css** property: https://emotion.sh/docs/css-prop#object-styles\n\n---\n\n### 3. Callbacks\n\n#### 3.1. Retrieve an element's data\n\n```python\nimport streamlit as st\n\nwith elements(\"callbacks_retrieve_data\"):\n\n    # Some element allows executing a callback on specific event.\n    #\n    # const [name, setName] = React.useState(\"\")\n    # const handleChange = (event) =\u003e {\n    #   // You can see here that a text field value\n    #   // is stored in event.target.value\n    #   setName(event.target.value)\n    # }\n    #\n    # \u003cTextField\n    #   label=\"Input some text here\"\n    #   onChange={handleChange}\n    # /\u003e\n\n    # Initialize a new item in session state called \"my_text\"\n    if \"my_text\" not in st.session_state:\n        st.session_state.my_text = \"\"\n\n    # When text field changes, this function will be called.\n    # To know which parameters are passed to the callback,\n    # you can refer to the element's documentation.\n    def handle_change(event):\n        st.session_state.my_text = event.target.value\n\n    # Here we display what we have typed in our text field\n    mui.Typography(st.session_state.my_text)\n\n    # And here we give our 'handle_change' callback to the 'onChange'\n    # property of the text field.\n    mui.TextField(label=\"Input some text here\", onChange=handle_change)\n```\n- MUI text field event: https://mui.com/components/text-fields/#uncontrolled-vs-controlled\n- MUI text field API: https://mui.com/api/text-field/\n\n---\n\n#### 3.2. Synchronize a session state item with an element event using sync()\n\n```python\nwith elements(\"callbacks_sync\"):\n\n    # If you just want to store callback parameters into Streamlit's session state\n    # like above, you can also use the special function sync().\n    #\n    # When an onChange event occurs, the callback is called with an event data object\n    # as argument. In the example below, we are synchronizing that event data object with\n    # the session state item 'my_event'.\n    #\n    # If an event passes more than one parameter, you can synchronize as many session state item\n    # as needed like so:\n    # \u003e\u003e\u003e sync(\"my_first_param\", \"my_second_param\")\n    #\n    # If you want to ignore the first parameter of an event but keep synchronizing the second,\n    # pass None to sync:\n    # \u003e\u003e\u003e sync(None, \"second_parameter_to_keep\")\n\n    from streamlit_elements import sync\n\n    if \"my_event\" not in st.session_state:\n        st.session_state.my_event = None\n\n    if st.session_state.my_event is not None:\n        text = st.session_state.my_event.target.value\n    else:\n        text = \"\"\n\n    mui.Typography(text)\n    mui.TextField(label=\"Input some text here\", onChange=sync(\"my_event\"))\n```\n\n---\n\n#### 3.3. Avoid too many reloads with lazy()\n\n```python\nwith elements(\"callbacks_lazy\"):\n\n    # With the two first examples, each time you input a letter into the text field,\n    # the callback is invoked but the whole app is reloaded as well.\n    #\n    # To avoid reloading the whole app on every input, you can wrap your callback with\n    # lazy(). This will defer the callback invocation until another non-lazy callback\n    # is invoked. This can be useful to implement forms.\n\n    from streamlit_elements import lazy\n\n    if \"first_name\" not in st.session_state:\n        st.session_state.first_name = None\n        st.session_state.last_name = None\n\n    if st.session_state.first_name is not None:\n        first_name = st.session_state.first_name.target.value\n    else:\n        first_name = \"John\"\n\n    if st.session_state.last_name is not None:\n        last_name = st.session_state.last_name.target.value\n    else:\n        last_name = \"Doe\"\n\n    def set_last_name(event):\n        st.session_state.last_name = event\n\n    # Display first name and last name\n    mui.Typography(\"Your first name: \", first_name)\n    mui.Typography(\"Your last name: \", last_name)\n\n    # Lazily synchronize onChange with first_name and last_name state.\n    # Inputting some text won't synchronize the value yet.\n    mui.TextField(label=\"First name\", onChange=lazy(sync(\"first_name\")))\n\n    # You can also pass regular python functions to lazy().\n    mui.TextField(label=\"Last name\", onChange=lazy(set_last_name))\n\n    # Here we give a non-lazy callback to onClick using sync().\n    # We are not interested in getting onClick event data object,\n    # so we call sync() with no argument.\n    #\n    # You can use either sync() or a regular python function.\n    # As long as the callback is not wrapped with lazy(), its invocation will\n    # also trigger every other defered callbacks.\n    mui.Button(\"Update first namd and last name\", onClick=sync())\n```\n\n---\n\n#### 3.4. Invoke a callback when a sequence is pressed using event.Hotkey()\n\n```python\nwith elements(\"callbacks_hotkey\"):\n\n    # Invoke a callback when a specific hotkey sequence is pressed.\n    #\n    # For more information regarding sequences syntax and supported keys,\n    # go to Mousetrap's project page linked below.\n    #\n    # /!\\ Hotkeys work if you don't have focus on Streamlit Elements's frame /!\\\n    # /!\\ As with other callbacks, this reruns the whole app /!\\\n\n    from streamlit_elements import event\n\n    def hotkey_pressed():\n        print(\"Hotkey pressed\")\n\n    event.Hotkey(\"g\", hotkey_pressed)\n\n    # If you want your hotkey to work even in text fields, set bind_inputs to True.\n    event.Hotkey(\"h\", hotkey_pressed, bindInputs=True)\n    mui.TextField(label=\"Try pressing 'h' while typing some text here.\")\n\n    # If you want to override default hotkeys (ie. ctrl+f to search in page),\n    # set overrideDefault to True.\n    event.Hotkey(\"ctrl+f\", hotkey_pressed, overrideDefault=True)\n```\n- Mousetrap: https://craig.is/killing/mice\n- Github page: https://github.com/ccampbell/mousetrap\n\n---\n\n#### 3.5. Invoke a callback periodically using event.Interval()\n\n```python\nwith elements(\"callbacks_interval\"):\n\n    # Invoke a callback every n seconds.\n    #\n    # /!\\ As with other callbacks, this reruns the whole app /!\\\n\n    def call_every_second():\n        print(\"Hello world\")\n\n    event.Interval(1, call_every_second)\n```\n\n---\n\n### 4. Draggable and resizable dashboard\n\n```python\nwith elements(\"dashboard\"):\n\n    # You can create a draggable and resizable dashboard using\n    # any element available in Streamlit Elements.\n\n    from streamlit_elements import dashboard\n\n    # First, build a default layout for every element you want to include in your dashboard\n\n    layout = [\n        # Parameters: element_identifier, x_pos, y_pos, width, height, [item properties...]\n        dashboard.Item(\"first_item\", 0, 0, 2, 2),\n        dashboard.Item(\"second_item\", 2, 0, 2, 2, isDraggable=False, moved=False),\n        dashboard.Item(\"third_item\", 0, 2, 1, 1, isResizable=False),\n    ]\n\n    # Next, create a dashboard layout using the 'with' syntax. It takes the layout\n    # as first parameter, plus additional properties you can find in the GitHub links below.\n\n    with dashboard.Grid(layout):\n        mui.Paper(\"First item\", key=\"first_item\")\n        mui.Paper(\"Second item (cannot drag)\", key=\"second_item\")\n        mui.Paper(\"Third item (cannot resize)\", key=\"third_item\")\n\n    # If you want to retrieve updated layout values as the user move or resize dashboard items,\n    # you can pass a callback to the onLayoutChange event parameter.\n\n    def handle_layout_change(updated_layout):\n        # You can save the layout in a file, or do anything you want with it.\n        # You can pass it back to dashboard.Grid() if you want to restore a saved layout.\n        print(updated_layout)\n\n    with dashboard.Grid(layout, onLayoutChange=handle_layout_change):\n        mui.Paper(\"First item\", key=\"first_item\")\n        mui.Paper(\"Second item (cannot drag)\", key=\"second_item\")\n        mui.Paper(\"Third item (cannot resize)\", key=\"third_item\")\n```\n- Dashboard item properties: https://github.com/react-grid-layout/react-grid-layout#grid-item-props\n- Dashboard grid properties (Streamlit Elements uses the Responsive grid layout):\n  - https://github.com/react-grid-layout/react-grid-layout#grid-layout-props\n  - https://github.com/react-grid-layout/react-grid-layout#responsive-grid-layout-props\n\n---\n\n### 5. Other third-party elements\n\n#### 5.1. Monaco code and diff editor\n\n```python\nwith elements(\"monaco_editors\"):\n\n    # Streamlit Elements embeds Monaco code and diff editor that powers Visual Studio Code.\n    # You can configure editor's behavior and features with the 'options' parameter.\n    #\n    # Streamlit Elements uses an unofficial React implementation (GitHub links below for\n    # documentation).\n\n    from streamlit_elements import editor\n\n    if \"content\" not in st.session_state:\n        st.session_state.content = \"Default value\"\n\n    mui.Typography(\"Content: \", st.session_state.content)\n\n    def update_content(value):\n        st.session_state.content = value\n\n    editor.Monaco(\n        height=300,\n        defaultValue=st.session_state.content,\n        onChange=lazy(update_content)\n    )\n\n    mui.Button(\"Update content\", onClick=sync())\n\n    editor.MonacoDiff(\n        original=\"Happy Streamlit-ing!\",\n        modified=\"Happy Streamlit-in' with Elements!\",\n        height=300,\n    )\n```\n- Monaco examples and properties: https://github.com/suren-atoyan/monaco-react\n- Code editor options: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html\n- Diff editor options: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneDiffEditorConstructionOptions.html\n- Monaco project page: https://microsoft.github.io/monaco-editor/\n\n---\n\n#### 5.2. Nivo charts\n\n```python\nwith elements(\"nivo_charts\"):\n\n    # Streamlit Elements includes 45 dataviz components powered by Nivo.\n\n    from streamlit_elements import nivo\n\n    DATA = [\n        { \"taste\": \"fruity\", \"chardonay\": 93, \"carmenere\": 61, \"syrah\": 114 },\n        { \"taste\": \"bitter\", \"chardonay\": 91, \"carmenere\": 37, \"syrah\": 72 },\n        { \"taste\": \"heavy\", \"chardonay\": 56, \"carmenere\": 95, \"syrah\": 99 },\n        { \"taste\": \"strong\", \"chardonay\": 64, \"carmenere\": 90, \"syrah\": 30 },\n        { \"taste\": \"sunny\", \"chardonay\": 119, \"carmenere\": 94, \"syrah\": 103 },\n    ]\n\n    with mui.Box(sx={\"height\": 500}):\n        nivo.Radar(\n            data=DATA,\n            keys=[ \"chardonay\", \"carmenere\", \"syrah\" ],\n            indexBy=\"taste\",\n            valueFormat=\"\u003e-.2f\",\n            margin={ \"top\": 70, \"right\": 80, \"bottom\": 40, \"left\": 80 },\n            borderColor={ \"from\": \"color\" },\n            gridLabelOffset=36,\n            dotSize=10,\n            dotColor={ \"theme\": \"background\" },\n            dotBorderWidth=2,\n            motionConfig=\"wobbly\",\n            legends=[\n                {\n                    \"anchor\": \"top-left\",\n                    \"direction\": \"column\",\n                    \"translateX\": -50,\n                    \"translateY\": -40,\n                    \"itemWidth\": 80,\n                    \"itemHeight\": 20,\n                    \"itemTextColor\": \"#999\",\n                    \"symbolSize\": 12,\n                    \"symbolShape\": \"circle\",\n                    \"effects\": [\n                        {\n                            \"on\": \"hover\",\n                            \"style\": {\n                                \"itemTextColor\": \"#000\"\n                            }\n                        }\n                    ]\n                }\n            ],\n            theme={\n                \"background\": \"#FFFFFF\",\n                \"textColor\": \"#31333F\",\n                \"tooltip\": {\n                    \"container\": {\n                        \"background\": \"#FFFFFF\",\n                        \"color\": \"#31333F\",\n                    }\n                }\n            }\n        )\n```\n- Nivo charts: https://nivo.rocks/\n- Github page: https://github.com/plouc/nivo\n\n---\n\n#### 5.3. Media player\n\n```python\nwith elements(\"media_player\"):\n\n    # Play video from many third-party sources: YouTube, Facebook, Twitch,\n    # SoundCloud, Streamable, Vimeo, Wistia, Mixcloud, DailyMotion and Kaltura.\n    #\n    # This element is powered by ReactPlayer (GitHub link below).\n\n    from streamlit_elements import media\n\n    media.Player(url=\"https://www.youtube.com/watch?v=iik25wqIuFo\", controls=True)\n```\n- ReactPlayer properties: https://github.com/cookpete/react-player#props\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokld%2Fstreamlit-elements","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokld%2Fstreamlit-elements","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokld%2Fstreamlit-elements/lists"}