v0 Anay commited on
Commit
13fe1f0
·
1 Parent(s): 6f593ca

style: enhance UI readability for cards and badges

Browse files

Increase card and badge sizes, adjust text sizes for better legibility.

Co-authored-by: Anay <129646663+anay1104@users.noreply.github.com>

frontend/src/components/PitchView.jsx CHANGED
@@ -9,20 +9,20 @@ import { DraggablePlayer } from "./DraggablePlayer";
9
  proportions identical across every screen size (no element gets relatively
10
  bigger or smaller than another when the viewport changes).
11
 
12
- Card: 80×96px (modest 6% bump from original 72×88)
13
- Label strip: ~48px
14
- Card slot total ≈ 145px per row
15
 
16
- DESIGN_WIDTH = 570: fits widest row (5 mids/defs) = 5×80 + 4×24 = 496570
17
- 4 starter rows + gaps ≈ 680px total height
18
- Bench ≈ 210px
19
 
20
  MAX_SCALE > 1 lets the pitch scale modestly on wide screens without badges
21
  and labels becoming disproportionately large.
22
  */
23
- const DESIGN_WIDTH = 570;
24
- const STARTERS_H = 720;
25
- const BENCH_H = 210;
26
  // Gap between player card wrappers in px (in design space)
27
  const CARD_GAP = 24;
28
  // Allow the pitch to scale up to 1.1× on wide screens so cards don't look
 
9
  proportions identical across every screen size (no element gets relatively
10
  bigger or smaller than another when the viewport changes).
11
 
12
+ Card: 88×106px (larger for better legibility)
13
+ Label strip: ~52px
14
+ Card slot total ≈ 158px per row
15
 
16
+ DESIGN_WIDTH = 620: fits widest row (5 mids/defs) = 5×88 + 4×24 = 536620
17
+ 4 starter rows + gaps ≈ 780px total height
18
+ Bench ≈ 230px
19
 
20
  MAX_SCALE > 1 lets the pitch scale modestly on wide screens without badges
21
  and labels becoming disproportionately large.
22
  */
23
+ const DESIGN_WIDTH = 620;
24
+ const STARTERS_H = 780;
25
+ const BENCH_H = 230;
26
  // Gap between player card wrappers in px (in design space)
27
  const CARD_GAP = 24;
28
  // Allow the pitch to scale up to 1.1× on wide screens so cards don't look
frontend/src/components/PlayerCardVisual.jsx CHANGED
@@ -5,15 +5,15 @@ import { getPlayerPrice } from "../utils/fplLogic";
5
  import { PlayerContext } from "../PlayerContext";
6
 
7
  // Fixed card dimensions — these are design-space pixels (before PitchView scaling).
8
- // Sized to be prominent on desktop and scale gracefully on mobile via the
9
- // PitchView scale transform. Keeps proportions consistent across devices.
10
- const CARD_W = 80;
11
- const CARD_H = 96; // photo card height only (label strip is separate, in flow below)
12
 
13
  // Badge sizing — using percentage of card width ensures badges scale proportionally
14
  // with the card rather than being fixed pixels that iOS may try to inflate.
15
- // 13.5% of 80px = ~10.8px at design scale, but will shrink/grow with the card.
16
- const BADGE_PCT = 0.135;
17
 
18
  export const PlayerCardVisual = ({
19
  player,
@@ -61,17 +61,17 @@ export const PlayerCardVisual = ({
61
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transition-colors border border-red-400 shadow-lg cursor-pointer select-none"
62
  title="Undo transfer"
63
  >
64
- <RotateCcw size={5} strokeWidth={3} />
65
  </div>
66
  </div>
67
  )}
68
- <Plus className="text-slate-500 group-hover:text-emerald-400 transition-colors mb-1" size={22} />
69
- <span className="text-[9px] font-black text-slate-500 group-hover:text-emerald-400 uppercase tracking-widest">
70
  {player.Pos}
71
  </span>
72
  </div>
73
  {/* Placeholder label area so blank slots have identical height to real cards */}
74
- <div style={{ height: 50 }} />
75
  </div>
76
  );
77
  }
