mirror of
https://github.com/supabase/supabase.git
synced 2026-06-13 10:09:12 +08:00
## What kind of change does this PR introduce? UI polish. ## What is the current behavior? - A few product sidebar areas render menu rows outside the shared ProductMenu/Menu.Item styling path, so their hover and selected states differ from the rest of Studio. - Database product menu shortcut tooltips are also scoped to the text label instead of the full hoverable row. ## What is the new behavior? - Integrations Explore/Installed, Observability, and Reports sidebar rows now use the shared ProductMenu or Menu.Item pill styling. - Observability spacing is tightened after the ProductMenu conversion. - Product menu shortcut tooltips now wrap the full row trigger, so the entire Database sidebar row opens the tooltip. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Enhanced navigation menu components with improved loading and error state handling across the dashboard. * Streamlined menu structure and styling consistency for integrations, reports, and observability sections. * Added enhanced tooltip support for navigation items. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
112 lines
3.0 KiB
TypeScript
112 lines
3.0 KiB
TypeScript
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
|
import { Edit2, MoreVertical, Trash } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import {
|
|
Button,
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
Menu,
|
|
} from 'ui'
|
|
|
|
import { ContentBase } from '@/data/content/content-query'
|
|
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
|
import { useProfile } from '@/lib/profile'
|
|
import type { Dashboards } from '@/types'
|
|
|
|
interface ReportMenuItemProps {
|
|
item: {
|
|
id?: string
|
|
name: string
|
|
description: string
|
|
key: string
|
|
url: string
|
|
hasDropdownActions: boolean
|
|
report: ContentBase & {
|
|
type: 'report'
|
|
content: Dashboards.Content
|
|
}
|
|
}
|
|
pageKey: string
|
|
onSelectEdit: () => void
|
|
onSelectDelete: () => void
|
|
}
|
|
|
|
export const ObservabilityMenuItem = ({
|
|
item,
|
|
pageKey,
|
|
onSelectEdit,
|
|
onSelectDelete,
|
|
}: ReportMenuItemProps) => {
|
|
const { profile } = useProfile()
|
|
const { can: canUpdateCustomReport } = useAsyncCheckPermissions(
|
|
PermissionAction.UPDATE,
|
|
'user_content',
|
|
{
|
|
resource: {
|
|
type: 'report',
|
|
visibility: item.report.visibility,
|
|
owner_id: item.report.owner_id,
|
|
},
|
|
subject: { id: profile?.id },
|
|
}
|
|
)
|
|
|
|
const menuItem = (
|
|
<Menu.Item active={item.key === pageKey}>
|
|
<div className="flex w-full items-center justify-between gap-1">
|
|
<span className="truncate">{item.name}</span>
|
|
|
|
{canUpdateCustomReport && (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button
|
|
type="text"
|
|
className="px-1 opacity-50 hover:opacity-100"
|
|
icon={<MoreVertical size={12} strokeWidth={2} />}
|
|
onClick={(e) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
}}
|
|
/>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="start" className="w-32 *:gap-x-2">
|
|
<DropdownMenuItem
|
|
onClick={(e) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
if (!item.id) return
|
|
onSelectEdit()
|
|
}}
|
|
>
|
|
<Edit2 size={12} />
|
|
<div>Rename report</div>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem
|
|
onClick={(e) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
if (!item.id) return
|
|
onSelectDelete()
|
|
}}
|
|
>
|
|
<Trash size={12} />
|
|
<div>Delete report</div>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
)}
|
|
</div>
|
|
</Menu.Item>
|
|
)
|
|
|
|
return (
|
|
<Link key={item.key + '-menukey'} href={item.url} className="block">
|
|
{menuItem}
|
|
</Link>
|
|
)
|
|
}
|