mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 04:15:04 +03:00
## 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 -->
155 lines
5.9 KiB
TypeScript
155 lines
5.9 KiB
TypeScript
import { RegistryDefinations } from '../types'
|
|
|
|
export const TABLE_EDITOR_SHORTCUT_IDS = {
|
|
TABLE_EDITOR_JUMP_FIRST_ROW: 'table-editor.jump-first-row',
|
|
TABLE_EDITOR_JUMP_LAST_ROW: 'table-editor.jump-last-row',
|
|
TABLE_EDITOR_JUMP_FIRST_COL: 'table-editor.jump-first-col',
|
|
TABLE_EDITOR_JUMP_LAST_COL: 'table-editor.jump-last-col',
|
|
TABLE_EDITOR_TOGGLE_ROW_SELECTION: 'table-editor.toggle-row-selection',
|
|
TABLE_EDITOR_TOGGLE_ALL_ROW_SELECTION: 'table-editor.toggle-all-row-selection',
|
|
TABLE_EDITOR_SELECT_ALL_IN_TABLE: 'table-editor.select-all-in-table',
|
|
TABLE_EDITOR_DELETE_SELECTED_ROWS: 'table-editor.delete-selected-rows',
|
|
TABLE_EDITOR_START_NAVIGATION_DOWN: 'table-editor.start-navigation-down',
|
|
TABLE_EDITOR_START_NAVIGATION_UP: 'table-editor.start-navigation-up',
|
|
TABLE_EDITOR_EXIT_SELECTION: 'table-editor.exit-selection',
|
|
TABLE_EDITOR_INSERT_ROW: 'table-editor.insert-row',
|
|
TABLE_EDITOR_INSERT_COLUMN: 'table-editor.insert-column',
|
|
TABLE_EDITOR_IMPORT_CSV: 'table-editor.import-csv',
|
|
TABLE_EDITOR_FOCUS_FILTERS: 'table-editor.focus-filters',
|
|
TABLE_EDITOR_CLEAR_FILTERS: 'table-editor.clear-filters',
|
|
TABLE_EDITOR_CLEAR_SORT: 'table-editor.clear-sort',
|
|
TABLE_EDITOR_REFRESH: 'table-editor.refresh',
|
|
}
|
|
|
|
export type TableEditorShortcutId =
|
|
(typeof TABLE_EDITOR_SHORTCUT_IDS)[keyof typeof TABLE_EDITOR_SHORTCUT_IDS]
|
|
|
|
export const tableEditorRegistry: RegistryDefinations<TableEditorShortcutId> = {
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_FIRST_ROW]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_FIRST_ROW,
|
|
label: 'Jump to first row',
|
|
sequence: ['Mod+ArrowUp'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_LAST_ROW]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_LAST_ROW,
|
|
label: 'Jump to last row',
|
|
sequence: ['Mod+ArrowDown'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_FIRST_COL]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_FIRST_COL,
|
|
label: 'Jump to first column',
|
|
sequence: ['Mod+ArrowLeft'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_LAST_COL]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_JUMP_LAST_COL,
|
|
label: 'Jump to last column',
|
|
sequence: ['Mod+ArrowRight'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_TOGGLE_ROW_SELECTION]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_TOGGLE_ROW_SELECTION,
|
|
label: 'Toggle selection on current row',
|
|
sequence: ['Shift+Space'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_TOGGLE_ALL_ROW_SELECTION]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_TOGGLE_ALL_ROW_SELECTION,
|
|
label: 'Toggle selection on all displayed rows',
|
|
sequence: ['Mod+A'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_SELECT_ALL_IN_TABLE]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_SELECT_ALL_IN_TABLE,
|
|
label: 'Toggle selection on all rows in table',
|
|
sequence: ['Mod+Shift+A'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_DELETE_SELECTED_ROWS]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_DELETE_SELECTED_ROWS,
|
|
label: 'Delete selected rows',
|
|
sequence: ['Mod+Backspace'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_START_NAVIGATION_DOWN]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_START_NAVIGATION_DOWN,
|
|
label: 'Start grid navigation (down)',
|
|
sequence: ['ArrowDown'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_START_NAVIGATION_UP]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_START_NAVIGATION_UP,
|
|
label: 'Start grid navigation (up)',
|
|
sequence: ['ArrowUp'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_EXIT_SELECTION]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_EXIT_SELECTION,
|
|
label: 'Exit grid selection',
|
|
sequence: ['Escape'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_INSERT_ROW]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_INSERT_ROW,
|
|
label: 'Insert row',
|
|
sequence: ['I', 'R'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_INSERT_COLUMN]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_INSERT_COLUMN,
|
|
label: 'Insert column',
|
|
sequence: ['I', 'C'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_IMPORT_CSV]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_IMPORT_CSV,
|
|
label: 'Import data from CSV',
|
|
sequence: ['I', 'U'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_FOCUS_FILTERS]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_FOCUS_FILTERS,
|
|
label: 'Focus filters',
|
|
sequence: ['Shift+F'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_CLEAR_FILTERS]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_CLEAR_FILTERS,
|
|
label: 'Clear filters',
|
|
sequence: ['F', 'C'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_CLEAR_SORT]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_CLEAR_SORT,
|
|
label: 'Clear sort',
|
|
sequence: ['S', 'C'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
[TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_REFRESH]: {
|
|
id: TABLE_EDITOR_SHORTCUT_IDS.TABLE_EDITOR_REFRESH,
|
|
label: 'Refresh table',
|
|
sequence: ['Shift+R'],
|
|
showInSettings: false,
|
|
options: { ignoreInputs: true },
|
|
},
|
|
}
|