@@ -153,11 +153,11 @@ export const PlayerCardVisual = ({
153
  };
154
 
155
  // EV text sizes — primary GW gets the strongest visual weight, subsequent
156
- // GWs taper down. The WebkitTextSizeAdjust fix prevents iOS inflation.
157
  const evStyles = [
158
- "text-emerald-400 text-[10px] font-extrabold",
159
- "text-emerald-500 text-[8px] font-bold",
160
- "text-emerald-600 text-[6px] font-semibold",
161
  ];
162
 
163
  const isTransferIn = Boolean(player.replacedPlayer || onSolverUndo);
@@ -215,7 +215,7 @@ export const PlayerCardVisual = ({
215
  minHeight: 0,
216
  touchAction: "manipulation",
217
  }}
218
- className={`flex items-center justify-center rounded-full text-[5px] font-bold leading-none transition-colors shadow-md transform-gpu cursor-pointer select-none
219
  ${isCap
220
  ? activeChipType === "tc"
221
  ? "bg-purple-500 text-white border border-purple-300"
@@ -237,7 +237,7 @@ export const PlayerCardVisual = ({
237
  minHeight: 0,
238
  touchAction: "manipulation",
239
  }}
240
- className={`flex items-center justify-center rounded-full text-[5px] font-bold leading-none transition-colors shadow-md cursor-pointer select-none
241
  ${isVice ? "bg-slate-300 text-slate-900 border border-white" : "bg-slate-900/90 text-slate-400 border border-slate-700 hover:text-white"}`}
242
  >
243
  V
@@ -259,7 +259,7 @@ export const PlayerCardVisual = ({
259
  }}
260
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transform-gpu transition-colors border border-red-400 shadow-md cursor-pointer select-none"
261
  >
262
- <RotateCcw size={5} strokeWidth={3} />
263
  </div>
264
  ) : player.replacedPlayer ? (
265
  <div
@@ -276,7 +276,7 @@ export const PlayerCardVisual = ({
276
  }}
277
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transform-gpu transition-colors border border-red-400 shadow-md cursor-pointer select-none"
278
  >
279
- <RotateCcw size={5} strokeWidth={3} />
280
  </div>
281
  ) : null}
282
  </div>
@@ -337,21 +337,21 @@ export const PlayerCardVisual = ({
337
  textSizeAdjust: "none",
338
  }}
339
  >
340
- <div className={`w-full text-center py-[2px] truncate px-1 font-bold text-[8px] leading-tight rounded-t shadow-md
341
  ${isTransferIn ? "bg-cyan-600 text-white" : "bg-slate-950 text-slate-100 border border-slate-700"}`}>
342
  {player.Name}
343
  </div>
344
- <div className="w-full bg-slate-200 border-x border-slate-700 flex justify-center items-center gap-1 py-[2px] shadow-inner">
345
- <span className={`text-[8px] font-black flex items-baseline gap-[2px] leading-none ${isBlankThisGw ? "text-slate-400" : "text-slate-800"}`}>
346
  {isBlankThisGw ? "-" : (player[`${activeGW}_xMins`] ?? 90)}
347
- <span className="text-[6px] font-bold text-slate-500 uppercase tracking-tight">xMins</span>
348
  </span>
349
- <span className="text-slate-400 font-light text-[8px] leading-none">|</span>
350
- <span className="text-[8px] font-black text-emerald-700 leading-none">
351
  £{getPlayerPrice(player).toFixed(1)}
352
  </span>
353
  </div>
354
- <div className="w-full bg-slate-900 border-x border-b border-slate-700 flex items-center rounded-b shadow-md px-0.5 overflow-hidden" style={{ height: 17 }}>
355
  <div className="flex items-center justify-center w-full whitespace-nowrap overflow-hidden">
356
  {renderFixtures(player.Team, activeGW)}
357
  </div>
 
5
  import { PlayerContext } from "../PlayerContext";
6
 
7
  // Fixed card dimensions — these are design-space pixels (before PitchView scaling).
8
+ // Sized to be prominent and legible on desktop, scaling gracefully on mobile via
9
+ // the PitchView scale transform. Keeps proportions consistent across devices.
10
+ const CARD_W = 88;
11
+ const CARD_H = 106; // photo card height only (label strip is separate, in flow below)
12
 
13
  // Badge sizing — using percentage of card width ensures badges scale proportionally
14
  // with the card rather than being fixed pixels that iOS may try to inflate.
15
+ // 15% of 88px = ~13px at design scale large enough to read and tap comfortably.
16
+ const BADGE_PCT = 0.15;
17
 
18
  export const PlayerCardVisual = ({
19
  player,
 
61
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transition-colors border border-red-400 shadow-lg cursor-pointer select-none"
62
  title="Undo transfer"
63
  >
64
+ <RotateCcw size={7} strokeWidth={2.5} />
65
  </div>
66
  </div>
67
  )}
68
+ <Plus className="text-slate-500 group-hover:text-emerald-400 transition-colors mb-1" size={24} />
69
+ <span className="text-[10px] font-black text-slate-500 group-hover:text-emerald-400 uppercase tracking-widest">
70
  {player.Pos}
71
  </span>
72
  </div>
73
  {/* Placeholder label area so blank slots have identical height to real cards */}
74
+ <div style={{ height: 55 }} />
75
  </div>
76
  );
77
  }
 
153
  };
154
 
155
  // EV text sizes — primary GW gets the strongest visual weight, subsequent
156
+ // GWs taper down. Sized for comfortable reading at the larger card scale.
157
  const evStyles = [
158
+ "text-emerald-400 text-[12px] font-extrabold",
159
+ "text-emerald-500 text-[10px] font-bold",
160
+ "text-emerald-600 text-[8px] font-semibold",
161
  ];
162
 
163
  const isTransferIn = Boolean(player.replacedPlayer || onSolverUndo);
 
215
  minHeight: 0,
216
  touchAction: "manipulation",
217
  }}
218
+ className={`flex items-center justify-center rounded-full text-[6px] font-bold leading-none transition-colors shadow-md transform-gpu cursor-pointer select-none
219
  ${isCap
220
  ? activeChipType === "tc"
221
  ? "bg-purple-500 text-white border border-purple-300"
 
237
  minHeight: 0,
238
  touchAction: "manipulation",
239
  }}
240
+ className={`flex items-center justify-center rounded-full text-[6px] font-bold leading-none transition-colors shadow-md cursor-pointer select-none
241
  ${isVice ? "bg-slate-300 text-slate-900 border border-white" : "bg-slate-900/90 text-slate-400 border border-slate-700 hover:text-white"}`}
242
  >
243
  V
 
259
  }}
