diff --git a/frontend/src/components/common/StatCard.tsx b/frontend/src/components/common/StatCard.tsx index f6c33cd..2944f1e 100644 --- a/frontend/src/components/common/StatCard.tsx +++ b/frontend/src/components/common/StatCard.tsx @@ -8,32 +8,58 @@ interface Props { onClick?: () => void } -export function StatCard({ title, value, sub, icon, color = '#e8ecff', trend, onClick }: Props) { +/* Variant 스타일 StatCard — screenshot9 카드 패턴 적용 */ +export function StatCard({ title, value, sub, icon, color = '#E8F0F8', trend, onClick }: Props) { return ( -
{ if (onClick) (e.currentTarget as HTMLDivElement).style.boxShadow = '0 4px 16px rgba(0,0,0,.1)' }} - onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.boxShadow = 'none' }} +
{ + const el = e.currentTarget as HTMLDivElement + el.style.boxShadow = '0 8px 24px rgba(0,51,102,.12)' + el.style.transform = 'translateY(-2px)' + }} + onMouseLeave={e => { + const el = e.currentTarget as HTMLDivElement + el.style.boxShadow = '0 2px 8px rgba(0,51,102,.06)' + el.style.transform = 'translateY(0)' + }} > -
+
+ {/* 아이콘 박스 — screenshot9 연파랑 박스 스타일 */}
{icon}
-
{value}
-
{title}
- {sub &&
{sub}
} +
+ {title} +
+
+ {value} +
+ {sub &&
{sub}
}
{trend && ( -
+
{trend.up ? '▲' : '▼'} {Math.abs(trend.val)}% 전주 대비
)} diff --git a/frontend/src/components/layout/AppLayout.tsx b/frontend/src/components/layout/AppLayout.tsx index 4fc07c6..d9a3346 100644 --- a/frontend/src/components/layout/AppLayout.tsx +++ b/frontend/src/components/layout/AppLayout.tsx @@ -35,7 +35,7 @@ export function AppLayout() {
{/* 페이지 타이틀 바 */}
diff --git a/frontend/src/components/layout/GNB.tsx b/frontend/src/components/layout/GNB.tsx index 91e9bcc..c891148 100644 --- a/frontend/src/components/layout/GNB.tsx +++ b/frontend/src/components/layout/GNB.tsx @@ -12,34 +12,53 @@ export function GNB() { return (
- {/* 로고 */} + {/* 로고 — Variant 스타일 */}
- 🛡️ - GUARDiA Manager - v2.0 +
G
+ + GUARDiA Manager + + v2.0
{/* 우측 */}
- + 🌐 ITSM 바로가기 {user && ( <> 👤 {user.display_name ?? user.username} )} diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index bda358c..1f11bd4 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -37,42 +37,66 @@ const NAV: NavItem[] = [ ]}, ] +/* Variant 스타일 색상 상수 */ +const V = { + navy: '#003366', + blue: '#005A8C', + cyan: '#00A0C8', + cyanLt: 'rgba(0,160,200,.10)', + cyanAct: 'rgba(0,160,200,.15)', + muted: '#64748B', + text: '#334155', + border: '#E2E8F0', + bg: '#F8FAFC', +} + function NavGroup({ item }: { item: NavItem }) { const [open, setOpen] = useState(true) + if (!item.children) { return ( ({ display: 'flex', alignItems: 'center', gap: 8, - padding: '8px 16px', fontSize: 13, color: isActive ? '#1a3a6b' : '#475569', - background: isActive ? '#dde4f5' : 'transparent', - borderLeft: isActive ? '3px solid #4f6ef7' : '3px solid transparent', + padding: '8px 16px', fontSize: 13, + color: isActive ? V.navy : V.muted, + background: isActive ? V.cyanAct : 'transparent', + borderLeft: isActive ? `3px solid ${V.cyan}` : '3px solid transparent', + fontWeight: isActive ? 700 : 400, transition: 'all .15s', + textDecoration: 'none', })}> {item.icon} {item.label} ) } + return (
{open && item.children.map(c => ( ({ display: 'flex', alignItems: 'center', padding: '7px 16px 7px 42px', fontSize: 12.5, - color: isActive ? '#1a3a6b' : '#64748b', - background: isActive ? '#dde4f5' : 'transparent', - borderLeft: isActive ? '3px solid #4f6ef7' : '3px solid transparent', + color: isActive ? V.navy : V.muted, + background: isActive ? V.cyanAct : 'transparent', + borderLeft: isActive ? `3px solid ${V.cyan}` : '3px solid transparent', + fontWeight: isActive ? 600 : 400, transition: 'all .15s', + textDecoration: 'none', })}> {c.label} @@ -84,11 +108,24 @@ function NavGroup({ item }: { item: NavItem }) { export function Sidebar() { return (