Jimin Huang commited on
Commit
7d8fea8
Β·
1 Parent(s): 2a89927

Change settings

Browse files
Files changed (1) hide show
  1. src/views/LiveView.vue +81 -28
src/views/LiveView.vue CHANGED
@@ -35,6 +35,7 @@
35
  class="card"
36
  :class="{ 'card--bh': c.kind==='bh', 'card--winner': c.isWinner }"
37
  >
 
38
  <div class="card__header">
39
  <div class="card__logo">
40
  <img v-if="c.logo" :src="c.logo" alt="" />
@@ -42,27 +43,36 @@
42
  <span v-if="c.isWinner" class="card__badge" aria-label="Top performer">πŸ‘‘</span>
43
  </div>
44
 
45
- <div class="card__title" :title="c.title">{{ c.title }}</div>
 
 
 
 
46
  <div class="card__balance">{{ fmtUSD(c.balance) }}</div>
47
  </div>
48
 
 
49
  <div class="card__meta">
50
- <div class="card__sub ellipsize" :title="c.subtitle">{{ c.subtitle }}</div>
 
 
 
51
 
52
- <template v-if="c.kind==='agent' && c.gapUsd != null">
53
- <div class="pill" :class="{ neg: c.gapUsd < 0 && !c.isWinner, pos: c.gapUsd >= 0 || c.isWinner }">
 
54
  <span v-if="mode==='usd'">{{ signedMoney(c.gapUsd) }}</span>
55
  <span v-else>{{ signedPct(c.gapPct) }}</span>
56
  </div>
57
- </template>
58
-
59
- <template v-else>
60
- <div class="pill pill--neutral">Buy&nbsp;&amp;&nbsp;Hold</div>
61
- </template>
62
  </div>
63
 
 
64
  <div class="card__footer">
65
- <div class="card__sub">EOD {{ c.date ? new Date(c.date).toLocaleDateString() : '–' }}</div>
66
  </div>
67
  </div>
68
  </div>
