style: apply exact F12 DevTools values from Design Planning header
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -16,7 +16,15 @@ interface DashboardHeaderProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ICON_BTN =
|
const ICON_BTN =
|
||||||
'grid h-8 w-8 shrink-0 place-items-center rounded-full border-[1.5px] border-[#1a4d42] bg-[linear-gradient(180deg,#0d3f34_0%,#051f19_100%)] text-[#cef1eb] shadow-[0_0_0_1px_#000,0_2px_2px_rgba(0,0,0,0.60)] transition hover:brightness-125';
|
'team-status-btn-new grid h-8 w-8 shrink-0 place-items-center rounded-full border-[1.5px] border-[#1a4d42] bg-[linear-gradient(180deg,#0d3f34_0%,#051f19_100%)] text-[#cef1eb] shadow-[0_0_0_1px_#000,0_2px_2px_rgba(0,0,0,0.60)] transition hover:brightness-125';
|
||||||
|
|
||||||
|
const STAT_ACCENT = {
|
||||||
|
전체: 'text-[#ffdb3a]',
|
||||||
|
IN_PROGRESS: 'text-[#10b981]',
|
||||||
|
REVIEW: 'text-[#ff9f0a]',
|
||||||
|
DONE: 'text-[#e2e8f0]',
|
||||||
|
ISSUES: 'text-[#ff5252]',
|
||||||
|
} as const;
|
||||||
|
|
||||||
export function DashboardHeader({
|
export function DashboardHeader({
|
||||||
quarter,
|
quarter,
|
||||||
@@ -28,41 +36,57 @@ export function DashboardHeader({
|
|||||||
}: DashboardHeaderProps) {
|
}: DashboardHeaderProps) {
|
||||||
const quarterLabel = quarter.replace(/^(\d{4})-Q(\d)$/, '$1 $2분기 업무');
|
const quarterLabel = quarter.replace(/^(\d{4})-Q(\d)$/, '$1 $2분기 업무');
|
||||||
|
|
||||||
|
const statItems = [
|
||||||
|
{ label: '전체', value: stats.total, statusKey: '전체' as const },
|
||||||
|
{ label: '진행', value: stats.inProgress, statusKey: 'IN_PROGRESS' as const },
|
||||||
|
{ label: '보류', value: stats.review, statusKey: 'REVIEW' as const },
|
||||||
|
{ label: '완료', value: stats.done, statusKey: 'DONE' as const },
|
||||||
|
{ label: '이슈', value: stats.issues, statusKey: 'ISSUES' as const, issue: true },
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="relative flex h-12 shrink-0 items-center overflow-hidden bg-[linear-gradient(180deg,#37a184_0%,#29724f_20%,#07412e_100%)] px-5 text-white shadow-[0_2px_10px_rgba(0,0,0,0.20)]">
|
<header className="relative flex h-12 shrink-0 items-center overflow-hidden bg-[linear-gradient(180deg,#37a184_0%,#29724f_20%,#07412e_100%)] px-5 text-white shadow-[0_2px_10px_rgba(0,0,0,0.20)]">
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 h-[45%] bg-white/10" />
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-[45%] bg-white/10" />
|
||||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-px bg-emerald-200/50" />
|
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-px bg-emerald-200/50" />
|
||||||
|
|
||||||
<div className="relative z-10 flex h-full min-w-0 shrink-0 items-center gap-3">
|
<div className="side-left-group relative z-10 flex h-full min-w-0 shrink-0 items-center gap-3">
|
||||||
<span className="shrink-0 text-[20px] font-bold tracking-[-0.5px] text-[#bad8ca] [text-shadow:1px_1px_1px_rgba(0,48,36,0.5)]">
|
<span className="side-title-main main_tit shrink-0 text-[20px] font-bold tracking-[-0.5px] text-[#bad8ca]">
|
||||||
총괄기획실 | People Growth Hub
|
총괄기획실 | People Growth Hub
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button type="button" title="팀 현황" className={`${ICON_BTN} text-[15px]`}>
|
||||||
type="button"
|
|
||||||
title="팀 현황"
|
|
||||||
className={`${ICON_BTN} text-[15px]`}
|
|
||||||
>
|
|
||||||
👥
|
👥
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="header-stats-bar absolute left-1/2 top-0 z-10 flex h-10 -translate-x-1/2 items-center justify-center gap-7 rounded-b-2xl border-b border-[#135643] bg-[linear-gradient(90deg,#093023_20%,#074833_50%,#093023_80%)] px-12 [filter:drop-shadow(0_2px_4px_rgba(0,0,0,0.2))]">
|
<div className="header-stats-bar side-polygon-stats absolute left-1/2 top-0 z-10 flex h-10 -translate-x-1/2 items-center justify-center rounded-b-2xl border-b border-[#135643] bg-[linear-gradient(90deg,#093023_20%,#074833_50%,#093023_80%)] px-12 [filter:drop-shadow(0_2px_4px_rgba(0,0,0,0.2))]">
|
||||||
<span className="shrink-0 whitespace-nowrap text-[20px] font-extrabold tracking-[-0.3px] text-white/90">
|
<div className="poly-stat-item flex items-center gap-2 text-[18px]">
|
||||||
{quarterLabel}
|
<span className="header-stat-text shrink-0 whitespace-nowrap font-semibold text-[rgba(255,255,255,0.77)]">
|
||||||
</span>
|
{quarterLabel}
|
||||||
<StatItem label="전체" value={stats.total} statusKey="전체" activeStatus={activeStatus} onClick={onStatusChange} accent="text-[#ffd60a]" />
|
</span>
|
||||||
<StatItem label="진행" value={stats.inProgress} statusKey="IN_PROGRESS" activeStatus={activeStatus} onClick={onStatusChange} accent="text-[#10b981]" />
|
<span className="header-stat-text text-[#eeeae3]/60">·</span>
|
||||||
<StatItem label="보류" value={stats.review} statusKey="REVIEW" activeStatus={activeStatus} onClick={onStatusChange} accent="text-[#ff9f0a]" dot="orange" />
|
{statItems.map((item, index) => (
|
||||||
<StatItem label="완료" value={stats.done} statusKey="DONE" activeStatus={activeStatus} onClick={onStatusChange} accent="text-[#e2e8f0]" />
|
<span key={item.statusKey} className="flex items-center gap-2">
|
||||||
<StatItem label="이슈" value={stats.issues} statusKey="ISSUES" activeStatus={activeStatus} onClick={onStatusChange} accent="text-[#ff5252]" dot="red" issue />
|
{index > 0 && <StatDivider />}
|
||||||
|
<StatClick
|
||||||
|
label={item.label}
|
||||||
|
value={item.value}
|
||||||
|
statusKey={item.statusKey}
|
||||||
|
activeStatus={activeStatus}
|
||||||
|
accent={STAT_ACCENT[item.statusKey]}
|
||||||
|
issue={item.issue}
|
||||||
|
onClick={onStatusChange}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10 ml-auto flex shrink-0 items-center gap-3">
|
<div className="side-right-actions relative z-10 ml-auto flex shrink-0 items-center gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onOpenTaskManager}
|
onClick={onOpenTaskManager}
|
||||||
title="업무관리"
|
title="업무관리"
|
||||||
className={`${ICON_BTN} text-[18px] font-bold leading-none`}
|
className={`header-action-btn-new ${ICON_BTN} text-[18px] font-bold leading-none`}
|
||||||
>
|
>
|
||||||
+
|
+
|
||||||
</button>
|
</button>
|
||||||
@@ -70,7 +94,7 @@ export function DashboardHeader({
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={onOpenDetailWindow}
|
onClick={onOpenDetailWindow}
|
||||||
title="우측 모니터에 상세 창 열기"
|
title="우측 모니터에 상세 창 열기"
|
||||||
className={`${ICON_BTN} text-[16px] leading-none`}
|
className={`header-view-btn-new ${ICON_BTN} text-[16px] leading-none`}
|
||||||
>
|
>
|
||||||
🖥
|
🖥
|
||||||
</button>
|
</button>
|
||||||
@@ -79,39 +103,34 @@ export function DashboardHeader({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StatItemProps {
|
function StatDivider() {
|
||||||
label: string;
|
return <span className="h-4 w-px shrink-0 bg-[rgba(238,234,227,0.4)]" aria-hidden />;
|
||||||
value: number;
|
|
||||||
statusKey: string;
|
|
||||||
activeStatus: string;
|
|
||||||
onClick: (key: string) => void;
|
|
||||||
accent: string;
|
|
||||||
dot?: 'orange' | 'red' | 'yellow';
|
|
||||||
issue?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function StatItem({ label, value, statusKey, activeStatus, onClick, accent, dot, issue }: StatItemProps) {
|
interface StatClickProps {
|
||||||
|
label: string;
|
||||||
|
value: number;
|
||||||
|
statusKey: keyof typeof STAT_ACCENT;
|
||||||
|
activeStatus: string;
|
||||||
|
accent: string;
|
||||||
|
issue?: boolean;
|
||||||
|
onClick: (key: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function StatClick({ label, value, statusKey, activeStatus, accent, issue, onClick }: StatClickProps) {
|
||||||
const isActive = activeStatus === statusKey;
|
const isActive = activeStatus === statusKey;
|
||||||
const bg = issue
|
|
||||||
? 'bg-[linear-gradient(180deg,#337c5f_0%,#1c4638_100%)] border border-[#1d6947]'
|
|
||||||
: isActive
|
|
||||||
? 'bg-[linear-gradient(180deg,rgba(0,0,0,0.54)_0%,rgba(0,0,0,0.25)_20%,rgba(0,0,0,0.09)_80%,rgba(0,0,0,0.54)_100%)] border border-black/80'
|
|
||||||
: 'border border-transparent hover:bg-[#1b543b] hover:border-[#1d6947]';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => onClick(isActive ? '전체' : statusKey)}
|
onClick={() => onClick(isActive ? '전체' : statusKey)}
|
||||||
className={`flex h-[30px] cursor-pointer select-none items-center gap-4 whitespace-nowrap rounded px-2 text-[24px] font-bold leading-none tracking-[-0.3px] text-[#eeeae3] transition hover:brightness-110 ${bg} ${
|
className={`poly-click-stat header-stat-text cursor-pointer whitespace-nowrap rounded px-1.5 py-0.5 text-[18px] leading-none ${
|
||||||
isActive && !issue ? 'font-semibold' : 'font-bold'
|
isActive ? 'active' : ''
|
||||||
}`}
|
} ${issue && !isActive ? 'issue' : ''}`}
|
||||||
>
|
>
|
||||||
{dot && <span className={`poly-stat-dot poly-stat-dot-${dot}`} />}
|
{label}{' '}
|
||||||
<span>{label}</span>
|
<span className={`font-extrabold ${accent}`}>{value}</span>
|
||||||
<span className={`font-extrabold ${accent}`}>
|
<span className="text-[14px] font-medium opacity-50">건</span>
|
||||||
{value}
|
|
||||||
<span className="font-normal">건</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,3 +59,59 @@ body,
|
|||||||
background-color: #ffeb3b;
|
background-color: #ffeb3b;
|
||||||
box-shadow: 0 0 8px #ffeb3b, inset 0 1px 2px rgba(255, 255, 255, 0.4);
|
box-shadow: 0 0 8px #ffeb3b, inset 0 1px 2px rgba(255, 255, 255, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* F12 Design Planning Hub — 타이틀 */
|
||||||
|
.main_tit {
|
||||||
|
color: #bad8ca;
|
||||||
|
font-weight: 700;
|
||||||
|
text-shadow:
|
||||||
|
-1px -1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
1px -1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
-1px 1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
1px 1px 1px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* F12 — 통계 영역 텍스트 그림자 */
|
||||||
|
.header-stat-text {
|
||||||
|
text-shadow:
|
||||||
|
-1px -1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
1px -1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
-1px 1px 1px rgba(0, 0, 0, 0.25),
|
||||||
|
1px 1px 1px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* F12 — poly-click-stat */
|
||||||
|
.poly-click-stat {
|
||||||
|
color: rgba(255, 255, 255, 0.99);
|
||||||
|
font-weight: 400;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background: transparent;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poly-click-stat:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: #1b543b;
|
||||||
|
border-color: #1d6947;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.poly-click-stat.active {
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(0, 0, 0, 0.54) 0%,
|
||||||
|
rgba(0, 0, 0, 0.25) 20%,
|
||||||
|
rgba(0, 0, 0, 0.09) 80%,
|
||||||
|
rgba(0, 0, 0, 0.54) 100%
|
||||||
|
);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.86);
|
||||||
|
box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.poly-click-stat.issue {
|
||||||
|
background: linear-gradient(180deg, #337c5f 0%, #1c4638 100%);
|
||||||
|
border: 1px solid #1d6947;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user