diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx index 0072ec3..2140380 100644 --- a/apps/web/app/(dashboard)/layout.tsx +++ b/apps/web/app/(dashboard)/layout.tsx @@ -1,4 +1,5 @@ import { Logo } from '@/components/logo'; +import { MobileActionBar } from '@/components/mobile-action-bar'; import { FileClock, LayoutGrid, Package, Server, Settings } from 'lucide-react'; import Link from 'next/link'; @@ -29,13 +30,14 @@ export default function DashboardLayout({ children }: { children: React.ReactNod + New server -
{children}
+
{children}
+ ); } diff --git a/apps/web/components/mobile-action-bar.tsx b/apps/web/components/mobile-action-bar.tsx new file mode 100644 index 0000000..ccce73c --- /dev/null +++ b/apps/web/components/mobile-action-bar.tsx @@ -0,0 +1,35 @@ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; + +// Routes where the global "+ New server" CTA makes no sense — the wizard is +// itself the create flow and owns its own primary action. +const HIDDEN_PATHS: readonly string[] = ['/servers/new']; + +/** + * Mobile-only sticky bottom action bar. On phones the dashboard top header is + * already tight with the nav icons; the primary action belongs in the thumb + * zone, not crammed top-right. Hidden from `sm:` upward where the header has + * room for the same button inline. + */ +export function MobileActionBar() { + const pathname = usePathname(); + if (HIDDEN_PATHS.includes(pathname)) return null; + + return ( +
+
+ + + New server + +
+
+ ); +}