Spaces:
Running
Running
File size: 5,876 Bytes
59aaeae |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
import streamlit as st
from pathlib import Path
import os
# Load custom CSS
def load_css():
css_file = Path(__file__).parent / "custom.css"
if css_file.exists():
with open(css_file) as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
else:
st.warning("Custom CSS file not found. Some styles may be missing.")
# Header component
def header():
st.markdown("""
<div class="main-header">
<h1 class="title-text">Historical OCR Workshop</h1>
</div>
""", unsafe_allow_html=True)
# Create a page wrapper similar to the React component
def page_wrapper(content_function, current_module=1):
"""
Creates a consistent page layout with navigation
Args:
content_function: Function that renders the page content
current_module: Current module number (1-6)
"""
# Load custom CSS
load_css()
# Display header
header()
# Ensure session state for navigation
if 'current_module' not in st.session_state:
st.session_state.current_module = current_module
# Main content area with bottom padding for the nav
st.markdown('<div class="main-content">', unsafe_allow_html=True)
# Call the content function to render the module content
content_function()
# Add spacer for fixed nav
st.markdown('<div class="footer-spacer"></div>', unsafe_allow_html=True)
# Navigation
render_navigation(current_module)
st.markdown('</div>', unsafe_allow_html=True)
# Navigation component
def render_navigation(current_module):
# Define modules names like in React
modules = ['Introduction', 'Historical Context', 'Methodology', 'Case Studies', 'Interactive OCR', 'Conclusion']
# Navigation container
st.markdown(f"""
<div class="nav-container">
<div class="nav-buttons">
{prev_button_html(current_module, modules)}
{next_button_html(current_module, modules)}
</div>
<div class="nav-dots">
{nav_dots_html(current_module, modules)}
</div>
</div>
""", unsafe_allow_html=True)
# Previous button HTML
def prev_button_html(current_module, modules):
if current_module > 1:
prev_module = current_module - 1
return f"""
<button class="prev-button"
onclick="document.getElementById('nav_prev_{prev_module}').click()"
aria-label="Go to previous module: {modules[prev_module-1]}">
β Previous
</button>
"""
return ""
# Next button HTML
def next_button_html(current_module, modules):
if current_module < len(modules):
next_module = current_module + 1
return f"""
<button class="next-button"
onclick="document.getElementById('nav_next_{next_module}').click()"
aria-label="Go to next module: {modules[next_module-1]}">
Next β
</button>
"""
return ""
# Navigation dots HTML
def nav_dots_html(current_module, modules):
dots_html = ""
for i, name in enumerate(modules, 1):
active_class = "active" if i == current_module else ""
dots_html += f"""
<a class="nav-dot {active_class}"
onclick="document.getElementById('nav_dot_{i}').click()"
aria-current="{i == current_module}"
aria-label="Go to module {i}: {name}">
{i}
</a>
"""
return dots_html
# Helper functions for container styles
def gray_container(content, padding="1.5rem"):
"""Renders content in a gray container with consistent styling"""
st.markdown(f'<div class="content-container" style="padding:{padding};">{content}</div>', unsafe_allow_html=True)
def blue_container(content, padding="1.5rem"):
"""Renders content in a blue container with consistent styling"""
st.markdown(f'<div class="blue-container" style="padding:{padding};">{content}</div>', unsafe_allow_html=True)
def yellow_container(content, padding="1.5rem"):
"""Renders content in a yellow container with consistent styling"""
st.markdown(f'<div class="yellow-container" style="padding:{padding};">{content}</div>', unsafe_allow_html=True)
def card_grid(cards):
"""
Renders a responsive grid of cards
Args:
cards: List of HTML strings for each card
"""
grid_html = '<div class="card-grid">'
for card in cards:
grid_html += f'<div class="card">{card}</div>'
grid_html += '</div>'
st.markdown(grid_html, unsafe_allow_html=True)
def module_card(number, title, description):
"""Creates a styled module card"""
return f"""
<div class="module-card">
<div class="module-number">Module {number}</div>
<div class="module-title">{title}</div>
<p>{description}</p>
</div>
"""
def key_concept(content):
"""Renders a key concept box"""
st.markdown(f'<div class="key-concept">{content}</div>', unsafe_allow_html=True)
def research_question(content):
"""Renders a research question box"""
st.markdown(f'<div class="research-question">{content}</div>', unsafe_allow_html=True)
def quote(content, author=""):
"""Renders a quote with optional author"""
quote_html = f'<div class="quote-container">{content}'
if author:
quote_html += f'<br/><br/><span style="font-size:0.9rem; text-align:right; display:block;">β {author}</span>'
quote_html += '</div>'
st.markdown(quote_html, unsafe_allow_html=True)
def tool_container(content):
"""Renders content in a tool container"""
st.markdown(f'<div class="tool-container">{content}</div>', unsafe_allow_html=True)
def upload_container(content):
"""Renders content in an upload container"""
st.markdown(f'<div class="upload-container">{content}</div>', unsafe_allow_html=True) |