From 0ace758c79f2410eff95b754e1b3f0b36122715a Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 16 Aug 2026 16:55:34 +0700 Subject: [PATCH] feat(frontend): safe-area insets + hardened reduced-motion - Add viewport export with viewportFit: "cover" so iOS exposes env(safe-area-inset-*) (required for the insets to take effect). - NavRail / TopBar / main / Toaster now respect safe-area insets so content clears the iPhone notch and home indicator in both portrait and landscape. - prefers-reduced-motion: the media query already disabled declared animation classes; harden it with a global transition/animation duration override and kill the scan-line shimmer so motion-sensitive users get a fully static UI. Verified tsc --noEmit + next build clean. --- services/frontend/src/app/globals.css | 12 ++++++++++++ services/frontend/src/app/layout.tsx | 9 ++++++++- .../frontend/src/components/primitives/toast.tsx | 2 +- .../frontend/src/components/shell/ambient-app.tsx | 2 +- services/frontend/src/components/shell/nav-rail.tsx | 2 +- services/frontend/src/components/shell/topbar.tsx | 2 +- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/services/frontend/src/app/globals.css b/services/frontend/src/app/globals.css index 50bc960..f4f7bc6 100644 --- a/services/frontend/src/app/globals.css +++ b/services/frontend/src/app/globals.css @@ -262,6 +262,7 @@ @media (prefers-reduced-motion: reduce) { .scan-line::after, + .scan-line, .animate-eq, .animate-spin-disc, .animate-pulse-ring, @@ -269,5 +270,16 @@ .animate-breathe { animation: none !important; } + .scan-line { + background: none !important; + } + *, + *::before, + *::after { + animation-duration: 0.001ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.001ms !important; + scroll-behavior: auto !important; + } html { scroll-behavior: auto; } } diff --git a/services/frontend/src/app/layout.tsx b/services/frontend/src/app/layout.tsx index 9b582d8..b209417 100644 --- a/services/frontend/src/app/layout.tsx +++ b/services/frontend/src/app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import { Bricolage_Grotesque, Inter, JetBrains_Mono } from "next/font/google"; import { ThemeProvider } from "next-themes"; import { Toaster } from "@/components/primitives/toast"; @@ -28,6 +28,13 @@ export const metadata: Metadata = { "AI-powered Discord moderation, voice monitoring, and media control console", }; +export const viewport: Viewport = { + themeColor: "#0a0a0c", + width: "device-width", + initialScale: 1, + viewportFit: "cover", +}; + export default function RootLayout({ children, }: Readonly<{ diff --git a/services/frontend/src/components/primitives/toast.tsx b/services/frontend/src/components/primitives/toast.tsx index 4c94698..4971fcf 100644 --- a/services/frontend/src/components/primitives/toast.tsx +++ b/services/frontend/src/components/primitives/toast.tsx @@ -57,7 +57,7 @@ export function Toaster({ position = "bottom-right" }: { position?: string }) { const pos = position === "bottom-right" - ? "bottom-4 right-4" + ? "bottom-[calc(1rem+env(safe-area-inset-bottom))] right-[calc(1rem+env(safe-area-inset-right))]" : position === "top-right" ? "top-4 right-4" : "bottom-4 left-1/2 -translate-x-1/2"; diff --git a/services/frontend/src/components/shell/ambient-app.tsx b/services/frontend/src/components/shell/ambient-app.tsx index 841bc3b..9baf89b 100644 --- a/services/frontend/src/components/shell/ambient-app.tsx +++ b/services/frontend/src/components/shell/ambient-app.tsx @@ -12,7 +12,7 @@ export function AppFrame({ children }: { children: React.ReactNode }) {
-
+
{children}
diff --git a/services/frontend/src/components/shell/nav-rail.tsx b/services/frontend/src/components/shell/nav-rail.tsx index 8a9e2ed..e859fe5 100644 --- a/services/frontend/src/components/shell/nav-rail.tsx +++ b/services/frontend/src/components/shell/nav-rail.tsx @@ -40,7 +40,7 @@ export function NavRail() { const path = pathname ?? "/"; return ( -