Files
supabase/apps/studio/components/grid/hooks
Ali Waseem 40791f9846 chore(studio): migrate useHotKey to useShortcut (#45099)
## 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 -->
2026-04-22 06:19:32 -06:00
..

Table Filtering and Sorting Developer notes

Overview

The table filtering and sorting system uses a URL-based state persistence pattern combined with custom hooks that abstract the implementation details from consuming components. This architecture provides several benefits:

  • Persistent state: Filters and sorts are stored in URL parameters, enabling bookmarking and sharing
  • Separation of concerns: Logic is separated from UI components
  • Draft-then-apply pattern: UI components maintain draft state until explicitly applied

Core Hooks

useTableFilter

// Returns: { filters, urlFilters, onApplyFilters }

The useTableFilter hook manages filter state with these responsibilities:

  • Retrieves raw filter parameters from URL
  • Formats filter parameters into usable Filter[] objects
  • Provides a callback to apply new filters
  • Persists changes to URL parameters
  • Triggers side effects through saveFiltersAndTriggerSideEffects

Key design aspects:

  • No direct snapshot interaction, keeping it focused solely on filter management
  • Uses URL parameters as the source of truth
  • Forwards filter changes to URL and triggers application-specific side effects

useTableSort

// Returns: { sorts, urlSorts, onApplySorts }

The useTableSort hook manages sort state with these responsibilities:

  • Retrieves raw filter parameters from URL
  • Formats sort parameters into usable Sort[] objects (needs table name)
  • Provides a callback to apply new sorts
  • Persists changes to URL parameters
  • Triggers side effects through saveSortsAndTriggerSideEffects

Key design aspects:

  • Handles applying table name to sort objects
  • Maintains URL parameters as source of truth
  • Forwards sort changes to URL and triggers application-specific side effects

Component Implementation

FilterPopoverPrimitive and SortPopoverPrimitive

These components follow a "draft and apply" pattern:

  1. Local state management: Both components maintain a local state copy of filters/sorts
  2. Edit operations: Changes like adding, modifying, or deleting are made to the local state
  3. Apply operations: Only when the user clicks "Apply" are the changes committed via the callback
  4. Synchronization: Local state is synchronized with props when external changes occur

Data Flow

  1. URL parameters store the raw filter/sort state
  2. Hooks read and format these parameters into usable objects
  3. UI components receive formatted objects and callbacks
  4. Components maintain draft state for editing
  5. When "Apply" is clicked, callbacks update URL parameters
  6. Side effects are triggered via dedicated save hooks

Component Usage

Components using these hooks should follow this pattern:

function TableComponent() {
  // Get filter data and callbacks
  const { filters, onApplyFilters } = useTableFilter()

  // Get sort data and callbacks
  const { sorts, onApplySorts } = useTableSort()

  return (
    <>
      <FilterPopoverPrimitive filters={filters} onApplyFilters={onApplyFilters} />

      <SortPopoverPrimitive sorts={sorts} onApplySorts={onApplySorts} />

      {/* Table rendering with filters and sorts applied */}
    </>
  )
}

Implementation Notes

  • Filter and sort parameters are stored in URL using specific formats
  • Conversion utilities (formatFilterURLParams, formatSortURLParams, etc.) handle translation between URL strings and typed objects
  • Side effect hooks manage database persistence and related operations