Spaces:
Running
Running
Space: drop the Gradio tab bar, navigate solely via sidebar (fixes mobile nav)
Browse filesGradio's tab bar is width-responsive and removes overflowing tab buttons from the
DOM on narrow screens, so the sidebar (which clicks those buttons) couldn't reach
'Barracks' on mobile. Hide the tab bar off-screen at a fixed wide width so every
tab button stays present and clickable on any viewport. Mark the first nav item
active by default so the sidebar reads as the sole navigation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
app.py
CHANGED
|
@@ -33,7 +33,15 @@ ANIMS = ["idle", "walk", "attack", "dmg", "die"]
|
|
| 33 |
# blocks as mixed content — so the theme font never loads. This CSP upgrades such
|
| 34 |
# same-host http subresources to https in the browser, fixing it deterministically
|
| 35 |
# regardless of proxy headers.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
HEAD = ('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">'
|
|
|
|
| 37 |
'<link rel="stylesheet" href="/web/shell/sidebar.css">'
|
| 38 |
'<script type="module" src="/web/tiny.js"></script>'
|
| 39 |
'<script src="/web/shell/sidebar.js"></script>')
|
|
@@ -50,12 +58,15 @@ def build_sidebar(nav):
|
|
| 50 |
f'<div class="tac-brand"><span class="tac-brand-icon">{b.get("icon","")}</span>'
|
| 51 |
f'<span>{b.get("title","")}</span>'
|
| 52 |
f'<button class="tac-collapse tac-toggle" title="Collapse">‹</button></div>']
|
|
|
|
| 53 |
for sec in nav.get("sections", []):
|
| 54 |
out.append('<div class="tac-section">')
|
| 55 |
if sec.get("title"):
|
| 56 |
out.append(f'<div class="tac-section-title">{sec["title"]}</div>')
|
| 57 |
for it in sec.get("items", []):
|
| 58 |
-
|
|
|
|
|
|
|
| 59 |
f'<span class="tac-ico">{it.get("icon","")}</span><span>{it["label"]}</span></a>')
|
| 60 |
out.append('</div>')
|
| 61 |
out.append('</aside>')
|
|
|
|
| 33 |
# blocks as mixed content — so the theme font never loads. This CSP upgrades such
|
| 34 |
# same-host http subresources to https in the browser, fixing it deterministically
|
| 35 |
# regardless of proxy headers.
|
| 36 |
+
# Hide Gradio's tab bar — the sidebar is the sole navigation. Keep it off-screen
|
| 37 |
+
# at a fixed wide width (NOT display:none): Gradio's tab bar is width-responsive
|
| 38 |
+
# and DROPS overflowing tabs from the DOM on narrow screens, which would leave the
|
| 39 |
+
# sidebar unable to find/click them (mobile nav breaks). Off-screen-but-wide keeps
|
| 40 |
+
# every tab button present so the sidebar can drive navigation on any viewport.
|
| 41 |
+
HIDE_TABS = ('<style>.tab-container[role="tablist"]{position:absolute!important;'
|
| 42 |
+
'left:-99999px!important;top:0!important;width:1400px!important;}</style>')
|
| 43 |
HEAD = ('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">'
|
| 44 |
+
+ HIDE_TABS +
|
| 45 |
'<link rel="stylesheet" href="/web/shell/sidebar.css">'
|
| 46 |
'<script type="module" src="/web/tiny.js"></script>'
|
| 47 |
'<script src="/web/shell/sidebar.js"></script>')
|
|
|
|
| 58 |
f'<div class="tac-brand"><span class="tac-brand-icon">{b.get("icon","")}</span>'
|
| 59 |
f'<span>{b.get("title","")}</span>'
|
| 60 |
f'<button class="tac-collapse tac-toggle" title="Collapse">‹</button></div>']
|
| 61 |
+
first = True # mark the default page active (matches Gradio's first/open tab)
|
| 62 |
for sec in nav.get("sections", []):
|
| 63 |
out.append('<div class="tac-section">')
|
| 64 |
if sec.get("title"):
|
| 65 |
out.append(f'<div class="tac-section-title">{sec["title"]}</div>')
|
| 66 |
for it in sec.get("items", []):
|
| 67 |
+
cls = "tac-nav-item active" if first else "tac-nav-item"
|
| 68 |
+
first = False
|
| 69 |
+
out.append(f'<a class="{cls}" data-target="{it["target"]}" href="#">'
|
| 70 |
f'<span class="tac-ico">{it.get("icon","")}</span><span>{it["label"]}</span></a>')
|
| 71 |
out.append('</div>')
|
| 72 |
out.append('</aside>')
|