From 70203732d25fd18d55e77fddfa2ee878f3fe233a Mon Sep 17 00:00:00 2001 From: moh Date: Sun, 20 Sep 2026 19:37:17 +0200 Subject: [PATCH] REVERTED - Restore corner radial controls; make dock icons full-bleed - Bring back the corner fan-out controls; drop the in-dock settings tile. - Regenerate public/dock/*.svg so the squircle fills the whole tile with no inner margin. --- components/layout/floating-controls.tsx | 149 ++++++++++++++++++++++++ components/layout/site-dock.tsx | 128 +------------------- public/dock/about-active.svg | 8 +- public/dock/about.svg | 8 +- public/dock/contact-active.svg | 8 +- public/dock/contact.svg | 8 +- public/dock/home-active.svg | 8 +- public/dock/home.svg | 8 +- public/dock/portfolio-active.svg | 8 +- public/dock/portfolio.svg | 8 +- public/dock/products-active.svg | 8 +- public/dock/products.svg | 8 +- 12 files changed, 195 insertions(+), 162 deletions(-) create mode 100644 components/layout/floating-controls.tsx diff --git a/components/layout/floating-controls.tsx b/components/layout/floating-controls.tsx new file mode 100644 index 0000000..dbf8832 --- /dev/null +++ b/components/layout/floating-controls.tsx @@ -0,0 +1,149 @@ +"use client"; + +import { AnimatePresence, motion, useReducedMotion } from "framer-motion"; +import { Plus, ShieldCheck } from "lucide-react"; +import { useLocale, useTranslations } from "next-intl"; +import { useState, type ReactNode } from "react"; + +import { LocaleToggle } from "@/components/layout/locale-toggle"; +import { SoundToggle } from "@/components/sound-toggle"; +import { ThemeToggle } from "@/components/theme-toggle"; +import { buildAdminUrl } from "@/lib/admin-routing"; +import type { AppLocale } from "@/lib/locale"; +import { cn } from "@/lib/utils"; + +type FloatingControlsProps = { + locale: string; + defaultLocale: AppLocale; + isSuperAdmin?: boolean; +}; + +const pill = + "flex h-11 w-11 items-center justify-center rounded-full border border-border/60 bg-background/85 text-foreground/80 shadow-panel backdrop-blur-chrome transition-colors hover:bg-accent hover:text-foreground"; + +/** Radius (px) of the arc the items fan out along. */ +const RADIUS = 92; + +export function FloatingControls({ + locale, + defaultLocale, + isSuperAdmin = false, +}: FloatingControlsProps) { + const [open, setOpen] = useState(false); + const t = useTranslations("navigation"); + const activeLocale = useLocale(); + const isRtl = activeLocale === "ar"; + const reducedMotion = useReducedMotion(); + + const controls: ReactNode[] = [ + , + , + , + ]; + + if (isSuperAdmin) { + controls.push( + + + , + ); + } + + const count = controls.length; + // Fan across a quarter arc from "up" (90°) to "sideways" (180°), mirrored for + // RTL so the items always spread away from the corner into the page. + const startAngle = 94; + const endAngle = 176; + const positionFor = (index: number) => { + const angle = count === 1 ? 135 : startAngle + ((endAngle - startAngle) * index) / (count - 1); + const radians = (angle * Math.PI) / 180; + return { + x: (isRtl ? -1 : 1) * Math.cos(radians) * RADIUS, + y: -Math.sin(radians) * RADIUS, + }; + }; + + return ( +
+
+ + {open ? ( + <> + {/* click-away scrim */} + setOpen(false)} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + exit={{ opacity: 0 }} + className="fixed inset-0 -z-10 cursor-default bg-transparent" + /> + {controls.map((control, index) => { + const { x, y } = positionFor(index); + return ( + + {control} + + ); + })} + + ) : null} + + + {/* trigger */} + +
+
+ ); +} diff --git a/components/layout/site-dock.tsx b/components/layout/site-dock.tsx index 66714b3..a9f05ab 100644 --- a/components/layout/site-dock.tsx +++ b/components/layout/site-dock.tsx @@ -1,18 +1,12 @@ "use client"; -import { AnimatePresence, motion, useReducedMotion } from "framer-motion"; -import { Settings, ShieldCheck } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { useLocale, useTranslations } from "next-intl"; -import { useState, type ReactNode } from "react"; -import { LocaleToggle } from "@/components/layout/locale-toggle"; -import { SoundToggle } from "@/components/sound-toggle"; -import { ThemeToggle } from "@/components/theme-toggle"; +import { FloatingControls } from "@/components/layout/floating-controls"; import { Dock, DockIcon } from "@/components/ui/dock"; -import { buildAdminUrl } from "@/lib/admin-routing"; import { getLocalizedPath, stripLocalePrefix, type AppLocale } from "@/lib/locale"; import { cn } from "@/lib/utils"; @@ -43,18 +37,6 @@ const navItems: NavItem[] = [ { key: "contact", path: "/contact" }, ]; -// Graphite squircle matching the SVG page icons, used for the settings tile. -const controlTile = - "group relative overflow-visible rounded-[26%] bg-gradient-to-b from-[#3f4551] to-[#191d24] shadow-[0_6px_14px_-6px_rgba(0,0,0,0.5)] ring-1 ring-white/10 transition-shadow duration-200 hover:shadow-[0_10px_22px_-8px_rgba(0,0,0,0.6)]"; -// Glass pill used for each control that fans out along the arc. -const fanPill = - "flex h-11 w-11 items-center justify-center rounded-full border border-transparent bg-background/90 text-foreground/85 shadow-panel backdrop-blur-chrome transition-colors hover:bg-accent hover:text-foreground"; - -// Radius (px) and opening angles of the arc the controls fan out along. -const ARC_RADIUS = 74; -const ARC_START = 46; -const ARC_END = 134; - function isNavItemActive(currentPath: string, itemPath: string) { if (itemPath === "/") { return currentPath === "/"; @@ -66,52 +48,13 @@ export function SiteDock({ defaultLocale, isSuperAdmin = false }: SiteDockProps) const locale = useLocale(); const pathname = usePathname(); const t = useTranslations("navigation"); - const reducedMotion = useReducedMotion(); - const [settingsOpen, setSettingsOpen] = useState(false); const currentPath = stripLocalePrefix(pathname); const homeHref = getLocalizedPath(locale, "/", defaultLocale); - const fanItems: ReactNode[] = [ - , - , - , - ]; - - if (isSuperAdmin) { - fanItems.push( - - - , - ); - } - - const arcPosition = (index: number) => { - const count = fanItems.length; - const angle = count === 1 ? 90 : ARC_START + ((ARC_END - ARC_START) * index) / (count - 1); - const radians = (angle * Math.PI) / 180; - return { x: Math.cos(radians) * ARC_RADIUS, y: -Math.sin(radians) * ARC_RADIUS }; - }; - return ( <> - {/* click-away scrim (below the dock, above the page) */} - {settingsOpen ? ( - - - {settingsOpen ? null : } - + + {/* ===== Corner controls — theme / language / sound / admin (fan out) ===== */} + ); } -function DockSeparator() { - return
; -} - -function TileGloss() { - return ( - - ); -} - function DockTip({ label, soon }: { label: string; soon?: string }) { return ( - + - - - + + + \ No newline at end of file diff --git a/public/dock/about.svg b/public/dock/about.svg index d38b0be..92ac5e4 100644 --- a/public/dock/about.svg +++ b/public/dock/about.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/contact-active.svg b/public/dock/contact-active.svg index 7018726..14b191e 100644 --- a/public/dock/contact-active.svg +++ b/public/dock/contact-active.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/contact.svg b/public/dock/contact.svg index 710dc97..1db08b1 100644 --- a/public/dock/contact.svg +++ b/public/dock/contact.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/home-active.svg b/public/dock/home-active.svg index d9eb81c..d306722 100644 --- a/public/dock/home-active.svg +++ b/public/dock/home-active.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/home.svg b/public/dock/home.svg index 09fb01f..132727e 100644 --- a/public/dock/home.svg +++ b/public/dock/home.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/portfolio-active.svg b/public/dock/portfolio-active.svg index 7e170fa..20e00c9 100644 --- a/public/dock/portfolio-active.svg +++ b/public/dock/portfolio-active.svg @@ -2,11 +2,11 @@ - + - - - + + + diff --git a/public/dock/portfolio.svg b/public/dock/portfolio.svg index e289f12..bcb809d 100644 --- a/public/dock/portfolio.svg +++ b/public/dock/portfolio.svg @@ -2,11 +2,11 @@ - + - - - + + + diff --git a/public/dock/products-active.svg b/public/dock/products-active.svg index 6c4db6c..5acf486 100644 --- a/public/dock/products-active.svg +++ b/public/dock/products-active.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file diff --git a/public/dock/products.svg b/public/dock/products.svg index e77e661..8c7074f 100644 --- a/public/dock/products.svg +++ b/public/dock/products.svg @@ -2,11 +2,11 @@ - + - - - + + + \ No newline at end of file