├── .gitattributes ├── .gitignore ├── Home.py ├── LICENSE ├── README.md ├── docs ├── _Playground.py ├── components │ ├── alert_dialog.md │ ├── avatar.md │ ├── badges.md │ ├── button.md │ ├── card.md │ ├── checkbox.md │ ├── date_picker.md │ ├── experiment.md │ ├── hover_card.md │ ├── input.md │ ├── link_button.md │ ├── metric_card.md │ ├── radio_group.md │ ├── select.md │ ├── slider.md │ ├── switch.md │ ├── table.md │ ├── tabs.md │ └── textarea.md └── introduction.md ├── local_components ├── __init__.py ├── containers.py └── headers.py ├── pages ├── AlertDialog.py ├── Avatar.py ├── Badges.py ├── Button.py ├── Card.py ├── Checkbox.py ├── DatePicker.py ├── Experiment(Cool).py ├── HoverCard.py ├── Input.py ├── LinkButton.py ├── MetricCard.py ├── RadioGroup.py ├── Select.py ├── Slider.py ├── Switch.py ├── Table.py ├── Tabs.py ├── TextArea.py └── Visualization.py └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 105 | __pypackages__/ 106 | 107 | # Celery stuff 108 | celerybeat-schedule 109 | celerybeat.pid 110 | 111 | # SageMath parsed files 112 | *.sage.py 113 | 114 | # Environments 115 | .env 116 | .venv 117 | env/ 118 | venv/ 119 | ENV/ 120 | env.bak/ 121 | venv.bak/ 122 | 123 | # Spyder project settings 124 | .spyderproject 125 | .spyproject 126 | 127 | # Rope project settings 128 | .ropeproject 129 | 130 | # mkdocs documentation 131 | /site 132 | 133 | # mypy 134 | .mypy_cache/ 135 | .dmypy.json 136 | dmypy.json 137 | 138 | # Pyre type checker 139 | .pyre/ 140 | 141 | # pytype static type analyzer 142 | .pytype/ 143 | 144 | # Cython debug symbols 145 | cython_debug/ 146 | 147 | # PyCharm 148 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 149 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 150 | # and can be added to the global gitignore or merged into this file. For a more nuclear 151 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 152 | #.idea/ 153 | -------------------------------------------------------------------------------- /Home.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | import pandas as pd 4 | import numpy as np 5 | from local_components import card_container 6 | from streamlit_shadcn_ui import slider, input, textarea, radio_group, switch 7 | 8 | # with open("docs/introduction.md", "r") as f: 9 | # st.markdown(f.read()) 10 | 11 | # ui.date_picker() 12 | 13 | st.header("Streamlit Shadcn UI") 14 | ui.badges(badge_list=[("shadcn", "default"), ("in", "secondary"), ("streamlit", "destructive")], class_name="flex gap-2", key="main_badges1") 15 | st.caption("A Streamlit component library for building beautiful apps easily. Bring the power of Shadcn UI to your Streamlit apps!") 16 | st.caption("Get started with pip install streamlit-shadcn-ui") 17 | 18 | 19 | with ui.element("div", className="flex gap-2", key="buttons_group1"): 20 | ui.element("button", text="Get Started", className="btn btn-primary", key="btn1") 21 | ui.element("link_button", text="Github", url="https://github.com/ObservedObserver/streamlit-shadcn-ui", variant="outline", key="btn2") 22 | 23 | st.subheader("Dashboard") 24 | 25 | ui.tabs(options=['Overview', 'Analytics', 'Reports', 'Notifications'], default_value='Overview', key="main_tabs") 26 | 27 | ui.date_picker(key="date_picker1") 28 | 29 | cols = st.columns(3) 30 | with cols[0]: 31 | # with ui.card(): 32 | # ui.element() 33 | ui.card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card1").render() 34 | with cols[1]: 35 | ui.card(title="Subscriptions", content="+2350", description="+180.1% from last month", key="card2").render() 36 | with cols[2]: 37 | ui.card(title="Sales", content="+12,234", description="+19% from last month", key="card3").render() 38 | 39 | def generate_sales_data(): 40 | np.random.seed(0) # For reproducible results 41 | months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 42 | sales = np.random.randint(1000, 5000, size=len(months)) 43 | return pd.DataFrame({'Month': months, 'Sales': sales}) 44 | 45 | with card_container(key="chart1"): 46 | st.vega_lite_chart(generate_sales_data(), { 47 | 'mark': {'type': 'bar', 'tooltip': True, 'fill': 'rgb(173, 250, 29)', 'cornerRadiusEnd': 4 }, 48 | 'encoding': { 49 | 'x': {'field': 'Month', 'type': 'ordinal'}, 50 | 'y': {'field': 'Sales', 'type': 'quantitative', 'axis': {'grid': False}}, 51 | }, 52 | }, use_container_width=True) 53 | 54 | # Sample data 55 | data = [ 56 | {"invoice": "INV001", "paymentStatus": "Paid", "totalAmount": 500, "paymentMethod": "Credit Card"}, 57 | {"invoice": "INV002", "paymentStatus": "Unpaid", "totalAmount": 200, "paymentMethod": "Cash"}, 58 | {"invoice": "INV003", "paymentStatus": "Paid", "totalAmount": 150, "paymentMethod": "Debit Card"}, 59 | {"invoice": "INV004", "paymentStatus": "Unpaid", "totalAmount": 350, "paymentMethod": "Credit Card"}, 60 | {"invoice": "INV005", "paymentStatus": "Paid", "totalAmount": 400, "paymentMethod": "PayPal"}, 61 | # Add more records as needed 62 | ] 63 | 64 | # Creating a DataFrame 65 | invoice_df = pd.DataFrame(data) 66 | 67 | with card_container(key="table1"): 68 | ui.table(data=invoice_df, maxHeight=300) 69 | 70 | 71 | ui_result = ui.button("Button", key="btn") 72 | st.write("UI Button Clicked:", ui_result) 73 | 74 | 75 | # Slider Component 76 | slider_value = slider(default_value=[20], min_value=0, max_value=100, step=2, label="Select a Range", key="slider1") 77 | st.write("Slider Value:", slider_value) 78 | 79 | # Input Component 80 | input_value = input(default_value="Hello, Streamlit!", type='text', placeholder="Enter text here", key="input1") 81 | st.write("Input Value:", input_value) 82 | 83 | # Textarea Component 84 | textarea_value = textarea(default_value="Type your message here...", placeholder="Enter longer text", key="textarea1") 85 | st.write("Textarea Value:", textarea_value) 86 | 87 | # Radio Group Component 88 | radio_options = [ 89 | {"label": "Option A", "value": "A", "id": "r1"}, 90 | {"label": "Option B", "value": "B", "id": "r2"}, 91 | {"label": "Option C", "value": "C", "id": "r3"} 92 | ] 93 | radio_value = radio_group(options=radio_options, default_value="B", key="radio1") 94 | st.write("Selected Radio Option:", radio_value) 95 | 96 | # Switch Component 97 | switch_value = switch(default_checked=True, label="Toggle Switch", key="switch1") 98 | st.write("Switch is On:", switch_value) 99 | 100 | st.subheader("Alert Dialog") 101 | trigger_btn = ui.button(text="Trigger Button", key="trigger_btn") 102 | ui.alert_dialog(show=trigger_btn, title="Alert Dialog", description="This is an alert dialog", confirm_label="OK", cancel_label="Cancel", key="alert_dialog1") -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 observedobserver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # steamlit-shadcn-ui-docs 2 | 3 | > Check steamlit-shadcn-ui repo here: https://github.com/ObservedObserver/streamlit-shadcn-ui 4 | 5 | [![PyPI - Version](https://img.shields.io/pypi/v/streamlit-shadcn-ui)](https://pypi.org/project/streamlit-shadcn-ui/) 6 | [![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://shadcn.streamlit.app/) 7 | 8 | Using shadcn-ui components in streamlit 9 | 10 | 11 | ## Installation 12 | 13 | ```bash 14 | pip install streamlit-shadcn-ui 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /docs/_Playground.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | cols = st.columns([0.7, 0.3]) 5 | 6 | with cols[0]: 7 | ui.textarea(key="textarea1", className="w-full h-96") 8 | with cols[1]: 9 | # st.text("Mode") 10 | ui.tabs(options=["Ma", "HT", "BA"], default_value="Ma", className="w-full", key="tabs1") 11 | with ui.element("div", className="flex flex-col gap-4 text-sm text-gray-500"): 12 | with ui.element("div", className="flex justify-between"): 13 | 14 | ui.element("h2", className="font-medium", children=["Model"]) 15 | ui.element("__select", className="my-0") 16 | 17 | with ui.element("div", className="flex justify-between"): 18 | 19 | ui.element("h2", className="font-medium", children=["Temperature"]) 20 | ui.element("span", children=["0.2"]) 21 | ui.element("slider", default_value=[20], min_value=0, max_value=100, step=2, key="slider1") 22 | with ui.element("div", className="flex justify-between"): 23 | 24 | ui.element("h2", className="font-medium", children=["Maximum Length"]) 25 | ui.element("span", children=["0.2"]) 26 | ui.element("slider", default_value=[20], min_value=0, max_value=100, step=2, key="slider2") 27 | with ui.element("div", className="flex justify-between"): 28 | 29 | ui.element("h2", className="font-medium", children=["Top P"]) 30 | ui.element("span", children=["0.2"]) 31 | ui.element("slider", default_value=[20], min_value=0, max_value=100, step=2, key="slider3") 32 | -------------------------------------------------------------------------------- /docs/components/alert_dialog.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | Alert Dialogs are used to display information to the user. It is a modal window, blocking other actions in the application until it is closed. 4 | 5 | ```py 6 | import streamlit_shadcn_ui as ui 7 | 8 | trigger_btn = ui.button(text="Trigger Button", key="trigger_btn_1") 9 | ui.alert_dialog(show=trigger_btn, title="Alert Dialog", description="This is an alert dialog", confirm_label="OK", cancel_label="Cancel", key="alert_dialog_1") 10 | ``` -------------------------------------------------------------------------------- /docs/components/avatar.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | 6 | ui.avatar(src="https://your_image_url") 7 | ``` -------------------------------------------------------------------------------- /docs/components/badges.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit_shadcn_ui as ui 5 | 6 | ui.badges(badge_list=[("default", "default"), ("secondary", "secondary"), ("outline", "outline"), ("Hello", "destructive"), ("World", "destructive")], class_name="flex gap-2", key="badges1") 7 | ``` -------------------------------------------------------------------------------- /docs/components/button.md: -------------------------------------------------------------------------------- 1 | ### Basic usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | 8 | clicked = ui.button("Click", key="clk_btn") 9 | ui.button("Reset", key="reset_btn") 10 | st.write("UI Button Clicked:", clicked) 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/components/card.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | Card is a container component that can be used to group other components together. 4 | 5 | example, card is still an experimental component, check more details at [experimental element](/Experiment(Cool)) 6 | 7 | ```python 8 | with ui.card(key="card1"): 9 | ui.element("span", children=["Email"], className="text-gray-400 text-sm font-medium m-1", key="label1") 10 | ui.element("input", key="email_input", placeholder="Your email") 11 | 12 | ui.element("span", children=["User Name"], className="text-gray-400 text-sm font-medium m-1", key="label2") 13 | ui.element("input", key="username_input", placeholder="Create a User Name") 14 | ui.element("button", text="Submit", key="button", className="m-1") 15 | ``` -------------------------------------------------------------------------------- /docs/components/checkbox.md: -------------------------------------------------------------------------------- 1 | ### Basic usage 2 | 3 | ```py 4 | import streamlit_shadcn_ui as ui 5 | 6 | ui.checkbox(checked=True, label="I am a Checkbox 1") 7 | ui.checkbox(checked=False, label="I am a Checkbox 2") 8 | ui.checkbox(checked=False, label="I am a Checkbox 3") 9 | ``` -------------------------------------------------------------------------------- /docs/components/date_picker.md: -------------------------------------------------------------------------------- 1 | ### Basic Uage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | # Date Picker 8 | dt = ui.date_picker(key="date_picker", mode="single", label="Date Picker") 9 | st.write("Date Value:", dt) 10 | 11 | # Date Range Picker 12 | dt2 = ui.date_picker(key="date_picker2", mode="range", label="Date Picker") 13 | st.write("Date Range:", dt2) 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/components/experiment.md: -------------------------------------------------------------------------------- 1 | This is a component for testing and experimenting with new features. 2 | 3 | It allows you to use any component like using in a React Framework. 4 | 5 | What you can benefit it from: 6 | + You can build nested components, all `streamlit-shadhcn-ui` component can combine together. 7 | + It allows you to write html and tailwindcss directly in python, without any extra work. 8 | 9 | **This component is still in experimental stage, it may change in the future.** Now I only refactor several components to work in this mode. If you have any idea or suggestion, please open an issue. 10 | 11 | ### Basic Usage 12 | 13 | Using `with` statement to create a component 14 | ```python 15 | with ui.card(key="base_ele_card_l1"): 16 | with ui.card(key="base_ele_card_l2"): 17 | ui.element("input", key="nst2_input", label="Value") 18 | ui.element("button", key="nst2_btn", text="Nest Submmit", variant="outline") 19 | 20 | ui.element("button", key="nst_btn", text="Hello World") 21 | ``` 22 | 23 | Using without `with` statement, remember to call `render` method to render the component. 24 | ```python 25 | st.header("Nest Element 2") 26 | card = ui.element("card", key="base_ele_2") 27 | card2 = ui.element("card", key="base_ele2_2") 28 | card2.add_child(ui.element("input", key="nst2_input_2", label="Value")) 29 | card2.add_child(ui.element("button", key="nst2_btn_2", text="Nest Submmit", variant="outline")) 30 | card.add_child(card2) 31 | card.add_child(ui.element("button", key="nst_btn_2", text="Hello World")) 32 | card.render() 33 | ``` 34 | 35 | Certainly! Here's a revised version of your text, adjusted for clarity and a more native tone. Minimal changes have been made to preserve the original meaning and technical context: 36 | 37 | 38 | ### Using tailwind and style 39 | 40 | Currently, only the `element` function allows for styling components with either `style` or `className` (using Tailwind). This feature is still experimental, but I plan to complete most of the work this week. For example: 41 | 42 | ```py 43 | import streamlit_shadcn_ui as UI 44 | 45 | with ui.card(key="card1"): 46 | ui.element("span", children=["Email"], className="text-gray-400 text-sm font-medium m-1", key="label1") 47 | ui.element("input", key="email_input", placeholder="Your email") 48 | 49 | ui.element("span", children=["User Name"], className="text-gray-400 text-sm font-medium m-1", key="label2") 50 | ui.element("input", key="username_input", placeholder="Create a User Name") 51 | ui.element("button", text="Submit", key="button", className="m-1") 52 | ``` 53 | 54 | One concern I have is preventing the frontend application from becoming too bulky. Each iframe incorporating its own complete bundle of Tailwind code could lead to excessively large files. Full Tailwind integration offers a great development experience, but at the cost of increased bundle size, which is particularly significant since a Streamlit app typically contains many iframe-based components. 55 | 56 | To address this, I am considering offering two initial options: including the complete Tailwind style by default, but also providing a 'lite-mode' with limited Tailwind for those who prefer a leaner approach. 57 | 58 | Another task to complete before making `element` a formal feature involves the handling of `element` values. When using nested elements, they share the same iframe and Streamlit values in the session state. Therefore, I need to slightly refactor the current value type to include the component key, allowing all components to share a single Streamlit value. 59 | -------------------------------------------------------------------------------- /docs/components/hover_card.md: -------------------------------------------------------------------------------- 1 | ### Basic usage 2 | 3 | ```py 4 | import streamlit as st 5 | 6 | import streamlit_shadcn_ui as ui 7 | 8 | ui.hover_card(label="Hover on me1!", content="I am a hover card1!", content_type="text", key="hover_card_1") 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/components/input.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | # Input Component 7 | input_value = ui.input(default_value="Hello, Streamlit!", type='text', placeholder="Enter text here", key="input1") 8 | st.write("Input Value:", input_value) 9 | ``` -------------------------------------------------------------------------------- /docs/components/link_button.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | link button is a button that can be used to link to other pages, it will open a new tab when clicked. 4 | 5 | ```py 6 | import streamlit_shadcn_ui as ui 7 | 8 | ui.link_button(text="Go To Github", url="https://github.com/ObservedObserver/streamlit-shadcn-ui", key="link_btn") 9 | 10 | ``` -------------------------------------------------------------------------------- /docs/components/metric_card.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | cols = st.columns(3) 8 | with cols[0]: 9 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card1") 10 | with cols[1]: 11 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card2") 12 | with cols[2]: 13 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card3") 14 | ``` -------------------------------------------------------------------------------- /docs/components/radio_group.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | # Radio Group Component 8 | radio_options = [ 9 | {"label": "Option A", "value": "A", "id": "r1"}, 10 | {"label": "Option B", "value": "B", "id": "r2"}, 11 | {"label": "Option C", "value": "C", "id": "r3"} 12 | ] 13 | radio_value = ui.radio_group(options=radio_options, default_value="B", key="radio1") 14 | st.write("Selected Radio Option:", radio_value) 15 | ``` -------------------------------------------------------------------------------- /docs/components/select.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | choice = ui.select(options=["Apple", "Banana", "Orange"]) 8 | 9 | st.markdown(f"Currrent value: {choice}") 10 | 11 | ``` -------------------------------------------------------------------------------- /docs/components/slider.md: -------------------------------------------------------------------------------- 1 | ### Slider 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | # Slider Component 8 | slider_value = ui.slider(default_value=[20], min_value=0, max_value=100, step=2, label="Select a Value", key="slider1") 9 | st.write("Slider Value:", slider_value) 10 | 11 | slider_range = ui.slider(default_value=[20, 80], min_value=0, max_value=100, step=2, label="Select a Range", key="slider2") 12 | st.write("Slider Range:", slider_range) 13 | ``` -------------------------------------------------------------------------------- /docs/components/switch.md: -------------------------------------------------------------------------------- 1 | ### Switch 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | 8 | switch_value = ui.switch(default_checked=True, label="Toggle Switch", key="switch1") 9 | st.write("Switch is On:", switch_value) 10 | ``` -------------------------------------------------------------------------------- /docs/components/table.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import pandas as pd 5 | import streamlit_shadcn_ui as ui 6 | # Sample data 7 | data = [ 8 | {"invoice": "INV001", "paymentStatus": "Paid", "totalAmount": 500, "paymentMethod": "Credit Card"}, 9 | {"invoice": "INV002", "paymentStatus": "Unpaid", "totalAmount": 200, "paymentMethod": "Cash"}, 10 | {"invoice": "INV003", "paymentStatus": "Paid", "totalAmount": 150, "paymentMethod": "Debit Card"}, 11 | {"invoice": "INV004", "paymentStatus": "Unpaid", "totalAmount": 350, "paymentMethod": "Credit Card"}, 12 | {"invoice": "INV005", "paymentStatus": "Paid", "totalAmount": 400, "paymentMethod": "PayPal"}, 13 | # Add more records as needed 14 | ] 15 | 16 | # Creating a DataFrame 17 | invoice_df = pd.DataFrame(data) 18 | 19 | ui.table(data=invoice_df, maxHeight=300) 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/components/tabs.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit_shadcn_ui as ui 5 | 6 | ui.tabs(options=['PyGWalker', 'Graphic Walker', 'GWalkR', 'RATH'], default_value='PyGWalker', key="kanaries") 7 | ``` -------------------------------------------------------------------------------- /docs/components/textarea.md: -------------------------------------------------------------------------------- 1 | ### Basic Usage 2 | 3 | ```py 4 | import streamlit as st 5 | import streamlit_shadcn_ui as ui 6 | 7 | # Textarea Component 8 | textarea_value = ui.textarea(default_value="Type your message here...", placeholder="Enter longer text", key="textarea1") 9 | st.write("Textarea Value:", textarea_value) 10 | ``` -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | # streamlit-shadcn-ui 2 | 3 | `streamlit-shadcn-ui` is a Python package that provides a set of [shadcn](https://ui.shadcn.com/) UI components for [Streamlit](https://www.streamlit.io/). 4 | 5 | ## Installation 6 | 7 | ```bash 8 | pip install streamlit-shadcn-ui 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /local_components/__init__.py: -------------------------------------------------------------------------------- 1 | from .containers import * 2 | from .headers import * -------------------------------------------------------------------------------- /local_components/containers.py: -------------------------------------------------------------------------------- 1 | from streamlit_extras.stylable_container import stylable_container 2 | 3 | def card_container(key=None): 4 | return stylable_container(key=key, css_styles=[ 5 | """ 6 | { 7 | --tw-ring-offset-shadow: 0 0 #0000; 8 | --tw-ring-shadow: 0 0 #0000; 9 | --tw-shadow: 0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1); 10 | border-radius: 8px; /* Rounded corners */ 11 | box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); /* Shadow effect */ 12 | transition: 0.3s; /* Smooth transition for hover effect */ 13 | padding: 1.5em; /* Inner spacing */ 14 | border: 1px solid #e5e7eb; 15 | box-sizing: border-box; 16 | overflow: hidden; /* Enable scroll on small screens */ 17 | box-shadow: var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow); 18 | } 19 | """, 20 | """ 21 | > div:not(:first-child) { 22 | width: 100%; 23 | min-width: 1px; 24 | overflow: hidden; 25 | } 26 | """, 27 | """ 28 | > div:first-child { 29 | display: none; 30 | } 31 | """, 32 | """ 33 | > div:not(:first-child) > iframe { 34 | display: inline-block; 35 | width: 100%; /* Adjusting for padding */ 36 | min-width: 1px; 37 | border: none; 38 | overflow: hidden; 39 | 40 | } 41 | """, 42 | """ 43 | > div:not(:first-child) canvas { 44 | display: inline-block; 45 | width: 100% !important; /* Adjusting for padding */ 46 | min-width: 1px; 47 | border: none; 48 | overflow: hidden; 49 | 50 | } 51 | """ 52 | ]) 53 | 54 | def buttons_container(unit_width: str, key=None): 55 | return stylable_container(key=key, css_styles=[ 56 | """ 57 | { 58 | display: flex; 59 | flex-direction: row; 60 | item-align: center; 61 | justify-content: flex-start; 62 | } 63 | """, 64 | f""" 65 | > div:not(:first-child) {{ 66 | width: {unit_width} !important; 67 | min-width: 1px; 68 | display: inline; 69 | }} 70 | """, 71 | f""" 72 | > div:first-child {{ 73 | display: none; 74 | }} 75 | """, 76 | f""" 77 | > div:not(:first-child) > iframe {{ 78 | display: inline-block; 79 | width: auto !important; 80 | min-width: 1px; 81 | border: none; 82 | }} 83 | """ 84 | ]) 85 | 86 | def float_container(direction: str="left", key=None): 87 | return stylable_container(key=key, css_styles=[ 88 | f""" 89 | {{ 90 | float: {direction}; 91 | }} 92 | """, 93 | f""" 94 | > div:not(:first-child) {{ 95 | float: {direction}; 96 | min-width: 1px; 97 | display: inline; 98 | }} 99 | """, 100 | f""" 101 | > div:first-child {{ 102 | display: none; 103 | }} 104 | """, 105 | f""" 106 | > div:not(:first-child) > iframe {{ 107 | display: inline-block; 108 | width: auto !important; 109 | min-width: 1px; 110 | border: none; 111 | }} 112 | """ 113 | ]) -------------------------------------------------------------------------------- /local_components/headers.py: -------------------------------------------------------------------------------- 1 | from streamlit_extras.stylable_container import stylable_container 2 | import streamlit as st 3 | def h2(text, key=None): 4 | st.markdown(f'{text}', unsafe_allow_html=True) 5 | # with stylable_container(key=key, css_styles=[ 6 | # f""" 7 | # h2 {{ 8 | # padding: 0em !important; 9 | # }} 10 | # """, 11 | # ]): 12 | # st.header("Dashboard") -------------------------------------------------------------------------------- /pages/AlertDialog.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.subheader("Alert Dialog") 5 | 6 | with open("docs/components/alert_dialog.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | trigger_btn = ui.button(text="Trigger Button", key="trigger_btn_1") 10 | ui.alert_dialog(show=trigger_btn, title="Alert Dialog", description="This is an alert dialog", confirm_label="OK", cancel_label="Cancel", key="alert_dialog_1") 11 | 12 | st.write(ui.alert_dialog) -------------------------------------------------------------------------------- /pages/Avatar.py: -------------------------------------------------------------------------------- 1 | import streamlit_shadcn_ui as ui 2 | import streamlit as st 3 | 4 | st.header("Avatar Component") 5 | 6 | with open("docs/components/avatar.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | ui.avatar(src="https://imagedelivery.net/tSvh1MGEu9IgUanmf58srQ/e2b094c8-8519-4e8b-e92e-1cf8d4b58f00/public") 10 | 11 | st.write(ui.avatar) -------------------------------------------------------------------------------- /pages/Badges.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Badges") 6 | 7 | with open("docs/components/badges.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | ui.badges(badge_list=[("default", "default"), ("secondary", "secondary"), ("outline", "outline"), ("Hello", "destructive"), ("World", "destructive")], class_name="flex gap-2", key="badges1") 11 | 12 | st.write(ui.badges) -------------------------------------------------------------------------------- /pages/Button.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | 6 | st.header("Button") 7 | 8 | with open("docs/components/button.md", "r") as f: 9 | st.markdown(f.read()) 10 | 11 | st.subheader("Click Events") 12 | 13 | clicked = ui.button("Click", key="clk_btn") 14 | reset = ui.button("Reset", variant="secondary", key="reset_btn") 15 | st.write("UI Button Clicked:", clicked) 16 | st.write("UI Reset Button Clicked:", reset) 17 | 18 | st.subheader("Variants") 19 | 20 | variant_options = ["default", "destructive", "outline", "secondary", "ghost", "link"] 21 | 22 | for variant in variant_options: 23 | ui.button(text=f"Button ({variant})", variant=variant, key=variant) 24 | 25 | st.subheader("Custom style of button") 26 | st.markdown(''' 27 | ```python 28 | ui.button(text="Beautiful Button", key="styled_btn_tailwind", className="bg-orange-500 text-white") 29 | ``` 30 | > class_name and className are both supported, class_name is used in python layer and will be converted to className for the frontend 31 | ''') 32 | ui.button(text="Beautiful Button", key="styled_btn_tailwind", className="bg-orange-500 text-white") 33 | 34 | st.write(ui.button) -------------------------------------------------------------------------------- /pages/Card.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Card") 6 | 7 | with open("docs/components/card.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | 11 | with ui.card(key="card1"): 12 | ui.element("span", children=["Email"], className="text-gray-400 text-sm font-medium m-1", key="label1") 13 | ui.element("input", key="email_input", placeholder="Your email") 14 | 15 | ui.element("span", children=["User Name"], className="text-gray-400 text-sm font-medium m-1", key="label2") 16 | ui.element("input", key="username_input", placeholder="Create a User Name") 17 | ui.element("button", text="Submit", key="button", className="m-1") 18 | 19 | st.write(ui.card) 20 | -------------------------------------------------------------------------------- /pages/Checkbox.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Checkbox") 6 | 7 | checkbox_values = [True, False, False] 8 | 9 | 10 | checkbox_values[0] = ui.checkbox(default_checked=True, label="I am a Checkbox 1", key="cb1") 11 | checkbox_values[1] = ui.checkbox(default_checked=False, label="I am a Checkbox 2", key="cb2") 12 | checkbox_values[2] = ui.checkbox(default_checked=False, label="I am a Checkbox 3", key="cb3") 13 | 14 | st.markdown(f""" 15 | + checkbox 1 value: {checkbox_values[0]} 16 | + checkbox 2 value: {checkbox_values[1]} 17 | + checkbox 3 value: {checkbox_values[2]} 18 | """) 19 | 20 | with open("docs/components/checkbox.md", "r") as f: 21 | st.markdown(f.read()) 22 | 23 | st.write(ui.checkbox) -------------------------------------------------------------------------------- /pages/DatePicker.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Date Picker") 5 | 6 | with open("docs/components/date_picker.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | dt = ui.date_picker(key="date_picker", mode="single", label="Date Picker") 10 | 11 | st.write("Date Value:", dt) 12 | 13 | dt2 = ui.date_picker(key="date_picker2", mode="range", label="Date Picker") 14 | 15 | st.write("Date Range:", dt2) 16 | 17 | 18 | st.write(ui.date_picker) -------------------------------------------------------------------------------- /pages/Experiment(Cool).py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Experiment(Cool)") 5 | 6 | with open("docs/components/experiment.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | with ui.card(key="base_ele_card_l1"): 10 | with ui.card(key="base_ele_card_l2"): 11 | # with ui.element("card", key="base_ele1") as card2: 12 | ui.element("input", key="nst2_input") 13 | ui.element("button", key="nst2_btn", text="Nest Submmit", variant="outline") 14 | 15 | ui.element("button", key="nst_btn", text="Hello World") 16 | 17 | st.write(ui.element) 18 | -------------------------------------------------------------------------------- /pages/HoverCard.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Hover Card") 6 | 7 | with open("docs/components/hover_card.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | ui.hover_card(label="Hover on me1!", content="I am a hover card1!", content_type="text", key="hover_card_1") 11 | 12 | ui.hover_card(label="Hover on me2!", content="I am a hover card2!", content_type="text", key="hover_card_2") 13 | 14 | ui.hover_card(label="Hover on me3!", content="I am a hover card3!", content_type="text", key="hover_card_3") 15 | 16 | st.write(ui.hover_card) -------------------------------------------------------------------------------- /pages/Input.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Input Component") 5 | 6 | with open("docs/components/input.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | # Input Component 10 | input_value = ui.input(default_value="Hello, Streamlit!", type='text', placeholder="Enter text here", key="input1") 11 | st.write("Input Value:", input_value) 12 | 13 | st.write(ui.input) -------------------------------------------------------------------------------- /pages/LinkButton.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Link Button") 6 | 7 | with open("docs/components/link_button.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | ui.link_button(text="Go To Github", url="https://github.com/ObservedObserver/streamlit-shadcn-ui", key="link_btn") 11 | 12 | st.write(ui.link_button) -------------------------------------------------------------------------------- /pages/MetricCard.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Metric Card") 6 | 7 | with open("docs/components/metric_card.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | cols = st.columns(3) 11 | 12 | with cols[0]: 13 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card1") 14 | with cols[1]: 15 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card2") 16 | with cols[2]: 17 | ui.metric_card(title="Total Revenue", content="$45,231.89", description="+20.1% from last month", key="card3") 18 | 19 | st.write(ui.metric_card) 20 | -------------------------------------------------------------------------------- /pages/RadioGroup.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Radio Group Component") 5 | with open("docs/components/radio_group.md", "r") as f: 6 | st.markdown(f.read()) 7 | 8 | # Radio Group Component 9 | radio_options = [ 10 | {"label": "Option A", "value": "A", "id": "r1"}, 11 | {"label": "Option B", "value": "B", "id": "r2"}, 12 | {"label": "Option C", "value": "C", "id": "r3"} 13 | ] 14 | radio_value = ui.radio_group(options=radio_options, default_value="B", key="radio1") 15 | st.write("Selected Radio Option:", radio_value) 16 | 17 | st.write(ui.radio_group) -------------------------------------------------------------------------------- /pages/Select.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Select") 5 | 6 | with open("docs/components/select.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | choice = ui.select(options=["Apple", "Banana", "Orange"]) 10 | 11 | st.markdown(f"Currrent value: {choice}") 12 | 13 | st.write(ui.select) -------------------------------------------------------------------------------- /pages/Slider.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Slider Component") 5 | 6 | with open("docs/components/slider.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | # Slider Component 10 | slider_value = ui.slider(default_value=[20], min_value=0, max_value=100, step=2, label="Select a Value", key="slider1") 11 | st.write("Slider Value:", slider_value) 12 | 13 | slider_range = ui.slider(default_value=[20, 80], min_value=0, max_value=100, step=2, label="Select a Range", key="slider2") 14 | st.write("Slider Range:", slider_range) 15 | 16 | st.write(ui.slider) -------------------------------------------------------------------------------- /pages/Switch.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Switch Component") 5 | 6 | with open("docs/components/switch.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | # Switch Component 10 | switch_value = ui.switch(default_checked=False, label="Toggle Switch", key="switch1") 11 | st.write("Switch is On:", switch_value) 12 | 13 | st.write(ui.switch) -------------------------------------------------------------------------------- /pages/Table.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import streamlit_shadcn_ui as ui 3 | import streamlit as st 4 | 5 | st.header("Table") 6 | with open("docs/components/table.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | # Sample data 10 | data = [ 11 | {"invoice": "INV001", "paymentStatus": "Paid", "totalAmount": 500, "paymentMethod": "Credit Card"}, 12 | {"invoice": "INV002", "paymentStatus": "Unpaid", "totalAmount": 200, "paymentMethod": "Cash"}, 13 | {"invoice": "INV003", "paymentStatus": "Paid", "totalAmount": 150, "paymentMethod": "Debit Card"}, 14 | {"invoice": "INV004", "paymentStatus": "Unpaid", "totalAmount": 350, "paymentMethod": "Credit Card"}, 15 | {"invoice": "INV005", "paymentStatus": "Paid", "totalAmount": 400, "paymentMethod": "PayPal"}, 16 | # Add more records as needed 17 | ] 18 | 19 | # Creating a DataFrame 20 | invoice_df = pd.DataFrame(data) 21 | 22 | ui.table(data=invoice_df, maxHeight=300) 23 | 24 | st.write(ui.table) -------------------------------------------------------------------------------- /pages/Tabs.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | import streamlit_shadcn_ui as ui 4 | 5 | st.header("Tabs") 6 | 7 | with open("docs/components/tabs.md", "r") as f: 8 | st.markdown(f.read()) 9 | 10 | value = ui.tabs(options=['PyGWalker', 'Graphic Walker', 'GWalkR', 'RATH'], default_value='PyGWalker', key="kanaries") 11 | 12 | with ui.card(key="image"): 13 | if value == "PyGWalker": 14 | ui.element("img", src="https://pub-8e7aa5bf51e049199c78b4bc744533f8.r2.dev/pygwalker-banner.png", className="w-full") 15 | ui.element("link_button", text=value + " Github", url="https://github.com/Kanaries/pygwalker", className="mt-2", key="btn2") 16 | elif value == "Graphic Walker": 17 | ui.element("img", src="https://pub-8e7aa5bf51e049199c78b4bc744533f8.r2.dev/graphic-walker-banner.png", className="w-full") 18 | ui.element("link_button", text=value + " Github", url="https://github.com/Kanaries/graphic-walker", className="mt-2", key="btn2") 19 | elif value == "GWalkR": 20 | ui.element("img", src="https://pub-8e7aa5bf51e049199c78b4bc744533f8.r2.dev/gwalkr-banner.png", className="w-full") 21 | ui.element("link_button", text=value + " Github", url="https://github.com/Kanaries/gwalkr", className="mt-2", key="btn2") 22 | elif value == "RATH": 23 | ui.element("img", src="https://pub-8e7aa5bf51e049199c78b4bc744533f8.r2.dev/rath-painter.png", className="w-full") 24 | ui.element("link_button", text=value + " Github", url="https://github.com/Kanaries/Rath", className="mt-2", key="btn2") 25 | st.write("Selected:", value) 26 | 27 | st.write(ui.tabs) 28 | -------------------------------------------------------------------------------- /pages/TextArea.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import streamlit_shadcn_ui as ui 3 | 4 | st.header("Textarea Component") 5 | 6 | with open("docs/components/textarea.md", "r") as f: 7 | st.markdown(f.read()) 8 | 9 | # Textarea Component 10 | textarea_value = ui.textarea(default_value="Type your message here...", placeholder="Enter longer text", key="textarea1") 11 | st.write("Textarea Value:", textarea_value) 12 | 13 | st.write(ui.textarea) -------------------------------------------------------------------------------- /pages/Visualization.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import streamlit.components.v1 as components 3 | import streamlit as st 4 | from pygwalker.api.streamlit import StreamlitRenderer 5 | import streamlit_shadcn_ui as ui 6 | 7 | st.set_page_config( 8 | page_title="PyGWalker + Streamlit, the tableau open source alternative", 9 | layout="wide" 10 | ) 11 | 12 | st.header("Use Pygwalker to build visualization with drag-and-drop operations") 13 | ui.badges(badge_list=[("Dataframe", "default"), ("to", "secondary"), ("Interactive Data App", "destructive")], class_name="flex gap-2", key="viz_badges1") 14 | st.caption("This is build with Pygwalker and Streamlit. PyGWalker is a Python library turns your dataframe into a tableau-alternative") 15 | st.page_link("https://kanaries.net/pygwalker", label="learn more abuout pygwalker") 16 | ui.badges(badge_list=[("pip install pygwalker", "secondary")], class_name="flex gap-2", key="viz_badges2") 17 | 18 | cols = st.columns(3) 19 | 20 | with cols[0]: 21 | ui.metric_card(title="Github Stars", content="9,916", description="1k stars in 12 hours.", key="card1") 22 | with cols[1]: 23 | ui.metric_card(title="Total Install", content="500,000", description="Since launched in 2023/02", key="card2") 24 | with cols[2]: 25 | ui.metric_card(title="HackerNews upvotes", content="712", description="Rank No.1 story of the day", key="card3") 26 | 27 | 28 | 29 | with ui.element("div", className="flex gap-2", key="buttons_group1"): 30 | ui.element("link_button", varient="primary", url="https://kanaries.net/pygwalker", text="Get Started", key="btn1") 31 | ui.element("link_button", text="Github", url="https://github.com/Kanaries/pygwalker", variant="outline", key="btn2") 32 | 33 | @st.cache_data 34 | def get_df() -> pd.DataFrame: 35 | return pd.read_csv("https://kanaries-app.s3.ap-northeast-1.amazonaws.com/public-datasets/bike_sharing_dc.csv") 36 | 37 | df = get_df() 38 | pyg_app = StreamlitRenderer(df, kernel_computation=True) 39 | 40 | pyg_app.explorer() 41 | 42 | st.header("More resources about pygwalker") 43 | st.page_link("https://docs.kanaries.net/topics/Tableau/tableau-dark-theme", label="Use PyGWalker to build a customized tableau alternative - dark mode example") 44 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit 2 | pandas 3 | streamlit-shadcn-ui>=0.1.18 4 | streamlit_extras 5 | pygwalker>=0.4.8.3 --------------------------------------------------------------------------------