When a user has sorted by some column in the Table Editor and the column
is deleted, the sort data is wrong so it causes issues. In the general
view in the Table Editor, the error is handled by removing the sort key
when a specific error is detected but it can still happen in
ForeignRowSelector.
To test:
1. Have 2 tables with references between them.
2. In the `sessionStorage`, under the `supabase_grid-<ref>` key, update
the sort key to a non-existant column for a table.
3. Try to open the `ForeignRowSelector` for that table by clicking on a
cell in the referencing column.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Sorting now validates referenced columns and ignores invalid sort
entries.
* Local sort restoration and UI sort application now derive sorts from
the original table context for more consistent behavior across editors
and popovers.
* Prefetch logic uses the resolved table context when falling back to
saved sorts.
* **Tests**
* Added cases for malformed and out-of-scope sort parameters to prevent
regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Broken by: #45504
- closes: #46744
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Refined the footer layout to improve alignment of view and table
toggle controls.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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?
- Noticing our code we have many patterns of calling localstorage and
handling those errors
- We should add those in a single well tested file
- Handle those errors in the singleton which makes it easier for us to
debug customer issues. Logger is outputing local storage warnings for
feature we expose
- Side effect of this is random crashes on studio when local storage
isn't available or handled correctly
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved browser storage handling across the app for more reliable
persistence and graceful behavior in restricted or non-browser
environments (settings, previews, charts, tabs, sign-in/session flows,
integrations, and UI state).
* **New Features**
* Introduced a safe storage layer to standardize and harden
local/session persistence.
* **Tests**
* Added comprehensive tests covering the new safe storage behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Follow-up to #46448, which removed the doubled DataGrid borders across
Studio. The table editor grid had the same doubled border at the bottom,
but unlike the other grids it still needs a top border — and that top
border was rendering in react-data-grid's own `--rdg-border-color`
rather than the studio default.
**Changed:**
- Removed the doubled bottom border on the table editor `<DataGrid>`
(`border-b-0!`)
- Forced the top border to the default border color via the
`border-t-default!` token (≈ rgb(46,46,46) / `--border-default`) instead
of leaning on react-data-grid's `--rdg-border-color`
## To test
- Open the table editor for any table (`/project/[ref]/editor/[id]`)
- Confirm there's a single top border between the filter/sort toolbar
and the grid header, in the standard border color
- Confirm there's no extra line at the bottom of the grid
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Refined grid visuals and spacing to improve alignment and visual
consistency across the app. Adjustments to border and growth behavior
reduce border inconsistencies and layout jitter during resizing. Context
menu display behavior remains intact, ensuring expected right-click
interactions continue to work smoothly for users.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Studio is on `react@^19.2.6`, and `useEffectEvent` shipped stable in
React 19.2 with the same signature as the userland polyfill. This drops
the local hook in `apps/studio` and `apps/www` in favor of the built-in.
**Removed:**
- `apps/studio/hooks/useStaticEffectEvent.ts`
- `apps/www/hooks/useStaticEffectEvent.ts`
- `.claude/skills/use-static-effect-event/` — skill is obsolete
**Changed:**
- 26 call sites: dropped the `useStaticEffectEvent` import, added
`useEffectEvent` to the existing `react` import, renamed call sites
- `.claude/CLAUDE.md`: `apps/studio` row updated React 18 → React 19
- `.claude/skills/vercel-composition-patterns/SKILL.md`: removed stale
"Studio uses React 18, skip these patterns" warning
## To test
- `pnpm typecheck --filter=studio` — passes locally
- `pnpm typecheck --filter=www` — passes locally
- `grep -rn "useStaticEffectEvent"` returns nothing outside
`node_modules`
- Smoke-test areas that use the hook: schema visualizer edges
(intersection check), spreadsheet import, sign-in/CLI login flows, side
panels with unsaved-changes prompts
**Out of scope:** pre-existing Tailwind lint warning on
`DefaultEdge.tsx:141` (`outline` + `outline-1` conflict) — unrelated to
this migration
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Internal event handling migrated to React’s built-in event hooks
across the Studio app; no user-facing changes.
* **Documentation**
* Clarified React 19 compatibility and noted Studio now targets React
19.
* Removed obsolete documentation for a deprecated internal hook.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46415?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Copy/export of selected rows in the Table Editor refetches full values
for cells truncated in the grid (via `getCellValue`), but that refetch
was bypassing role impersonation. The main grid query respects the
impersonated role; the truncated-cell hydration didn't, so the copy
could fetch as the service role even when "View as <role>" was active –
an inconsistency, since the UI still indicates the impersonated role is
in effect.
Threads `roleImpersonationState` through `hydrateTruncatedRows` →
`getCellValue`, and wraps the SQL in `wrapWithRoleImpersonation`
(matching how `getTableRows` does it). Addresses FE-3493.
**Changed:**
- `getCellValue` accepts an optional `roleImpersonationState` and wraps
its SQL with `wrapWithRoleImpersonation` + flags
`isRoleImpersonationEnabled` on `executeSql`
- `hydrateTruncatedRows` threads `roleImpersonationState` through to
`getCellValue`
- `Header.tsx`'s `onCopyRows` passes the in-scope
`roleImpersonationState` into `hydrateTruncatedRows`
## To test
1. Open the Table Editor on a table with a row containing a
large/truncated string value and a primary key
2. Enable role impersonation → "View as role" → pick any role with read
access to the table
3. Select the row, then `Copy → Copy as JSON` (also try CSV / SQL)
4. The copy should succeed and contain the full (non-truncated) value
5. Inspect the SQL request – it should now be wrapped with the
impersonation context, matching how the main grid query is wrapped
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
## Context
There's an issue with copying / exporting rows from the table editor
with the following conditions:
- Row has a column value that exceeds 10,240 and hence is truncated for
performance reasons
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/4639edbb-ece6-4028-89b6-769ac314c3f3"
/>
- User is trying to copy/export selected rows (not all rows in the
table)
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/e7c0da77-051c-4c46-af0d-f9510e0b37c4"
/>
The copy/export action will return the truncated data which is incorrect
(Should return the full data)
## Problem
This is happening as if we're only copying/exporting selected rows,
we're just using what's been loaded in the table editor to export (as
opposed to if the user is copying/exporting all rows in the table, we'd
be fetching the data from the database first before doing so)
Hence am opting to add a data hydration logic, such that if there's a
selected row that's been truncated, we'd fetch them on demand first
before copying/exporting.
There's limitations to this though - e.g if the table doesn't have a
primary key we can't do this (since we need to run a query to fetch the
data). This is already an existing behaviour when trying to load the
column value in the table editor in the grid so no issues I believe.
We'll just show this toast:
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/442637bb-4b9b-492d-b202-bbf6e5ae7512"
/>
## To test
You'll need a column with a really large value - the way I do it is to
load the data directly into the DB via TablePlus
- [ ] Verify that copying / exporting selected rows with really large
column values copies/exports all the data correctly (there shouldn't be
any truncated value)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Improved handling of truncated cell values during copy and export
operations
* **Bug Fixes**
* Copy and export operations now require an active project selection
* Fixed data export for tables without primary keys
* **Style**
* Updated grid header copy and export control layout
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46268?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Closes
[FE-3399](https://linear.app/supabase/issue/FE-3399/make-table-editor-filter-bar-wait-for-a-value)
- Table editor's filter bar was firing a row request as soon as a
property was selected, before any operator/value was set. This regressed
after #46071 unified the table editor and unified logs onto the shared
`FilterBar`.
- `LogsFilterBar` already validates that each condition has a
propertyName, operator, and non-empty value before applying.
`FilterPopoverNew.handleApply` did not — it called `setFilters`
unconditionally on every `onApply` from the shared bar (property change,
operator change, blur, etc.). This PR mirrors the `LogsFilterBar`
validation so the table editor stops requesting rows until the condition
is complete.
## Test plan
- [ ] Open the table editor on any table
- [ ] Click the filter bar, pick a column → no network request fires, no
toast, grid unchanged
- [ ] Pick an operator → still no request
- [ ] Type a value and hit Enter → row request fires, grid filters
- [ ] Remove the filter → grid refetches with no filter
- [ ] New e2e test: `pnpm --prefix e2e/studio run e2e --
features/filter-bar.spec.ts --grep "does not trigger a row request"`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Filter validation now prevents incomplete filter conditions from being
applied, ensuring only fully-specified filters affect table data.
* **Tests**
* Added end-to-end test coverage for filter bar operations to verify
expected behavior during filter setup.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46113?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Context
Swaps out (and deprecates) the unified logs's own filter bar, for our
existing design system's filter bar
<img width="1450" height="355" alt="image"
src="https://github.com/user-attachments/assets/c5e83bd1-4e67-4bb5-8f27-a3d9beacbbb5"
/>
Other changes involved for the FilterBar itself includes the following
(more details in subsequent sections)
- Add `onApply` param for `FilterBar` that will only trigger when an
entered filter is "complete" (e.g on enter or blur)
- Automatically select the operator if only one exists
## To test
- Verify that the filter bar in general works BUT note there's some odd
behaviour when searching on say the "status" column (more details under
known issues)
- likely something with the internal SQL i think, will need to
investigate separately
- afaict testing on the method seems to be working at least
---
### Add `onApply` parameter for `FilterBar`
The search behaviour for the filter bar feels a bit awkward atm -
referencing the table editor:
- selecting the column triggers a search, which returns an error cause
the search query is incorrect (operator and value not selected yet)
- when typing the search value (after selecting the column + operator),
the search triggers on debounce, which feels odd in this context as I'd
expect the search to only trigger when i've hit enter (e.g to "finalize"
my search parameters)
- Am adding an `onApply` parameter gets called when a filter is
"complete" -> column, operator, and value are finalized (e.g via Enter
or onBlur)
- Updated both Unified logs and table editor to use this behaviour
### Automatically select operator if only one exists in `FilterBar`
This one's more specific to unified logs since there's only an `=`
operator - but saves an unnecessary "enter" key event when filtering in
unified logs
### Known issues
- For some reason (even with the existing filter bar) - searching
against status for e.g for postgres logs doesnt return the expected
rows. e.g i've got rows with status as `00000`, but searching for
`00000` doesnt return anything. Suspect its something to do with the SQL
we're firing?
<img width="1167" height="271" alt="image"
src="https://github.com/user-attachments/assets/1dde74cf-8366-4cf1-8d8f-6907ba2473f6"
/>
<img width="1184" height="453" alt="image"
src="https://github.com/user-attachments/assets/bf55f0fb-cb27-4e8f-b2d9-cd913d6ac6b9"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a dedicated Logs filter bar with an explicit "apply"/commit
callback for filter UI.
* **Bug Fixes**
* Filter edits are buffered locally and only committed on apply to
prevent aggressive data requests.
* **Refactor**
* Replaced legacy command-style table filter UI and removed related
utilities.
* Updated filter commit lifecycle and narrowed option value typing;
adjusted top-level provider ordering.
* **Style**
* Small layout and trigger behavior tweaks for filter controls, timeline
chart spacing, and download button.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46071?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
## Summary
Resolves 13 findings (2 HIGH, 5 MEDIUM, 6 LOW) from the frontend
telemetry audit: 1 action-string collision, 1 camelCase experiment name,
9 dead events removed, 4 missing org groups attached, 1 ambiguous
property renamed, 1 raw-string property narrowed, plus consolidations
and a structural tightening on TABLE_EVENT_ACTIONS.
## Changes
### HIGH
- Rename `EventPageCtaClickedEvent.action` to
`www_event_page_cta_clicked` so it no longer collides with the pricing
CTA event (which had a different schema sharing the same action string)
- Snake_case the header-upgrade experiment exposure name
(`headerUpgradeCta_experiment_exposed` →
`header_upgrade_cta_experiment_exposed`); PostHog flag key and
`?source=` URL param unchanged
### MEDIUM
- Remove 4 dead `ProjectCreation*Step*` events (referenced a v2 route
that doesn't exist; 0 emissions)
- Remove 4 dead experiment exposure events:
`ProjectCreationRlsOptionExperimentExposed`, `HomeNewExperimentExposed`,
`TableCreateGeneratePoliciesExperimentExposed`,
`TableCreateGeneratePoliciesExperimentConverted` (0 emissions)
- Attach org group to `dpa_request_button_clicked` (0% had `$group_0`
per Hex)
- Delete `RegisterStateOfStartups2025NewsletterClicked` (interface
naming outlier, 0 emissions, page renamed to 2026)
- Rename `AssistantSuggestionRunQueryClickedEvent.category` to
`mutationType` with tightened literal union (`'functions' |
'rls-policies' | 'unknown'`)
- Attach org group to `project_creation_default_privileges_exposed` on
Vercel surface via explicit `groupOverrides` (auto-injection misses
because `useSelectedOrganizationQuery` is undefined on that page)
### LOW
- Consolidate `IndexAdvisorBannerEnableButtonClickedEvent` +
`IndexAdvisorDialogEnableButtonClickedEvent` into one event with
`origin: 'banner' | 'dialog'`
- Rename `ImportDataFileDroppedEvent` → `ImportDataFileAddedEvent` so
the interface name matches the action and the verb is on the approved
list
- Rename `LogDrainConfirmButtonSubmittedEvent` → `LogDrainRemovedEvent`
and action to `log_drain_removed` (fires on delete-confirm modal,
matches `CronJobRemovedEvent` pattern)
- Add `type` property to `CronJobRemovedEvent` (parsed from the job's
command), matching the create/update event shape
- Tighten `TABLE_EVENT_ACTIONS` values with `satisfies` against the
event union so renames in the union fail typecheck here too
- Attach org group to `www_pricing_plan_cta_clicked` at 5 emission sites
when an org is available in the page context
- Narrow `unified_logs_row_clicked.logType` from raw `string` to the
5-literal `LOG_TYPES` union (zod already validates server values)
### Bundled refactor
Migrated 5 emission sites from deprecated `useSendEventMutation` to
`useTrack` while their containing files were being edited: `DPA.tsx`,
`DisplayBlockRenderer.tsx`, `Grid.tsx` (2 events), `DeleteCronJob.tsx`.
Full sweep of the remaining ~79 files is a separate follow-up.
## Testing
Mostly just renaming of events
## Linear
- fixes GROWTH-798
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Standardized telemetry to a unified tracking system for more
consistent analytics.
* Simplified experiment exposure reporting for upgrade prompts.
* **New Features**
* More granular tracking for CSV import, cron job deletions, log drain
removals, DPA downloads/requests, and pricing CTAs.
* Assistant now classifies mutation queries more precisely.
* **Bug Fixes**
* Improved default-privileges exposure logic on Vercel deployments
(skips when org missing).
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45964)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
The `_Shadcn_` suffix isn't needed anymore on `Select` components
## Solution
Remove it. No other changes
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated internal component architecture to standardize and simplify
the codebase. These changes improve code maintainability and consistency
across the application without affecting existing functionality or user
experience.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45988)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Most changes are related to either types or `useRef` usages (it now
requires an initial value).
- also updated `vaul` to its latest version and haven't noticed any
change ([design-system
demo](https://design-system-git-react-19-supabase.vercel.app/design-system/docs/components/drawer))
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Upgraded workspace to React 19.
* **Bug Fixes**
* Improved null-safety and ref handling across editors, UI components,
shortcuts, and markdown/image rendering to reduce runtime errors.
* Safer event/timeout/interval cleanup and more robust command/context
handling.
* **Chores**
* Bumped vaul dependency versions.
* **Documentation**
* Type and TypeScript accuracy improvements for clearer developer
feedback.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We have multiple Popover components
## Solution
- [x] migrate Popover usages to Shadcn components
- Migrated JSON and text editor in the `TableEditor` (inline row
edition)
- Migrated the template popover in the logs explorer templates page
- [x] remove `_Shadcn_` suffix from Popover components (renaming +
prettier)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Unified popover implementation across the app and design system;
dropdowns, calendars, menus and tooltips now use a consistent popover
API with no visual or interaction changes.
* **Chores**
* Minor prop typing update for the logs date-picker to align with the
consolidated popover content type.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45980)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45971)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Fix a grammar error in `GridError.tsx`: the `title` prop used `"is not
supporting on"` (wrong verb form) while the body text immediately below
in the same component already correctly reads `"is not supported on"`.
- Add `aria-label` to two icon-only `<Button>` elements in the table
grid editor — `RefreshButton` and the TextEditor expand button — which
had no accessible name for screen readers. Tooltip content alone is not
announced by assistive technology (WCAG 2.1 §4.1.2).
## Changes
- `apps/studio/components/grid/components/grid/GridError.tsx` — grammar
fix (`supporting` → `supported`)
- `apps/studio/components/grid/components/header/RefreshButton.tsx` —
add `aria-label="Refresh table data"`
- `apps/studio/components/grid/components/editor/TextEditor.tsx` — add
`aria-label="Expand editor"`
## Test plan
- [ ] No logic changed; UI text and accessibility attributes only
- [ ] Visually identical for sighted users
- [ ] Screen reader users can now identify both icon-only buttons by
their accessible name
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Corrected error message text for invalid sorting operations.
* **Accessibility**
* Added descriptive labels for screen readers to the "Expand editor" and
"Refresh table data" buttons.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45762)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 / dependency cleanup.
## What is the current behavior?
`apps/studio` lists both `@supabase/pg-meta` (workspace package) as a
runtime dep and `@supabase/postgres-meta` (external npm package,
`^0.64.4`) as a devDependency. The external package is used only for
type imports across 44 files — there is no runtime usage and no codegen
pipeline that needs it.
## What is the new behavior?
Every `Postgres*` type import (`PostgresTable`, `PostgresColumn`,
`PostgresPolicy`, `PostgresTrigger`, `PostgresView`,
`PostgresMaterializedView`, `PostgresForeignTable`, `PostgresSchema`,
`PostgresPublication`, `PostgresRelationship`, `PostgresPrimaryKey`) is
replaced with its `PG*` counterpart from `@supabase/pg-meta`, and the
external dep is removed from \`apps/studio/package.json\`. Top-level
type re-exports were added to \`packages/pg-meta/src/index.ts\` so
consumers can import directly from the package root.
Two latent issues surfaced by the stricter pg-meta types are also fixed:
- \`data/foreign-tables/foreign-tables-query.ts\` was casting
foreign-table results as \`PostgresView[]\`; corrected to
\`PGForeignTable[]\`.
- \`pg-meta\`'s \`PGTrigger\` Zod schema declared
\`orientation\`/\`activation\` as \`z.string()\`, inconsistent with
pg-meta's own \`getDatabaseTriggerUpdateSQL\` helper that requires the
narrow literal unions; tightened to \`z.enum\`.
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated internal TypeScript type definitions across the codebase to
use the latest type system from `@supabase/pg-meta`.
* Removed `@supabase/postgres-meta` dependency.
* Enhanced type validation for database triggers and schemas to enforce
stricter constraints.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45844)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Consolidate Table Editor grid header actions into a single row
https://github.com/user-attachments/assets/1020c385-8fa9-4ef1-b5e7-03983111508b
## Changes involved
- Index advisor, Realtime, and API docs are now behind a dropdown menu
button (Treated as secondary actions)
- Grid header actions shifted into the same row as filter bar (more
space for data grid)
- Header actions will hide while filter bar is in focus (remove
distractions, more space for filter bar)
## Changes to filter bar
- Filter bar will refocus when deleting a filter
- Clicking on the search icon will focus on the free form input of the
filter bar
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a “More” dropdown in grid actions to access Realtime, API docs,
and Index Advisor.
* New dialogs for enabling Index Advisor and toggling Realtime are now
consistently managed.
* **Improvements**
* Improved filter focus handling with auto-refocus when conditions
change and responsive header behavior.
* Adjusted popover alignment, separator visuals,
header/footer/pagination layout and sizing.
* Filter bar now supports programmatic focus; Connect button supports
icon-only mode.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
## Context
Realised that MultiSelector's content is not scrollable when rendered
within a sheet (e.g Auth policies, Database indexes)
### Explanation from Claude:
- The issue is that Radix Dialog (Sheet) adds
@radix-ui/react-remove-scroll which intercepts wheel events. The Popover
portal renders outside the Sheet's DOM tree, so the scroll lock blocks
wheel events on CommandList.
- The fix is to stop wheel event propagation on the CommandList so it
doesn't reach the RemoveScroll handler.
### To test
- [ ] Verify that MultiSelector can be scrollable within a sheet (e.g
Auth policies roles) and outside of a sheet (e.g Data API -> Exposed
schemas)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed scroll wheel propagation in multi-select dropdown to prevent
unintended scrolling of parent elements.
* **Updates**
* Simplified filter component interface by removing an unused
configuration property.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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?
- Safari Table Editor cells fail to copy from a focused cell with `⌘C`.
- Safari right-click can show the browser menu instead of the custom
cell menu.
- Copy can leave RDG's copied-cell fill behind.
## What is the new behavior?
- Reuses the existing shared `copyToClipboard(value, onSuccess)`
pattern, with the Safari clipboard fix inside that util.
- Handles selected-cell `⌘C` in the RDG keydown path, preventing
browser/RDG defaults and showing the success toast only after copy.
- Replaces the row-level synthetic context-menu shim with RDG's
`onCellContextMenu`, so we prevent Safari's browser menu at the source
and select/focus the target cell.
- Keeps the selected-cell outline while the controlled menu is open.
## Additional context
- `RowRenderer` was only supporting the old context-menu shim; removing
it is part of moving to RDG's cell event path.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Context menu now provides feedback with toast notifications when
copying cells or rows.
* Selected cells retain their visual styling when context menu is open.
* **Bug Fixes**
* Improved keyboard shortcut handling for copy functionality.
* Enhanced clipboard error handling with user-friendly error messages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## TL;DR
typing into a cell after single click was broken for keys like `I`, `F`,
`C`,`R`, `U` & `S`
because those keys could be picked up as shortcut prefixes instead of
starting cell editing
## sol:
https://github.com/user-attachments/assets/e388b79f-5334-47ef-a834-9164b255b88c
## ref:
- Closes https://github.com/supabase/supabase/issues/45445
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved keyboard interaction in grid cells: typing a single printable
character now enters editable cells directly (allowing immediate
edit-mode), while other registered keyboard shortcuts still take
precedence and continue to block default grid behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Context
Resolves FE-3126
Just cleaning up the table editor header with a bit of refactors
(pre-req to investigating collapsing filter bar and table editor header
actions into a single row)
## Non-visual changes involved
- Break down components within `GridHeaderActions` into smaller ones
- `IndexAdvisorPopover`
- `SecurityDefinerViewPopover`
- `RealtimeToggle`
- Deprecate use of `useUrlState` in `GridHeaderActions` to use
`useQueryState` instead
- Improve types for `TwoOptionToggle`
## Visual changes involved
- Collapse realtime button toggle into a button icon, with no text (just
tooltip)
- Adjust layout of buttons a little
### Before
<img width="796" height="118" alt="image"
src="https://github.com/user-attachments/assets/436bca94-4d91-471a-a184-487c6f78dc04"
/>
### After
<img width="731" height="132" alt="image"
src="https://github.com/user-attachments/assets/5fd30982-a1fc-4f92-a590-146d1e69d52a"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Index Advisor popover with recommendations.
* Realtime toggle to manage realtime table publication.
* Security Definer view popover with optional autofix.
* Insert menu for adding rows/columns and CSV import.
* **Bug Fixes**
* Adjusted filter bar input sizing for improved readability.
* **Refactor**
* Header layout updated and insert/import actions moved into dedicated
components.
* **Tests**
* Updated end-to-end selectors for the Insert row menu item.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR migrates the whole monorepo to use Tailwind v4:
- Removed `@tailwindcss/container-queries` plugin since it's included by
default in v4,
- Bump all instances of Tailwind to v4. Made minimal changes to the
shared config to remove non-supported features (`alpha` mentions),
- Migrate all apps to be compatible with v4 configs,
- Fix the `typography.css` import in 3 apps,
- Add missing rules which were included by default in v3,
- Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot
of classes
- Rename all misnamed classes according to
https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all
apps.
---------
Co-authored-by: Jordi Enric <jordi.err@gmail.com>
## 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?
Feature — a second batch of table editor shortcuts, stacked on top of
#45178.
## What is the current behavior?
Inserts / filters / sort / refresh are all mouse-only. No keyboard
access, and no affordance for discovering what keybinds might exist.
## What is the new behavior?
### New shortcuts
| Keybind | Action | Surface |
|---|---|---|
| `I` then `R` | Insert row | hotkey + Cmd+K + inline keybind in Insert
dropdown |
| `I` then `C` | Insert column | hotkey + Cmd+K + inline keybind in
Insert dropdown |
| `I` then `U` | Import data from CSV | hotkey + Cmd+K + inline keybind
in Insert dropdown |
| `Shift+F` | Focus filters | hotkey + Cmd+K — focuses the new filter
bar's freeform input |
| `F` then `C` | Clear filters | hotkey + Cmd+K — gated on
`filters.length > 0` |
| `S` then `C` | Clear sort | hotkey + Cmd+K — gated on `sorts.length >
0` |
| `Shift+R` | Refresh table | hotkey + Cmd+K + hover tooltip on the
Refresh button |
All are `ignoreInputs: true` so they don't fire while typing. The insert
/ clear-filters / clear-sort shortcuts use two-step chords so they don't
clobber single-letter keys users might reach for elsewhere; Focus
filters and Refresh keep their Shift-prefixed single-step bindings.
### Infrastructure
- **New `<ShortcutBadge>`** (`components/ui/ShortcutBadge.tsx`) — inline
keybind display. Reads the sequence straight from the registry, so the
ID is the single source of truth. Renders multi-step chords with a
"then" separator between steps. Defaults to `variant="inline"` (the flat
`text-foreground/40` style used across the app in `RunButton`,
`ActionBar`, `OperationQueueSidePanel`, etc.) with `variant="pill"`
available if someone needs the boxed style.
- **Insert dropdown restyled** — each `DropdownMenuItem` in
`HeaderNew`'s Insert menu now shows its keybind inline on the right
(centered vertically, with `pr-4` + `shrink-0` so long table names in
the description never crowd the badge).
- **`RefreshButton`** swapped from `ButtonTooltip` to `<Shortcut>` so
the keybind tooltip renders automatically from the registry.
- **`FilterPopoverPrimitive` untouched** — the old filter bar is being
deleted, so Shift+F is scoped to the new filter bar only. The handler
focuses `[data-testid="filter-bar-freeform-input"]` (the existing
freeform input in the ui-patterns `FilterBar` → `FilterGroup`).
## Additional context
Stacked on #45178 (FE-3057 — initial table editor shortcuts). Rebase
after that one merges.
### Test plan
- [x] Open a table → Insert dropdown shows keybind to the right of each
item, no wrap encroachment even with long table names
- [x] `I` then `R` opens the Row editor; `I` then `C` opens the Column
editor; `I` then `U` opens the CSV import flow
- [x] `Shift+F` focuses the new filter bar's freeform input
- [x] Add a filter → `F` then `C` clears it; shortcut disabled in Cmd+K
when no filters are applied
- [x] Sort a column → `S` then `C` clears sort; shortcut disabled when
no sorts
- [x] `Shift+R` refreshes the table (spinner shows on the Refresh
button); hover the button → keybind tooltip
- [x] All seven new entries show up in Cmd+K when their gates are
satisfied
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added keyboard shortcuts for table actions: insert row, insert column,
import CSV, refresh, focus filters, clear filters, and clear sorts.
* Shortcuts are available in the command menu and show visual keyboard
hints.
* **UI**
* Menu entries now display shortcut badges.
* Refined dropdown spacing/layout and updated the refresh control to
surface its shortcut.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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?
Feature — a set of new keyboard shortcuts for the table editor, along
with infrastructure to register, gate, and surface them.
## What is the current behavior?
Clicking into the grid "traps" the keyboard: Escape doesn't pop out,
there are no shortcuts for row selection / deletion / navigation, and
the search-tables input grabs focus on page load.
## What is the new behavior?
### New shortcuts (all scoped to the table editor)
| Keybind | Action | Surface |
|---|---|---|
| `Esc` | Exit grid selection — clears the highlighted cell and drops
focus back to the page | hotkey |
| `↑` / `↓` | Start grid navigation from the first cell when no cell is
selected | hotkey |
| `Shift+Space` | Toggle selection on the current row | hotkey +
checkbox tooltip |
| `Mod+A` | Toggle selection on all displayed rows (matches Excel) |
hotkey + header-checkbox tooltip + Cmd+K |
| `Mod+Shift+A` | Toggle selection on all rows in the table | hotkey +
"Select all rows in table" button tooltip + Cmd+K |
| `Mod+Backspace` | Delete selected rows | hotkey + delete-button
tooltip + Cmd+K |
### Infrastructure
- **Split registry** — table-editor shortcuts moved to
`state/shortcuts/registry/table-editor.ts`, spread into `SHORTCUT_IDS`.
Makes it easy to scope a runtime check to a specific surface.
- **`eventMatchesAnyShortcut`** (`state/shortcuts/matchEvent.ts`) —
queries the hotkey library's live `SequenceManager` so gated shortcuts
(`enabled: false`) are correctly excluded. Covered by
`matchEvent.test.ts`.
- **`handleCellKeyDown`** now calls `event.preventGridDefault()`
whenever the keystroke matches an active table-editor shortcut, so rdg's
"start editing on key press" default doesn't compete with shortcut
actions (e.g. typing `Shift+X` no longer opens edit mode with `X` as
input).
- **`<Shortcut>` / `<ShortcutTooltip>`** used on the header checkbox,
the per-row checkbox, the "Select all rows in table" button, and the
delete button — keybinds show up on hover (Linear-style) so users can
discover them without reading docs.
- **CSS** — `.rdg:not(:focus-within) .rdg-cell[aria-selected='true']`
drops the selected-cell outline whenever focus leaves the grid,
reinforcing the "you're out" feedback after `Esc`.
- **`useShortcut`** wraps the Cmd+K-registered action to close the
command menu after firing (previously menu stayed open after selecting
an action).
- **Search-tables input** no longer auto-focuses on load, so arrow
shortcuts work immediately without clicking out first.
## Additional context
Linear: FE-3057
### Test plan
- [x] Open any table → `↓` selects the first cell; subsequent arrows
navigate rows
- [x] `Esc` drops focus out of the grid and re-enables `↓` to re-enter
- [x] Click a cell → `Shift+Space` toggles that row's selection
(checkbox)
- [x] `Mod+A` toggles all displayed rows
- [x] With pagination + some rows selected → `Mod+Shift+A` toggles
"Select all rows in table"
- [x] With rows selected → `Mod+Backspace` deletes them (existing
confirmation flow)
- [x] Hover the header checkbox / per-row checkbox / delete button →
keybind tooltip after ~500ms
- [x] Cmd+K with selection → the relevant action shows up; selecting it
closes the palette and runs
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added table editor keyboard shortcuts for navigation, row selection,
and cell actions, with command-menu integration and visible shortcut
tooltips.
* **Improvements**
* Better keyboard handling in grid cells allowing external shortcuts to
override default behavior.
* Select-all/deselect-all toggle and improved select-row UX;
selected-cell styling no longer shows when grid loses focus.
* Command menu now reliably closes before executing shortcut actions.
* Removed autofocus on the table editor search input for consistent
focus behavior.
* **Tests**
* Added unit tests covering shortcut matching and command-menu shortcut
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR preps the monorepo for a migration to Tailwind v4:
- Bump all Tailwind dependencies and libraries to the latest possible
version, while still compatible with Tailwind 3.
- Cleans up obsolete Tailwind 3 specific options and configs.
- Cleans up unused CSS files and fixes the CSS imports.
- Migrates all `important` uses in `@apply` lines to using the `!`
prefix.
- Move `typography.css` to the `config` package and import it from the
apps.
- Migrated all occurrences of `flex-grow`, `flex-shrink`,
`overflow-clip` and `overflow-ellipsis` since they're deprecated and
will be removed in Tailwind 4.
- Make the default theme object typesafe in the `ui` package.
- Migrate all `bg-opacity`, `border-opacity`, `ring-opacity` and
`divider-opacity` to the new format where they're declared as part of
the property color.
- Bump and unify all imports of `postcss` dependency.
## Summary
- Removes the legacy Table Editor filter bar and its
`supabase-ui-table-filter-bar` feature-preview flag (opt-out rate
~0.13%, no plans to keep supporting it).
- Merges `HeaderNew` into `Header`, consolidates `useTableFilterNew`
into `useTableFilter`, and adds
`useOptionalTableEditorTableStateSnapshot` so `useTableFilter` can
safely fall back to URL params when called outside the table-editor
provider (e.g. from the sidebar).
- Drops the associated preview modal entry, screenshot, and local
storage key.
Based on the closed PR https://github.com/supabase/supabase/pull/44867.
Closes
[FE-3071](https://linear.app/supabase/issue/FE-3071/remove-old-table-editor-filter-bar).
## Test plan
- [x] `pnpm --filter=studio typecheck` passes
- [x] `pnpm --filter=studio lint` passes
- [x] Open the Table Editor, confirm the new filter bar renders and
filters apply/clear correctly
- [x] Apply filters, reload the page — filters persist via URL params
- [x] Delete a column that has an active filter — filter is removed
cleanly
- [x] Right-click a cell — "Filter by value" still appears for simple
values
- [x] Select rows — row-selection header (copy / export / delete) still
works
- [x] Foreign Row Selector still renders (`FilterPopoverPrimitive`
retained for this usage)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Table filter bar is now permanently available (no longer gated behind
preview feature).
* **Improvements**
* Reorganized table header layout with improved filter UI placement and
styling.
* Streamlined and unified filter behavior across the grid for more
consistent operation.
* Simplified insert row/column functionality with clearer permission
handling.
* **Refactor**
* Consolidated filter system by removing redundant implementations and
feature flags.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Follow-up to #45099 — migrates the final legacy hotkey hook
(`useKeyboardShortcuts` in
`apps/studio/components/grid/components/common/Hooks.tsx`) to
`useShortcut`, backed by `SHORTCUT_DEFINITIONS`.
- Adds 4 registry entries (`TABLE_EDITOR_JUMP_FIRST_ROW` / `_LAST_ROW` /
`_FIRST_COL` / `_LAST_COL`), all `showInSettings: false` so they stay
non-configurable (same as today).
- Adds `ignoreInputs` to `ShortcutOptions` and threads it through
`useShortcut` → `useHotkeySequence`. Replaces the legacy
`whitelistNodes: ['INPUT', 'TEXTAREA', 'SELECT']` with the built-in
TanStack option, which also covers `contenteditable`.
- Drops the `navigator.appVersion` macOS/Windows detection in
`Shortcuts.tsx` (`Mod` resolves this automatically) and the manual
`event.stopPropagation()` calls (TanStack's default is `stopPropagation:
true`).
- Deletes `Hooks.tsx` — no remaining consumers.
Closes FE-3049.
## Why `ignoreInputs: true` on these entries
`Mod+Arrow*` is a Ctrl/Meta combo. TanStack's default for Ctrl/Meta
combos is `ignoreInputs: false`, which would fire the shortcut even when
focus is in a text input — not what we want. Setting `ignoreInputs:
true` in the registry preserves the legacy whitelist behavior.
## Test plan
All shortcuts should still fire with **Cmd** (macOS) / **Ctrl**
(Win/Linux). Test surface: **Table Editor** → open any table with rows
and multiple columns.
**Grid navigation (with a cell selected — click a cell first)**
- [x] `Cmd+ArrowUp` jumps selection to row 0 in the same column
- [x] `Cmd+ArrowDown` jumps selection to the last row in the same column
- [x] `Cmd+ArrowLeft` jumps selection to the first non-frozen column in
the same row
- [x] `Cmd+ArrowRight` jumps selection to the last column in the same
row (not the trailing "add column" cell)
**Whitelist regression (most important — the `ignoreInputs` check)**
- [x] Open the **Filter** popover on a table → put focus in the filter
value `<input>` → type with arrow keys / use `Cmd+ArrowLeft/Right` for
word-jump → cursor moves in the input, grid selection does **not** jump
- [x] Same for a `<textarea>` (e.g. row editor → a text column with a
textarea) — `Cmd+ArrowUp/Down` should not hijack focus away from the
textarea
- [x] Same for a `<select>` (e.g. row editor → enum / boolean column) —
arrow keys behave normally
- [x] Editing a cell value in-place (double-click a cell to enter edit
mode) — arrow keys navigate the text, don't jump the grid
**Platform check**
- [x] On macOS, the shortcuts fire with `Cmd` (not `Ctrl`)
- [x] On Windows/Linux, they fire with `Ctrl` (not `Cmd`) — `Mod`
resolution
- [x] None of the new entries appear in Account → Preferences → Keyboard
shortcuts (all `showInSettings: false`)
**Regression checks**
- [x] `pnpm --filter=studio typecheck` passes (verified locally)
- [x] Existing shortcuts from #45099 (`Cmd+K`, `Cmd+I`, `Cmd+S` in op
queue, results copy, etc.) still work unchanged
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added four keyboard shortcuts for table navigation: jump to first/last
row and first/last column using Mod+Arrow keys.
* Added a shortcut option to prevent triggers when focus is in input
fields.
* **Bug Fixes**
* Improved keyboard shortcut handling for more consistent behavior
across platforms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Migrates all 11 `useHotKey` call sites across 9 files to
`useShortcut`, backed by `SHORTCUT_DEFINITIONS` in
`state/shortcuts/registry.ts`.
- Adds 10 new registry entries (all `showInSettings: false` to keep
behavior identical to today — these were not previously
user-configurable).
- Deletes `apps/studio/hooks/ui/useHotKey.ts`.
- Simplifies `ActionBar.handleSave` — the legacy hook passed a
`KeyboardEvent` the callback used for `preventDefault`/`stopPropagation`
and a textarea-plain-Enter guard; all of that is redundant under
`useShortcut` (TanStack handles default/propagation; `Mod+Enter` never
fires on plain Enter).
- Removes a stale commented-out `useHotKey` reference in
`DataTableFilterCommand.tsx`.
Part of FE-3025 (legacy hotkey hook cleanup). `useKeyboardShortcuts` in
`grid/components/common/Hooks.tsx` will be migrated in a follow-up.
## Test plan
All shortcuts should still fire with **Cmd** (macOS) / **Ctrl**
(Win/Linux).
**Table Editor — operation queue** (requires pending unsaved edits on a
row)
- [x] `Cmd+S` saves pending edits
- [x] `Cmd+.` toggles the operation queue side panel
- [x] `Cmd+Z` undoes the latest edit and re-fetches the affected table
rows
- [x] With no pending edits, none of the above fire (gated by
`isEnabled`)
**Table Editor — side panel editor forms** (row, table, column, policy,
etc.)
- [x] `Cmd+Enter` submits the form when the panel is visible
- [x] Does not submit if the form is disabled/loading or the panel is
hidden
**Unified Logs — data table**
- [x] `Cmd+B` toggles the filter controls sidebar (desktop)
- [x] `Cmd+B` opens the filter drawer (mobile, `<sm` breakpoint)
- [x] `Cmd+Esc` resets active column filters (reset button visible)
- [x] `Cmd+U` resets column order + visibility
- [x] `Cmd+J` toggles live mode
**Unified Logs — reset focus**
- [x] `Cmd+.` blurs the currently focused element / resets focus to body
**AI Assistant panel**
- [x] While editing a message, `Cmd+Esc` cancels the edit
**Regression checks**
- [x] `pnpm --filter=studio typecheck` passes (verified locally)
- [x] None of the new shortcut entries appear in Account → Preferences →
Keyboard shortcuts (all `showInSettings: false`)
- [x] Existing shortcuts (`Cmd+K`, `Cmd+I`, `Cmd+E`, results
copy/download) still work unchanged
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Refactor
* Implemented a centralized keyboard shortcut registry system for
managing shortcuts consistently across the application
* Updated multiple UI components throughout the interface to use the new
shortcut management system
* All existing keyboard shortcuts continue to function without any
changes in behavior or user experience
## Chores
* Removed legacy keyboard shortcut hook implementation
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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?
- Brand new hook APIs for registering shortcuts using tanstack hotkeys
- Support for command menu injection when shortcut is added
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Centralized keyboard shortcuts system with per‑shortcut registration
and per‑user enable/disable preferences stored locally
* Added a "Copy results as Markdown" shortcut (Mod+Shift+M)
* Shortcuts can be surfaced in the Command Menu with a visual shortcut
badge for discoverability
* **Documentation**
* Legacy keyboard shortcut hooks marked as deprecated and documentation
updated to point to the new shortcut API
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
Since the drag & drop refactor, users cannot double click to select the
column name in the columns headers of the table editor. Besides, the
advisor button cannot be clicked either.
## Solution
- Add a delay constraint on the drag & drop operation, allowing click
events to trigger
- Add e2e tests to prevent future reggressions
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Double-click column headers to copy column names to clipboard
* Index Advisor warnings now accessible in the Table Editor
* **Improvements**
* Improved drag start timing and tolerance for smoother column dragging
* Better screen reader announcement for index suggestion actions
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Reset the table rows query after the user confirms loading data on a
high-cost table, so React Query re-executes the fetch without the
preflight check
- Close the confirmation dialog after the user clicks "I understand,
proceed"
**Root cause:** `preflightCheck` is intentionally excluded from the
React Query query key (to avoid duplicate cache entries). When the user
clicked "Load data", the preflight flag flipped to `false` but the query
key stayed the same — so React Query returned the cached error instead
of refetching.
## Test plan
- [x] Navigate to a table with high estimated query cost (triggers "Data
not loaded to protect database performance")
- [x] Click "Load data" → "I understand, proceed"
- [x] Verify the dialog closes and table data loads
- [x] Verify the warning does not reappear for the same table in the
same session
To test this you can run this locally with COST_THRESHOLD set to a low
value (< 10)
Fixes FE-2979
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Confirming the high-cost warning now closes the dialog and proceeds
with loading as expected.
* Improved query cache key composition so queries reflect the full set
of relevant parameters for correct caching.
* Loading from the grid error now properly clears related cached results
and proceeds when the user confirms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What kind of change does this PR introduce?
Chore / UI consistency fix. Resolves DEPR-418.
## What is the current behavior?
Shortcut hints are still hand-built in several high-traffic Studio
surfaces, which leads to inconsistent rendering and stale
platform-specific markup. Buttons in particular can end up with awkward
spacing and baseline alignment when shortcut labels are inserted
directly into the button text.
## What is the new behavior?
This PR standardises those shortcut hints around `KeyboardShortcut` and
updates the surrounding layout primitives to support that approach more
cleanly.
It includes:
- Design docs
- using `KeyboardShortcut` in the table side-panel `ActionBar`
- replacing hardcoded operation queue button shortcuts in
`OperationQueueSidePanel`
- standardising the command menu trigger shortcut chip and updating the
`LayoutHeader` overrides to match the new DOM shape
- replacing the AI editor empty-state `Cmd/Ctrl + K` hint with
`KeyboardShortcut`
- refining shared shortcut/button primitives so inline shortcuts align
better when used as button accessories
- keeping the SQL utility shortcut work on this branch consistent with
the same shared component approach
| Before | After |
| --- | --- |
| <img width="1454" height="902" alt="CleanShot 2026-03-27 at 15 55
32@2x"
src="https://github.com/user-attachments/assets/3a8de192-3f4c-480b-9d26-9b28becd0ee3"
/> | <img width="1488" height="906" alt="CleanShot 2026-03-27 at 15 29
31@2x-63A17C58-D023-4D3A-9355-6C40A6485328"
src="https://github.com/user-attachments/assets/46ef7f7a-2b8b-4c10-8935-84ca5ad44562"
/> |
| <img width="738" height="328" alt="CleanShot 2026-03-27 at 15 57
07@2x"
src="https://github.com/user-attachments/assets/ad459c41-867d-42f9-a8cb-c936af8326b7"
/> | <img width="726" height="290" alt="CleanShot 2026-03-27 at 15 56
29@2x-ECE4E10F-9693-4ED8-B085-DC436A839F52"
src="https://github.com/user-attachments/assets/95b4bfb4-ec34-4080-8b69-211b5045ca26"
/> |
## Later todo
- [ ] Replace the string-based SQL editor placeholder shortcut in
`SQLEditor` once that placeholder API supports rich content
- [ ] Refactor `CommandOption` to use `KeyboardShortcut` instead of
bespoke platform detection and command-key markup
- [ ] Standardise the remaining DataTable shortcut hints
(`DataTableToolbar`, `DataTableResetButton`, `DataTableFilterCommand`,
`DataTableFilterControlsDrawer`) around `KeyboardShortcut`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Introduced a new KeyboardShortcut component for displaying keyboard
shortcuts with two visual variants (pill and inline).
* Standardized keyboard shortcut indicators across the application
interface for consistent user experience.
* **Bug Fixes**
* Fixed capitalization inconsistencies in button labels and hotkey
settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We currently have 3 different libraries for drag & drop, two of which
are not actively maintained anymore.
## Solution
Migrate all usage of the two unmaintained libraries to DndKit.
This PR focuses on using DndKit instead of `react-dnd` for column
reordering in the table editor
## Screencast
https://github.com/user-attachments/assets/54fb36f4-5671-42e2-9698-2ae928a69f55
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Column drag-and-drop rebuilt with a live drag preview and improved
pointer/keyboard handling
* **Improvements**
* More reliable column reordering with refined move/freeze/unfreeze
behavior and stable index recomputation
* Standardized column type/format display and simplified grid rendering
* **Accessibility**
* Added accessible labeling for column actions controls
* **Tests**
* End-to-end locator updated to target the column actions button
deterministically
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We currently have 3 different libraries for drag & drop, two of which
are not actively maintained anymore.
## Solution
Migrate all usage of the two unmaintained libraries to DndKit.
This PR focuses on using DndKit instead of `react-dnd` for the row
sorting popover in the table editor
## Screencast
https://github.com/user-attachments/assets/9d5cf43c-fbbd-4e5e-8b5a-e9e803b71421
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Enhanced sorting functionality with drag-and-drop support to reorder
sort rules.
* **Improvements**
* Updated drag handle styling for better visual clarity and usability.
* Simplified sorting interface architecture.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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
## What is the current behavior?
Studio uses `react-contexify` (an imperative, ID-based context menu
library) for right-click menus in the Table Editor grid, Log Table, and
Storage file explorer. This requires `createPortal` workarounds, a
separate CSS file, and has known bugs with fragment rendering.
## What is the new behavior?
All context menus now use the declarative `ContextMenu_Shadcn_`
(Radix-based) component that is already the standard across Studio. Each
context menu wraps its trigger element directly, removing the need for
imperative `show()` calls, portal hacks, and menu ID constants. The
`react-contexify` dependency and all associated styles are removed.
**Changes by area:**
- **Grid row context menu**: `RowRenderer` wraps each `<Row>` with
`ContextMenu_Shadcn_`. `RowContextMenu` refactored to accept `row`
directly as a prop instead of looking it up by index.
- **Log table**: Row renderer wraps each row with a context menu for
"Copy event message". Removes `cellPosition` state and `createPortal`.
- **Storage**: `FileExplorerRow` reuses its existing `rowOptions` array
for both the dropdown and context menu. `FileExplorerColumn` inlines the
column menu (new folder, select all, view/sort submenus). Three
standalone context menu files deleted.
- **Cleanup**: Removed `react-contexify` from `package.json`, deleted
`contextMenu.scss`, removed styles from `grid.scss`.
## Additional context
Net -370 lines. Follows the TODO comment in `CellContextMenuWrapper.tsx`
and the existing eslint ban on `react-contexify` imports.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Replaced legacy right-click menus with a unified shadcn-style context
menu across grids, logs, and the storage explorer.
* Simplified row/column/item context menu behavior and copy actions;
menus now mount and trigger more reliably.
* **New Features**
* Added row-level context menu providers to ensure consistent triggering
and positioning for row actions.
* **Chores**
* Removed legacy context-menu styles and deprecated menu components.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## 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?
- Remove queue operations from feature preview into settings
- Refactor dashboard settings
- Resolves DEPR-434
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Dashboard settings panel in Account preferences with toggles for
Inline Editor and Queue Operations; “Dashboard” added to project
Configuration.
* **Removed**
* Old Inline Editor settings UI and the Queue Operations feature-preview
UI removed.
* **Refactor**
* Consolidated dashboard preferences into a single settings surface;
banners and actions now navigate to preferences; account/preferences
layouts and back-navigation behavior adjusted for platform vs
self-hosted.
* **Tests**
* Added tests for settings UI, menu generation, redirects, and
local-storage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
## Context
Resolves https://github.com/supabase/supabase/issues/43548
There's currently an issue with the Table Editor where if you have, for
example, a nullable `text` column with a default value, inserting a new
row and selecting "Set to NULL" doesn't do anything, and saving will
insert the row with the default value
<img width="700" height="258" alt="image"
src="https://github.com/user-attachments/assets/6a284ebb-c346-40a6-9a30-793118844084"
/>
This stems from a legacy logic in the Table Editor whereby we treat
`null` values as "no input" - which is incorrect as `null` values are
also valid values. So the PR here changes a few things to resolve this
properly:
## Changes involved
Main fix:
- `undefined` will be the "no input" value instead, and it'll be the
default value when generating the row object for inserting a new row
- `NULL` or even empty string like `''` will be treated as they are
(valid inputs)
Secondary adjustments:
- (Queue operations) Queueing an insert with no value but default value
is NULL, will show the placeholder as `DEFAULT` instead of `NULL` for
better accuracy in representation
<img width="892" height="96" alt="image"
src="https://github.com/user-attachments/assets/02cf86bf-c17b-4e25-9a8f-17960b1d2575"
/>
- Added a `Set to Default` CTA here, but will only show up if adding a
new row or updating a queued insert row operation, which will set the
value of the input field back to `undefined` for PG to handle it as the
default value
<img width="734" height="208" alt="image"
src="https://github.com/user-attachments/assets/23887c0c-533e-4494-acbe-61309ff5d7c5"
/>
## To test
Verify within the Table Editor (along with queue operation feature
preview)
- For inserting a new row, setting value to NULL and setting value to
Default works
- For updating a row, setting value to NULL works
This PR moves several components which rely on `next` out of the `ui`
package to the `ui-patterns` package.
`ui-patterns` package is intented to be imported with specific imports
so it's ok if there are components reliant on `next` in there.
The `SonnerToaster` component has removed its dependency by requiring a
prop for `theme`.
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES/NO
## What kind of change does this PR introduce?
fixes: #37454
The context menu on the FK row is a lie, its just exposing the cell
underneath. Ideally this should have its own context menu, right now we
only support copy operations.
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## 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?
- Index mismatch on ADD then DELETE/EDIT:
formatGridDataWithOperationValues was searching the original rows array
for DELETE_ROW and EDIT_CELL_CONTENT operations, then using those
indices on the modified formattedRows array (which had been shifted by
ADD_ROW's unshift). Both now search formattedRows directly.
- Cross-table operation leaking: The entire operation queue was passed
to formatGridDataWithOperationValues without filtering by the current
table, causing pending ADD_ROW and DELETE_ROW operations from one table
to appear in other tables. Operations are now filtered by tableId before
rendering.