From 2e904abebfda38a24e58433e8667d5d81a2ec8cb Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Tue, 5 May 2026 09:57:25 -0600 Subject: [PATCH] feat(studio): add D + letter shortcuts for Database sub-pages (#45546) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds a contextual `D + ` chord pattern for jumping between Database sub-pages, mounted only while `DatabaseLayout` is active. Establishes the pattern we can repeat for other sections (Auth, Storage, Functions, etc.). Linear: [FE-3140](https://linear.app/supabase/issue/FE-3140/define-subnavigation-pattern-for-database-management-page) ## Pattern - Chords are 2-key sequences (`D`, ``) — no global leader, no `G` prefix. - Registration is contextual: `` lives inside `DatabaseLayout`, so the leading `D` is only "owned" while the user is under `/project//database/*`. Doesn't burn a global key. - Hover tooltips on each sub-menu item show the chord, anchored to the label text (Linear-style). Powered by `` already used in the main nav. - Items hidden by feature flags (Roles, Column Privileges, Replication) auto-disable the chord — no muscle-memory navigating to a 404. ## Shortcuts added | Sub-page | Chord | Notes | |---|---|---| | Tables | `D T` | | | Functions | `D F` | | | Triggers | `D R` | t**R**iggers — `T` taken by Tables | | Indexes | `D I` | | | Extensions | `D X` | e**X**tensions | | Schema Visualizer | `D V` | | | Enumerated Types | `D E` | | | Publications | `D U` | p**U**blications — avoids collision with Schema Visualizer's `D P` (Download as PNG) | | Column Privileges | `D C` | flag-gated | | Settings | `D ,` | mirrors global `G ,` for project settings — avoids collision with Schema Visualizer's `D S` (Download as SVG) | | Replication | `D L` | rep**L**ication — flag-gated | | Roles | `D O` | r**O**les — flag-gated | | Backups | `D B` | platform-only | | Migrations | `D M` | | External-link sub-menu items (Policies, Wrappers, Webhooks, Security Advisor, Performance Advisor, Query Performance) are intentionally not chorded — they route out of `/database/*` and don't belong to the section's namespace. ## Collision audit Other shortcuts active on database pages (table-list, schema-visualizer) were checked against the new chords: - **Schema Visualizer** (`/database/schemas`): `D P` (Download PNG), `D S` (Download SVG), `O A`, `O S`. Publications and Settings were remapped to `D U` and `D ,` to avoid the `D P` / `D S` clashes. - **List pages** (`/database/tables`, etc.): `Shift+F`, `Shift+N`, `O S`, `F C` — no overlap with `D + `. ## Files - `state/shortcuts/registry/database-nav.ts` — new registry module with the 14 chord definitions. - `state/shortcuts/registry.ts` — spreads the new IDs/definitions into the canonical registry. - `components/interfaces/DatabaseNavShortcuts.tsx` — null-rendering hook component that wires `useShortcut` for each chord, keyed off `useGenerateDatabaseMenu` so URLs and feature gating stay in sync with the sidebar. - `components/layouts/DatabaseLayout/DatabaseLayout.tsx` — mounts the component. - `components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx` — tags each menu item with its `shortcutId`. - `components/ui/ProductMenu/ProductMenu.types.ts` — adds optional `shortcutId?: ShortcutId` field. - `components/ui/ProductMenu/ProductMenuItem.tsx` — renders the hover tooltip when an item has a `shortcutId`, anchored to the label span. ## Test plan - [ ] On `/project//database/tables`, press `D F` — navigates to `/database/functions`. - [ ] On `/project//database/schemas`, press `D P` — downloads the PNG (Schema Visualizer wins, no nav conflict). - [ ] On `/project//database/schemas`, press `D U` — navigates to `/database/publications`. - [ ] On `/project//database/tables`, press `D ,` — navigates to `/database/settings`. - [ ] Hover any sub-menu item with a chord — pill appears next to the label after ~1s. - [ ] On a project with the Replication flag off — `D L` does nothing. - [ ] Navigate to `/auth` — pressing `D F` does nothing (chord unmounts with the layout). - [ ] Type `D` then `F` slowly inside an input — does not navigate (input-focus guard). --- .../interfaces/DatabaseNavShortcuts.tsx | 96 ++++++++++++++ .../layouts/DatabaseLayout/DatabaseLayout.tsx | 2 + .../DatabaseLayout/DatabaseMenu.utils.tsx | 81 ++++++++++-- .../ui/ProductMenu/ProductMenu.types.ts | 3 + .../ui/ProductMenu/ProductMenuItem.tsx | 17 ++- apps/studio/state/shortcuts/registry.ts | 7 ++ .../state/shortcuts/registry/database-nav.ts | 117 ++++++++++++++++++ 7 files changed, 309 insertions(+), 14 deletions(-) create mode 100644 apps/studio/components/interfaces/DatabaseNavShortcuts.tsx create mode 100644 apps/studio/state/shortcuts/registry/database-nav.ts diff --git a/apps/studio/components/interfaces/DatabaseNavShortcuts.tsx b/apps/studio/components/interfaces/DatabaseNavShortcuts.tsx new file mode 100644 index 00000000000..1b524aeaa73 --- /dev/null +++ b/apps/studio/components/interfaces/DatabaseNavShortcuts.tsx @@ -0,0 +1,96 @@ +import { useRouter } from 'next/router' +import { useCallback, useMemo } from 'react' + +import { useGenerateDatabaseMenu } from '@/components/layouts/DatabaseLayout/DatabaseMenu.utils' +import { SHORTCUT_IDS, type ShortcutId } from '@/state/shortcuts/registry' +import { useShortcut } from '@/state/shortcuts/useShortcut' + +export const DatabaseNavShortcuts = () => { + const router = useRouter() + const groups = useGenerateDatabaseMenu() + + const urlByShortcut = useMemo(() => { + const map = new Map() + for (const group of groups) { + for (const item of group.items) { + if (item.shortcutId && item.url) map.set(item.shortcutId, item.url) + } + } + return map + }, [groups]) + + const navigate = useCallback( + (id: ShortcutId) => { + const url = urlByShortcut.get(id) + if (url) router.push(url) + }, + [router, urlByShortcut] + ) + + useShortcut(SHORTCUT_IDS.NAV_DATABASE_TABLES, () => navigate(SHORTCUT_IDS.NAV_DATABASE_TABLES), { + enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_TABLES), + }) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_TRIGGERS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_TRIGGERS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_TRIGGERS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_INDEXES, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_INDEXES), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_INDEXES) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER) } + ) + useShortcut(SHORTCUT_IDS.NAV_DATABASE_ROLES, () => navigate(SHORTCUT_IDS.NAV_DATABASE_ROLES), { + enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_ROLES), + }) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_BACKUPS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_BACKUPS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_BACKUPS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS) } + ) + useShortcut(SHORTCUT_IDS.NAV_DATABASE_TYPES, () => navigate(SHORTCUT_IDS.NAV_DATABASE_TYPES), { + enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_TYPES), + }) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_SETTINGS, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_SETTINGS), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_SETTINGS) } + ) + useShortcut( + SHORTCUT_IDS.NAV_DATABASE_REPLICATION, + () => navigate(SHORTCUT_IDS.NAV_DATABASE_REPLICATION), + { enabled: urlByShortcut.has(SHORTCUT_IDS.NAV_DATABASE_REPLICATION) } + ) + + return null +} diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx index 30db23926f0..7365cd2c3c3 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx @@ -3,6 +3,7 @@ import type { PropsWithChildren } from 'react' import { ProjectLayout } from '../ProjectLayout' import { useGenerateDatabaseMenu } from './DatabaseMenu.utils' +import { DatabaseNavShortcuts } from '@/components/interfaces/DatabaseNavShortcuts' import { ProductMenu } from '@/components/ui/ProductMenu' import { withAuth } from '@/hooks/misc/withAuth' @@ -26,6 +27,7 @@ const DatabaseLayout = ({ children, title }: PropsWithChildren} isBlocking={false} > + {children} ) diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx index b42d5ce4e7d..f8f93ed79a6 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx @@ -12,6 +12,7 @@ import { useProjectAddonsQuery } from '@/data/subscriptions/project-addons-query import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { IS_PLATFORM } from '@/lib/constants' +import { SHORTCUT_IDS } from '@/state/shortcuts/registry' const ExternalLinkIcon = @@ -42,24 +43,70 @@ export const useGenerateDatabaseMenu = (): ProductMenuGroup[] => { { title: 'Database Management', items: [ - { name: 'Schema Visualizer', key: 'schemas', url: getDatabaseURL('schemas') }, - { name: 'Tables', key: 'tables', url: getDatabaseURL('tables') }, - { name: 'Functions', key: 'functions', url: getDatabaseURL('functions') }, - { name: 'Triggers', key: 'triggers', url: getDatabaseURL('triggers/data') }, - { name: 'Enumerated Types', key: 'types', url: getDatabaseURL('types') }, - { name: 'Extensions', key: 'extensions', url: getDatabaseURL('extensions') }, - { name: 'Indexes', key: 'indexes', url: getDatabaseURL('indexes') }, - { name: 'Publications', key: 'publications', url: getDatabaseURL('publications') }, + { + name: 'Schema Visualizer', + key: 'schemas', + url: getDatabaseURL('schemas'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER, + }, + { + name: 'Tables', + key: 'tables', + url: getDatabaseURL('tables'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_TABLES, + }, + { + name: 'Functions', + key: 'functions', + url: getDatabaseURL('functions'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS, + }, + { + name: 'Triggers', + key: 'triggers', + url: getDatabaseURL('triggers/data'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_TRIGGERS, + }, + { + name: 'Enumerated Types', + key: 'types', + url: getDatabaseURL('types'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_TYPES, + }, + { + name: 'Extensions', + key: 'extensions', + url: getDatabaseURL('extensions'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS, + }, + { + name: 'Indexes', + key: 'indexes', + url: getDatabaseURL('indexes'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_INDEXES, + }, + { + name: 'Publications', + key: 'publications', + url: getDatabaseURL('publications'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS, + }, ], }, { title: 'Configuration', items: [ - showRoles && { name: 'Roles', key: 'roles', url: getDatabaseURL('roles') }, + showRoles && { + name: 'Roles', + key: 'roles', + url: getDatabaseURL('roles'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_ROLES, + }, columnLevelPrivileges && { name: 'Column Privileges', key: 'column-privileges', url: getDatabaseURL('column-privileges'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES, }, { name: 'Policies', @@ -67,7 +114,12 @@ export const useGenerateDatabaseMenu = (): ProductMenuGroup[] => { url: `/project/${ref}/auth/policies`, rightIcon: ExternalLinkIcon, }, - { name: 'Settings', key: 'settings', url: getDatabaseURL('settings') }, + { + name: 'Settings', + key: 'settings', + url: getDatabaseURL('settings'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_SETTINGS, + }, ].filter(Boolean) as ProductMenuGroupItem[], }, { @@ -79,13 +131,20 @@ export const useGenerateDatabaseMenu = (): ProductMenuGroup[] => { key: 'replication', url: getDatabaseURL('replication'), label: enablePgReplicate ? 'New' : undefined, + shortcutId: SHORTCUT_IDS.NAV_DATABASE_REPLICATION, }, IS_PLATFORM && { name: 'Backups', key: 'backups', url: pitrEnabled ? getDatabaseURL('backups/pitr') : getDatabaseURL('backups/scheduled'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_BACKUPS, + }, + { + name: 'Migrations', + key: 'migrations', + url: getDatabaseURL('migrations'), + shortcutId: SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS, }, - { name: 'Migrations', key: 'migrations', url: getDatabaseURL('migrations') }, showWrappers && { name: 'Wrappers', key: 'wrappers', diff --git a/apps/studio/components/ui/ProductMenu/ProductMenu.types.ts b/apps/studio/components/ui/ProductMenu/ProductMenu.types.ts index 477022c9b23..54a8f3fcffc 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenu.types.ts +++ b/apps/studio/components/ui/ProductMenu/ProductMenu.types.ts @@ -1,5 +1,7 @@ import { ReactNode } from 'react' +import type { ShortcutId } from '@/state/shortcuts/registry' + export interface ProductMenuGroup { title?: string /** Set to "main" if page is on a '/' route */ @@ -25,6 +27,7 @@ export interface ProductMenuGroupItem { childIcon?: ReactNode childItems?: ProductMenuGroupItem[] pages?: string[] + shortcutId?: ShortcutId } /** diff --git a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx index eb751c6891e..53b02d68042 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx +++ b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx @@ -2,6 +2,7 @@ import Link from 'next/link' import { Badge, Button, Menu } from 'ui' import { ProductMenuGroupItem } from './ProductMenu.types' +import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip' interface ProductMenuItemProps { item: ProductMenuGroupItem @@ -18,16 +19,26 @@ export const ProductMenuItem = ({ hoverText = '', onClick, }: ProductMenuItemProps) => { - const { name = '', url = '', icon, rightIcon, isExternal, label, disabled } = item + const { name = '', url = '', icon, rightIcon, isExternal, label, disabled, shortcutId } = item + + const labelNode = shortcutId ? ( + + {name} + + ) : ( + {name} + ) const menuItem = (
- {name} + {labelNode} {label !== undefined && ( = { // Shared list-page shortcut registration ...listPageRegistry, + + // Database sub-page navigation chord registration + ...databaseNavRegistry, } diff --git a/apps/studio/state/shortcuts/registry/database-nav.ts b/apps/studio/state/shortcuts/registry/database-nav.ts new file mode 100644 index 00000000000..9a437c3b390 --- /dev/null +++ b/apps/studio/state/shortcuts/registry/database-nav.ts @@ -0,0 +1,117 @@ +import { RegistryDefinations } from '../types' + +/** + * Contextual chords for jumping between Database sub-pages — `D + `. + * + * Active only while DatabaseLayout is mounted (i.e. the user is somewhere + * under `/project//database/*`). The chord intentionally lives on the + * page rather than globally so the leading `D` doesn't burn a global key for + * a destination most users only care about while already in the section. + * + */ +export const DATABASE_NAV_SHORTCUT_IDS = { + NAV_DATABASE_TABLES: 'nav.database-tables', + NAV_DATABASE_FUNCTIONS: 'nav.database-functions', + NAV_DATABASE_TRIGGERS: 'nav.database-triggers', + NAV_DATABASE_INDEXES: 'nav.database-indexes', + NAV_DATABASE_EXTENSIONS: 'nav.database-extensions', + NAV_DATABASE_SCHEMA_VISUALIZER: 'nav.database-schema-visualizer', + NAV_DATABASE_ROLES: 'nav.database-roles', + NAV_DATABASE_BACKUPS: 'nav.database-backups', + NAV_DATABASE_MIGRATIONS: 'nav.database-migrations', + NAV_DATABASE_TYPES: 'nav.database-types', + NAV_DATABASE_PUBLICATIONS: 'nav.database-publications', + NAV_DATABASE_COLUMN_PRIVILEGES: 'nav.database-column-privileges', + NAV_DATABASE_SETTINGS: 'nav.database-settings', + NAV_DATABASE_REPLICATION: 'nav.database-replication', +} + +export type DatabaseNavShortcutId = + (typeof DATABASE_NAV_SHORTCUT_IDS)[keyof typeof DATABASE_NAV_SHORTCUT_IDS] + +export const databaseNavRegistry: RegistryDefinations = { + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TABLES]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TABLES, + label: 'Go to Tables', + sequence: ['D', 'T'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_FUNCTIONS, + label: 'Go to Functions', + sequence: ['D', 'F'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TRIGGERS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TRIGGERS, + label: 'Go to Triggers', + sequence: ['D', 'R'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_INDEXES]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_INDEXES, + label: 'Go to Indexes', + sequence: ['D', 'I'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_EXTENSIONS, + label: 'Go to Extensions', + sequence: ['D', 'X'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_SCHEMA_VISUALIZER, + label: 'Go to Schema Visualizer', + sequence: ['D', 'V'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_ROLES]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_ROLES, + label: 'Go to Roles', + sequence: ['D', 'O'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_BACKUPS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_BACKUPS, + label: 'Go to Backups', + sequence: ['D', 'B'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_MIGRATIONS, + label: 'Go to Migrations', + sequence: ['D', 'M'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TYPES]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_TYPES, + label: 'Go to Enumerated Types', + sequence: ['D', 'E'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_PUBLICATIONS, + label: 'Go to Publications', + sequence: ['D', 'U'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_COLUMN_PRIVILEGES, + label: 'Go to Column Privileges', + sequence: ['D', 'C'], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_SETTINGS]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_SETTINGS, + label: 'Go to Database Settings', + sequence: ['D', ','], + showInSettings: false, + }, + [DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_REPLICATION]: { + id: DATABASE_NAV_SHORTCUT_IDS.NAV_DATABASE_REPLICATION, + label: 'Go to Replication', + sequence: ['D', 'L'], + showInSettings: false, + }, +}