IMPROVED - Add custom macOS-style squircle app icons to the dock
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
"use client";
|
||||
|
||||
import { useId } from "react";
|
||||
|
||||
export type DockSymbol = "home" | "about" | "portfolio" | "products" | "contact";
|
||||
|
||||
/**
|
||||
* macOS Big Sur–style squircle app icon, drawn entirely in SVG so it stays
|
||||
* crisp at every magnification step. Inactive icons use a neutral graphite
|
||||
* gradient; the active icon lights up in the brand coral.
|
||||
*/
|
||||
export function DockAppIcon({
|
||||
symbol,
|
||||
active = false,
|
||||
disabled = false,
|
||||
}: {
|
||||
symbol: DockSymbol;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const uid = useId().replace(/[:]/g, "");
|
||||
const bg = `bg-${uid}`;
|
||||
const gloss = `gloss-${uid}`;
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
className="h-full w-full"
|
||||
role="presentation"
|
||||
style={disabled ? { opacity: 0.55 } : undefined}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id={bg} x1="0" y1="0" x2="0" y2="1">
|
||||
{active ? (
|
||||
<>
|
||||
<stop offset="0" stopColor="#ff8a5f" />
|
||||
<stop offset="1" stopColor="#e5431f" />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<stop offset="0" stopColor="#454b57" />
|
||||
<stop offset="1" stopColor="#1c2027" />
|
||||
</>
|
||||
)}
|
||||
</linearGradient>
|
||||
<linearGradient id={gloss} x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stopColor="#ffffff" stopOpacity="0.28" />
|
||||
<stop offset="0.5" stopColor="#ffffff" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
{/* tile */}
|
||||
<rect x="4" y="4" width="92" height="92" rx="26" fill={`url(#${bg})`} />
|
||||
<rect x="4" y="4" width="92" height="92" rx="26" fill={`url(#${gloss})`} />
|
||||
<rect
|
||||
x="4.75"
|
||||
y="4.75"
|
||||
width="90.5"
|
||||
height="90.5"
|
||||
rx="25.25"
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
strokeOpacity="0.14"
|
||||
strokeWidth="1.5"
|
||||
/>
|
||||
|
||||
{/* symbol */}
|
||||
<g
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
strokeWidth="6"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
{symbol === "home" && (
|
||||
<>
|
||||
<path d="M29 49 L50 30 L71 49" />
|
||||
<path d="M34 46 V70 H66 V46" />
|
||||
</>
|
||||
)}
|
||||
{symbol === "about" && (
|
||||
<>
|
||||
<circle cx="50" cy="41" r="11" />
|
||||
<path d="M30 72 C30 57, 70 57, 70 72" />
|
||||
</>
|
||||
)}
|
||||
{symbol === "contact" && (
|
||||
<>
|
||||
<rect x="27" y="35" width="46" height="30" rx="6" />
|
||||
<path d="M30 40 L50 54 L70 40" />
|
||||
</>
|
||||
)}
|
||||
</g>
|
||||
|
||||
{/* filled symbols */}
|
||||
{symbol === "portfolio" && (
|
||||
<g fill="#ffffff">
|
||||
<rect x="32" y="32" width="15" height="15" rx="4" />
|
||||
<rect x="53" y="32" width="15" height="15" rx="4" />
|
||||
<rect x="32" y="53" width="15" height="15" rx="4" />
|
||||
<rect x="53" y="53" width="15" height="15" rx="4" />
|
||||
</g>
|
||||
)}
|
||||
{symbol === "products" && (
|
||||
<g
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
strokeWidth="6"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M50 28 L71 40 L71 60 L50 72 L29 60 L29 40 Z" />
|
||||
<path d="M29 40 L50 52 L71 40" />
|
||||
<path d="M50 52 L50 72" />
|
||||
</g>
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user