thread-master/apps/web/src/components/ui/AppIcons.tsx

130 lines
3.8 KiB
TypeScript
Raw Normal View History

2026-07-10 05:10:31 +00:00
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} />
</>
),
};