polats commited on
Commit
0d345ef
·
1 Parent(s): 48bdfa8

Space: brand title in Fraunces w/ red dot + 'small minds, big dreams' subtitle; CHARACTERS title small+red; stage fixed-fills full height like main sidebar

Browse files
Files changed (4) hide show
  1. app.py +19 -9
  2. web/shell/nav.json +1 -1
  3. web/shell/sidebar.css +18 -17
  4. web/shell/spriteScene.css +5 -2
app.py CHANGED
@@ -43,7 +43,7 @@ HIDE_TABS = ('<style>.tab-container[role="tablist"]{position:absolute!important;
43
  FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">'
44
  '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>'
45
  '<link rel="stylesheet" href="https://fonts.googleapis.com/css2?'
46
- 'family=JetBrains+Mono:wght@400;500;700&'
47
  'family=Space+Grotesk:wght@400;500;600;700&display=swap">')
48
  # Parchment theme, applied THEME-INDEPENDENTLY: we override Gradio's own colour +
49
  # font CSS variables with `!important`, so the app renders identically whether the
@@ -69,13 +69,17 @@ THEME = ('<style>'
69
  f'body,gradio-app,.gradio-container,.gradio-container.dark,.dark{{{PALETTE_IMP}}}'
70
  "body,gradio-app,.gradio-container{background:#f3ebdc !important;color:#141821 !important;"
71
  "font-family:'Space Grotesk',-apple-system,sans-serif !important;}"
72
- # Sprite tab fills the content area (like the app): trim Gradio's tab
73
- # padding and let the playground use the full page height. The picker keeps
74
- # its own border-right (a sidebar the same width as the main one); the
75
- # canvas fills the rest no extra frame.
 
76
  '.gradio-container .tabitem{padding:0 !important;}'
77
  '.gradio-container .tabs{border:0 !important;}'
78
- '#sprite-stage{height:calc(100vh - 52px) !important;}'
 
 
 
79
  '</style>')
80
  HEAD = ('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">'
81
  + HIDE_TABS + FONTS + THEME +
@@ -96,10 +100,16 @@ def build_sidebar(nav):
96
  # sidebar.js against the tab buttons). React-only sandbox items (href but no
97
  # `space`) and sections with no space-items are skipped.
98
  b = nav.get("brand", {})
 
 
99
  out = ['<aside class="tac-sidebar">',
100
- f'<div class="tac-brand"><span class="tac-brand-icon">{b.get("icon","")}</span>'
101
- f'<span>{b.get("title","")}</span>'
102
- f'<button class="tac-collapse tac-toggle" title="Collapse">‹</button></div>']
 
 
 
 
103
  first = True # mark the default page active (matches Gradio's first/open tab)
104
  for sec in nav.get("sections", []):
105
  items = [it for it in sec.get("items", []) if it.get("space")]
 
43
  FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">'
44
  '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>'
45
  '<link rel="stylesheet" href="https://fonts.googleapis.com/css2?'
46
+ 'family=Fraunces:opsz,wght@9..144,400..900&family=JetBrains+Mono:wght@400;500;700&'
47
  'family=Space+Grotesk:wght@400;500;600;700&display=swap">')
48
  # Parchment theme, applied THEME-INDEPENDENTLY: we override Gradio's own colour +
49
  # font CSS variables with `!important`, so the app renders identically whether the
 
69
  f'body,gradio-app,.gradio-container,.gradio-container.dark,.dark{{{PALETTE_IMP}}}'
70
  "body,gradio-app,.gradio-container{background:#f3ebdc !important;color:#141821 !important;"
71
  "font-family:'Space Grotesk',-apple-system,sans-serif !important;}"
72
+ # Sprite tab fills the WHOLE content area, like the main sidebar. The
73
+ # picker lives in Gradio's flow (pushed ~110px down, bounded by the tab
74
+ # box) so it can't reach full height there so we lift the stage out of
75
+ # flow with position:fixed to span top→bottom, right of the main sidebar.
76
+ # Gradio still hides it (display:none on the inactive tab's ancestor).
77
  '.gradio-container .tabitem{padding:0 !important;}'
