2026_MLB_Model / visualization /loading_shell.py
Syntrex's picture
Expand props with verdicts strikeouts and loader
6989587
raw
history blame
3.06 kB
from __future__ import annotations
from typing import Any
import streamlit as st
def render_loading_shell(title: str = "Project Kasper", message: str | None = None) -> dict[str, Any]:
message = message or "We apologize for the very long load times. Sometimes it can take multiple minutes."
shell = st.empty()
progress_slot = st.empty()
status_slot = st.empty()
shell.markdown(
f"""
<style>
.kasper-loader {{
border: 1px solid rgba(92, 122, 168, 0.28);
border-radius: 22px;
padding: 1.4rem 1.35rem;
background:
radial-gradient(circle at top right, rgba(56,132,255,0.16), transparent 30%),
radial-gradient(circle at bottom left, rgba(88,210,111,0.10), transparent 28%),
linear-gradient(180deg, rgba(14, 22, 36, 0.98), rgba(9, 15, 27, 0.98));
box-shadow: 0 12px 32px rgba(0,0,0,0.20);
margin: 0.4rem 0 1rem 0;
}}
.kasper-loader-kicker {{
letter-spacing: 0.18em;
text-transform: uppercase;
font-size: 0.72rem;
color: #78d99a;
font-weight: 700;
}}
.kasper-loader-title {{
font-size: 2rem;
line-height: 1.05;
font-weight: 800;
color: #f7fafc;
margin-top: 0.35rem;
}}
.kasper-loader-message {{
color: #9fb3c8;
font-size: 0.97rem;
margin-top: 0.45rem;
}}
.kasper-loader-bar {{
margin-top: 0.95rem;
width: 100%;
height: 10px;
border-radius: 999px;
overflow: hidden;
background: rgba(255,255,255,0.08);
position: relative;
}}
.kasper-loader-bar::before {{
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, #2f75ff 0%, #6fd2ff 45%, #78d99a 100%);
transform: translateX(-55%);
animation: kasperSlide 1.4s ease-in-out infinite;
}}
@keyframes kasperSlide {{
0% {{ transform: translateX(-55%); }}
100% {{ transform: translateX(100%); }}
}}
</style>
<div class="kasper-loader">
<div class="kasper-loader-kicker">Loading</div>
<div class="kasper-loader-title">{title}</div>
<div class="kasper-loader-message">{message}</div>
<div class="kasper-loader-bar"></div>
</div>
""",
unsafe_allow_html=True,
)
progress = progress_slot.progress(0)
status = status_slot.caption("Preparing page...")
def update(step_text: str, pct: float) -> None:
progress.progress(int(max(0, min(100, round(pct * 100)))))
status_slot.caption(step_text)
def clear() -> None:
shell.empty()
progress_slot.empty()
status_slot.empty()
return {"update": update, "clear": clear, "progress": progress, "status": status}