feat: replace header emoji buttons with reference Lucide-style icons
Add users, plus, and dual-monitor SVG icons with matching 32px circular button styles from Design Planning Hub. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { isDetailWindowOpen } from '../../lib/dualMonitor';
|
||||
import { DualMonitorIcon, PlusIcon, UsersIcon } from './HeaderIcons';
|
||||
|
||||
interface Stats {
|
||||
total: number;
|
||||
inProgress: number;
|
||||
@@ -15,9 +19,6 @@ interface DashboardHeaderProps {
|
||||
onOpenTaskManager: () => void;
|
||||
}
|
||||
|
||||
const ICON_BTN =
|
||||
'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]',
|
||||
@@ -34,8 +35,15 @@ export function DashboardHeader({
|
||||
onOpenDetailWindow,
|
||||
onOpenTaskManager,
|
||||
}: DashboardHeaderProps) {
|
||||
const [detailViewActive, setDetailViewActive] = useState(isDetailWindowOpen);
|
||||
const quarterLabel = quarter.replace(/^(\d{4})-Q(\d)$/, '$1 $2분기 업무');
|
||||
|
||||
const handleOpenDetailWindow = () => {
|
||||
void Promise.resolve(onOpenDetailWindow()).then(() => {
|
||||
setDetailViewActive(isDetailWindowOpen());
|
||||
});
|
||||
};
|
||||
|
||||
const statItems = [
|
||||
{ label: '전체', value: stats.total, statusKey: '전체' as const },
|
||||
{ label: '진행', value: stats.inProgress, statusKey: 'IN_PROGRESS' as const },
|
||||
@@ -52,8 +60,8 @@ export function DashboardHeader({
|
||||
<span>|</span>
|
||||
<span>People Growth Hub</span>
|
||||
</span>
|
||||
<button type="button" title="팀 현황" className={`${ICON_BTN} text-[15px]`}>
|
||||
👥
|
||||
<button type="button" title="팀 현황" className="team-status-btn-new">
|
||||
<UsersIcon size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -78,21 +86,16 @@ export function DashboardHeader({
|
||||
</div>
|
||||
|
||||
<div className="side-right-actions shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenTaskManager}
|
||||
title="업무관리"
|
||||
className={`header-action-btn-new ${ICON_BTN} text-[18px] font-bold leading-none`}
|
||||
>
|
||||
+
|
||||
<button type="button" onClick={onOpenTaskManager} title="신규 프로젝트 추가" className="header-action-btn-new">
|
||||
<PlusIcon size={16} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenDetailWindow}
|
||||
title="우측 모니터에 상세 창 열기"
|
||||
className={`header-view-btn-new ${ICON_BTN} text-[16px] leading-none`}
|
||||
onClick={handleOpenDetailWindow}
|
||||
title="듀얼뷰"
|
||||
className={`header-view-btn-new ${detailViewActive ? 'active' : ''}`}
|
||||
>
|
||||
🖥
|
||||
<DualMonitorIcon size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
73
frontend/src/components/dashboard/HeaderIcons.tsx
Normal file
73
frontend/src/components/dashboard/HeaderIcons.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
interface IconProps {
|
||||
size?: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function LucideSvg({ size = 16, className, children }: IconProps & { children: ReactNode }) {
|
||||
return (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={className}
|
||||
aria-hidden
|
||||
>
|
||||
{children}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/** 참고 사이트 lucide `users` */
|
||||
export function UsersIcon({ size = 16, className }: IconProps) {
|
||||
return (
|
||||
<LucideSvg size={size} className={className}>
|
||||
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
|
||||
<path d="M16 3.128a4 4 0 0 1 0 7.744" />
|
||||
<path d="M22 21v-2a4 4 0 0 0-3-3.87" />
|
||||
<circle cx="9" cy="7" r="4" />
|
||||
</LucideSvg>
|
||||
);
|
||||
}
|
||||
|
||||
/** 참고 사이트 lucide `plus` */
|
||||
export function PlusIcon({ size = 16, className }: IconProps) {
|
||||
return (
|
||||
<LucideSvg size={size} className={className}>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5v14" />
|
||||
</LucideSvg>
|
||||
);
|
||||
}
|
||||
|
||||
function MonitorIcon({ size = 16, className }: IconProps) {
|
||||
return (
|
||||
<LucideSvg size={size} className={className}>
|
||||
<rect width="20" height="14" x="2" y="3" rx="2" />
|
||||
<line x1="8" x2="16" y1="21" y2="21" />
|
||||
<line x1="12" x2="12" y1="17" y2="21" />
|
||||
</LucideSvg>
|
||||
);
|
||||
}
|
||||
|
||||
/** 참고 사이트 `dual-monitor-icon-wrap` — monitor 2개 겹침 */
|
||||
export function DualMonitorIcon({ size = 16, className }: IconProps) {
|
||||
const monitorSize = size * 0.75;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`dual-monitor-icon-wrap ${className ?? ''}`}
|
||||
style={{ width: size, height: size }}
|
||||
aria-hidden
|
||||
>
|
||||
<MonitorIcon size={monitorSize} className="m-icon m-back" />
|
||||
<MonitorIcon size={monitorSize} className="m-icon m-front" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -115,6 +115,78 @@ body,
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* F12 — 헤더 원형 아이콘 버튼 (team / + / 듀얼모니터) */
|
||||
.header-action-btn-new,
|
||||
.header-view-btn-new,
|
||||
.team-status-btn-new {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 1.5px solid #1a4d42;
|
||||
border-radius: 50%;
|
||||
color: #cef1eb;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(180deg, #0d3f34 0%, #051f19 100%);
|
||||
box-shadow: 0 0 0 1px #000, 0 2px 2px rgba(0, 0, 0, 0.6);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.header-action-btn-new svg,
|
||||
.header-view-btn-new svg,
|
||||
.team-status-btn-new svg {
|
||||
color: inherit;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.header-action-btn-new:hover,
|
||||
.header-view-btn-new:hover,
|
||||
.team-status-btn-new:hover {
|
||||
color: #fff;
|
||||
border-color: #36816d;
|
||||
background: linear-gradient(180deg, #115244 0%, #072b23 100%);
|
||||
transform: translateY(-1px);
|
||||
box-shadow:
|
||||
0 0 0 1px #000,
|
||||
0 0 8px rgba(36, 204, 158, 0.4),
|
||||
0 4px 8px rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
.header-action-btn-new:active,
|
||||
.header-action-btn-new.active,
|
||||
.header-view-btn-new.active,
|
||||
.team-status-btn-new.active {
|
||||
color: #cef1eb;
|
||||
border-color: #1a4d42;
|
||||
background: linear-gradient(180deg, #072b23 0%, #051f19 100%);
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 0 0 1px #000, 0 1px 2px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.dual-monitor-icon-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dual-monitor-icon-wrap .m-icon {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.dual-monitor-icon-wrap .m-back {
|
||||
top: 0;
|
||||
left: -3px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.dual-monitor-icon-wrap .m-front {
|
||||
right: -3px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* F12 Design Planning Hub — 타이틀 */
|
||||
.main_tit {
|
||||
color: #bad8ca;
|
||||
|
||||
Reference in New Issue
Block a user