From 0cf9e02c4ead794c6baf8cd57236167a3d4ce326 Mon Sep 17 00:00:00 2001 From: Nicholai Date: Sat, 24 Jan 2026 13:01:28 -0700 Subject: [PATCH] feat(ui): update landing + dashboard, fix scroll, share search - replace template home page with Compass branding and WIP notice - rewrite dashboard as project status page with working/in-progress/planned sections - fix content scrolling inside inset panel (no more clipped rounded corners) - extract command menu into shared context so sidebar search triggers it too --- src/app/dashboard/layout.tsx | 44 ++++--- src/app/dashboard/page.tsx | 143 +++++++++++++++++++++-- src/app/page.tsx | 6 +- src/components/app-sidebar.tsx | 94 +++++++++------ src/components/command-menu-provider.tsx | 32 +++++ src/components/nav-secondary.tsx | 23 +++- src/components/site-header.tsx | 97 ++++++++++++++- 7 files changed, 364 insertions(+), 75 deletions(-) create mode 100755 src/components/command-menu-provider.tsx diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index 9a9aae4..52a191b 100755 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,34 +1,40 @@ import { AppSidebar } from "@/components/app-sidebar" +import { SiteHeader } from "@/components/site-header" +import { CommandMenuProvider } from "@/components/command-menu-provider" import { SidebarInset, SidebarProvider, - SidebarTrigger, } from "@/components/ui/sidebar" +import { getProjects } from "@/app/actions/projects" -export default function DashboardLayout({ +export default async function DashboardLayout({ children, }: { children: React.ReactNode }) { + const projectList = await getProjects() + return ( - - - -
-
-
- + + + + + +
+
+ {children}
- {children}
-
- - + + + ) } diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index b6705f9..f6ce108 100755 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,17 +1,142 @@ -import { ChartAreaInteractive } from "@/components/chart-area-interactive" -import { DataTable } from "@/components/data-table" -import { SectionCards } from "@/components/section-cards" +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { IconExternalLink } from "@tabler/icons-react" -import data from "./data.json" +const GITHUB_URL = + "https://github.com/High-Performance-Structures/compass" + +const working = [ + "Projects — create and manage projects with D1 database", + "Schedule — Gantt chart with phases, tasks, dependencies, and baselines", + "File browser — drive-style UI with folder navigation", + "Sidebar navigation with contextual project/file views", +] + +const inProgress = [ + "User authentication and accounts", + "Settings page", + "Search functionality", + "Notifications", +] + +const planned = [ + "Role-based permissions", + "File uploads and storage (R2)", + "Project activity feed", + "Mobile-responsive layout improvements", +] export default function Page() { return ( -
- -
- +
+
+
+

+ Compass +

+

+ Development preview — features may be incomplete + or change without notice. +

+
+ +
+ + + + + Working + + {working.length} + + + + Features that are functional in this preview + + + +
    + {working.map((item) => ( +
  • + + {item} +
  • + ))} +
+
+
+ + + + + + In Progress + + {inProgress.length} + + + + Currently being developed + + + +
    + {inProgress.map((item) => ( +
  • + + {item} +
  • + ))} +
+
+
+ + + + + + Planned + + {planned.length} + + + + On the roadmap but not started + + + +
    + {planned.map((item) => ( +
  • + + {item} +
  • + ))} +
+
+
+
+ +
-
) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 381863f..405c261 100755 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -7,14 +7,14 @@ export default function Home() {
- Dashboard App Template + Compass - A Next.js starter with shadcn/ui components and Cloudflare deployment + Work-in-progress development preview diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index b03fcc9..0488ec8 100755 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -16,7 +16,9 @@ import { usePathname } from "next/navigation" import { NavMain } from "@/components/nav-main" import { NavSecondary } from "@/components/nav-secondary" import { NavFiles } from "@/components/nav-files" +import { NavProjects } from "@/components/nav-projects" import { NavUser } from "@/components/nav-user" +import { useCommandMenu } from "@/components/command-menu-provider" import { Sidebar, SidebarContent, @@ -25,17 +27,18 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, + useSidebar, } from "@/components/ui/sidebar" const data = { user: { - name: "shadcn", - email: "m@example.com", - avatar: "/avatars/shadcn.jpg", + name: "Martine Vogel", + email: "martine@compass.io", + avatar: "/avatars/martine.jpg", }, navMain: [ { - title: "Dashboard", + title: "Compass", url: "/dashboard", icon: IconDashboard, }, @@ -66,20 +69,61 @@ const data = { url: "#", icon: IconHelp, }, - { - title: "Search", - url: "#", - icon: IconSearch, - }, ], } -export function AppSidebar({ ...props }: React.ComponentProps) { +function SidebarNav({ + projects, +}: { + projects: { id: string; name: string }[] +}) { const pathname = usePathname() + const { state } = useSidebar() + const { open: openSearch } = useCommandMenu() + const isExpanded = state === "expanded" const isFilesMode = pathname?.startsWith("/dashboard/files") + const isProjectMode = /^\/dashboard\/projects\/[^/]+/.test( + pathname ?? "" + ) + const showContext = isExpanded && (isFilesMode || isProjectMode) + + const mode = showContext && isFilesMode + ? "files" + : showContext && isProjectMode + ? "projects" + : "main" + + const secondaryItems = [ + ...data.navSecondary, + { title: "Search", icon: IconSearch, onClick: openSearch }, + ] return ( - +
+ {mode === "files" && ( + + + + )} + {mode === "projects" && } + {mode === "main" && ( + <> + + + + )} +
+ ) +} + +export function AppSidebar({ + projects = [], + ...props +}: React.ComponentProps & { + projects?: { id: string; name: string }[] +}) { + return ( + @@ -89,36 +133,16 @@ export function AppSidebar({ ...props }: React.ComponentProps) { > - COMPASS + + COMPASS + -
-
- - -
-
- - - -
-
+
diff --git a/src/components/command-menu-provider.tsx b/src/components/command-menu-provider.tsx new file mode 100755 index 0000000..46df749 --- /dev/null +++ b/src/components/command-menu-provider.tsx @@ -0,0 +1,32 @@ +"use client" + +import * as React from "react" +import { CommandMenu } from "@/components/command-menu" + +const CommandMenuContext = React.createContext<{ + open: () => void +}>({ open: () => {} }) + +export function useCommandMenu() { + return React.useContext(CommandMenuContext) +} + +export function CommandMenuProvider({ + children, +}: { + children: React.ReactNode +}) { + const [isOpen, setIsOpen] = React.useState(false) + + const value = React.useMemo( + () => ({ open: () => setIsOpen(true) }), + [] + ) + + return ( + + {children} + + + ) +} diff --git a/src/components/nav-secondary.tsx b/src/components/nav-secondary.tsx index 3f3636f..a6319d8 100755 --- a/src/components/nav-secondary.tsx +++ b/src/components/nav-secondary.tsx @@ -17,8 +17,9 @@ export function NavSecondary({ }: { items: { title: string - url: string + url?: string icon: Icon + onClick?: () => void }[] } & React.ComponentPropsWithoutRef) { return ( @@ -27,11 +28,21 @@ export function NavSecondary({ {items.map((item) => ( - - - - {item.title} - + + {item.onClick ? ( + <> + + {item.title} + + ) : ( + + + {item.title} + + )} ))} diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx index 9356fe3..4b0dbba 100755 --- a/src/components/site-header.tsx +++ b/src/components/site-header.tsx @@ -1,11 +1,102 @@ +"use client" + +import * as React from "react" +import { useTheme } from "next-themes" +import { + IconLogout, + IconMoon, + IconSearch, + IconSun, + IconUserCircle, +} from "@tabler/icons-react" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" import { SidebarTrigger } from "@/components/ui/sidebar" +import { NotificationsPopover } from "@/components/notifications-popover" +import { useCommandMenu } from "@/components/command-menu-provider" +import { AccountModal } from "@/components/account-modal" export function SiteHeader() { + const { theme, setTheme } = useTheme() + const { open: openCommand } = useCommandMenu() + const [accountOpen, setAccountOpen] = React.useState(false) + return ( -
-
- +
+ + +
{ + if (e.key === "Enter" || e.key === " ") openCommand() + }} + > + +
+ + Search... + + + K + +
+ +
+ + + + + + + + +

Martine Vogel

+

martine@compass.io

+
+ + setAccountOpen(true)}> + + Account + + + + + Log out + +
+
+
+ +
) }