Commit Graph
15 Commits
Author SHA1 Message Date
Saxon Fletcher 9718eea593 refine role impersonation popover (#49467)
**Old**
<img width="979" height="839" alt="image"
src="https://github.com/user-attachments/assets/7239604f-a37f-483c-84eb-dbafabdeb73c"
/>

**New**
<img width="1185" height="645" alt="image"
src="https://github.com/user-attachments/assets/e699d75f-fd04-47dc-a8da-97f880e39796"
/>


## 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?

Studio UI refinement. This is PR 2 of 2 and depends on #49466.

## What is the current behavior?

The Run SQL query as a role submenu uses the full role-impersonation
card layout, making the nested popover substantially larger than the
surrounding query controls.

## What is the new behavior?

- Adds a compact role-impersonation presentation used only by the query
submenu.
- Uses horizontal FormItemLayout rows and base ToggleGroup, InputGroup,
Input, and Button components.
- Keeps role choices stacked while using tiny controls for user source,
user lookup, external-user fields, and MFA level.
- Keeps authenticated-user controls visible but disabled for Postgres
and Anonymous roles.
- Preserves project-user search, external-user claims, impersonation,
and stop-impersonating behavior.
- Leaves existing role selectors in GraphQL, Table Editor, Realtime, and
other surfaces unchanged.

## Verification

- Focused compact role-selector test
- Studio, UI, and UI Patterns typechecks
- Existing focused Toggle and MultiSelector tests
- Studio ESLint
- Local visual and interaction verification against the supplied
prototype



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

## Summary by CodeRabbit

* **New Features**
* Redesigned role impersonation with role-specific summaries and native
role icons.
* Added native and external user impersonation, including user-source
switching and MFA controls.
* Added user search, external user ID entry, and clearer active-user
controls with accessible labels.

* **Bug Fixes**
* Improved role switching, impersonation clearing, pending selections,
and error recovery.

* **Tests**
* Expanded coverage for role selection, user impersonation, MFA updates,
state transitions, and error handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-26 16:28:02 +08:00
Charis 0ed49231b7 refactor(studio): unify CellSource and the SQL editor's QuerySource into QuerySourceBinding (#49072)
Third of a stack. **Stacked on #49070** (which is stacked on #49069) —
review those first. Base retargets automatically as each merges.

Mechanical throughout; no behavior change.

## The problem

Three types described where a query runs, and no two agreed:

| | shape |
|---|---|
| `CellSource` (registry) | `{ id, type, parameters: { … } }` — `id` and
`type` always held the same literal |
| `QuerySource` (SQL editor) | `{ type: 'database' } \| { type: 'logs',
dateRange }` |
| notebook cells | flat per-backend fields, neither of the above |

Anything crossing between them needed a translation that dropped fields
on the way — which is how a notebook cell's replica selection had
nowhere to go.

## What changed

One `QuerySourceBinding`: a backend `_tag` with that backend's
parameters spread flat beside it, borrowed from the wire schema (#49069)
so the binding and the persisted cell agree by construction.

- **`QuerySource` is deleted.** `useRunSource` returns the shared
binding, so `runSource.type`/`dateRange` become `_tag`/`time_range`
across the SQL editor — that is most of the file count here.
- **`getQuerySourceBinding`** projects a notebook cell onto a binding;
**`toQuerySourceBinding`** does the same for any backend-tagged carrier.
Both overloaded so an already-narrowed caller gets the matching binding
back rather than the union, which keeps the result spreadable without
re-narrowing.
- **`ExplorerQuerySourceMenu`** drops its inline copy of the
custom-range and upgrade-prompt logic in favor of `useLogsCustomRange`,
which the SQL editor menu already used.

The registry keeps only what is genuinely runtime: endpoints, labels,
icons, availability, defaults. What a query *is* stays in the wire
schema.

## Verification

Typecheck, Prettier, and the lint ratchet clean. 405 tests pass across
the notebook schema, query sources, the logs components, the SQL editor,
and the Explorer surfaces.

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

* **Improvements**
* Updated query source handling across Explorer and SQL Editor for a
more consistent selection experience.
* Database and log sources now preserve identifiers and time ranges more
reliably when switching or editing queries.
* Source menus, labels, icons, validation, and query execution now
reflect the selected source more accurately.

* **Bug Fixes**
* Invalid or outdated saved source settings now safely fall back to a
database source.
* Improved log-source detection and time-range handling throughout query
editing and execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-14 15:09:29 +07:00
Joshen Lim 67d4fed40d Joshenlim/fe 4157 explorer migrate results component into explorer (#49066)
## Context

Related to Notebooks/Explorers - this one's just shifting files from the
SQLEditor into more generic folders from a file organization POV, such
that files under the Explorer folder have no dependency on files within
the SQLEditor folder

Mainly
- UtilityTabResults.utils: `getSqlErrorLines`
  - Moved into `data/sql/utils.ts`
- SQLEditor.utils: `applyAutoLimit`, `getSqlErrorLines`,
`trimTrailingSemicolons`
  - Moved into `data/sql/utils.ts`
- SQLEditor/UtilityPanel: `ResultCell`, `Results`, `CellDetailPanel`
  - Moved into `components/ui/DataGridResults`
  - Also shifted corresponding tests over here
- Also addressed some `any` type casts 

## To test
- Just need to ensure that the SQL Editor still works as expected

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

## Summary by CodeRabbit

* **New Features**
* Standardized query results across the Studio with a shared data grid.
* Improved result-table formatting, column sizing, clipboard handling,
and large-value display.
  * Added safer automatic row limits for eligible SQL queries.
  * Centralized SQL error display and formatting utilities.

* **Refactor**
  * Improved type safety for query rows and cell values.

* **Tests**
* Added comprehensive coverage for result-grid and SQL utility behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-14 11:29:39 +07:00
Saxon Fletcher cc6fe2100a refactor(studio): centralize query sources (#49027)
## Summary

- define application-owned database and logs source contracts, defaults,
validation, labels, and execution endpoints
- extract controlled database and logs parameter controls for reuse
outside SQL snippets
- adapt the SQL editor to the shared source model without changing
snippet behavior
- standardize source icons at 16px with a 2px stroke
- keep relative logs ranges aligned with the existing date picker units

## To test

1. Open an existing query in the SQL Editor and run it against the
database.
2. Switch the query source to Logs, change the time range, and confirm
the query still runs as expected.

## Why

Explorer queries and notebook query cells need to select an execution
source without coupling that source to SQL snippets. This provides the
shared registry and controlled UI foundation for those consumers.

## Impact

Existing SQL snippets retain their current database/logs routing and
session behavior. The registry documents the SQL editor legacy
database-selector adapter while new consumers own their identifier
inline. The shared Logs date picker remains unchanged; query ranges
support its existing minute, hour, and day units. This PR does not add
the Explorer query tab itself.

## Validation

- pnpm --filter studio typecheck
- focused Vitest coverage for the registry, canonical log-range
utilities, SQL execution adapters, source filtering, retention locking,
custom ranges, and preset selection
- pnpm --filter studio run lint:ratchet

Component and state tests cover this change per the Studio testing
guidance; no E2E test is added.

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

* **New Features**
  * Added a unified query-source menu for database queries and logs.
* Added custom log time-range selection with calendar support and
retention-aware upgrade prompts.
* Added consistent source icons and improved database selection
handling.
  * Added support for relative and absolute log time ranges.

* **Bug Fixes**
  * Improved log-range validation, defaults, and current-time handling.
* Updated query execution to use the correct source-specific endpoints.

* **Tests**
* Expanded coverage for query sources, log ranges, menus, and retention
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-13 16:51:06 +07:00
Charis 2165746784 fix(studio): keep SQL editor source menu open when switching sources (#48715)
## 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?

Bug fix

## What is the current behavior?

Selecting Database/Logs in the SQL Editor's query-source dropdown closes
the menu (Radix's default select behavior), so switching to Logs gives
no visible indication that a Time range control just became available
until the dropdown is reopened.

## What is the new behavior?

Selecting a source keeps the dropdown open, so the newly-available
source-specific controls (e.g. Time range for Logs) are immediately
visible.

## Additional context

Fixes FE-4036

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved source switching in the SQL editor so the selection menu
remains open while changing between database and logs sources.
  * Ensured source-specific controls update correctly after switching.

* **Tests**
* Added coverage for source selection, menu behavior, and
source-specific control updates.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 20:23:12 +00:00
Charis 0bef8e7d90 test(sql-editor): e2e coverage + delete jsdom test + merge Results.utils tests (Steps 5-6) (#48217)
## Summary

Steps 5 and 6 of the SQL editor test refactor plan (the final two
steps).

**Step 5** — extends `e2e/studio/features/sql-editor.spec.ts` (real
browser, zero mocks) with cases that need the real Monaco editor / full
app render:
- destructive-query warning modal: confirm actually re-runs the forced
query (previously only `Cancel` was exercised)
- debug button opens the AI Assistant with the query error pre-filled

Deletes `apps/studio/tests/components/SQLEditor/SQLEditor.test.tsx` —
its logic-level cases are now covered mock-free by the Step 4 hook
tests, and its integration cases by e2e. Deleting rather than narrowing
is the honest consequence of "no mocking": every remaining assertion it
could make in jsdom requires a Monaco mock.

**Step 6** — merges
`apps/studio/tests/components/SQLEditor/Results.utils.test.ts`
(`formatClipboardValue`/`formatCellValue`) into the colocated
`apps/studio/components/interfaces/SQLEditor/UtilityPanel/Results.utils.test.ts`
(`formatResults`/`convertResultsToMarkdown`/`convertResultsToJSON`/`getResultsHeaders`/`isLargeValue`/`convertResultsToCSV`)
— both tested disjoint exports of the same source file. Deletes the
`tests/` copy.

This is the last step in the plan.

## Test plan

- [x] `pnpm --filter studio typecheck` — no new errors in changed files
- [x] `npx prettier --check` on all changed files
- [x] Ran the new/changed e2e cases locally end-to-end against a live
local stack — both pass
- [x] `cd apps/studio && npx vitest run
components/interfaces/SQLEditor/UtilityPanel/Results.utils.test.ts` —
42/42 passing after the merge

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

* **Tests**
* Added end-to-end coverage for destructive SQL query warning modal flow
before forced execution.
* Added end-to-end coverage for the AI Assistant debug flow when SQL
execution fails.
* Expanded unit test coverage for SQL editor results formatting
utilities (clipboard and cell value formatting).
* Removed the prior SQLEditor unit test suite and the older
results-formatting unit tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-22 16:55:17 -04:00
Danny White 6f6badae51 fix(eslint): promote require-explicit-tabindex to error (#48170)
## What kind of change does this PR introduce?

Accessibility / lint hardening (Safari keyboard focus).

## What is the current behavior?

`supabase/require-explicit-tabindex` is `'warn'`. Studio’s ratchet was
at 0 but the rule was still ratcheted; www / docs / design-system still
had raw `<button>` / `role="button"` call sites without an explicit
`tabIndex`.

[DEPR-627](https://linear.app/supabase/issue/DEPR-627) · follow-up to
#47984 / #48040

## What is the new behavior?

- Shared config: `'supabase/require-explicit-tabindex': 'error'`
- Swept www / docs / design-system (+ Studio test fixtures the ratchet
skipped)
- Removed the rule from the Studio ratchet + baselines

## To test

Prefer **Safari**. This PR only adds explicit `tabIndex` to raw
`<button>` / `role="button"` call sites — not links, and not controls
that already go through `Button` from `ui`.

### Marketing (`www`) ([staging
link](https://zone-www-dot-com-git-danny-depr-627-promote-req-7ae43c-supabase.vercel.app/))

- [x] Homepage frameworks / dashboard feature tabs — Tab through each
tab button
- [x] Product pages (e.g. `/auth`, `/database`) — section tab switchers
- [x] Narrow viewport — open the hamburger; Tab through menu buttons
- [x] `/partners/catalog` — filter / view controls
- [x] Blog view toggle (list ↔ grid)

### Docs ([staging
link](https://docs-git-danny-depr-627-promote-require-explici-25e46d-supabase.vercel.app/))

- [x] **Desktop (≥ lg):** top-right **⋯ menu** (hamburger icon) — opens
a dropdown that includes Theme. Not a separate theme button.
- [x] **Mobile (< lg):** top-right **hamburger** opens the sheet; close
(X) is the raw button we tagged. Theme inside the sheet uses
`ThemeToggle` / `DropdownMenuTrigger` from `ui` (already supposed to set
`tabIndex`).
- [x] **Code blocks** — copy / language controls
- [x] **Is this helpful?** — X / check are `Button` from `ui` (should
already Tab). After voting **while signed in**, the follow-up “What went
well?” / “How can we improve?” text button is the raw one we tagged.
- [x] **AI Tools → Copy as Markdown** (right rail on a guide) — this is
the only GuidesSidebar control this PR changed. “On this page” TOC items
are **links**, not covered by this lint.
- [x] **Reference docs** (e.g. JS client reference) — section headers
that expand/collapse in the left nav (`Collapsible.Trigger`)
- [x] **Troubleshooting index** — type in the search field, then Tab to
the **clear (X)** control

### Dashboard (`studio`)

No production UI changes in this PR (tests + lint config only). Quick
Safari smoke that prior tabindex work still holds:

- [x] Project sidebar — Tab through primary nav links
- [x] Settings → General — Tab through inputs / buttons
- [x] Storage → Files — Tab a bucket row / file actions
2026-07-23 05:21:15 +10:00
Ali Waseem b100272376 chore(sql-editor): remove Pretty Explain feature (#47981)
Removes the SQL Editor Pretty Explain feature — the Explain tab, the Run
EXPLAIN ANALYZE action + shortcut, and its dead plumbing. It's been
gated off behind the `DisablePrettyExplainOnSqlEditor` kill switch for
weeks with no usage or complaints.

`ExplainVisualizer` / `isExplainQuery` are kept — they're used
independently by Query Insights, Query Performance, and the EditorPanel
quick-runner. Manually-run `EXPLAIN` queries still render as raw rows in
the Results tab.

Typecheck, lint, and all affected unit tests pass.

Closes FE-3930

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

## Summary by CodeRabbit

* **Changes**
* Removed the SQL editor’s EXPLAIN execution workflow, including its
toolbar action, keyboard shortcut, utility tab, and visual query-plan
display.
  * Simplified query execution to focus on standard results and charts.
* Improved result clearing when switching databases and refined
execution error handling.
* Updated SQL editor state and tests to reflect the streamlined
experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 11:04:34 +08:00
Charis 52a25c2ebb refactor(sql-editor): extract AI/diff + shortcuts hooks (decompose 5/6) (#47935)
## What

Decompose step **5 of 6** for `SQLEditor.tsx`. Extracts the Assistant /
diff cluster and the keyboard-shortcut wiring out of the
`SQLEditorContent` monolith into two focused, individually-testable
hooks:

- **`useSqlEditorAi`** — SQL completion (`complete`), the ask-AI prompt
flow (`handlePrompt`), accept/discard diff handlers, `onDebug` /
`buildDebugPrompt` helpers, `handleDiffEditorMount`, and the fragile
diff lifecycle effects (one-shot diff-request drain, diff-editor value
sync, ask-AI widget visibility).
- **`useSqlEditorShortcuts`** — the registered shortcuts (focus editor,
new snippet, format, explain) plus the accept/discard/escape keydown
handling.

`SQLEditorContent` now composes these hooks alongside the
execution/explain hooks landed in decompose 4.

## Behavior-preserving

This is a pure extraction. The moved function bodies, effect logic,
dependency arrays, and JSX are unchanged from the previous monolith
(verified via `git diff` against the pre-decomposition source). In
particular:

- `useEffectEvent` is preserved for `drainDiffRequest` / `resetDiff`.
- `editorMountCount` remains single-owner (passed into the AI hook to
drive the one-shot drain).
- The untrusted→safe SQL promotion (`acceptUntrustedSql`) continues to
happen in the run/explain gesture and warning-modal handlers in
`SQLEditorContent`, as close to the explicit user action as possible.

The Phase-1 characterization suite (`SQLEditor.test.tsx`, 11 tests)
remains green.

## Stack

Part of the SQLEditor decomposition stack (1/6 … 6/6). Builds on
decompose 4 (execution + explain hooks, #47923). Next: PR6 splits the
JSX into panes + final cleanup.


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

## Summary by CodeRabbit

* **New Features**
* Improved SQL editor AI assistance, including completion prompts,
debugging support, and diff review controls.
* Added keyboard shortcuts for accepting or discarding AI-generated SQL
changes.
* Added shortcuts for focusing the editor, creating snippets, formatting
queries, and explaining SQL.

* **Bug Fixes**
  * Prevented SQL execution while reviewing AI-generated differences.
* Improved handling of AI diff state during editor loading and
interaction.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 15:14:12 -04:00
Charis d453e57086 test(sql-editor): characterization tests for SQLEditor (decompose 1/6) (#47820)
## Summary

Add some tests for the SQL editor so I can refactor it without
regressions. Tests are not best practice because they are intended to be
temporary and improving them would require refactoring first (currently
they are over-mocking and asserting on internal details).

Stacked on top of #47792 (`charislam/sql-editor-top-bar-controls`).

## What this adds

`apps/studio/tests/components/SQLEditor/SQLEditor.test.tsx` (11 tests):

- Run success → `addResult` + Results tab; EXPLAIN-shaped result
auto-switches to the explain tab; a non-EXPLAIN run switches back.
- Run error with `position` → error-highlight line math +
`deltaDecorations` + `revealLineInCenter`; the next run clears the
highlight.
- Run button refocuses the editor; disabled + short-circuits while a
diff is open.
- Diff request queued before mount drains exactly once (one-shot; no
re-apply on remount).
- Ask-AI widget renders only while the prompt is open (render-time
`editorRef.current` read).
- Destructive query → warning modal → confirm forces the re-run;
confirm-with-RLS appends enable-RLS statements.

## Test approach

Real Monaco / DiffEditor are replaced with lightweight fakes exposing a
controllable editor; child panels + orthogonal context hooks are
stubbed; the execute mutation runs for real against an MSW-mocked
`/platform/pg-meta/:ref/query`. Tests assert on public behavior so they
survive the internal refactor unchanged.

## Verification

- `pnpm --filter studio exec vitest run
tests/components/SQLEditor/SQLEditor.test.tsx` — 11/11 pass (stable
across repeated runs)
- `pnpm --filter studio typecheck` — clean
- `eslint` — 0 errors

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

## Summary by CodeRabbit

* **Tests**
* Added comprehensive coverage for SQL editor behavior, including query
execution, result and explain views, error highlighting, editor focus,
and diff mode.
* Added validation for destructive-query confirmations, including RLS
confirmation flows.
* Added coverage for queued diff requests and conditional AI prompt
display.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 10:47:45 -04:00
Gildas Garcia c6fc456910 chore: cleanup duplicate exports studio (#47387)
## Problem

Knip reports many duplicate exports (both named and default). Besides,
we're moving away from default exports and even have an eslint rule to
enforce it on new code.

## Solution

- Cleanup those exports
- Update imports when necessary

No functional changes. If it builds, it's fine
2026-06-29 15:46:16 +02:00
Gildas Garcia 4e86c39ea1 chore: remove <ContextMenu> _Shadcn_ suffix (#45971)
## Problem

The `_Shadcn_` suffix isn't needed anymore on `<ContextMenu_Shadcn_>`
and related components

## Solution

Remove it. No other changes

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

* **Refactor**
* Replaced legacy context-menu component variants with the unified UI
context-menu components across the app for consistent rendering and
imports; behavior and menu content remain unchanged.
* **Tests**
* Updated a test mock to track the unified context-menu component mount
count.
* **Chores**
* Simplified UI package re-exports to expose the canonical context-menu
symbols.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45971)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 15:09:25 +02:00
Ali Waseem 153f2619bc feat(studio): show expand affordance for large SQL result cells (#45589)
## Summary

- Adds a hover-revealed expand button to SQL result cells whose value is
unlikely to fit on one line (objects, arrays, strings >60 chars, or
strings with newlines). Clicking opens the existing `CellDetailPanel`
for that cell.
- Switches the expand state from a boolean tied to the selected cell to
a direct `{ column, value }` reference, so the context menu and the new
button both target the right-clicked / clicked cell.
- Extracts the per-cell renderer into its own `ResultCell` component to
keep `Results.tsx` digestible and the new affordance isolated.
- Covers the new logic with exhaustive `isLargeValue` unit tests and a
`ResultCell` component test (visibility, click, right-click).

Linear: [FE-3130](https://linear.app/supabase/issue/FE-3130)

## Test plan

- [x] Run a SQL query that returns mixed cell types (short strings, long
strings, JSON objects, arrays, nulls) and confirm the expand button
appears only on cells where content is likely truncated.
- [x] Hover a large cell and click the expand button — `CellDetailPanel`
opens with the correct column + value.
- [x] Right-click a large cell and choose "View cell content" — same
panel opens with the right cell.
- [x] Right-click a small cell and "Copy cell content" — clipboard
contains the raw value.
- [x] Resize a column wider than its content and confirm the button
still positions correctly.
- [x] `pnpm vitest` for `Results.utils.test.ts`, `Results.test.tsx`,
`ResultCell.test.tsx` — all green.

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

## Summary by CodeRabbit

* **New Features**
* Enhanced SQL result cells with automatic detection and expansion
functionality for large values (exceeding 60 characters or containing
line breaks)
  * Added expand button to view full cell content directly in results
  * Integrated right-click context menu for cell content options
  * Improved display of null values in query results

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 11:00:09 -06:00
Charis 205cbe7d26 chore(studio}: enforce import order, remove bare import specifiers (#44585) 2026-04-07 20:34:10 -04:00
Ali Waseem fbb0770b47 fix(studio): AI assistant results make page unresponsive (#44578)
## Summary

Fixes https://linear.app/supabase/issue/FE-2941

- Replaced per-cell `ContextMenu_Shadcn_` in SQL result tables with a
single shared instance
- Each Radix ContextMenu registers a `keydown` listener on `document`
via `useEffect`. With 1000+ row result sets, this created thousands of
document-level listeners. Chrome trace showed listeners growing from 21k
to 347k, with every keystroke taking ~250ms (70k+ function calls per
long task)
- Fixed DataGrid not rendering in Firefox by using flex layout instead
of `height: 100%` for sizing
- Fixed double scrollbar in QueryBlock results by making the container a
flex column and removing `overflow-auto`
- Moved format utils into `Results.utils.ts`

## Test plan

The `Results` component and `QueryBlock` are used in several places.
Each should be verified:

- [x] **AI Assistant** — Have the assistant run a query returning 1000+
rows. Verify the page stays responsive while typing and there is only a
single scrollbar on the results table
- [x] **AI Assistant (Firefox)** — Same as above but in Firefox. Verify
the results table actually renders
- [x] **SQL Editor results panel** — Run a query in the SQL Editor.
Verify results render correctly with a single scrollbar in the utility
panel
- [x] **SQL Editor explain tab** — Run an EXPLAIN query. Verify explain
results render
- [x] **Editor Panel** (used in Table Editor SQL preview) — Verify
results display correctly
- [x] **Context menu** — Right-click a cell in any of the above and
verify "Copy cell content" and "View cell content" still work

## Traces
<img width="891" height="599" alt="image"
src="https://github.com/user-attachments/assets/6e1b710b-ca9e-4748-9369-d03457d80206"
/>


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

* **Bug Fixes**
* Fixed context menu behavior so it opens at the cursor and is
instantiated once.
* Improved clipboard copy formatting for cell values; NULLs copy as
empty and cells render as "NULL".

* **Style**
* Adjusted table layout and scrolling behavior to improve results
container sizing.

* **Tests**
* Added tests for results rendering, context-menu behavior, and
cell/clipboard formatting utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-06 13:04:24 -06:00