kaveh commited on
Commit
fa3d48f
·
1 Parent(s): 3dd7d71

color cards in home page

Browse files
Files changed (2) hide show
  1. streamlit_hf/home.py +147 -4
  2. streamlit_hf/lib/ui.py +1 -59
streamlit_hf/home.py CHANGED
@@ -273,15 +273,158 @@ else:
273
 
274
  # --- Workspace cards (directly under metrics); hidden spans pair with CSS for per-card colours ---
275
  _NAV_SLOT = '<span id="ff-nav-slot-{}" class="ff-nav-slot-marker" aria-hidden="true"></span>'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  c1, c2, c3, c4 = st.columns(4, gap="small")
277
  with c1:
278
- st.markdown(_NAV_SLOT.format(1), unsafe_allow_html=True)
279
  with st.container(border=True):
 
280
  st.page_link("pages/1_Single_Cell_Explorer.py", label="Single-Cell Explorer", icon=":material/scatter_plot:")
281
  st.caption("UMAP, filters, and per-cell inspection: fate, prediction, fold, batch, modalities.")
282
  with c2:
283
- st.markdown(_NAV_SLOT.format(2), unsafe_allow_html=True)
284
  with st.container(border=True):
 
285
  st.page_link(
286
  "pages/feature_insights/1_Global_overview.py",
287
  label="Feature Insights",
@@ -289,13 +432,13 @@ with c2:
289
  )
290
  st.caption("Shift probes, attention rollout, cohort views, and full multimodal tables.")
291
  with c3:
292
- st.markdown(_NAV_SLOT.format(3), unsafe_allow_html=True)
293
  with st.container(border=True):
 
294
  st.page_link("pages/flux_analysis/5_Interactive_map.py", label="Flux Analysis", icon=":material/account_tree:")
295
  st.caption("Reaction pathways, differential flux, rankings, and model metadata.")
296
  with c4:
297
- st.markdown(_NAV_SLOT.format(4), unsafe_allow_html=True)
298
  with st.container(border=True):
 
