Files
supabase/apps/studio/components/interfaces/QueryInsights/QueryInsightsTable/QueryInsightsDetailSheet.tsx
Gildas Garcia cabe14e5ca chore: remove _Shadcn_ suffix from ui tabs components (#47628)
## Problem

Now that we migrated all usages of the deprecated `Tabs` component, we
don't need the `_Shadcn_` suffix anymore.

## Solution

Remove `_Shadcn_` suffix from `ui` tabs components. That's all this PR
does, no visual nor functional changes

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Standardized tab components across the app so pages and dialogs now
use the same consistent tab UI.
* Improved tab-based views in design, docs, studio, learn, and website
experiences for a more uniform interface.

* **Chores**
* Updated shared UI exports to expose tab components directly,
simplifying future usage across the product.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-06 15:29:16 +02:00

160 lines
6.2 KiB
TypeScript

import { Loader2 } from 'lucide-react'
import {
AiIconAnimation,
Button,
Sheet,
SheetContent,
SheetDescription,
SheetTitle,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from 'ui'
import { QueryDetail } from '../../QueryPerformance/QueryDetail'
import { QueryIndexes } from '../../QueryPerformance/QueryIndexes'
import { buildExplainOptimizationPrompt } from '../../QueryPerformance/QueryPerformance.ai'
import type { ClassifiedQuery } from '../QueryInsightsHealth/QueryInsightsHealth.types'
import { ExplainVisualizer } from '@/components/interfaces/ExplainVisualizer/ExplainVisualizer'
import type { QueryPlanRow } from '@/components/interfaces/ExplainVisualizer/ExplainVisualizer.types'
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
interface QueryInsightsDetailSheetProps {
open: boolean
onOpenChange: (open: boolean) => void
activeSheetRow: ClassifiedQuery | undefined
sheetView: 'details' | 'indexes' | 'explain'
onSheetViewChange: (view: 'details' | 'indexes' | 'explain') => void
onClose: () => void
dataGridContainerRef: React.RefObject<HTMLDivElement | null>
triageContainerRef: React.RefObject<HTMLDivElement | null>
explainLoadingQuery: string | null
explainResults: Record<string, QueryPlanRow[]>
}
export const QueryInsightsDetailSheet = ({
open,
onOpenChange,
activeSheetRow,
sheetView,
onSheetViewChange,
onClose,
dataGridContainerRef,
triageContainerRef,
explainLoadingQuery,
explainResults,
}: QueryInsightsDetailSheetProps) => {
const { openSidebar } = useSidebarManagerSnapshot()
const aiSnap = useAiAssistantStateSnapshot()
return (
<Sheet open={open} onOpenChange={onOpenChange} modal={false}>
<SheetTitle className="sr-only">Query details</SheetTitle>
<SheetDescription className="sr-only">Query Insights Details &amp; Indexes</SheetDescription>
<SheetContent
side="right"
className="flex flex-col h-full bg-studio border-l lg:w-[calc(100vw-802px)]! max-w-[700px] w-full"
hasOverlay={false}
onInteractOutside={(event) => {
if (
dataGridContainerRef.current?.contains(event.target as Node) ||
triageContainerRef.current?.contains(event.target as Node)
) {
event.preventDefault()
}
}}
>
<Tabs
value={sheetView}
className="flex flex-col h-full"
onValueChange={(v) => onSheetViewChange(v as 'details' | 'indexes' | 'explain')}
>
<div className="px-5 border-b">
<TabsList className="px-0 flex gap-x-4 min-h-[46px] border-b-0 [&>button]:h-[47px]">
<TabsTrigger
value="details"
className="px-0 pb-0 data-[state=active]:bg-transparent shadow-none!"
>
Query details
</TabsTrigger>
<TabsTrigger
value="indexes"
className="px-0 pb-0 data-[state=active]:bg-transparent shadow-none!"
>
Indexes
</TabsTrigger>
{activeSheetRow?.issueType !== 'error' && (
<TabsTrigger
value="explain"
className="px-0 pb-0 data-[state=active]:bg-transparent shadow-none!"
>
Explain
</TabsTrigger>
)}
</TabsList>
</div>
<TabsContent value="details" className="mt-0 grow min-h-0 overflow-y-auto">
{activeSheetRow && (
<QueryDetail
selectedRow={activeSheetRow}
onClickViewSuggestion={() => onSheetViewChange('indexes')}
onClose={onClose}
/>
)}
</TabsContent>
<TabsContent value="indexes" className="mt-0 grow min-h-0 overflow-y-auto">
{activeSheetRow && <QueryIndexes selectedRow={activeSheetRow} />}
</TabsContent>
<TabsContent value="explain" className="mt-0 grow min-h-0 flex flex-col overflow-hidden">
{explainLoadingQuery ? (
<div className="px-6 py-4 flex items-center gap-2 text-sm text-foreground-light">
<Loader2 size={14} className="animate-spin" /> Running EXPLAIN ANALYZE...
</div>
) : activeSheetRow && explainResults[activeSheetRow.query]?.length > 0 ? (
<>
<div className="flex items-center justify-between px-5 py-2 border-b shrink-0">
<p className="text-xs text-foreground-lighter">EXPLAIN ANALYZE output</p>
<Button
variant="default"
size="tiny"
icon={<AiIconAnimation size={14} />}
onClick={() => {
const rows = explainResults[activeSheetRow.query]
const { query, prompt } = buildExplainOptimizationPrompt(
activeSheetRow.query,
rows,
{
mean_time: activeSheetRow.mean_time,
calls: activeSheetRow.calls,
total_time: activeSheetRow.total_time,
}
)
openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
aiSnap.newChat({
sqlSnippets: [{ label: 'Query', content: query }],
initialMessage: prompt,
})
}}
>
Optimize with AI
</Button>
</div>
<div className="flex-1 min-h-0 overflow-y-auto">
<ExplainVisualizer rows={explainResults[activeSheetRow.query]} />
</div>
</>
) : (
<div className="px-6 py-4 text-sm text-foreground-lighter">
No explain results available.
</div>
)}
</TabsContent>
</Tabs>
</SheetContent>
</Sheet>
)
}