From 3461d60abae9fe87a29ae45fee65e9f1fb2f3bc3 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:27:43 -0400 Subject: [PATCH] feat(sql-editor): consolidate controls into a single top bar (#47792) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor / UI improvement ## What is the current behavior? SQL editor controls are split across two rows: a bar between the editor and results (tabs, download, run/save/format/db-selector/role/favorite/intellisense) and a separate footer at the very bottom (row count + limit dropdown). ## What is the new behavior? All controls are consolidated into a single top bar above the editor (⋮ overflow menu, database selector, role impersonation, limit, save, run). The bar between the editor and results now holds only result-relevant information: the Results/Explain/Chart tabs, the row-count summary, and the Export button. The limit dropdown is now always visible as a persistent query setting. --- .../interfaces/SQLEditor/SQLEditor.tsx | 95 +++---------------- .../SQLEditor/UtilityPanel/UtilityActions.tsx | 33 ++++++- .../SQLEditor/UtilityPanel/UtilityPanel.tsx | 54 +++++++---- 3 files changed, 82 insertions(+), 100 deletions(-) diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx index 085cfdf1714..304389598bf 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx @@ -9,32 +9,17 @@ import { import { wrapWithRollback } from '@supabase/pg-meta/src/query' import { useQueryClient } from '@tanstack/react-query' import { IS_PLATFORM, LOCAL_STORAGE_KEYS, useFlag, useParams } from 'common' -import { ChevronUp, Loader2 } from 'lucide-react' +import { Loader2 } from 'lucide-react' import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import { useCallback, useEffect, useEffectEvent, useMemo, useRef, useState } from 'react' import { toast } from 'sonner' -import { - Button, - cn, - DropdownMenu, - DropdownMenuContent, - DropdownMenuRadioGroup, - DropdownMenuRadioItem, - DropdownMenuTrigger, - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, - Tooltip, - TooltipContent, - TooltipTrigger, -} from 'ui' +import { cn, ResizableHandle, ResizablePanel, ResizablePanelGroup } from 'ui' import { useSqlEditorDiff, useSqlEditorPrompt } from './hooks' import { RunQueryWarningModal } from './RunQueryWarningModal' import { generateSnippetTitle, - ROWS_PER_PAGE_OPTIONS, sqlAiDisclaimerComment, untitledSnippetTitle, } from './SQLEditor.constants' @@ -57,6 +42,7 @@ import { suffixWithLimit, } from './SQLEditor.utils' import { useAddDefinitions } from './useAddDefinitions' +import { UtilityActions } from './UtilityPanel/UtilityActions' import { UtilityPanel } from './UtilityPanel/UtilityPanel' import { isExplainQuery, @@ -65,7 +51,6 @@ import { } from '@/components/interfaces/ExplainVisualizer/ExplainVisualizer.utils' import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import ResizableAIWidget from '@/components/ui/AIEditor/ResizableAIWidget' -import { GridFooter } from '@/components/ui/GridFooter' import { useSqlTitleGenerateMutation } from '@/data/ai/sql-title-mutation' import { useDatabaseEventTriggersQuery } from '@/data/database-event-triggers/database-event-triggers-query' import { constructHeaders, isValidConnString } from '@/data/fetchers' @@ -207,7 +192,6 @@ export const SQLEditor = () => { const id = !urlId || urlId === 'new' ? generatedId : urlId const limit = sessionSnap.limit - const results = sessionSnap.results[id]?.[0] const snippetIsLoading = !( id in snapV2.snippets && snapV2.snippets[id].snippet.content !== undefined ) @@ -916,9 +900,18 @@ export const SQLEditor = () => { }} /> -
- - {results.rows.length} row{results.rows.length > 1 ? 's' : ''} - - - {results.autoLimit !== undefined && - ` (Limited to only ${results.autoLimit} rows)`} - -
-- - Results are automatically limited to preserve browser performance, in - particular if your query returns an exceptionally large number of rows. - - - - You may change or remove this limit from the dropdown on the right - -
-+ + {result.rows.length} row{result.rows.length === 1 ? '' : 's'} + + + {result.autoLimit !== undefined && `(Limited to only ${result.autoLimit} rows)`} + +
++ + Results are automatically limited to preserve browser performance, in particular + if your query returns an exceptionally large number of rows. + + + You may change or remove this limit from the toolbar above. + +
+