├── MANIFEST.in ├── streamlit_option_menu ├── frontend │ ├── .browserslistrc │ ├── vue.config.js │ ├── .prettierrc │ ├── babel.config.js │ ├── src │ │ ├── main.ts │ │ ├── shims-vue.d.ts │ │ ├── streamlit │ │ │ ├── index.ts │ │ │ ├── StreamlitVue.ts │ │ │ └── WithStreamlitConnection.vue │ │ ├── App.vue │ │ └── MyComponent.vue │ ├── .env │ ├── .gitignore │ ├── .eslintrc.js │ ├── public │ │ └── index.html │ ├── tsconfig.json │ └── package.json └── __init__.py ├── img ├── menu.png ├── styled_menu.png └── horizontal_menu.png ├── LICENSE ├── .gitignore ├── setup.py └── README.md /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include streamlit_option_menu/frontend/dist * 2 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /img/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victoryhb/streamlit-option-menu/HEAD/img/menu.png -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: './' 3 | } -------------------------------------------------------------------------------- /img/styled_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victoryhb/streamlit-option-menu/HEAD/img/styled_menu.png -------------------------------------------------------------------------------- /img/horizontal_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victoryhb/streamlit-option-menu/HEAD/img/horizontal_menu.png -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { defineComponent } from 'vue' 3 | const component: ReturnType 4 | export default component 5 | } 6 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/.env: -------------------------------------------------------------------------------- 1 | # Run the component's dev server on :3001 2 | # (The Streamlit dev server already runs on :3000) 3 | PORT=3001 4 | 5 | # Don't automatically open the web browser on `npm run start`. 6 | BROWSER=none -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | "plugin:@typescript-eslint/eslint-recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | 'eslint:recommended', 11 | '@vue/typescript/recommended' 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2020 15 | }, 16 | rules: { 17 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 18 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/streamlit/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2018-2020 Streamlit Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | export { useStreamlit } from "./StreamlitVue" 18 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowJs": true, 12 | "allowSyntheticDefaultImports": true, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "types": [ 16 | "webpack-env" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "esnext", 25 | "dom", 26 | "dom.iterable", 27 | "scripthost" 28 | ] 29 | }, 30 | "include": [ 31 | "src/**/*.ts", 32 | "src/**/*.tsx", 33 | "src/**/*.vue", 34 | "tests/**/*.ts", 35 | "tests/**/*.tsx" 36 | ], 37 | "exclude": [ 38 | "node_modules" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/streamlit/StreamlitVue.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vue.js specific composables 3 | */ 4 | import { onMounted, onUpdated } from "vue" 5 | import { Streamlit } from "streamlit-component-lib" 6 | 7 | export function useStreamlit() { 8 | /** 9 | * Optional Streamlit Vue-based setup. 10 | * 11 | * You are not required call this function on your Streamlit 12 | * component. If you decide not to call it, you should implement the 13 | * `onMounted` and `onUpdated` functions in your own component, 14 | * so that your plugin properly resizes. 15 | */ 16 | 17 | onMounted((): void => { 18 | // After we're rendered for the first time, tell Streamlit that our height 19 | // has changed. 20 | Streamlit.setFrameHeight() 21 | }) 22 | 23 | onUpdated((): void => { 24 | // After we're updated, tell Streamlit that our height may have changed. 25 | Streamlit.setFrameHeight() 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 The Python Packaging Authority 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "streamlit_component_template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve", 7 | "build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build", 8 | "lint": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "bootstrap": "^5.1.3", 12 | "bootstrap-icons": "^1.10.5", 13 | "core-js": "^3.6.5", 14 | "fontawesome": "^5.6.3", 15 | "streamlit-component-lib": "^1.4.0", 16 | "vue": "^3.2.13" 17 | }, 18 | "devDependencies": { 19 | "@fortawesome/fontawesome-free": "^5.15.4", 20 | "@typescript-eslint/eslint-plugin": "^2.33.0", 21 | "@typescript-eslint/parser": "^2.33.0", 22 | "@vue/cli-plugin-babel": "~4.5.0", 23 | "@vue/cli-plugin-eslint": "~4.5.0", 24 | "@vue/cli-plugin-typescript": "^4.5.0", 25 | "@vue/cli-service": "~4.5.0", 26 | "@vue/eslint-config-typescript": "^5.0.2", 27 | "babel-eslint": "^10.1.0", 28 | "eslint": "^6.7.2", 29 | "eslint-plugin-vue": "^7.0.0-0", 30 | "typescript": "4.3.5" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 33 | 34 | 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # Python - https://github.com/github/gitignore/blob/master/Python.gitignore 3 | ######################################################################## 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # Distribution / packaging 10 | build/ 11 | dist/ 12 | eggs/ 13 | .eggs/ 14 | *.egg-info/ 15 | *.egg 16 | 17 | # Unit test / coverage reports 18 | .coverage 19 | .coverage\.* 20 | .pytest_cache/ 21 | .mypy_cache/ 22 | test-reports 23 | 24 | # Test fixtures 25 | cffi_bin 26 | 27 | # Pyenv Stuff 28 | .python-version 29 | 30 | ######################################################################## 31 | # OSX - https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 32 | ######################################################################## 33 | .DS_Store 34 | .DocumentRevisions-V100 35 | .fseventsd 36 | .Spotlight-V100 37 | .TemporaryItems 38 | .Trashes 39 | .VolumeIcon.icns 40 | .com.apple.timemachine.donotpresent 41 | 42 | ######################################################################## 43 | # node - https://github.com/github/gitignore/blob/master/Node.gitignore 44 | ######################################################################## 45 | # Logs 46 | npm-debug.log* 47 | yarn-debug.log* 48 | yarn-error.log* 49 | 50 | # Dependency directories 51 | node_modules/ 52 | 53 | # Coverage directory used by tools like istanbul 54 | coverage/ 55 | 56 | # Lockfiles 57 | yarn.lock 58 | package-lock.json 59 | 60 | ######################################################################## 61 | # JetBrains 62 | ######################################################################## 63 | .idea 64 | 65 | ######################################################################## 66 | # VSCode 67 | ######################################################################## 68 | .vscode/ 69 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/streamlit/WithStreamlitConnection.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 76 | 77 | 83 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | setuptools.setup( 4 | name="streamlit-option-menu", 5 | version="0.4.0", 6 | author="Victor Yan", 7 | author_email="victoryhb@163.com", 8 | description="streamlit-option-menu is a simple Streamlit component that allows users to select a single item from a list of options in a menu.", 9 | long_description="""streamlit-option-menu is a simple Streamlit component that allows users to select a single item from a list of options in a menu. 10 | It is similar in function to st.selectbox(), except that: 11 | - It uses a simple static list to display the options instead of a dropdown 12 | - It has configurable icons for each option item and the menu title 13 | 14 | It is built on [streamlit-component-template-vue](https://github.com/andfanilo/streamlit-component-template-vue), styled with [Bootstrap](https://getbootstrap.com/) and with icons from [bootstrap-icons](https://icons.getbootstrap.com/) 15 | 16 | ## Installation 17 | ``` 18 | pip install streamlit-option-menu 19 | ``` 20 | 21 | ## Parameters 22 | The `option_menu` function accepts the following parameters: 23 | - menu_title (required): the title of the menu; pass None to hide the title 24 | - options (required): list of (string) options to display in the menu; set an option to "---" if you want to insert a section separator 25 | - default_index (optional, default=0): the index of the selected option by default 26 | - menu_icon (optional, default="menu-up"): name of the [bootstrap-icon](https://icons.getbootstrap.com/) to be used for the menu title 27 | - icons (optional, default=["caret-right"]): list of [bootstrap-icon](https://icons.getbootstrap.com/) names to be used for each option; its length should be equal to the length of options 28 | - orientation (optional, default="vertical"): "vertical" or "horizontal"; whether to display the menu vertically or horizontally 29 | 30 | The function returns the (string) option currently selected 31 | 32 | ## Example 33 | ``` 34 | import streamlit as st 35 | from streamlit_option_menu import option_menu 36 | 37 | with st.sidebar: 38 | selected = option_menu("Main Menu", ["Home", 'Settings'], 39 | icons=['house', 'gear'], menu_icon="cast", default_index=1) 40 | selected 41 | 42 | # horizontal Menu 43 | selected2 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 44 | icons=['house', 'cloud-upload', "list-task", 'gear'], 45 | menu_icon="cast", default_index=0, orientation="horizontal") 46 | selected2 47 | ``` 48 | """, 49 | long_description_content_type="text/plain", 50 | url="https://github.com/victoryhb/streamlit-option-menu", 51 | packages=setuptools.find_packages(), 52 | include_package_data=True, 53 | classifiers=[], 54 | python_requires=">=3.6", 55 | install_requires=[ 56 | # By definition, a Custom Component depends on Streamlit. 57 | # If your component has other Python dependencies, list 58 | # them here. 59 | "streamlit >= 1.36", 60 | ], 61 | ) 62 | -------------------------------------------------------------------------------- /streamlit_option_menu/__init__.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit.components.v1 as components 3 | import os 4 | 5 | _RELEASE = True 6 | 7 | # Declare a Streamlit component. `declare_component` returns a function 8 | # that is used to create instances of the component. We're naming this 9 | # function "_component_func", with an underscore prefix, because we don't want 10 | # to expose it directly to users. Instead, we will create a custom wrapper 11 | # function, below, that will serve as our component's public API. 12 | 13 | # It's worth noting that this call to `declare_component` is the 14 | # *only thing* you need to do to create the binding between Streamlit and 15 | # your component frontend. Everything else we do in this file is simply a 16 | # best practice. 17 | 18 | if not _RELEASE: 19 | _component_func = components.declare_component( 20 | "option_menu", 21 | url="http://localhost:3001", 22 | ) 23 | else: 24 | parent_dir = os.path.dirname(os.path.abspath(__file__)) 25 | build_dir = os.path.join(parent_dir, "frontend/dist") 26 | _component_func = components.declare_component( 27 | "option_menu", path=build_dir) 28 | 29 | # Create a wrapper function for the component. This is an optional 30 | # best practice - we could simply expose the component function returned by 31 | # `declare_component` and call it done. The wrapper allows us to customize 32 | # our component's API: we can pre-process its input args, post-process its 33 | # output value, and add a docstring for users. 34 | 35 | 36 | def option_menu(menu_title, options, default_index=0, menu_icon=None, icons=None, orientation="vertical", 37 | styles=None, manual_select=None, key=None, on_change=None): 38 | """_summary_ 39 | 40 | Args: 41 | menu_title (_type_): Title of the menu 42 | options (_type_): The options to present 43 | default_index (int, optional): Default index to start on. Defaults to 0. 44 | menu_icon (_type_, optional): Add a menu Icon. Defaults to None. 45 | icons (_type_, optional): Add icons for the options. Defaults to None. 46 | orientation (str, optional): Horizontal or Vertical. Defaults to "vertical". 47 | styles (_type_, optional): You can add a css style here. Defaults to None. 48 | manual_select (_type_, optional): An index to select. If passed, will change current selection to the passsed. 49 | key (_type_, optional): The component key. Defaults to None. 50 | on_change (_type_, optional): A callback function to call when the selection changes. Defaults to None. The callback function must accept a single argument, which will be the key of the option menu. You can fetch current selection by calling st.session_state[key] 51 | 52 | Returns: 53 | str: The selected option 54 | """ 55 | _on_change = None 56 | if on_change is not None: 57 | if key is None: 58 | st.error("You must pass a key if you want to use the on_change callback for the option menu") 59 | else: 60 | def _on_change() -> any: 61 | return on_change(key) 62 | 63 | if manual_select is not None: 64 | default_index = manual_select 65 | 66 | component_value = _component_func(options=options, 67 | key=key, defaultIndex=default_index, icons=icons, menuTitle=menu_title, 68 | menuIcon=menu_icon, default=options[default_index], 69 | orientation=orientation, styles=styles, manualSelect=manual_select, on_change=_on_change) 70 | return component_value 71 | 72 | # Create a second instance of our component whose `name` arg will vary 73 | # based on a text_input widget. 74 | # 75 | # We use the special "key" argument to assign a fixed identity to this 76 | # component instance. By default, when a component's arguments change, 77 | # it is considered a new instance and will be re-mounted on the frontend 78 | # and lose its current state. In this case, we want to vary the component's 79 | # "name" argument without having it get recreated. 80 | if __name__ == "__main__": 81 | st.set_page_config(page_title="Option Menu", layout="wide") 82 | with st.sidebar: 83 | selected = option_menu("Main Menu", ["Home", "Upload","---", "Tasks", 'Settings'], 84 | icons=['house', 'cloud-upload', None, "list-task", 'gear'], menu_icon="cast", default_index=1) 85 | 86 | selected2 = option_menu(None, ["Home", "Upload", "---", "Tasks", 'Settings'], 87 | icons=['house', 'cloud-upload', None, "list-task", 'gear'], 88 | menu_icon="cast", default_index=0, orientation="horizontal") 89 | 90 | selected3 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 91 | icons=['house', 'cloud-upload', "list-task", 'gear'], 92 | menu_icon="cast", default_index=0, orientation="horizontal", 93 | styles={ 94 | "container": {"padding": "0!important", "background-color": "#fafafa"}, 95 | "icon": {"color": "orange", "font-size": "25px"}, 96 | "nav-link": {"font-size": "25px", "text-align": "left", "margin":"0px", "--hover-color": "#eee"}, 97 | "nav-link-selected": {"background-color": "green"}, 98 | } 99 | ) 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # streamlit-option-menu 2 | ![](./img/menu.png) 3 | ![](./img/horizontal_menu.png) 4 | ![](./img/styled_menu.png) 5 | 6 | streamlit-option-menu is a simple Streamlit component that allows users to select a single item from a list of options in a menu. 7 | It is similar in function to st.selectbox(), except that: 8 | - It uses a simple static list to display the options instead of a dropdown 9 | - It has configurable icons for each option item and the menu title 10 | - The CSS styles of most HTML elements in the menu can be customized (see the styles parameter and Example #3 below) 11 | 12 | It is built on [streamlit-component-template-vue](https://github.com/andfanilo/streamlit-component-template-vue), styled with [Bootstrap](https://getbootstrap.com/) and with icons from [bootstrap-icons](https://icons.getbootstrap.com/) 13 | 14 | ## Installation 15 | ``` 16 | pip install streamlit-option-menu 17 | ``` 18 | 19 | ## Parameters 20 | The `option_menu` function accepts the following parameters: 21 | - menu_title (required): the title of the menu; pass None to hide the title 22 | - options (required): list of (string) options to display in the menu; set an option to "---" if you want to insert a section separator 23 | - default_index (optional, default=0): the index of the selected option by default 24 | - menu_icon (optional, default="menu-up"): name of the [bootstrap-icon](https://icons.getbootstrap.com/) to be used for the menu title 25 | - icons (optional, default=["caret-right"]): list of [bootstrap-icon](https://icons.getbootstrap.com/) names to be used for each option; its length should be equal to the length of options 26 | - orientation (optional, default="vertical"): "vertical" or "horizontal"; whether to display the menu vertically or horizontally 27 | - styles (optional, default=None): A dictionary containing the CSS definitions for most HTML elements in the menu, including: 28 | * "container": the container div of the entire menu 29 | * "menu-title": the <a> element containing the menu title 30 | * "menu-icon": the icon next to the menu title 31 | * "nav": the <ul> containing "nav-link" 32 | * "nav-item": the <li> element containing "nav-link" 33 | * "nav-link": the <a> element containing the text of each option 34 | * "nav-link-selected": the <a> element containing the text of the selected option 35 | * "icon": the icon next to each option 36 | * "separator": the <hr> element separating the options 37 | - manual_select: Pass to manually change the menu item selection. 38 | The function returns the (string) option currently selected 39 | - on_change: A callback that will happen when the selection changes. The callback function should accept one argument "key". You can use it to fetch the value of the menu (see [example 5](#examples)) 40 | 41 | 42 | 43 | ### Manual Selection 44 | This option was added to allow the user to manually move to a specific option in the menu. This could be useful when the user wants to move to another option automatically after finishing with one option (for example, if settings are approved, then move back to the main option). 45 | 46 | To use this option, you need to pass the index of the desired option as `manual_select`. **Notice**: This option behaves like a button. This means that you should only pass `manual_select` once when you want to select the option, and not keep it as a constant value in your menu creation call (see example below). 47 | 48 | 49 | ## Examples 50 | ```python 51 | import streamlit as st 52 | from streamlit_option_menu import option_menu 53 | 54 | # 1. as sidebar menu 55 | with st.sidebar: 56 | selected = option_menu("Main Menu", ["Home", 'Settings'], 57 | icons=['house', 'gear'], menu_icon="cast", default_index=1) 58 | selected 59 | 60 | # 2. horizontal menu 61 | selected2 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 62 | icons=['house', 'cloud-upload', "list-task", 'gear'], 63 | menu_icon="cast", default_index=0, orientation="horizontal") 64 | selected2 65 | 66 | # 3. CSS style definitions 67 | selected3 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 68 | icons=['house', 'cloud-upload', "list-task", 'gear'], 69 | menu_icon="cast", default_index=0, orientation="horizontal", 70 | styles={ 71 | "container": {"padding": "0!important", "background-color": "#fafafa"}, 72 | "icon": {"color": "orange", "font-size": "25px"}, 73 | "nav-link": {"font-size": "25px", "text-align": "left", "margin":"0px", "--hover-color": "#eee"}, 74 | "nav-link-selected": {"background-color": "green"}, 75 | } 76 | ) 77 | 78 | # 4. Manual item selection 79 | if st.session_state.get('switch_button', False): 80 | st.session_state['menu_option'] = (st.session_state.get('menu_option', 0) + 1) % 4 81 | manual_select = st.session_state['menu_option'] 82 | else: 83 | manual_select = None 84 | 85 | selected4 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 86 | icons=['house', 'cloud-upload', "list-task", 'gear'], 87 | orientation="horizontal", manual_select=manual_select, key='menu_4') 88 | st.button(f"Move to Next {st.session_state.get('menu_option', 1)}", key='switch_button') 89 | selected4 90 | 91 | # 5. Add on_change callback 92 | def on_change(key): 93 | selection = st.session_state[key] 94 | st.write(f"Selection changed to {selection}") 95 | 96 | selected5 = option_menu(None, ["Home", "Upload", "Tasks", 'Settings'], 97 | icons=['house', 'cloud-upload', "list-task", 'gear'], 98 | on_change=on_change, key='menu_5', orientation="horizontal") 99 | selected5 100 | ``` 101 | -------------------------------------------------------------------------------- /streamlit_option_menu/frontend/src/MyComponent.vue: -------------------------------------------------------------------------------- 1 | 31 | 133 | 134 | 215 | --------------------------------------------------------------------------------