시스템 상태 카드 — 눈금 레이블+블록바+신호등 동일 높이 정렬

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Macbook
2026-06-11 16:48:32 +09:00
parent 50aed38f62
commit 7b4a7e1950
2 changed files with 85 additions and 31 deletions
@@ -1,13 +1,15 @@
import React from 'react';
interface Props {
label: string;
pct: number; // 0100
usedLabel: string; // e.g. "5.8GB"
totalLabel: string; // e.g. "7.8GB"
label: string;
pct: number; // 0100
usedLabel: string;
totalLabel: string;
}
const BLOCKS = 12;
const BLOCKS = 10; // 10단계 (0%~100%, 10%씩)
// 눈금 레이블: top→bottom (100%→0%)
const TICK_LABELS = ['100%', '80%', '60%', '40%', '20%', '0%'];
function trafficLevel(pct: number): 'green' | 'yellow' | 'red' {
if (pct >= 90) return 'red';
@@ -15,9 +17,17 @@ function trafficLevel(pct: number): 'green' | 'yellow' | 'red' {
return 'green';
}
/** 리소스 카드 — 세로 블록 바 + 신호등 */
/** 블록 인덱스(0=bottom)에 따른 색상 — 낮은 사용률=초록, 높은 사용률=빨강 */
function blockTone(idx: number): string {
if (idx >= 8) return 'gc-sys-block--hi'; // 80100% → 빨강
if (idx >= 5) return 'gc-sys-block--mid'; // 5080% → 노랑
return 'gc-sys-block--lo'; // 050% → 초록
}
/** 리소스 카드 — 눈금 + 세로 블록 바 + 신호등 (같은 높이 정렬) */
export default function DashboardSystemCard({ label, pct, usedLabel, totalLabel }: Props) {
const clamped = Math.max(0, Math.min(100, pct));
// 아래→위로 채움: filled 개수만큼 하단부터 켜짐
const filled = Math.round((clamped / 100) * BLOCKS);
const level = trafficLevel(clamped);
@@ -25,15 +35,23 @@ export default function DashboardSystemCard({ label, pct, usedLabel, totalLabel
<div className="gc-sys-card">
<span className="gc-sys-card-title">{label}</span>
{/* 바 + 신호등을 같은 높이로 정렬 */}
<div className="gc-sys-card-body">
{/* 눈금 레이블 열 */}
<div className="gc-sys-ticks" aria-hidden>
{TICK_LABELS.map(t => (
<span key={t} className="gc-sys-tick">{t}</span>
))}
</div>
{/* 세로 블록 바 */}
<div className="gc-sys-bar-wrap" aria-hidden>
{Array.from({ length: BLOCKS }, (_, i) => {
const idx = BLOCKS - 1 - i; // 위→낮음, 아래→높음
const on = idx < filled;
let tone = 'gc-sys-block--mid';
if (idx >= BLOCKS - 3) tone = 'gc-sys-block--lo'; // 하위(초록)
else if (idx <= 2) tone = 'gc-sys-block--hi'; // 상위(빨강)
// i=0 → 화면 상단(100%), i=BLOCKS-1 → 화면 하단(0%)
const idxFromBottom = BLOCKS - 1 - i;
const on = idxFromBottom < filled;
const tone = blockTone(idxFromBottom);
return (
<span
key={i}
@@ -43,14 +61,18 @@ export default function DashboardSystemCard({ label, pct, usedLabel, totalLabel
})}
</div>
{/* 신호등 */}
<div className={`gc-traffic-light gc-traffic-light--${level}`} aria-label={`${label} 상태`}>
{/* 신호등 (바와 같은 높이) */}
<div
className={`gc-traffic-light gc-traffic-light--${level} gc-traffic-light--sized`}
aria-label={`${label} 상태`}
>
<span className="gc-traffic-bulb gc-traffic-bulb--r" />
<span className="gc-traffic-bulb gc-traffic-bulb--y" />
<span className="gc-traffic-bulb gc-traffic-bulb--g" />
</div>
</div>
{/* 하단 수치 */}
<div className="gc-sys-card-foot">
<span className="gc-sys-card-pct">{clamped.toFixed(0)}%</span>
<span className="gc-sys-card-detail">{usedLabel} / {totalLabel}</span>