299
  st.page_link(
300
  "pages/gene_expression/1_Pathway_enrichment.py",
301
  label="Gene Expression & TF Activity",
 
273
 
274
  # --- Workspace cards (directly under metrics); hidden spans pair with CSS for per-card colours ---
275
  _NAV_SLOT = '<span id="ff-nav-slot-{}" class="ff-nav-slot-marker" aria-hidden="true"></span>'
276
+
277
+ # Inject per-card colour rules here (rather than in lib.ui) so Streamlit hot-reload picks up
278
+ # tweaks without needing to reimport the cached lib module.
279
+ st.markdown(
280
+ """
281
+ <style>
282
+ /*
283
+ * Home workspace nav cards (Streamlit 1.56+).
284
+ * Marker row: take it out of normal flow so it cannot reserve vertical space (fixes top gap).
285
+ * Tighten default block gap, page-link, and caption spacing (fixes title–description gap).
286
+ */
287
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) {
288
+ position: relative !important;
289
+ gap: 0 !important;
290
+ row-gap: 0 !important;
291
+ margin-bottom: 0 !important;
292
+ padding: 0.5rem 0.75rem 0.5rem !important;
293
+ border-radius: 14px !important;
294
+ transition: box-shadow 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important;
295
+ }
296
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) > div[data-testid="stElementContainer"]:has(span[id^="ff-nav-slot-"]) {
297
+ position: absolute !important;
298
+ left: 0 !important;
299
+ top: 0 !important;
300
+ width: 0 !important;
301
+ height: 0 !important;
302
+ margin: 0 !important;
303
+ padding: 0 !important;
304
+ overflow: hidden !important;
305
+ clip: rect(0, 0, 0, 0) !important;
306
+ pointer-events: none !important;
307
+ z-index: 0 !important;
308
+ }
309
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) > div[data-testid="stElementContainer"]:has(span[id^="ff-nav-slot-"]) div[data-testid="stMarkdownContainer"],
310
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) > div[data-testid="stElementContainer"]:has(span[id^="ff-nav-slot-"]) div[data-testid="stMarkdownContainer"] p {
311
+ margin: 0 !important;
312
+ padding: 0 !important;
313
+ min-height: 0 !important;
314
+ line-height: 0 !important;
315
+ }
316
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) > div[data-testid="stElementContainer"]:has([data-testid="stPageLink"]) {
317
+ margin-top: 0 !important;
318
+ margin-bottom: 0 !important;
319
+ padding-top: 0 !important;
320
+ padding-bottom: 0 !important;
321
+ }
322
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) [data-testid="stPageLink"] {
323
+ margin-bottom: 0 !important;
324
+ padding-bottom: 0 !important;
325
+ }
326
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) [data-testid="stCaptionContainer"] {
327
+ margin-top: 0.28rem !important;
328
+ margin-bottom: 0 !important;
329
+ padding-top: 0 !important;
330
+ padding-bottom: 0 !important;
331
+ /* Subtitle flush with icon / link row (starts under the icon, not under the title text) */
332
+ padding-left: 0 !important;
333
+ box-sizing: border-box !important;
334
+ }
335
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) [data-testid="stCaptionContainer"] div[data-testid="stMarkdownContainer"] {
336
+ padding-left: 0 !important;
337
+ margin-left: 0 !important;
338
+ }
339
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) > div[data-testid="stElementContainer"]:has([data-testid="stCaptionContainer"]) {
340
+ margin-bottom: 0 !important;
341
+ padding-bottom: 0 !important;
342
+ }
343
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span[id^="ff-nav-slot-"]) [data-testid="stCaptionContainer"] p {
344
+ margin-bottom: 0 !important;
345
+ }
346
+ /* Row of four columns: drop default block margin below the nav cards */
347
+ section[data-testid="stMain"] div[data-testid="stHorizontalBlock"]:has(span#ff-nav-slot-1):has(span#ff-nav-slot-4) {
348
+ margin-bottom: 0 !important;
349
+ }
350
+ /* Each column’s outer vertical block often keeps trailing margin */
351
+ section[data-testid="stMain"] div[data-testid="stHorizontalBlock"]:has(span#ff-nav-slot-1):has(span#ff-nav-slot-4) > div[data-testid="stVerticalBlock"] {
352
+ margin-bottom: 0 !important;
353
+ }
354
+ /* Fine dot lattice on a flat tinted base (no banded multi-stop gradients) */
355
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-1) {
356
+ background-color: #f1f3fa !important;
357
+ background-image: radial-gradient(rgba(67, 56, 202, 0.07) 0.9px, transparent 1px) !important;
358
+ background-size: 11px 11px !important;
359
+ border: 1px solid rgba(67, 56, 202, 0.34) !important;
360
+ box-shadow: 0 2px 16px rgba(49, 46, 129, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.88) !important;
361
+ }
362
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-1):hover {
363
+ border-color: rgba(67, 56, 202, 0.55) !important;
364
+ box-shadow: 0 8px 26px rgba(49, 46, 129, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.98) !important;
365
+ transform: translateY(-1px) !important;
366
+ }
367
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-2) {
368
+ background-color: #faf6f1 !important;
369
+ background-image: radial-gradient(rgba(180, 83, 9, 0.065) 0.9px, transparent 1px) !important;
370
+ background-size: 11px 11px !important;
371
+ border: 1px solid rgba(180, 83, 9, 0.3) !important;
372
+ box-shadow: 0 2px 16px rgba(154, 52, 18, 0.09), inset 0 1px 0 rgba(255, 255, 255, 0.88) !important;
373
+ }
374
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-2):hover {
375
+ border-color: rgba(154, 52, 18, 0.5) !important;
376
+ box-shadow: 0 8px 26px rgba(154, 52, 18, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.98) !important;
377
+ transform: translateY(-1px) !important;
378
+ }
379
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-3) {
380
+ background-color: #f0f7f6 !important;
381
+ background-image: radial-gradient(rgba(15, 118, 110, 0.068) 0.9px, transparent 1px) !important;
382
+ background-size: 11px 11px !important;
383
+ border: 1px solid rgba(15, 118, 110, 0.32) !important;
384
+ box-shadow: 0 2px 16px rgba(15, 118, 110, 0.09), inset 0 1px 0 rgba(255, 255, 255, 0.88) !important;
385
+ }
386
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-3):hover {
387
+ border-color: rgba(15, 118, 110, 0.52) !important;
388
+ box-shadow: 0 8px 26px rgba(15, 118, 110, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.98) !important;
389
+ transform: translateY(-1px) !important;
390
+ }
391
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-4) {
392
+ background-color: #f4f2f9 !important;
393
+ background-image: radial-gradient(rgba(109, 40, 217, 0.065) 0.9px, transparent 1px) !important;
394
+ background-size: 11px 11px !important;
395
+ border: 1px solid rgba(109, 40, 217, 0.3) !important;
396
+ box-shadow: 0 2px 16px rgba(91, 33, 182, 0.09), inset 0 1px 0 rgba(255, 255, 255, 0.88) !important;
397
+ }
398
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-4):hover {
399
+ border-color: rgba(91, 33, 182, 0.5) !important;
400
+ box-shadow: 0 8px 26px rgba(91, 33, 182, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.98) !important;
401
+ transform: translateY(-1px) !important;
402
+ }
403
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-1) [data-testid="stIconMaterial"] {
404
+ color: #4338ca !important;
405
+ }
406
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-2) [data-testid="stIconMaterial"] {
407
+ color: #b45309 !important;
408
+ }
409
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-3) [data-testid="stIconMaterial"] {
410
+ color: #0f766e !important;
411
+ }
412
+ section[data-testid="stMain"] div[data-testid="stVerticalBlock"]:has(> div[data-testid="stElementContainer"] span#ff-nav-slot-4) [data-testid="stIconMaterial"] {
413
+ color: #6d28d9 !important;
414
+ }
415
+ </style>
416
+ """,
417
+ unsafe_allow_html=True,
418
+ )
419
  c1, c2, c3, c4 = st.columns(4, gap="small")
420
  with c1:
 
421
  with st.container(border=True):
422
+ st.markdown(_NAV_SLOT.format(1), unsafe_allow_html=True)
423
  st.page_link("pages/1_Single_Cell_Explorer.py", label="Single-Cell Explorer", icon=":material/scatter_plot:")
424
  st.caption("UMAP, filters, and per-cell inspection: fate, prediction, fold, batch, modalities.")
425
  with c2:
 
426
  with st.container(border=True):
427
+ st.markdown(_NAV_SLOT.format(2), unsafe_allow_html=True)
428
  st.page_link(
429
  "pages/feature_insights/1_Global_overview.py",
430
  label="Feature Insights",
 
432
  )
433
  st.caption("Shift probes, attention rollout, cohort views, and full multimodal tables.")
434
  with c3:
 
435
  with st.container(border=True):
436
+ st.markdown(_NAV_SLOT.format(3), unsafe_allow_html=True)
437
  st.page_link("pages/flux_analysis/5_Interactive_map.py", label="Flux Analysis", icon=":material/account_tree:")
438
  st.caption("Reaction pathways, differential flux, rankings, and model metadata.")
439
  with c4:
 
440
  with st.container(border=True):
441
+ st.markdown(_NAV_SLOT.format(4), unsafe_allow_html=True)
442
  st.page_link(
443
  "pages/gene_expression/1_Pathway_enrichment.py",
444
  label="Gene Expression & TF Activity",
streamlit_hf/lib/ui.py CHANGED
@@ -201,65 +201,7 @@ section[data-testid="stMain"] .ff-hero .ff-hero-text h1 {
201
  overflow: hidden !important;
202
  clip-path: inset(50%) !important;
203
  }
204
- /*
205
- * Home workspace nav cards: each column renders span#ff-nav-slot-N, then the bordered tile.
206
- * Target the bordered wrapper as the next sibling block after the markdown that contains the span.
207
- */
208
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * [data-testid="stVerticalBlockBorderWrapper"],
209
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * + * [data-testid="stVerticalBlockBorderWrapper"],
210
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * [data-testid="stVerticalBlockBorderWrapper"],
211
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * + * [data-testid="stVerticalBlockBorderWrapper"],
212
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * [data-testid="stVerticalBlockBorderWrapper"],
213
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * + * [data-testid="stVerticalBlockBorderWrapper"],
214
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * [data-testid="stVerticalBlockBorderWrapper"],
215
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * + * [data-testid="stVerticalBlockBorderWrapper"] {
216
- border-radius: 14px !important;
217
- transition: box-shadow 0.15s ease, border-color 0.15s ease !important;
218
- }
219
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * [data-testid="stVerticalBlockBorderWrapper"],
220
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * + * [data-testid="stVerticalBlockBorderWrapper"] {
221
- background: linear-gradient(152deg, #eff6ff 0%, #ffffff 52%, #dbeafe 100%) !important;
222
- border: 1px solid rgba(37, 99, 235, 0.38) !important;
223
- box-shadow: 0 2px 14px rgba(37, 99, 235, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
224
- }
225
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * [data-testid="stVerticalBlockBorderWrapper"]:hover,
226
- section[data-testid="stMain"] *:has(span#ff-nav-slot-1) + * + * [data-testid="stVerticalBlockBorderWrapper"]:hover {
227
- border-color: rgba(29, 78, 216, 0.55) !important;
228
- box-shadow: 0 6px 22px rgba(37, 99, 235, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
229
- }
230
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * [data-testid="stVerticalBlockBorderWrapper"],
231
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * + * [data-testid="stVerticalBlockBorderWrapper"] {
232
- background: linear-gradient(152deg, #fff7ed 0%, #ffffff 52%, #ffedd5 100%) !important;
233
- border: 1px solid rgba(234, 88, 12, 0.35) !important;
234
- box-shadow: 0 2px 14px rgba(234, 88, 12, 0.09), inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
235
- }
236
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * [data-testid="stVerticalBlockBorderWrapper"]:hover,
237
- section[data-testid="stMain"] *:has(span#ff-nav-slot-2) + * + * [data-testid="stVerticalBlockBorderWrapper"]:hover {
238
- border-color: rgba(194, 65, 12, 0.5) !important;
239
- box-shadow: 0 6px 22px rgba(234, 88, 12, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
240
- }
241
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * [data-testid="stVerticalBlockBorderWrapper"],
242
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * + * [data-testid="stVerticalBlockBorderWrapper"] {
243
- background: linear-gradient(152deg, #ecfdf5 0%, #ffffff 52%, #d1fae5 100%) !important;
244
- border: 1px solid rgba(5, 150, 105, 0.36) !important;
245
- box-shadow: 0 2px 14px rgba(5, 150, 105, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
246
- }
247
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * [data-testid="stVerticalBlockBorderWrapper"]:hover,
248
- section[data-testid="stMain"] *:has(span#ff-nav-slot-3) + * + * [data-testid="stVerticalBlockBorderWrapper"]:hover {
249
- border-color: rgba(4, 120, 87, 0.52) !important;
250
- box-shadow: 0 6px 22px rgba(5, 150, 105, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
251
- }
252
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * [data-testid="stVerticalBlockBorderWrapper"],
253
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * + * [data-testid="stVerticalBlockBorderWrapper"] {
254
- background: linear-gradient(152deg, #f5f3ff 0%, #ffffff 52%, #ede9fe 100%) !important;
255
- border: 1px solid rgba(124, 58, 237, 0.34) !important;
256
- box-shadow: 0 2px 14px rgba(124, 58, 237, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
257
- }
258
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * [data-testid="stVerticalBlockBorderWrapper"]:hover,
259
- section[data-testid="stMain"] *:has(span#ff-nav-slot-4) + * + * [data-testid="stVerticalBlockBorderWrapper"]:hover {
260
- border-color: rgba(109, 40, 217, 0.5) !important;
261
- box-shadow: 0 6px 22px rgba(124, 58, 237, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
262
- }
263
  </style>
264
  """,
265
  unsafe_allow_html=True,
 
201
  overflow: hidden !important;
202
  clip-path: inset(50%) !important;
203
  }
204
+ /* Nav-card colour rules live in home.py so they stay in sync with the per-rerun script. */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  </style>
206
  """,
207
  unsafe_allow_html=True,