Skip to content

Commit 3eb7da7

Browse files
charislamjoshenlim
andauthored
feat(preferences): allow disable hotkeys (supabase#39573)
* feat(preferences): allow disable hotkeys Add a section in /account/me for disabling hotkeys. Only added one hotkey for now (Cmd + E for toggling editor side panel) but we can add more with the same pattern. * refactor: remove default export on ProjectLayout * feat(hotkeys): allow toggling of command menu and ai assistant hotkeys * Nit * PRettier lint --------- Co-authored-by: Joshen Lim <[email protected]>
1 parent c6d7092 commit 3eb7da7

File tree

27 files changed

+205
-51
lines changed

27 files changed

+205
-51
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { LOCAL_STORAGE_KEYS } from 'common'
2+
import Panel from 'components/ui/Panel'
3+
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
4+
import { KeyboardShortcut, Toggle } from 'ui'
5+
6+
export const HotkeySettings = () => {
7+
const [inlineEditorEnabled, setInlineEditorEnabled] = useLocalStorageQuery(
8+
LOCAL_STORAGE_KEYS.HOTKEY_INLINE_EDITOR,
9+
true
10+
)
11+
const [commandMenuEnabled, setCommandMenuEnabled] = useLocalStorageQuery(
12+
LOCAL_STORAGE_KEYS.HOTKEY_COMMAND_MENU,
13+
true
14+
)
15+
const [aiAssistantEnabled, setAiAssistantEnabled] = useLocalStorageQuery(
16+
LOCAL_STORAGE_KEYS.HOTKEY_AI_ASSISTANT,
17+
true
18+
)
19+
20+
return (
21+
<Panel
22+
title={
23+
<div>
24+
<h5 id="keyboard-shortcuts">Keyboard shortcuts</h5>
25+
<p className="text-sm text-foreground-lighter">
26+
Choose which shortcuts stay active while working in the dashboard
27+
</p>
28+
</div>
29+
}
30+
>
31+
<Panel.Content className="space-y-3">
32+
<Toggle
33+
checked={commandMenuEnabled}
34+
onChange={() => setCommandMenuEnabled(!commandMenuEnabled)}
35+
label={
36+
<div className="flex items-center gap-x-2">
37+
<KeyboardShortcut keys={['Meta', 'k']} />
38+
<span>Command menu</span>
39+
</div>
40+
}
41+
descriptionText="Toggles the global command menu."
42+
/>
43+
<Toggle
44+
checked={aiAssistantEnabled}
45+
onChange={() => setAiAssistantEnabled(!aiAssistantEnabled)}
46+
label={
47+
<div className="flex items-center gap-x-2">
48+
<KeyboardShortcut keys={['Meta', 'i']} />
49+
<span>AI Assistant</span>
50+
</div>
51+
}
52+
descriptionText="Toggles the AI Assistant panel."
53+
/>
54+
<Toggle
55+
checked={inlineEditorEnabled}
56+
onChange={() => setInlineEditorEnabled(!inlineEditorEnabled)}
57+
label={
58+
<div className="flex items-center gap-x-2">
59+
<KeyboardShortcut keys={['Meta', 'e']} />
60+
<span>Inline SQL Editor</span>
61+
</div>
62+
}
63+
descriptionText="Toggles the inline SQL editor in a side panel"
64+
/>
65+
</Panel.Content>
66+
</Panel>
67+
)
68+
}

apps/studio/components/layouts/AdvisorsLayout/AdvisorsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useIsAdvisorRulesEnabled } from 'components/interfaces/App/FeaturePrevi
55
import { ProductMenu } from 'components/ui/ProductMenu'
66
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
77
import { withAuth } from 'hooks/misc/withAuth'
8-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
8+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
99
import { generateAdvisorsMenu } from './AdvisorsMenu.utils'
1010

