diff --git a/components/layout/dock-app-icon.tsx b/components/layout/dock-app-icon.tsx
new file mode 100644
index 0000000..568558d
--- /dev/null
+++ b/components/layout/dock-app-icon.tsx
@@ -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 (
+
+ );
+}
diff --git a/components/layout/site-dock.tsx b/components/layout/site-dock.tsx
index b9f3fc6..5b0be07 100644
--- a/components/layout/site-dock.tsx
+++ b/components/layout/site-dock.tsx
@@ -1,13 +1,14 @@
"use client";
-import { FolderKanban, Home, Mail, Package, ShieldCheck, User } from "lucide-react";
+import { ShieldCheck } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useTheme } from "next-themes";
import { useLocale, useTranslations } from "next-intl";
-import { useEffect, useState, type ComponentType } from "react";
+import { useEffect, useState } from "react";
+import { DockAppIcon, type DockSymbol } from "@/components/layout/dock-app-icon";
import { LocaleToggle } from "@/components/layout/locale-toggle";
import { SoundToggle } from "@/components/sound-toggle";
import { ThemeToggle } from "@/components/theme-toggle";
@@ -30,18 +31,17 @@ type SiteDockProps = {
};
type NavItem = {
- key: "home" | "about" | "portfolio" | "products" | "contact";
+ key: DockSymbol;
path: string;
- Icon: ComponentType<{ className?: string }>;
disabled?: boolean;
};
const navItems: NavItem[] = [
- { key: "home", path: "", Icon: Home },
- { key: "about", path: "/about", Icon: User },
- { key: "portfolio", path: "/portfolio", Icon: FolderKanban },
- { key: "products", path: "/products", Icon: Package, disabled: true },
- { key: "contact", path: "/contact", Icon: Mail },
+ { key: "home", path: "" },
+ { key: "about", path: "/about" },
+ { key: "portfolio", path: "/portfolio" },
+ { key: "products", path: "/products", disabled: true },
+ { key: "contact", path: "/contact" },
];
function isNavItemActive(currentPath: string, itemPath: string) {
@@ -192,7 +192,7 @@ export function SiteDock({
className="pointer-events-auto h-[68px] gap-2.5 border-border/60 bg-background/70 shadow-panel"
>
{/* Logo — first icon in the dock */}
-
+
@@ -216,38 +216,29 @@ export function SiteDock({
- {navItems.map(({ key, path, Icon, disabled }) => {
+ {navItems.map(({ key, path, disabled }) => {
const itemPath = path || "/";
const isActive = isNavItemActive(currentPath, itemPath);
const label = t(key);
- const inner = (
-
-
-
- );
+ const icon = ;
return (
- {/* top gloss */}
-
{disabled ? (
-
- {inner}
+
+ {icon}
) : (
- {inner}
+ {icon}
)}
diff --git a/components/ui/dock.tsx b/components/ui/dock.tsx
index 4457be2..0b5d53d 100644
--- a/components/ui/dock.tsx
+++ b/components/ui/dock.tsx
@@ -107,7 +107,7 @@ const DockIcon = ({
...props
}: DockIconProps) => {
const ref = useRef(null);
- const padding = Math.max(4, size * 0.12);
+ const padding = Math.max(2, size * 0.05);
const defaultMouseX = useMotionValue(Infinity);
const distanceCalc = useTransform(mouseX ?? defaultMouseX, (val: number) => {