OwenStOnge commited on
Commit
fcc84d7
Β·
verified Β·
1 Parent(s): 8861913

Upload theme.R

Browse files
Files changed (1) hide show
  1. theme.R +348 -0
theme.R ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ library(bslib)
2
+ library(glue)
3
+
4
+ HAWKS_ORANGE <- "#F25B00"
5
+ HAWKS_BLUE <- "#164EA7"
6
+ HAWKS_DARK <- "#0D1B2A"
7
+ HAWKS_LIGHT <- "#F5F7FA"
8
+ HAWKS_GRAY <- "#6B7280"
9
+ HAWKS_BORDER <- "#E2E8F0"
10
+
11
+ hawks_theme <- bs_theme(
12
+ version = 5,
13
+ bg = "#FFFFFF",
14
+ fg = HAWKS_DARK,
15
+ primary = HAWKS_BLUE,
16
+ secondary = HAWKS_ORANGE,
17
+ success = "#16a34a",
18
+ warning = "#d97706",
19
+ danger = "#dc2626",
20
+ base_font = font_google("Inter"),
21
+ heading_font = font_google("Inter"),
22
+ `border-radius` = "0.5rem",
23
+ `font-size-base` = "0.925rem"
24
+ )
25
+
26
+ # ── Shared CSS ────────────────────────────────────────────────────────────────
27
+ hawks_css <- tags$style(HTML(glue("
28
+ * {{ box-sizing: border-box; }}
29
+
30
+ body {{
31
+ background: {HAWKS_LIGHT};
32
+ font-family: 'Inter', system-ui, sans-serif;
33
+ }}
34
+
35
+ /* ── Sidebar shell ── */
36
+ .hawks-shell {{
37
+ display: flex;
38
+ height: 100vh;
39
+ overflow: hidden;
40
+ }}
41
+
42
+ .hawks-sidebar {{
43
+ width: 220px;
44
+ min-width: 220px;
45
+ background: {HAWKS_DARK};
46
+ display: flex;
47
+ flex-direction: column;
48
+ transition: width 0.2s ease, min-width 0.2s ease;
49
+ overflow: hidden;
50
+ }}
51
+ .hawks-sidebar.collapsed {{
52
+ width: 52px;
53
+ min-width: 52px;
54
+ }}
55
+
56
+ .sb-brand {{
57
+ padding: 16px 14px;
58
+ border-bottom: 1px solid #ffffff18;
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 10px;
62
+ min-height: 56px;
63
+ }}
64
+ .sb-brand-text {{ overflow: hidden; white-space: nowrap; }}
65
+ .sb-brand-text .t1 {{ color: #fff; font-size: 13px; font-weight: 700; display: block; }}
66
+ .sb-brand-text .t2 {{ color: #ffffff55; font-size: 10px; display: block; letter-spacing: .03em; }}
67
+ .hawks-sidebar.collapsed .sb-brand-text {{ display: none; }}
68
+
69
+ .sb-section {{
70
+ padding: 12px 14px 4px;
71
+ color: #ffffff33;
72
+ font-size: 9px;
73
+ font-weight: 700;
74
+ letter-spacing: .1em;
75
+ text-transform: uppercase;
76
+ white-space: nowrap;
77
+ }}
78
+ .hawks-sidebar.collapsed .sb-section {{ visibility: hidden; }}
79
+
80
+ .sb-item {{
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 10px;
84
+ padding: 9px 14px;
85
+ margin: 1px 6px;
86
+ border-radius: 6px;
87
+ cursor: pointer;
88
+ color: #ffffffaa;
89
+ font-size: 13px;
90
+ font-weight: 500;
91
+ white-space: nowrap;
92
+ text-decoration: none;
93
+ transition: background 0.15s, color 0.15s;
94
+ }}
95
+ .sb-item:hover {{ background: #ffffff12; color: #fff; }}
96
+ .sb-item.active {{ background: {HAWKS_BLUE}; color: #fff; }}
97
+ .sb-icon {{ font-size: 16px; width: 18px; text-align: center; flex-shrink: 0; }}
98
+ .sb-label {{ overflow: hidden; }}
99
+ .hawks-sidebar.collapsed .sb-label {{ display: none; }}
100
+
101
+ .sb-footer {{
102
+ margin-top: auto;
103
+ padding: 12px 6px;
104
+ border-top: 1px solid #ffffff18;
105
+ display: flex;
106
+ justify-content: center;
107
+ }}
108
+ .sb-toggle {{
109
+ width: 32px; height: 32px;
110
+ border-radius: 6px;
111
+ display: flex; align-items: center; justify-content: center;
112
+ cursor: pointer;
113
+ color: #ffffff66;
114
+ transition: background 0.15s, color 0.15s;
115
+ }}
116
+ .sb-toggle:hover {{ background: #ffffff15; color: #fff; }}
117
+
118
+ /* ── Main area ── */
119
+ .hawks-main {{
120
+ flex: 1;
121
+ display: flex;
122
+ flex-direction: column;
123
+ overflow: hidden;
124
+ min-width: 0;
125
+ }}
126
+
127
+ .hawks-topbar {{
128
+ background: #fff;
129
+ border-bottom: 1px solid {HAWKS_BORDER};
130
+ padding: 0 20px;
131
+ height: 54px;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: space-between;
135
+ flex-shrink: 0;
136
+ }}
137
+ .topbar-title {{ font-size: 15px; font-weight: 700; color: {HAWKS_DARK}; }}
138
+ .topbar-sub {{ font-size: 11px; color: #9CA3AF; margin-left: 8px; }}
139
+
140
+ /* ── Content scroll area ── */
141
+ .hawks-content {{
142
+ flex: 1;
143
+ overflow-y: auto;
144
+ padding: 24px;
145
+ }}
146
+
147
+ /* ── Filter panel ── */
148
+ .hawks-body {{ display: flex; flex: 1; overflow: hidden; }}
149
+ .filter-panel {{
150
+ width: 210px;
151
+ min-width: 210px;
152
+ background: #fff;
153
+ border-right: 1px solid {HAWKS_BORDER};
154
+ padding: 16px 13px;
155
+ overflow-y: auto;
156
+ flex-shrink: 0;
157
+ }}
158
+ .fp-section {{
159
+ font-size: 10px; font-weight: 700; text-transform: uppercase;
160
+ letter-spacing: .08em; color: #9CA3AF; margin-bottom: 10px;
161
+ }}
162
+ .fp-group {{ margin-bottom: 16px; }}
163
+ .fp-label {{
164
+ font-size: 11px; font-weight: 600; color: #374151;
165
+ margin-bottom: 5px; display: block;
166
+ }}
167
+ .fp-input {{
168
+ width: 100%; background: {HAWKS_LIGHT};
169
+ border: 1px solid {HAWKS_BORDER}; border-radius: 5px;
170
+ padding: 5px 8px; font-size: 11px; color: #374151;
171
+ }}
172
+ .fp-pills {{ display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }}
173
+ .fp-pill {{
174
+ background: {HAWKS_LIGHT}; border: 1px solid {HAWKS_BORDER};
175
+ border-radius: 4px; padding: 3px 8px;
176
+ font-size: 10px; color: #374151; cursor: pointer;
177
+ }}
178
+ .fp-pill.active {{
179
+ background: #164EA714; border-color: #164EA755;
180
+ color: {HAWKS_BLUE}; font-weight: 600;
181
+ }}
182
+ .fp-apply {{
183
+ width: 100%; background: {HAWKS_BLUE}; color: #fff;
184
+ border: none; border-radius: 6px; padding: 7px;
185
+ font-size: 11px; font-weight: 600; cursor: pointer; margin-top: 4px;
186
+ }}
187
+ .fp-reset {{
188
+ text-align: center; font-size: 10px; color: #9CA3AF;
189
+ margin-top: 6px; cursor: pointer;
190
+ }}
191
+
192
+ /* ── Tab strip ── */
193
+ .hawks-tabs {{
194
+ background: #fff;
195
+ border-bottom: 1px solid {HAWKS_BORDER};
196
+ padding: 0 20px;
197
+ display: flex;
198
+ flex-shrink: 0;
199
+ }}
200
+ .h-tab {{
201
+ padding: 11px 14px;
202
+ font-size: 12px; font-weight: 500;
203
+ color: #6B7280;
204
+ border-bottom: 2px solid transparent;
205
+ cursor: pointer;
206
+ white-space: nowrap;
207
+ transition: color .15s, border-color .15s;
208
+ }}
209
+ .h-tab:hover {{ color: #374151; }}
210
+ .h-tab.active {{ color: {HAWKS_BLUE}; border-bottom-color: {HAWKS_BLUE}; font-weight: 600; }}
211
+
212
+ /* ── Stat cards ── */
213
+ .stat-grid {{
214
+ display: grid;
215
+ grid-template-columns: repeat(4, 1fr);
216
+ gap: 12px;
217
+ margin-bottom: 18px;
218
+ }}
219
+ .stat-box {{
220
+ background: #fff; border: 1px solid {HAWKS_BORDER};
221
+ border-radius: 8px; padding: 14px 16px;
222
+ }}
223
+ .stat-val {{ font-size: 22px; font-weight: 700; color: {HAWKS_DARK}; line-height: 1; }}
224
+ .stat-lbl {{
225
+ font-size: 10px; color: {HAWKS_GRAY};
226
+ text-transform: uppercase; letter-spacing: .07em; margin-top: 4px;
227
+ }}
228
+ .stat-delta {{ font-size: 10px; margin-top: 3px; }}
229
+ .stat-delta.up {{ color: #16a34a; }}
230
+ .stat-delta.dn {{ color: #dc2626; }}
231
+ .stat-bar {{ height: 3px; background: {HAWKS_BORDER}; border-radius: 2px; margin-top: 10px; }}
232
+ .stat-bar-fill {{ height: 3px; border-radius: 2px; background: {HAWKS_BLUE}; }}
233
+
234
+ /* ── Cards ── */
235
+ .data-card {{
236
+ background: #fff; border: 1px solid {HAWKS_BORDER};
237
+ border-radius: 8px; overflow: hidden;
238
+ }}
239
+ .data-card-hdr {{
240
+ padding: 10px 14px; border-bottom: 1px solid {HAWKS_BORDER};
241
+ display: flex; align-items: center; justify-content: space-between;
242
+ }}
243
+ .data-card-title {{
244
+ font-size: 11px; font-weight: 700; color: {HAWKS_DARK};
245
+ text-transform: uppercase; letter-spacing: .05em;
246
+ }}
247
+ .data-card-sub {{ font-size: 10px; color: #9CA3AF; }}
248
+ .data-card-body {{ padding: 12px 14px; }}
249
+
250
+ /* ── Player selector ── */
251
+ .player-select {{
252
+ background: {HAWKS_LIGHT}; border: 1px solid {HAWKS_BORDER};
253
+ border-radius: 6px; padding: 6px 10px;
254
+ display: flex; align-items: center; gap: 6px; cursor: pointer;
255
+ }}
256
+ .player-select .ps-name {{ font-size: 12px; font-weight: 600; color: #374151; }}
257
+
258
+ /* ── Placeholder ── */
259
+ .placeholder-panel {{
260
+ background: {HAWKS_LIGHT};
261
+ border: 1.5px dashed {HAWKS_BORDER};
262
+ border-radius: 8px;
263
+ padding: 3rem 1rem;
264
+ text-align: center; color: {HAWKS_GRAY};
265
+ }}
266
+ .placeholder-panel .ph-label {{ font-weight: 500; font-size: 0.9rem; }}
267
+ .placeholder-panel .ph-sub {{ font-size: 0.8rem; margin-top: 0.25rem; opacity: .7; }}
268
+ ")))
269
+
270
+ # ── Sidebar builder ───────────────────────────────────────────────────────────
271
+ hawks_sidebar <- function(items, app_title = "Analytics") {
272
+ nav_items <- lapply(items, function(item) {
273
+ tags$div(
274
+ class = paste("sb-item", if (isTRUE(item$active)) "active" else ""),
275
+ id = paste0("sb_", item$id),
276
+ onclick = if (!is.null(item$tab)) {
277
+ sprintf("Shiny.setInputValue('active_tab','%s',{priority:'event'})", item$tab)
278
+ },
279
+ tags$i(class = paste("ti", item$icon, "sb-icon")),
280
+ tags$span(class = "sb-label", item$label)
281
+ )
282
+ })
283
+
284
+ tags$div(
285
+ class = "hawks-sidebar",
286
+ id = "hawksSidebar",
287
+
288
+ tags$div(
289
+ class = "sb-brand",
290
+ tags$svg(
291
+ width = "28", height = "28", viewBox = "0 0 30 30", fill = "none",
292
+ tags$polygon(points = "15,2 28,26 15,21 2,26", fill = HAWKS_ORANGE, opacity = "0.9"),
293
+ tags$polygon(points = "15,2 15,21 2,26", fill = "#FFFFFF", opacity = "0.18")
294
+ ),
295
+ tags$div(
296
+ class = "sb-brand-text",
297
+ tags$span(class = "t1", "Harbor Hawks"),
298
+ tags$span(class = "t2", app_title)
299
+ )
300
+ ),
301
+
302
+ tags$div(class = "sb-section", "Navigation"),
303
+ tagList(nav_items),
304
+
305
+ tags$div(
306
+ class = "sb-footer",
307
+ tags$div(
308
+ class = "sb-toggle",
309
+ id = "sbToggle",
310
+ onclick = "toggleSidebar()",
311
+ tags$i(class = "ti ti-chevrons-left", id = "sbToggleIcon")
312
+ )
313
+ )
314
+ )
315
+ }
316
+
317
+ # ── Topbar ────────────────────────────────────────────────────────────────────
318
+ hawks_topbar <- function(title, subtitle = "Cape Cod League \u00b7 2025", right = NULL) {
319
+ tags$div(
320
+ class = "hawks-topbar",
321
+ tags$div(
322
+ style = "display:flex; align-items:baseline; gap:6px;",
323
+ tags$span(class = "topbar-title", title),
324
+ tags$span(class = "topbar-sub", subtitle)
325
+ ),
326
+ if (!is.null(right)) right
327
+ )
328
+ }
329
+
330
+ # ── Sidebar JS ────────────────────────────────────────────────────────────────
331
+ hawks_sidebar_js <- tags$script(HTML("
332
+ function toggleSidebar() {
333
+ var sb = document.getElementById('hawksSidebar');
334
+ var icon = document.getElementById('sbToggleIcon');
335
+ sb.classList.toggle('collapsed');
336
+ var isCollapsed = sb.classList.contains('collapsed');
337
+ icon.className = isCollapsed ? 'ti ti-chevrons-right' : 'ti ti-chevrons-left';
338
+ }
339
+ "))
340
+
341
+ # ── Helpers ───────────────────────────────────────────────────────────────────
342
+ placeholder_panel <- function(label, sub = "Coming soon") {
343
+ tags$div(
344
+ class = "placeholder-panel",
345
+ tags$div(class = "ph-label", label),
346
+ tags$div(class = "ph-sub", sub)
347
+ )
348
+ }