130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
|
|
import type { ReactNode, SVGProps } from "react";
|
|||
|
|
import type { NavKey } from "../../lib/nav";
|
|||
|
|
|
|||
|
|
export type AppIconName = NavKey | "more" | "spark";
|
|||
|
|
|
|||
|
|
type Props = {
|
|||
|
|
name: AppIconName;
|
|||
|
|
size?: number;
|
|||
|
|
className?: string;
|
|||
|
|
} & Omit<SVGProps<SVGSVGElement>, "name">;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 精緻線稿 icon:圓潤端點、雙層深度、細微星芒(魔法感但不吵)
|
|||
|
|
* 可隨 currentColor 換色,適配 light / dark。
|
|||
|
|
*/
|
|||
|
|
export function AppIcon({ name, size = 22, className = "", ...rest }: Props) {
|
|||
|
|
return (
|
|||
|
|
<svg
|
|||
|
|
width={size}
|
|||
|
|
height={size}
|
|||
|
|
viewBox="0 0 24 24"
|
|||
|
|
fill="none"
|
|||
|
|
className={`hb-app-icon ${className}`.trim()}
|
|||
|
|
aria-hidden
|
|||
|
|
{...rest}
|
|||
|
|
>
|
|||
|
|
{glyphs[name]}
|
|||
|
|
</svg>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const stroke = {
|
|||
|
|
stroke: "currentColor",
|
|||
|
|
strokeWidth: 1.5,
|
|||
|
|
strokeLinecap: "round" as const,
|
|||
|
|
strokeLinejoin: "round" as const,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/** 小星芒 */
|
|||
|
|
function Spark({ x = 18, y = 5, s = 1 }: { x?: number; y?: number; s?: number }) {
|
|||
|
|
return (
|
|||
|
|
<g opacity={0.85} transform={`translate(${x} ${y}) scale(${s})`}>
|
|||
|
|
<path d="M0-2.2V2.2M-2.2 0H2.2" {...stroke} strokeWidth={1.35} />
|
|||
|
|
</g>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const glyphs: Record<AppIconName, ReactNode> = {
|
|||
|
|
// 今日:圓角日曆 + 星
|
|||
|
|
today: (
|
|||
|
|
<>
|
|||
|
|
<rect x="3.5" y="5" width="17" height="15" rx="3.5" {...stroke} />
|
|||
|
|
<path d="M8 3.75v3.1M16 3.75v3.1M3.5 10.25h17" {...stroke} />
|
|||
|
|
<circle cx="9.2" cy="14.6" r="1.05" fill="currentColor" opacity={0.9} />
|
|||
|
|
<Spark x={16.2} y={14.4} s={0.72} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 帳號:雙圓 + 柔弧(島民)
|
|||
|
|
crew: (
|
|||
|
|
<>
|
|||
|
|
<circle cx="9" cy="8.6" r="3" {...stroke} />
|
|||
|
|
<path d="M4 18.2c.55-2.9 2.7-4.35 5-4.35 2.3 0 4.45 1.45 5 4.35" {...stroke} />
|
|||
|
|
<circle cx="16.6" cy="9.4" r="2.35" {...stroke} opacity={0.85} />
|
|||
|
|
<path d="M14.2 18.2c.35-1.85 1.55-2.85 3.15-2.85 1.35 0 2.45.7 3.05 1.9" {...stroke} opacity={0.85} />
|
|||
|
|
<Spark x={18.8} y={5.2} s={0.55} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 創作:羽毛筆 + 星
|
|||
|
|
studio: (
|
|||
|
|
<>
|
|||
|
|
<path
|
|||
|
|
d="M5.2 19.2 14.6 5.4a1.7 1.7 0 0 1 2.45-.15l1.9 1.9a1.7 1.7 0 0 1-.15 2.45L9.3 19.2H5.2z"
|
|||
|
|
{...stroke}
|
|||
|
|
/>
|
|||
|
|
<path d="M12.7 7.9 16.1 11.3" {...stroke} />
|
|||
|
|
<path d="M5.2 19.2 8.1 18.3" {...stroke} opacity={0.7} />
|
|||
|
|
<Spark x={18.5} y={5.5} s={0.7} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 海巡:水晶球 / 羅盤弧 + 十字光
|
|||
|
|
scout: (
|
|||
|
|
<>
|
|||
|
|
<circle cx="11.2" cy="11.2" r="6.4" {...stroke} />
|
|||
|
|
<circle cx="11.2" cy="11.2" r="2.15" {...stroke} opacity={0.55} />
|
|||
|
|
<path d="M11.2 6.4v9.6M6.4 11.2h9.6" {...stroke} opacity={0.55} />
|
|||
|
|
<path d="M15.8 15.8 20.2 20.2" {...stroke} />
|
|||
|
|
<Spark x={18.2} y={6.2} s={0.62} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 發送:紙飛機 + 軌跡星
|
|||
|
|
outbox: (
|
|||
|
|
<>
|
|||
|
|
<path d="M4.2 11.1 19.6 4.6 12.2 19.8l-1.7-6.3z" {...stroke} />
|
|||
|
|
<path d="M10.5 13.5 19.6 4.6" {...stroke} opacity={0.65} />
|
|||
|
|
<Spark x={7.2} y={7.5} s={0.5} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 任務:魔法卷軸/手提袋簡化
|
|||
|
|
jobs: (
|
|||
|
|
<>
|
|||
|
|
<rect x="4.2" y="7.2" width="15.6" height="12.2" rx="2.6" {...stroke} />
|
|||
|
|
<path d="M9 7.2V5.9a2.1 2.1 0 0 1 2.1-2.1h1.8A2.1 2.1 0 0 1 15 5.9v1.3" {...stroke} />
|
|||
|
|
<path d="M4.2 12.1h15.6" {...stroke} opacity={0.55} />
|
|||
|
|
<Spark x={17.5} y={15.8} s={0.55} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
// 品牌:旗幟堡壘簡化 + 星
|
|||
|
|
brands: (
|
|||
|
|
<>
|
|||
|
|
<path d="M6.2 20V9.1L12 5.2 17.8 9.1V20" {...stroke} />
|
|||
|
|
<path d="M10.2 20v-4.6h3.6V20" {...stroke} />
|
|||
|
|
<path d="M12 9.6v2.4" {...stroke} opacity={0.55} />
|
|||
|
|
<Spark x={17.8} y={6.4} s={0.58} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
more: (
|
|||
|
|
<>
|
|||
|
|
<circle cx="6.5" cy="12" r="1.45" fill="currentColor" />
|
|||
|
|
<circle cx="12" cy="12" r="1.45" fill="currentColor" />
|
|||
|
|
<circle cx="17.5" cy="12" r="1.45" fill="currentColor" />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
spark: (
|
|||
|
|
<>
|
|||
|
|
<Spark x={12} y={12} s={1.35} />
|
|||
|
|
<circle cx="12" cy="12" r="1.1" fill="currentColor" opacity={0.35} />
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
};
|