You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
6.3 KiB
JavaScript
124 lines
6.3 KiB
JavaScript
/* 아리 — 공용 셸 (아이콘 + 상단바)
|
|
전용 페이지(결재함·스마트 인박스 등)에서 재사용.
|
|
window.AriShell = { Icon, Topbar } */
|
|
(function () {
|
|
const { useState, useEffect } = React;
|
|
|
|
const P = {
|
|
spark: "M12 3l1.9 5.2L19 10l-5.1 1.8L12 17l-1.9-5.2L5 10l5.1-1.8z|M19 4v3|M5 17v3",
|
|
grid: "M3 3h7v7H3z|M14 3h7v7h-7z|M14 14h7v7h-7z|M3 14h7v7H3z",
|
|
route: "M6 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6z|M18 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z|M9 16h6a3 3 0 0 0 3-3V11",
|
|
cal: "M8 2v4M16 2v4M3 10h18M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",
|
|
check: "M9 11l3 3L22 4|M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11",
|
|
tick: "M20 6 9 17l-5-5",
|
|
mail: "M22 7 13.03 12.7a1.94 1.94 0 0 1-2.06 0L2 7|M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",
|
|
target: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20z|M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z|M12 12h.01",
|
|
heart: "M19 14c1.5-1.5 3-3.4 3-5.5A4.5 4.5 0 0 0 12 5.5 4.5 4.5 0 0 0 2 8.5c0 2.1 1.5 4 3 5.5l7 7z",
|
|
wallet: "M19 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0 0 4h15a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5|M16 12h.01",
|
|
brain: "M12 5a3 3 0 1 0-5.9.8A3 3 0 0 0 4 9.5 3 3 0 0 0 6 14a3 3 0 0 0 6 1zM12 5a3 3 0 1 1 5.9.8A3 3 0 0 1 20 9.5 3 3 0 0 1 18 14a3 3 0 0 1-6 1z|M12 5v14",
|
|
zap: "M13 2 3 14h9l-1 8 10-12h-9z",
|
|
more: "M5 12a1 1 0 1 0 2 0 1 1 0 0 0-2 0zM11 12a1 1 0 1 0 2 0 1 1 0 0 0-2 0zM17 12a1 1 0 1 0 2 0 1 1 0 0 0-2 0z",
|
|
search: "M21 21l-4.34-4.34|M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z",
|
|
bell: "M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9|M10.3 21a1.94 1.94 0 0 0 3.4 0",
|
|
back: "M19 12H5|M12 19l-7-7 7-7",
|
|
send: "M22 2 11 13|M22 2 15 22l-4-9-9-4z",
|
|
sun: "M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10z|M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4",
|
|
moon: "M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8z",
|
|
swap: "M16 3h5v5|M21 3l-7 7|M8 21H3v-5|M3 21l7-7",
|
|
up: "M12 19V5|M5 12l7-7 7 7",
|
|
arrow: "M5 12h14|M13 6l6 6-6 6",
|
|
inbox: "M22 12h-6l-2 3h-4l-2-3H2|M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",
|
|
mic: "M12 2a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z|M19 10v1a7 7 0 0 1-14 0v-1|M12 18v4M8 22h8",
|
|
image: "M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z|M8.5 11a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z|M21 15l-5-5L5 21",
|
|
pen: "M12 20h9|M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z",
|
|
users: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2|M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z|M23 21v-2a4 4 0 0 0-3-3.87|M16 3.13a4 4 0 0 1 0 7.75",
|
|
clock: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20z|M12 7v5l3 2",
|
|
play: "M6 3l15 9-15 9z",
|
|
plus: "M12 5v14M5 12h14",
|
|
shield: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",
|
|
pin: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z|M12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",
|
|
};
|
|
|
|
function Icon({ d, w }) {
|
|
return (
|
|
<svg className="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
strokeWidth={w || 1.9} strokeLinecap="round" strokeLinejoin="round">
|
|
{P[d].split("|").map((s, i) => <path key={i} d={s} />)}
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
const MAIN = [
|
|
{ id: "dash", label: "대시보드", icon: "grid", href: "대시보드.html" },
|
|
{ id: "sbox", label: "인박스", icon: "inbox", href: "인박스.html" },
|
|
{ id: "appr", label: "결재함", icon: "spark", badge: "3", href: "결재함.html" },
|
|
{ id: "auto", label: "자동화", icon: "zap", href: "자동화.html" },
|
|
{ id: "journey", label: "여정", icon: "route", href: "여정.html" },
|
|
{ id: "cal", label: "일정", icon: "cal", href: "일정.html" },
|
|
{ id: "task", label: "작업", icon: "check", badge: "4", href: "작업.html" },
|
|
{ id: "mail", label: "메일", icon: "mail", href: "메일.html" },
|
|
{ id: "noti", label: "알림", icon: "bell", badge: "6", href: "알림.html" },
|
|
{ id: "research", label: "리서치", icon: "brain", href: "리서치.html" },
|
|
{ id: "trip", label: "여행", icon: "send", href: "여행.html" },
|
|
{ id: "life", label: "라이프", icon: "heart", href: "라이프.html" },
|
|
{ id: "wrap", label: "하루 마감", icon: "moon", href: "하루 마감.html" },
|
|
];
|
|
|
|
function Topbar({ current }) {
|
|
const [theme, setTheme] = useState("light");
|
|
useEffect(() => { document.documentElement.setAttribute("data-theme", theme); }, [theme]);
|
|
const D = window.AriData;
|
|
return (
|
|
<header className="topbar">
|
|
<div className="brand">
|
|
<div className="brand-mark"><Icon d="spark" /></div>
|
|
<div className="brand-tag"><b>아리</b><span>AI LIFE OS</span></div>
|
|
</div>
|
|
<nav className="mainnav">
|
|
{MAIN.map((m) => (
|
|
<a key={m.id} href={m.href} className={current === m.id ? "active" : ""}>
|
|
<Icon d={m.icon} />
|
|
{m.label}
|
|
{m.badge && <span className="badge">{m.badge}</span>}
|
|
</a>
|
|
))}
|
|
</nav>
|
|
<div className="top-actions">
|
|
<button className="t-btn" aria-label="검색"><Icon d="search" /></button>
|
|
<button className="t-btn dot" aria-label="알림"><Icon d="bell" /></button>
|
|
<button className="t-btn" aria-label="테마" onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
|
|
<Icon d={theme === "light" ? "moon" : "sun"} />
|
|
</button>
|
|
<div className="t-ava">{D.user.initial}</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|
|
|
|
/* 좌측 서브 레일 — 페이지 안에서 하위 화면을 전환 (아이콘 + 툴팁)
|
|
items: [{ id, icon, label, dot? } | { sep:true }] */
|
|
function SubRail({ items, active, onPick }) {
|
|
return (
|
|
<aside className="rail">
|
|
{items.map((r, i) =>
|
|
r.sep ? <span className="sp" key={"s" + i} /> : (
|
|
<button
|
|
key={r.id}
|
|
className={active === r.id ? "active" : ""}
|
|
onClick={() => onPick(r.id)}
|
|
aria-label={r.label}
|
|
aria-current={active === r.id ? "page" : undefined}
|
|
>
|
|
<Icon d={r.icon} />
|
|
{r.dot && <span className="rdot" />}
|
|
<span className="tip">{r.label}</span>
|
|
</button>
|
|
)
|
|
)}
|
|
</aside>
|
|
);
|
|
}
|
|
|
|
window.AriShell = { Icon, Topbar, SubRail };
|
|
})();
|