feat: display hot key mappings in settings (#173)

This commit is contained in:
Jinjing 2026-03-28 13:55:06 -07:00 committed by GitHub
parent d4fc4bef19
commit bbbe378467
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 121 additions and 4 deletions

View File

@ -3,11 +3,12 @@ import type { OrcaHooks } from '../../../../shared/types'
import { useAppStore } from '../../store'
import { ScrollArea } from '../ui/scroll-area'
import { Button } from '../ui/button'
import { ArrowLeft, Palette, SlidersHorizontal, SquareTerminal } from 'lucide-react'
import { ArrowLeft, Palette, SlidersHorizontal, SquareTerminal, Keyboard } from 'lucide-react'
import { getSystemPrefersDark } from '@/lib/terminal-theme'
import { SCROLLBACK_PRESETS_MB, getFallbackTerminalFonts } from './SettingsConstants'
import { GeneralPane } from './GeneralPane'
import { AppearancePane } from './AppearancePane'
import { ShortcutsPane } from './ShortcutsPane'
import { TerminalPane } from './TerminalPane'
import { RepositoryPane } from './RepositoryPane'
@ -20,9 +21,9 @@ function Settings(): React.JSX.Element {
const updateRepo = useAppStore((s) => s.updateRepo)
const removeRepo = useAppStore((s) => s.removeRepo)
const [selectedPane, setSelectedPane] = useState<'general' | 'appearance' | 'terminal' | 'repo'>(
'general'
)
const [selectedPane, setSelectedPane] = useState<
'general' | 'appearance' | 'terminal' | 'shortcuts' | 'repo'
>('general')
const [selectedRepoId, setSelectedRepoId] = useState<string | null>(null)
const [repoHooksMap, setRepoHooksMap] = useState<
Record<string, { hasHooks: boolean; hooks: OrcaHooks | null }>
@ -151,6 +152,7 @@ function Settings(): React.JSX.Element {
const showGeneralPane = selectedPane === 'general'
const showAppearancePane = selectedPane === 'appearance'
const showTerminalPane = selectedPane === 'terminal'
const showShortcutsPane = selectedPane === 'shortcuts'
const showRepoPane = selectedPane === 'repo' && !!selectedRepo
const displayedGitUsername = (selectedRepo ?? repos[0])?.gitUsername ?? ''
@ -180,6 +182,11 @@ function Settings(): React.JSX.Element {
Terminal appearance, previews, and defaults for new panes.
</p>
</div>
) : showShortcutsPane ? (
<div className="space-y-1">
<h1 className="text-2xl font-semibold">Shortcuts</h1>
<p className="text-sm text-muted-foreground">Keyboard shortcuts for common actions.</p>
</div>
) : selectedRepo ? (
<div className="space-y-1">
<div className="flex items-center gap-3">
@ -249,6 +256,17 @@ function Settings(): React.JSX.Element {
<SquareTerminal className="mr-2 size-4" />
Terminal
</button>
<button
onClick={() => setSelectedPane('shortcuts')}
className={`flex w-full items-center rounded-lg px-3 py-2 text-left text-sm transition-colors ${
showShortcutsPane
? 'bg-accent font-medium text-accent-foreground'
: 'text-muted-foreground hover:bg-muted/60 hover:text-foreground'
}`}
>
<Keyboard className="mr-2 size-4" />
Shortcuts
</button>
</div>
<div className="space-y-2">
@ -315,6 +333,8 @@ function Settings(): React.JSX.Element {
scrollbackMode={scrollbackMode}
setScrollbackMode={setScrollbackMode}
/>
) : showShortcutsPane ? (
<ShortcutsPane />
) : selectedRepo ? (
<RepositoryPane
repo={selectedRepo}

View File

@ -0,0 +1,97 @@
import React, { useMemo } from 'react'
type ShortcutItem = {
action: string
keys: string[]
}
type ShortcutGroup = {
title: string
items: ShortcutItem[]
}
export function ShortcutsPane(): React.JSX.Element {
const isMac = navigator.userAgent.includes('Mac')
const mod = isMac ? '⌘' : 'Ctrl'
const shift = isMac ? '⇧' : 'Shift'
const enter = isMac ? '↵' : 'Enter'
const groups = useMemo<ShortcutGroup[]>(
() => [
{
title: 'Global',
items: [
{ action: 'Create worktree', keys: [mod, 'N'] },
{ action: 'Toggle File Explorer', keys: [mod, shift, 'E'] },
{ action: 'Toggle Search', keys: [mod, shift, 'F'] },
{ action: 'Toggle Source Control', keys: [mod, shift, 'G'] }
]
},
{
title: 'Terminal Tabs',
items: [
{ action: 'New tab', keys: [mod, 'T'] },
{ action: 'Close active tab / pane', keys: [mod, 'W'] },
{ action: 'Next tab', keys: [mod, shift, ']'] },
{ action: 'Previous tab', keys: [mod, shift, '['] }
]
},
{
title: 'Terminal Panes',
items: [
{ action: 'Split pane right', keys: [mod, 'D'] },
{ action: 'Split pane down', keys: [mod, shift, 'D'] },
{ action: 'Close pane (EOF)', keys: ['Ctrl', 'D'] },
{ action: 'Focus next pane', keys: [mod, ']'] },
{ action: 'Focus previous pane', keys: [mod, '['] },
{ action: 'Clear active pane', keys: [mod, 'K'] },
{ action: 'Expand / collapse pane', keys: [mod, shift, enter] }
]
}
],
[mod, shift, enter]
)
return (
<div className="space-y-8">
<section className="space-y-4">
<div className="space-y-1">
<h2 className="text-sm font-semibold">Keyboard Shortcuts</h2>
<p className="text-xs text-muted-foreground">
View common hotkeys used across the application. Shortcuts customization is not
currently supported.
</p>
</div>
<div className="grid gap-8">
{groups.map((group) => (
<div key={group.title} className="space-y-3">
<h3 className="text-sm font-medium border-b border-border/50 pb-2 text-muted-foreground">
{group.title}
</h3>
<div className="grid gap-2">
{group.items.map((item, idx) => (
<div key={idx} className="flex items-center justify-between py-1">
<span className="text-sm text-foreground">{item.action}</span>
<div className="flex items-center gap-1">
{item.keys.map((key, kIdx) => (
<React.Fragment key={kIdx}>
<span className="inline-flex min-w-6 items-center justify-center rounded border border-border/80 bg-secondary/70 px-1.5 py-0.5 text-xs font-medium text-muted-foreground shadow-sm">
{key}
</span>
{!isMac && kIdx < item.keys.length - 1 && (
<span className="text-muted-foreground text-xs mx-0.5">+</span>
)}
</React.Fragment>
))}
</div>
</div>
))}
</div>
</div>
))}
</div>
</section>
</div>
)
}