260
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transform-gpu transition-colors border border-red-400 shadow-md cursor-pointer select-none"
261
  >
262
+ <RotateCcw size={7} strokeWidth={2.5} />
263
  </div>
264
  ) : player.replacedPlayer ? (
265
  <div
 
276
  }}
277
  className="flex items-center justify-center rounded-full bg-red-600 hover:bg-red-500 text-white transform-gpu transition-colors border border-red-400 shadow-md cursor-pointer select-none"
278
  >
279
+ <RotateCcw size={7} strokeWidth={2.5} />
280
  </div>
281
  ) : null}
282
  </div>
 
337
  textSizeAdjust: "none",
338
  }}
339
  >
340
+ <div className={`w-full text-center py-[3px] truncate px-1 font-bold text-[9px] leading-tight rounded-t shadow-md
341
  ${isTransferIn ? "bg-cyan-600 text-white" : "bg-slate-950 text-slate-100 border border-slate-700"}`}>
342
  {player.Name}
343
  </div>
344
+ <div className="w-full bg-slate-200 border-x border-slate-700 flex justify-center items-center gap-1 py-[3px] shadow-inner">
345
+ <span className={`text-[9px] font-black flex items-baseline gap-[2px] leading-none ${isBlankThisGw ? "text-slate-400" : "text-slate-800"}`}>
346
  {isBlankThisGw ? "-" : (player[`${activeGW}_xMins`] ?? 90)}
347
+ <span className="text-[7px] font-bold text-slate-500 uppercase tracking-tight">xMins</span>
348
  </span>
349
+ <span className="text-slate-400 font-light text-[9px] leading-none">|</span>
350
+ <span className="text-[9px] font-black text-emerald-700 leading-none">
351
  £{getPlayerPrice(player).toFixed(1)}
352
  </span>
353
  </div>
354
+ <div className="w-full bg-slate-900 border-x border-b border-slate-700 flex items-center rounded-b shadow-md px-0.5 overflow-hidden" style={{ height: 19 }}>
355
  <div className="flex items-center justify-center w-full whitespace-nowrap overflow-hidden">
356
  {renderFixtures(player.Team, activeGW)}
357
  </div>