@@ -305,39 +315,82 @@ watchEffect(() => {
305
  @media (max-width: 1200px) { .cards5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
306
  @media (max-width: 720px) { .cards5 { grid-template-columns: 1fr; } }
307
 
308
- /* card */
309
- .card { display: grid; grid-template-rows: auto auto auto; gap: 8px; padding: 12px 14px; border: 1px solid #EEF1F6; border-radius: 14px; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.04); position: relative; }
 
 
 
 
 
 
 
 
 
 
310
  .card--bh { outline: 2px dashed rgba(15,23,42,.08); }
311
  .card--winner { border-color: #16a34a; box-shadow: 0 0 0 3px rgba(22,163,74,.12); }
312
 
313
- /* header layout: logo | title | balance */
314
- .card__header { display: grid; grid-template-columns: 52px minmax(0,1fr) auto; align-items: start; gap: 12px; }
 
 
 
 
 
315
 
316
  /* logo */
317
- .card__logo { width: 44px; height: 44px; border-radius: 999px; background: #F3F4F6; display: grid; place-items: center; overflow: hidden; position: relative; }
 
 
 
 
318
  .card__logo img { width: 100%; height: 100%; object-fit: contain; }
319
  .card__logo-fallback { width: 60%; height: 60%; border-radius: 999px; background: #E5E7EB; }
320
  .card__badge { position: absolute; right: -6px; top: -6px; font-size: 16px; filter: drop-shadow(0 1px 1px rgba(0,0,0,.15)); }
321
 
322
- /* title: clamp to 2 lines so balance never overlaps */
 
323
  .card__title {
324
- min-width: 0; font-weight: 800; color: #0F172A;
325
- white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
326
- overflow: hidden; line-height: 1.15;
 
 
327
  }
328
 
329
- /* right-side balance never shrinks */
330
- .card__balance { white-space: nowrap; font-weight: 900; color: #0F172A; font-size: 20px; }
 
 
 
 
 
331
 
332
- /* meta row + footer */
333
- .card__meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
334
- .card__sub { font-size: 12px; color: #5B6476; opacity: .85; }
335
- .ellipsize { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
 
 
 
 
 
 
336
  .card__footer { margin-top: -2px; }
 
337
 
338
  /* pills */
339
- .pill { padding: 4px 9px; border-radius: 999px; font-size: 12px; font-weight: 800; line-height: 1; white-space: nowrap; background: #EEF2F7; color: #0F172A; }
340
- .pill.neg { background: #FEE2E2; color: #B91C1C; }
 
 
341
  .pill.pos { background: #DCFCE7; color: #166534; }
342
- .pill.pill--neutral { background: #EEF2F7; color: #0F172A; }
 
 
 
 
 
 
 
343
  </style>
 
35
  class="card"
36
  :class="{ 'card--bh': c.kind==='bh', 'card--winner': c.isWinner }"
37
  >
38
+ <!-- Header: logo | title (trunc) | balance (no-wrap) -->
39
  <div class="card__header">
40
  <div class="card__logo">
41
  <img v-if="c.logo" :src="c.logo" alt="" />
 
43
  <span v-if="c.isWinner" class="card__badge" aria-label="Top performer">πŸ‘‘</span>
44
  </div>
45
 
46
+ <div class="card__title-wrap">
47
+ <div class="card__title ellipsize" :title="c.title">{{ c.title }}</div>
48
+ <div class="card__subtitle ellipsize" :title="c.subtitle">{{ c.subtitle }}</div>
49
+ </div>
50
+
51
  <div class="card__balance">{{ fmtUSD(c.balance) }}</div>
52
  </div>
53
 
54
+ <!-- Meta row: strategy/badge on the left, performance pill on the right -->
55
  <div class="card__meta">
56
+ <div class="meta__left">
57
+ <div v-if="c.kind==='bh'" class="pill pill--neutral">Buy&nbsp;&amp;&nbsp;Hold</div>
58
+ <div v-else class="pill pill--outline">Strategy</div>
59
+ </div>
60
 
61
+ <div class="meta__right" v-if="c.kind==='agent' && c.gapUsd != null">
62
+ <div class="pill"
63
+ :class="{ neg: c.gapUsd < 0 && !c.isWinner, pos: c.gapUsd >= 0 || c.isWinner }">
64
  <span v-if="mode==='usd'">{{ signedMoney(c.gapUsd) }}</span>
65
  <span v-else>{{ signedPct(c.gapPct) }}</span>
66
  </div>
67
+ </div>
68
+ <div class="meta__right" v-else>
69
+ <!-- spacer to keep height consistent -->
70
+ </div>
 
71
  </div>
72
 
73
+ <!-- Footer: EOD date -->
74
  <div class="card__footer">
75
+ <div class="card__foot">EOD {{ c.date ? new Date(c.date).toLocaleDateString() : '–' }}</div>
76
  </div>
77
  </div>
78
  </div>
 
315
  @media (max-width: 1200px) { .cards5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
316
  @media (max-width: 720px) { .cards5 { grid-template-columns: 1fr; } }
317
 
318
+ /* card container */
319
+ .card {
320
+ display: grid;
321
+ grid-template-rows: auto auto auto; /* header, meta, footer */
322
+ gap: 10px;
323
+ padding: 12px 14px;
324
+ border: 1px solid #EEF1F6;
325
+ border-radius: 14px;
326
+ background: #fff;
327
+ box-shadow: 0 1px 2px rgba(0,0,0,.04);
328
+ min-width: 0; /* let children truncate */
329
+ }
330
  .card--bh { outline: 2px dashed rgba(15,23,42,.08); }
331
  .card--winner { border-color: #16a34a; box-shadow: 0 0 0 3px rgba(22,163,74,.12); }
332
 
333
+ /* header grid: logo | title block | balance */
334
+ .card__header {
335
+ display: grid;
336
+ grid-template-columns: 48px minmax(0, 1fr) auto;
337
+ align-items: center;
338
+ gap: 12px;
339
+ }
340
 
341
  /* logo */
342
+ .card__logo {
343
+ width: 44px; height: 44px; border-radius: 999px;
344
+ background: #F3F4F6; display: grid; place-items: center;
345
+ overflow: hidden; position: relative; flex: 0 0 44px;
346
+ }
347
  .card__logo img { width: 100%; height: 100%; object-fit: contain; }
348
  .card__logo-fallback { width: 60%; height: 60%; border-radius: 999px; background: #E5E7EB; }
349
  .card__badge { position: absolute; right: -6px; top: -6px; font-size: 16px; filter: drop-shadow(0 1px 1px rgba(0,0,0,.15)); }
350
 
351
+ /* title block */
352
+ .card__title-wrap { min-width: 0; display: grid; gap: 2px; }
353
  .card__title {
354
+ font-weight: 800; color: #0F172A; line-height: 1.1;
355
+ font-size: clamp(16px, 2vw, 20px); /* scale a bit with width */
356
+ }
357
+ .card__subtitle {
358
+ font-size: 12px; color: #5B6476; opacity: .85; line-height: 1.1;
359
  }
360
 
361
+ /* balance (never wraps) */
362
+ .card__balance {
363
+ white-space: nowrap;
364
+ font-weight: 900; color: #0F172A;
365
+ font-size: clamp(18px, 2.2vw, 22px);
366
+ margin-left: 8px;
367
+ }
368
 
369
+ /* meta row */
370
+ .card__meta {
371
+ display: grid;
372
+ grid-template-columns: 1fr auto;
373
+ align-items: center;
374
+ gap: 10px;
375
+ }
376
+ .meta__left, .meta__right { min-width: 0; display: flex; align-items: center; gap: 8px; }
377
+
378
+ /* footer */
379
  .card__footer { margin-top: -2px; }
380
+ .card__foot { font-size: 12px; color: #5B6476; opacity: .85; }
381
 
382
  /* pills */
383
+ .pill {
384
+ padding: 4px 9px; border-radius: 999px; font-size: 12px; font-weight: 800;
385
+ line-height: 1; white-space: nowrap; background: #EEF2F7; color: #0F172A;
386
+ }
387
  .pill.pos { background: #DCFCE7; color: #166534; }
388
+ .pill.neg { background: #FEE2E2; color: #B91C1C; }
389
+ .pill--neutral { background: #EEF2F7; color: #0F172A; }
390
+ .pill--outline {
391
+ background: transparent; color: #475569; border: 1px solid #E5E7EB; padding: 3px 8px;
392
+ }
393
+
394
+ /* utilities */
395
+ .ellipsize { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
396
  </style>