fix(ui): make dashboard context menu work everywhere (#85)

Move DashboardContextMenu to wrap SidebarProvider so the
right-click menu triggers across the entire dashboard
viewport including sidebar, header, and main content.

- MainContent now forwards refs and spreads props for Radix
  asChild compatibility
- FeedbackWidget hoisted above SidebarProvider so
  DashboardContextMenu can access useFeedback from wider
  scope
- NavFiles uses useFilesOptional to avoid crash when
  rendered outside FilesProvider (sidebar is in dashboard
  layout, not files route layout)

Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
This commit is contained in:
Nicholai 2026-02-15 16:58:33 -07:00 committed by GitHub
parent 77130dea9b
commit 909af53711
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 24 deletions

View File

@ -51,6 +51,8 @@ export default async function DashboardLayout({
<CommandMenuProvider>
<BiometricGuard>
<DesktopShell>
<FeedbackWidget>
<DashboardContextMenu>
<SidebarProvider
defaultOpen={false}
className="h-screen overflow-hidden"
@ -61,21 +63,17 @@ export default async function DashboardLayout({
}
>
<AppSidebar variant="inset" projects={projectList} dashboards={dashboardList} user={user} />
<FeedbackWidget>
<SidebarInset className="overflow-hidden">
<DesktopOfflineBanner />
<OfflineBanner />
<SiteHeader user={user} />
<div className="flex min-h-0 flex-1 overflow-hidden">
<DashboardContextMenu>
<MainContent>
{children}
</MainContent>
</DashboardContextMenu>
<ChatPanelShell />
</div>
</SidebarInset>
</FeedbackWidget>
<MobileBottomNav />
<NativeShell />
<PushNotificationRegistrar />
@ -84,6 +82,8 @@ export default async function DashboardLayout({
</p>
<Toaster position="bottom-right" />
</SidebarProvider>
</DashboardContextMenu>
</FeedbackWidget>
</DesktopShell>
</BiometricGuard>
</CommandMenuProvider>

View File

@ -6,9 +6,9 @@ import { useRenderState } from "./chat-provider"
export function MainContent({
children,
}: {
readonly children: React.ReactNode
}) {
className: classNameProp,
...rest
}: React.ComponentPropsWithRef<"div">) {
const pathname = usePathname()
const { spec, isRendering } = useRenderState()
const hasRenderedUI = !!spec?.root || isRendering
@ -18,6 +18,7 @@ export function MainContent({
return (
<div
{...rest}
className={cn(
"flex flex-col overflow-x-hidden min-w-0",
"transition-[flex,opacity] duration-300 ease-in-out",
@ -25,7 +26,8 @@ export function MainContent({
? "flex-[0_0_0%] opacity-0 overflow-hidden pointer-events-none"
: isConversations
? "flex-1 overflow-hidden"
: "flex-1 overflow-y-auto pb-14 md:pb-0"
: "flex-1 overflow-y-auto pb-14 md:pb-0",
classNameProp
)}
>
<div className={cn(

View File

@ -11,7 +11,7 @@ import {
import Link from "next/link"
import { usePathname, useSearchParams } from "next/navigation"
import { useFiles } from "@/hooks/use-files"
import { useFilesOptional } from "@/hooks/use-files"
import { StorageIndicator } from "@/components/files/storage-indicator"
import {
SidebarGroup,
@ -49,7 +49,8 @@ export function NavFiles() {
const pathname = usePathname()
const searchParams = useSearchParams()
const activeView = searchParams.get("view") ?? "my-files"
const { storageUsage } = useFiles()
const files = useFilesOptional()
const storageUsage = files?.storageUsage
return (
<>
@ -102,9 +103,11 @@ export function NavFiles() {
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
{storageUsage && (
<div className="mt-auto px-3 pb-3">
<StorageIndicator usage={storageUsage} />
</div>
)}
</>
)
}

View File

@ -733,6 +733,10 @@ export function useFiles() {
return ctx
}
export function useFilesOptional() {
return useContext(FilesContext)
}
function sortFiles(
files: FileItem[],
sortBy: SortField,