Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from typing import List, Dict, Tuple, Optional, Any | |
| import traceback | |
| class StreamlitTutorial: | |
| """ | |
| Main class for the Streamlit Tutorial application. | |
| Handles rendering of all tutorial content, user interaction, and state management. | |
| Provides modular components for different tutorial topics and interactive examples. | |
| """ | |
| def __init__(self): | |
| """ | |
| Initializes the Streamlit Tutorial application. | |
| Sets up page configuration, session state, and custom styling. | |
| Prepares the application environment for tutorial content. | |
| """ | |
| st.set_page_config(page_title="Learn Streamlit", layout="wide") | |
| self.init_session_state() | |
| self.setup_styles() | |
| def init_session_state(self) -> None: | |
| """ | |
| Initializes session state variables for persistent data storage. | |
| Creates state variables for code input and current topic tracking. | |
| Ensures consistent state across reruns. | |
| Returns: | |
| None | |
| """ | |
| if 'code_input' not in st.session_state: | |
| st.session_state.code_input = "" | |
| st.session_state.current_topic = "Basic Text Elements" | |
| def setup_styles(self) -> None: | |
| """ | |
| Configures custom CSS styles for the application. | |
| Sets up consistent styling for code examples, outputs, and layout. | |
| Enhances visual presentation of tutorial content. | |
| Returns: | |
| None | |
| """ | |
| st.markdown(""" | |
| <style> | |
| .code-example { margin-bottom: 1.5rem; } | |
| .live-output { | |
| border: 1px solid #ddd; | |
| border-radius: 4px; | |
| padding: 1rem; | |
| margin: 0.5rem 0 1.5rem 0; | |
| } | |
| .section-title { | |
| margin-bottom: 1rem; | |
| padding: 0.5rem 0; | |
| } | |
| .button-container { | |
| display: flex; | |
| justify-content: space-between; | |
| gap: 1rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Add these helper methods in the StreamlitTutorial class | |
| def _get_basic_concepts_content(self) -> str: | |
| """ | |
| Provides content for Basic Concepts section. | |
| Contains fundamental explanations and examples. | |
| Returns: | |
| str: Markdown formatted basic concepts content | |
| """ | |
| return """ | |
| **What are Text Elements?** | |
| - Basic building blocks for displaying text | |
| - Range from titles to formatted text | |
| - Support markdown formatting | |
| **Key Components:** | |
| 1. Title & Headers | |
| 2. Regular text | |
| 3. Formatted text | |
| 4. Colored text | |
| """ | |
| def _get_best_practices_content(self) -> str: | |
| """ | |
| Provides content for Best Practices section. | |
| Contains guidelines and recommended approaches. | |
| Returns: | |
| str: Markdown formatted best practices content | |
| """ | |
| return """ | |
| **Writing Tips:** | |
| 1. Use appropriate heading levels | |
| 2. Keep text concise and clear | |
| 3. Use formatting for emphasis | |
| 4. Add visual hierarchy with headers | |
| **Code Structure:** | |
| ```python | |
| st.title('Main Title') | |
| st.header('Section Header') | |
| st.subheader('Sub-section') | |
| st.write('Regular text') | |
| ``` | |
| """ | |
| def _get_examples_content(self) -> str: | |
| """ | |
| Provides content for Examples section. | |
| Contains practical examples and use cases. | |
| Returns: | |
| str: Markdown formatted examples content | |
| """ | |
| return """ | |
| **Common Patterns:** | |
| 1. Page Structure | |
| ```python | |
| st.title('Dashboard') | |
| st.header('Sales Data') | |
| st.subheader('Monthly Trends') | |
| ``` | |
| 2. Formatted Text | |
| ```python | |
| st.markdown('**Bold** and *italic*') | |
| st.markdown(':blue[Colored text]') | |
| ``` | |
| 3. Mixed Elements | |
| ```python | |
| st.title('Report') | |
| st.write('Regular text') | |
| st.markdown('- Bullet point') | |
| ``` | |
| """ | |
| def _get_common_mistakes_content(self) -> str: | |
| """ | |
| Provides content for Common Mistakes section. | |
| Contains typical errors and how to avoid them. | |
| Returns: | |
| str: Markdown formatted common mistakes content | |
| """ | |
| return """ | |
| 1. Skipping header levels | |
| 2. Overusing formatting | |
| 3. Inconsistent styling | |
| 4. Missing hierarchy | |
| **How to Avoid:** | |
| - Plan your page structure | |
| - Use consistent formatting | |
| - Test different screen sizes | |
| - Keep it simple | |
| """ | |
| def _get_widgets_help_content(self) -> str: | |
| """ | |
| Enhanced help content for widgets section | |
| """ | |
| return """ | |
| **Widget Best Practices:** | |
| 1. Input Validation | |
| ```python | |
| # Add validation to inputs | |
| age = st.number_input('Age', min_value=0, max_value=150, key='age_1') | |
| if age < 18: | |
| st.warning('Must be 18 or older') | |
| ``` | |
| 2. Default Values | |
| ```python | |
| # Provide sensible defaults | |
| st.text_input('Name', value='Guest User', key='name_2') | |
| st.slider('Rating', 1, 5, value=3, key='rating_1') | |
| ``` | |
| 3. Responsive Widgets | |
| ```python | |
| # React to widget changes | |
| if st.checkbox('Show advanced options', key='advanced_1'): | |
| st.number_input('Threshold', key='threshold_1') | |
| st.slider('Sensitivity', key='sensitivity_1') | |
| ``` | |
| 4. Form Submission | |
| ```python | |
| with st.form('my_form'): | |
| st.text_input('Username', key='form_user') | |
| st.text_input('Password', type='password', key='form_pass') | |
| submitted = st.form_submit_button('Login') | |
| ``` | |
| 5. File Handling | |
| ```python | |
| file = st.file_uploader('Upload CSV', key='file_2') | |
| if file is not None: | |
| # Handle file upload | |
| st.success('File uploaded!') | |
| ``` | |
| 6. Interactive Filters | |
| ```python | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| category = st.selectbox('Category', ['A', 'B', 'C'], key='cat_1') | |
| with col2: | |
| subcategory = st.multiselect('Subcategory', ['X', 'Y', 'Z'], key='subcat_1') | |
| ``` | |
| **Tips for Widget Usage:** | |
| - Use clear, concise labels | |
| - Group related widgets together | |
| - Provide help text when needed | |
| - Use appropriate widget types | |
| - Handle all possible states | |
| - Validate inputs properly | |
| - Always use unique keys | |
| - Consider mobile responsiveness | |
| """ | |
| def _get_advanced_tips_content(self) -> str: | |
| """ | |
| Provides content for Advanced Tips section. | |
| Contains advanced usage and techniques. | |
| Returns: | |
| str: Markdown formatted advanced tips content | |
| """ | |
| return """ | |
| **Advanced Formatting:** | |
| ```python | |
| # Custom HTML | |
| st.markdown(''' | |
| <span style='color:blue'> | |
| Custom styled text | |
| </span> | |
| ''', unsafe_allow_html=True) | |
| # Complex Markdown | |
| st.markdown(''' | |
| # Title | |
| ## Subtitle | |
| * Point 1 | |
| * Subpoint | |
| > Quote | |
| ''') | |
| ``` | |
| **Layout Combinations:** | |
| ```python | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.header('Column 1') | |
| with col2: | |
| st.header('Column 2') | |
| ``` | |
| """ | |
| def get_text_elements(self) -> List[Tuple[str, str]]: | |
| """ | |
| Provides collection of text element examples with corresponding code. | |
| Defines basic text manipulation and display examples. | |
| Used for generating code examples and quick snippets. | |
| Returns: | |
| List[Tuple[str, str]]: List of (element name, code snippet) pairs | |
| """ | |
| return [ | |
| ("Title", "st.title('Main Title')"), | |
| ("Header", "st.header('Header')"), | |
| ("Subheader", "st.subheader('Subheader')"), | |
| ("Normal text", "st.write('Normal text')"), | |
| ("Markdown text", "st.markdown('**Bold** and *italic*')"), | |
| ("Colored text", "st.markdown(':blue[Blue text]')") | |
| ] | |
| def render_text_elements(self, col: st.delta_generator.DeltaGenerator) -> None: | |
| """ | |
| Renders text element examples in the specified column. | |
| Displays code snippets with live output for each text element. | |
| Creates interactive learning environment for text elements. | |
| Arguments: | |
| col: Streamlit column object for content rendering | |
| Returns: | |
| None | |
| """ | |
| with col: | |
| st.markdown("### π Code Examples") | |
| for title, code in self.get_text_elements(): | |
| with st.container(border=True): | |
| st.markdown(f"**{title}**") | |
| st.code(code) | |
| st.markdown("Live output:") | |
| with st.container(border=True): | |
| exec(code) | |
| def get_input_elements(self) -> List[Tuple[str, str]]: | |
| """ | |
| Cross-validated collection of input widgets with unique keys | |
| """ | |
| return [ | |
| ("Text Input", """st.text_input('Enter your name', | |
| key='text_input_demo_1', | |
| placeholder='John Doe')"""), | |
| ("Text Area", """st.text_area('Enter long text', | |
| key='text_area_demo_1', | |
| height=100, | |
| placeholder='Write something...')"""), | |
| ("Number Input", """st.number_input('Enter a number', | |
| key='number_input_demo_1', | |
| min_value=0, | |
| max_value=100, | |
| value=50, | |
| step=5)"""), | |
| ("Slider", """st.slider('Select value', | |
| key='slider_demo_1', | |
| min_value=0, | |
| max_value=100, | |
| value=50, | |
| step=5)"""), | |
| ("Select Box", """st.selectbox('Choose an option', | |
| key='select_box_demo_1', | |
| options=['Option 1', 'Option 2', 'Option 3'], | |
| index=0)""") | |
| ] | |
| def render_input_elements(self, col: st.delta_generator.DeltaGenerator) -> None: | |
| """ | |
| Renders input examples with unique keys for both examples and live output | |
| """ | |
| with col: | |
| st.markdown("### π Code Examples") | |
| for idx, (title, code) in enumerate(self.get_input_elements()): | |
| with st.container(border=True, key=f"demo_container_{idx}"): | |
| st.markdown(f"**{title}**") | |
| st.code(code) | |
| st.markdown("Live output:") | |
| with st.container(border=True, key=f"output_container_{idx}"): | |
| try: | |
| # Create runtime version with unique key | |
| runtime_code = code.replace('demo_1', f'runtime_{idx}') | |
| exec(runtime_code) | |
| except Exception as e: | |
| st.error(f"Error: {str(e)}") | |
| def render_help_section(self, col: st.delta_generator.DeltaGenerator) -> None: | |
| """ | |
| Renders comprehensive help content in the specified column. | |
| Provides educational content, best practices, and examples. | |
| Creates expandable sections for different learning topics. | |
| Arguments: | |
| col: Streamlit column object for content rendering | |
| Returns: | |
| None | |
| """ | |
| with col: | |
| st.markdown("### π Learning Guide") | |
| # Basic Concepts Section | |
| with st.expander("π― Basic Concepts", expanded=True): | |
| st.markdown(self._get_basic_concepts_content()) | |
| # Best Practices Section | |
| with st.expander("π‘ Best Practices"): | |
| st.markdown(self._get_best_practices_content()) | |
| # Examples Section | |
| with st.expander("π Examples & Use Cases"): | |
| st.markdown(self._get_examples_content()) | |
| # Common Mistakes Section | |
| with st.expander("β οΈ Common Mistakes"): | |
| st.markdown(self._get_common_mistakes_content()) | |
| # Advanced Tips Section | |
| with st.expander("π Advanced Tips"): | |
| st.markdown(self._get_advanced_tips_content()) | |
| def render_playground(self, col: st.delta_generator.DeltaGenerator, snippets: Dict[str, str]) -> None: | |
| """ | |
| Renders interactive coding playground with live execution. | |
| Arguments: | |
| col: Streamlit column object for rendering | |
| snippets: Dictionary of available code snippets | |
| """ | |
| with col: | |
| st.markdown("### π» Practice Playground") | |
| # Code input area | |
| code_input = st.text_area( | |
| "Try Streamlit commands:", | |
| key="playground_input", | |
| value=st.session_state.get('code_input', ''), | |
| height=200, | |
| placeholder="Example:\nst.title('My Title')" | |
| ) | |
| # Quick Snippets section | |
| st.markdown("#### Quick Snippets") | |
| # Split into two columns with better ratio for button alignment | |
| snippet_col, button_col = st.columns([4, 1]) | |
| with snippet_col: | |
| selected_snippet = st.selectbox( | |
| "Choose snippet:", | |
| list(snippets.keys()), | |
| label_visibility="collapsed" | |
| ) | |
| with button_col: | |
| if st.button("Add", type="primary", use_container_width=True): | |
| if 'code_input' not in st.session_state: | |
| st.session_state.code_input = snippets[selected_snippet] | |
| else: | |
| # Add new line only if there's existing code | |
| existing_code = st.session_state.code_input.strip() | |
| new_code = snippets[selected_snippet] | |
| st.session_state.code_input = f"{existing_code}\n{new_code}" if existing_code else new_code | |
| st.rerun() | |
| # Control buttons in equal columns | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| if st.button("βΆοΈ Run", use_container_width=True): | |
| try: | |
| if code_input.strip(): | |
| exec(code_input) | |
| except Exception as e: | |
| st.error(f"Error: {str(e)}") | |
| with col2: | |
| if st.button("π Reset", use_container_width=True): | |
| st.session_state.code_input = "" | |
| st.rerun() | |
| with col3: | |
| if st.button("πΎ Copy", use_container_width=True): | |
| st.code(code_input) | |
| # Live output section | |
| st.markdown("#### π¨ Live Output") | |
| with st.container(border=True): | |
| if code_input.strip(): | |
| try: | |
| exec(code_input) | |
| except Exception as e: | |
| st.error(f"Error: {str(e)}") | |
| # Tips section | |
| with st.expander("π‘ Tips & Help"): | |
| st.markdown(""" | |
| **Quick Tips:** | |
| - Type or paste Streamlit commands | |
| - Use snippets for quick start | |
| - Click Run to see results | |
| - Reset to clear all code | |
| """) | |
| def render_widget_help(self, col: st.delta_generator.DeltaGenerator) -> None: | |
| """ | |
| Renders comprehensive widget help content | |
| """ | |
| with col: | |
| st.markdown("### π Widget Guide") | |
| with st.expander("π― Basic Concepts", expanded=True): | |
| st.markdown(""" | |
| **Widget Types:** | |
| - Input widgets (text, numbers, dates) | |
| - Selection widgets (dropdown, checkbox, radio) | |
| - File widgets (uploaders, downloads) | |
| - Display widgets (progress, status) | |
| **Key Features:** | |
| - Real-time updates | |
| - State management | |
| - Input validation | |
| - Responsive layout | |
| - Form handling | |
| - Unique widget keys | |
| """) | |
| with st.expander("π‘ Best Practices"): | |
| st.markdown(self._get_widgets_help_content()) | |
| with st.expander("π Examples"): | |
| st.code(""" | |
| # Basic form example | |
| with st.form('contact'): | |
| name = st.text_input('Name', key='contact_name') | |
| email = st.text_input('Email', key='contact_email') | |
| message = st.text_area('Message', key='contact_message') | |
| submit = st.form_submit_button('Send') | |
| if submit: | |
| st.success('Message sent!') | |
| """) | |
| def get_topic_tips(self, topic: str) -> str: | |
| """ | |
| Provides topic-specific tips and guidance. | |
| Returns formatted markdown string with helpful information. | |
| Customizes content based on current tutorial topic. | |
| Arguments: | |
| topic: Current tutorial topic name | |
| Returns: | |
| str: Markdown formatted tips and help content | |
| """ | |
| tips = { | |
| "Basic Text Elements": """ | |
| **Quick Tips:** | |
| - Use markdown for formatting | |
| - Try different header levels | |
| - Combine text elements | |
| - Use colored text with :color[text] | |
| """, | |
| "Input Widgets": """ | |
| **Quick Tips:** | |
| - Use unique keys for widgets | |
| - Store widget values in variables | |
| - Add validation for inputs | |
| - Combine widgets for complex inputs | |
| """ | |
| } | |
| return tips.get(topic, "Tips coming soon!") | |
| def run(self) -> None: | |
| """ | |
| Main execution method for the Streamlit Tutorial application. | |
| Handles topic selection and content rendering. | |
| Manages overall application flow and state. | |
| """ | |
| with st.sidebar: | |
| st.title("Streamlit Tutorial") | |
| st.session_state.current_topic = st.radio( | |
| "Choose a Topic:", | |
| ["Basic Text Elements", "Input Widgets", "Layouts & Containers", | |
| "Data Display", "Charts & Plots", "Interactive Components"] | |
| ) | |
| if st.session_state.current_topic == "Basic Text Elements": | |
| cols = st.columns([1.2, 1, 1]) | |
| self.render_text_elements(cols[0]) | |
| self.render_help_section(cols[1]) | |
| self.render_playground(cols[2], dict(self.get_text_elements())) | |
| elif st.session_state.current_topic == "Input Widgets": | |
| cols = st.columns([1.2, 1, 1]) | |
| self.render_input_elements(cols[0]) | |
| self.render_help_section(cols[1]) | |
| self.render_playground(cols[2], dict(self.get_input_elements())) | |
| def main(): | |
| try: | |
| app = StreamlitTutorial() | |
| app.run() | |
| except Exception as e: | |
| st.error(f"Application Error: {str(e)}") | |
| st.write(f"Traceback: {traceback.format_exc()}") | |
| if __name__ == "__main__": | |
| main() | |