1111
export interface AdvisorsLayoutProps {

apps/studio/components/layouts/AppLayout/AssistantButton.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
import { LOCAL_STORAGE_KEYS } from 'common'
12
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
3+
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
24
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
3-
import { AiIconAnimation } from 'ui'
4-
import { KeyboardShortcut } from 'ui'
5+
import { AiIconAnimation, KeyboardShortcut } from 'ui'
56

67
export const AssistantButton = () => {
78
const snap = useAiAssistantStateSnapshot()
9+
const [isAIAssistantHotkeyEnabled] = useLocalStorageQuery<boolean>(
10+
LOCAL_STORAGE_KEYS.HOTKEY_AI_ASSISTANT,
11+
true
12+
)
813

914
return (
1015
<ButtonTooltip
@@ -20,7 +25,7 @@ export const AssistantButton = () => {
2025
text: (
2126
<div className="flex items-center gap-4">
2227
<span>AI Assistant</span>
23-
<KeyboardShortcut keys={['Meta', 'i']} />
28+
{isAIAssistantHotkeyEnabled && <KeyboardShortcut keys={['Meta', 'i']} />}
2429
</div>
2530
),
2631
},

apps/studio/components/layouts/AppLayout/InlineEditorButton.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ import { ButtonTooltip } from 'components/ui/ButtonTooltip'
22
import { SqlEditor } from 'icons'
33
import { KeyboardShortcut } from 'ui'
44

5-
export const InlineEditorButton = ({ onClick }: { onClick: () => void }) => {
5+
export const InlineEditorButton = ({
6+
onClick,
7+
showShortcut = true,
8+
}: {
9+
onClick: () => void
10+
showShortcut?: boolean
11+
}) => {
612
return (
713
<ButtonTooltip
814
type="text"
@@ -15,7 +21,7 @@ export const InlineEditorButton = ({ onClick }: { onClick: () => void }) => {
1521
text: (
1622
<div className="flex items-center gap-4">
1723
<span>SQL Editor</span>
18-
<KeyboardShortcut keys={['Meta', 'e']} />
24+
{showShortcut && <KeyboardShortcut keys={['Meta', 'e']} />}
1925
</div>
2026
),
2127
},

apps/studio/components/layouts/AuthLayout/AuthLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ProductMenu } from 'components/ui/ProductMenu'
66
import { useAuthConfigPrefetch } from 'data/auth/auth-config-query'
77
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
88
import { withAuth } from 'hooks/misc/withAuth'
9-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
9+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
1010
import { generateAuthMenu } from './AuthLayout.utils'
1111
import { useFlag } from 'common'
1212

apps/studio/components/layouts/BranchLayout/BranchLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useParams } from 'common'
55
import { GitHubStatus } from 'components/interfaces/Settings/Integrations/GithubIntegration/GitHubStatus'
66
import { ProductMenu } from 'components/ui/ProductMenu'
77
import { withAuth } from 'hooks/misc/withAuth'
8-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
8+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
99
import { generateBranchMenu } from './BranchLayout.utils'
1010

1111
const BranchProductMenu = () => {

apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
99
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
1010
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
1111
import { withAuth } from 'hooks/misc/withAuth'
12-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
12+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
1313
import { generateDatabaseMenu } from './DatabaseMenu.utils'
1414

1515
export interface DatabaseLayoutProps {

apps/studio/components/layouts/DocsLayout/DocsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
1010
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
1111
import { withAuth } from 'hooks/misc/withAuth'
1212
import { PROJECT_STATUS } from 'lib/constants'
13-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
13+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
1414
import { generateDocsMenu } from './DocsLayout.utils'
1515

1616
function DocsLayout({ title, children }: { title: string; children: ReactElement }) {

apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
Separator,
2828
} from 'ui'
2929
import { Input } from 'ui-patterns/DataInputs/Input'
30-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
30+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
3131
import EdgeFunctionsLayout from './EdgeFunctionsLayout'
3232

3333
interface EdgeFunctionDetailsLayoutProps {

apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { PropsWithChildren } from 'react'
44
import { useParams } from 'common'
55
import { ProductMenu } from 'components/ui/ProductMenu'
66
import { withAuth } from 'hooks/misc/withAuth'
7-
import ProjectLayout from '../ProjectLayout/ProjectLayout'
7+
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
88

99
const EdgeFunctionsProductMenu = () => {
1010
const { ref: projectRef = 'default' } = useParams()

0 commit comments

Comments
 (0)