techfreakworm commited on
Commit
ce2a030
·
unverified ·
1 Parent(s): 46d16df

feat(ui): add brutalist mono theme tokens and responsive css

Browse files
Files changed (2) hide show
  1. tests/test_theme.py +28 -0
  2. theme.py +110 -0
tests/test_theme.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """L1 theme assertions — palette tokens, CSS presence."""
2
+ from __future__ import annotations
3
+
4
+ import theme
5
+
6
+
7
+ def test_palette_tokens_are_brutalist_mono():
8
+ assert theme.BG == "#0A0A0A"
9
+ assert theme.INK == "#E5E5E5"
10
+ assert theme.PRIMARY == "#FFFFFF"
11
+ # No color accent — that's the whole point of Brutalist Mono
12
+ for v in (theme.BG, theme.SURFACE, theme.SURFACE_STRONG, theme.BORDER, theme.BORDER_STRONG, theme.INK, theme.INK_MUTED, theme.PRIMARY):
13
+ assert v.startswith("#")
14
+ assert len(v) == 7 # all hex, no rgba
15
+
16
+
17
+ def test_css_contains_responsive_breakpoints():
18
+ css = theme.CSS
19
+ assert "@media" in css
20
+ assert "1024px" in css # tablet breakpoint
21
+ assert "640px" in css # mobile breakpoint
22
+
23
+
24
+ def test_build_theme_returns_gradio_theme():
25
+ import gradio as gr
26
+ t = theme.build_theme()
27
+ # gr.themes.Base is the parent class
28
+ assert isinstance(t, gr.themes.Base)
theme.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Brutalist Mono — pure black/white, no color accent.
2
+
3
+ Palette tokens are the source of truth; CSS pulls from them. The audio
4
+ waveform is the only optionally-colored element (rendered white in v1).
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import gradio as gr
9
+
10
+ # --- Palette ----------------------------------------------------------------
11
+ BG = "#0A0A0A"
12
+ SURFACE = "#141414"
13
+ SURFACE_STRONG = "#000000"
14
+ BORDER = "#1F1F1F"
15
+ BORDER_STRONG = "#2A2A2A"
16
+ INK = "#E5E5E5"
17
+ INK_MUTED = "#6B6B6B"
18
+ PRIMARY = "#FFFFFF"
19
+ ERROR_BG = "#1A1A1A"
20
+ RADIUS = "6px"
21
+ FONT_STACK = (
22
+ '"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif'
23
+ )
24
+
25
+
26
+ def build_theme() -> gr.themes.Base:
27
+ """Returns a Gradio theme keyed to Brutalist Mono tokens."""
28
+ return gr.themes.Base(
29
+ primary_hue=gr.themes.colors.gray,
30
+ neutral_hue=gr.themes.colors.gray,
31
+ font=[gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"],
32
+ ).set(
33
+ body_background_fill=BG,
34
+ body_text_color=INK,
35
+ block_background_fill=SURFACE,
36
+ block_border_color=BORDER,
37
+ block_border_width="1px",
38
+ block_radius=RADIUS,
39
+ input_background_fill=SURFACE_STRONG,
40
+ input_border_color=BORDER_STRONG,
41
+ input_border_color_focus=PRIMARY,
42
+ button_primary_background_fill=PRIMARY,
43
+ button_primary_text_color=BG,
44
+ button_primary_background_fill_hover=PRIMARY,
45
+ button_secondary_background_fill=SURFACE_STRONG,
46
+ button_secondary_text_color=INK,
47
+ button_secondary_border_color=BORDER_STRONG,
48
+ )
49
+
50
+
51
+ CSS = f"""
52
+ /* --- Sole brand bits --------------------------------------------------- */
53
+ .ams-header {{
54
+ display:flex; justify-content:space-between; align-items:baseline;
55
+ padding:8px 0 4px 0;
56
+ }}
57
+ .ams-brand {{
58
+ font-size:16px; font-weight:600; letter-spacing:-0.01em; color:{INK};
59
+ }}
60
+ .ams-brand-period {{ color:{PRIMARY}; }}
61
+ .ams-status {{ font-size:11px; color:{INK_MUTED}; letter-spacing:0.02em; }}
62
+
63
+ /* --- CTA banner -------------------------------------------------------- */
64
+ .ams-cta {{
65
+ font-size:13px; color:{INK_MUTED}; margin:2px 0 12px 0; padding-bottom:10px;
66
+ border-bottom:1px solid {BORDER};
67
+ }}
68
+ .ams-cta strong {{ color:{INK}; }}
69
+ .ams-cta-heart {{ color:{PRIMARY}; }}
70
+ .ams-cta a {{ color:{INK}; text-decoration:underline; }}
71
+
72
+ /* --- Sidebar nav (desktop >= 1024) ------------------------------------ */
73
+ .ams-sidebar {{ background:{SURFACE_STRONG}; padding:14px 10px; border-radius:{RADIUS}; min-width:170px; }}
74
+ .ams-side-item {{
75
+ display:block; padding:8px 10px; border-radius:4px; margin-bottom:3px;
76
+ font-size:13px; color:{INK_MUTED}; cursor:pointer; text-decoration:none;
77
+ }}
78
+ .ams-side-item.active {{
79
+ background:#1A1A1A; color:{PRIMARY};
80
+ border-left:2px solid {PRIMARY}; padding-left:8px;
81
+ }}
82
+
83
+ /* --- LoRA chip pill --------------------------------------------------- */
84
+ .ams-chip {{
85
+ display:inline-block; padding:5px 10px; border-radius:14px;
86
+ font-size:11px; margin:0 5px 5px 0; background:{SURFACE_STRONG};
87
+ border:1px solid {BORDER_STRONG}; color:{INK_MUTED}; cursor:pointer;
88
+ }}
89
+ .ams-chip.on {{ border-color:{PRIMARY}; color:{PRIMARY}; }}
90
+ .ams-chip.upload {{ border-style:dashed; color:{PRIMARY}; }}
91
+
92
+ /* --- LoRA file drop zone (tighten Gradio default ~400px height) ------ */
93
+ .ams-lora-file .upload-container {{ min-height:56px !important; }}
94
+
95
+ /* --- Hide Gradio footer ----------------------------------------------- */
96
+ footer {{ display:none !important; }}
97
+
98
+ /* --- Responsive: tablet 640-1024 px ----------------------------------- */
99
+ @media (max-width: 1024px) {{
100
+ .ams-sidebar {{ min-width:34px; padding:6px 4px; }}
101
+ .ams-side-item {{ font-size:0; padding:6px; }}
102
+ .ams-side-item::first-letter {{ font-size:16px; }}
103
+ }}
104
+
105
+ /* --- Responsive: mobile < 640 px -------------------------------------- */
106
+ @media (max-width: 640px) {{
107
+ .ams-sidebar {{ display:none; }}
108
+ .ams-cta {{ font-size:11px; }}
109
+ }}
110
+ """