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)