78
  '.gradio-container .tabs{border:0 !important;}'
79
+ '#sprite-stage{position:fixed !important;top:0;bottom:0;right:0;'
80
+ 'left:var(--tac-w,240px);height:auto !important;z-index:1;}'
81
+ 'body.tac-collapsed #sprite-stage{left:0;}'
82
+ '@media (max-width:768px){#sprite-stage{left:0;}}'
83
  '</style>')
84
  HEAD = ('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">'
85
  + HIDE_TABS + FONTS + THEME +
 
100
  # sidebar.js against the tab buttons). React-only sandbox items (href but no
101
  # `space`) and sections with no space-items are skipped.
102
  b = nav.get("brand", {})
103
+ # Brand block mirrors the app's .sidebar-title: a big display-font title with a
104
+ # red dot, plus a small uppercase subtitle.
105
  out = ['<aside class="tac-sidebar">',
106
+ '<div class="tac-brand">'
107
+ '<div class="tac-brand-row">'
108
+ f'<strong class="tac-title">{b.get("title","")}</strong>'
109
+ '<button class="tac-collapse tac-toggle" title="Collapse">‹</button>'
110
+ '</div>'
111
+ f'<p class="tac-subtitle">{b.get("subtitle","")}</p>'
112
+ '</div>']
113
  first = True # mark the default page active (matches Gradio's first/open tab)
114
  for sec in nav.get("sections", []):
115
  items = [it for it in sec.get("items", []) if it.get("space")]
web/shell/nav.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "_doc": "Shared navigation IR — ONE source for both the React app (src/layout/Sidebar.jsx) and the Gradio Space (tiny-army app.py build_sidebar). Each item carries routing for both hosts: `href` + `view`/`page` drive React's hash router and active state; `space` is the Gradio tab label the item navigates to. React renders items with an `href`; the Space renders items with a `space`. `brand` is used by the Space only (React uses config.name).",
3
- "brand": { "title": "Tiny Army", "icon": "⚔️" },
4
  "sections": [
5
  {
6
  "title": "World",
 
1
  {
2
  "_doc": "Shared navigation IR — ONE source for both the React app (src/layout/Sidebar.jsx) and the Gradio Space (tiny-army app.py build_sidebar). Each item carries routing for both hosts: `href` + `view`/`page` drive React's hash router and active state; `space` is the Gradio tab label the item navigates to. React renders items with an `href`; the Space renders items with a `space`. `brand` is used by the Space only (React uses config.name).",
3
+ "brand": { "title": "Tiny Army", "icon": "⚔️", "subtitle": "small minds, big dreams" },
4
  "sections": [
5
  {
6
  "title": "World",
web/shell/sidebar.css CHANGED
@@ -39,26 +39,27 @@ body.tac-collapsed .tac-sidebar { transform: translateX(-100%); }
39
  .gradio-container { transition: margin-left .22s ease; }
40
  body:not(.tac-collapsed) .gradio-container { margin-left: var(--tac-w); }
41
 
42
- .tac-brand {
43
- display: flex; align-items: center; gap: 8px;
44
- padding: 14px 14px 12px; font-weight: 700; font-size: 16px; letter-spacing: .01em;
45
- color: var(--tac-ink); border-bottom: 2px solid var(--tac-border);
 
 
 
46
  }
47
- .tac-brand .tac-brand-icon { font-size: 18px; }
48
- /* The collapse/reopen controls are <button>s; a host button theme (Gradio's
49
- * `.gradio-container button` reset) strips their padding/background. We define a
50
- * self-contained icon-button look and defend the visual props with `!important`
51
- * so it renders identically with or without the host theme. */
52
- .tac-sidebar .tac-brand .tac-collapse {
53
- margin-left: auto; cursor: pointer; line-height: 1; font-size: 16px;
54
- display: inline-flex !important; align-items: center; justify-content: center;
55
- width: 28px; height: 28px; padding: 0 !important;
56
- background: var(--tac-bg-2) !important; color: var(--tac-muted) !important;
57
- border: 1.5px solid var(--tac-border) !important; border-radius: 6px !important;
58
  }
59
- .tac-sidebar .tac-brand .tac-collapse:hover {
60
- background: var(--tac-ink) !important; color: var(--tac-paper) !important;
 
 
 
 
61
  }
 
62
 
63
  .tac-section { padding: 12px 8px 0; }
64
  /* Section headers: red (transmit) with a short ink line prefix, like the app's
 
39
  .gradio-container { transition: margin-left .22s ease; }
40
  body:not(.tac-collapsed) .gradio-container { margin-left: var(--tac-w); }
41
 
42
+ /* Brand block mirrors the app's `.sidebar-title`: a big display-font title with a
43
+ * red dot, plus a small uppercase subtitle. */
44
+ .tac-brand { padding: 16px 14px 12px; border-bottom: 2px solid var(--tac-border); }
45
+ .tac-brand-row { display: flex; align-items: flex-start; justify-content: space-between; }
46
+ .tac-sidebar .tac-title {
47
+ display: block; font-family: 'Fraunces', Georgia, serif; font-weight: 900;
48
+ font-size: 28px; line-height: .92; letter-spacing: -.03em; color: var(--tac-ink) !important;
49
  }
50
+ .tac-sidebar .tac-title::after { content: "·"; color: var(--tac-accent); }
51
+ .tac-subtitle {
52
+ margin: 8px 0 0 !important; font-family: var(--tac-mono); font-size: 9px;
53
+ color: var(--tac-muted) !important; letter-spacing: .14em; text-transform: uppercase; line-height: 1.5;
 
 
 
 
 
 
 
54
  }
55
+ /* Plain ‹ collapse control (like the app's .sidebar-collapse); defend against the
56
+ * host button reset so it stays a borderless glyph. */
57
+ .tac-sidebar .tac-brand .tac-collapse {
58
+ cursor: pointer; line-height: 1; font-size: 18px; margin-left: 8px; flex-shrink: 0;
59
+ background: none !important; color: var(--tac-muted) !important;
60
+ border: 0 !important; padding: 0 !important; box-shadow: none !important;
61
  }
62
+ .tac-sidebar .tac-brand .tac-collapse:hover { color: var(--tac-ink) !important; }
63
 
64
  .tac-section { padding: 12px 8px 0; }
65
  /* Section headers: red (transmit) with a short ink line prefix, like the app's
web/shell/spriteScene.css CHANGED
@@ -26,9 +26,12 @@
26
  width: 240px; flex-shrink: 0; border-right: 2px solid var(--mv-ink);
27
  background: var(--mv-paper-2); overflow-y: auto; padding: 12px;
28
  }
 
 
29
  .movement-picker-title {
30
- margin: 0 0 8px; font-family: var(--mv-mono); font-size: 11px; letter-spacing: .2em;
31
- text-transform: uppercase; color: var(--mv-transmit);
 
32
  }
33
  .movement-pack { margin-top: 8px; border-top: 1px solid var(--mv-paper); }
34
  .movement-pack > summary {
 
26
  width: 240px; flex-shrink: 0; border-right: 2px solid var(--mv-ink);
27
  background: var(--mv-paper-2); overflow-y: auto; padding: 12px;
28
  }
29
+ /* It's an <h2>, so the host (Gradio's `.prose h2`) blows it up and blackens it —
30
+ * defend size + colour with `!important`. */
31
  .movement-picker-title {
32
+ margin: 0 0 8px !important; font-family: var(--mv-mono); font-size: 11px !important;
33
+ font-weight: 500 !important; letter-spacing: .2em; line-height: 1.4 !important;
34
+ text-transform: uppercase; color: var(--mv-transmit) !important;
35
  }
36
  .movement-pack { margin-top: 8px; border-top: 1px solid var(--mv-paper); }
37
  .movement-pack > summary {