QUICK START KEYBOARD SHORTCUTS - nself-org/nchat GitHub Wiki
Get the keyboard shortcuts system up and running in 5 minutes.
// src/app/layout.tsx or src/app/chat/layout.tsx
'use client'
import { useState } from 'react'
import { ShortcutsModal } from '@/components/modals/ShortcutsModal'
import { useGlobalShortcuts } from '@/hooks/use-global-shortcuts'
export default function RootLayout({ children }) {
const [shortcutsOpen, setShortcutsOpen] = useState(false)
// Register global shortcuts
useGlobalShortcuts({
onShowShortcuts: () => setShortcutsOpen(true),
})
return (
<html>
<body>
{children}
{/* Shortcuts Modal - opens with ? or Cmd+/ */}
<ShortcutsModal open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
</body>
</html>
)
}// src/app/settings/keyboard/page.tsx
import { KeyboardShortcuts } from '@/components/settings/KeyboardShortcuts'
export default function KeyboardSettingsPage() {
return (
<div className="container max-w-4xl py-8">
<h1 className="mb-8 text-3xl font-bold">Keyboard Settings</h1>
<KeyboardShortcuts />
</div>
)
}// src/components/QuickSwitcher.tsx
import { useHotkey } from '@/hooks/use-hotkey'
import { useState } from 'react'
export function QuickSwitcher() {
const [isOpen, setIsOpen] = useState(false)
// Open with Cmd+K
useHotkey('mod+k', () => setIsOpen(true), {
preventDefault: true,
})
// Close with Escape
useHotkey('escape', () => setIsOpen(false), {
enabled: isOpen,
})
if (!isOpen) return null
return (
<div className="quick-switcher">
<input placeholder="Search channels..." autoFocus />
{/* Your switcher UI */}
</div>
)
}// src/components/MessageList.tsx
import { useShortcut, useScopedKeyboard } from '@/lib/keyboard'
import { useState } from 'react'
export function MessageList({ messages }) {
const [selectedId, setSelectedId] = useState(null)
// Activate scope when message is selected
useScopedKeyboard('message-selected', !!selectedId)
// Reply with 'R'
useShortcut('REPLY', () => {
if (selectedId) {
handleReply(selectedId)
}
})
// Delete with 'Backspace'
useShortcut('DELETE_MESSAGE', () => {
if (selectedId) {
handleDelete(selectedId)
}
})
return (
<div>
{messages.map((msg) => (
<div
key={msg.id}
onClick={() => setSelectedId(msg.id)}
className={selectedId === msg.id ? 'selected' : ''}
>
{msg.content}
</div>
))}
</div>
)
}// src/components/MessageEditor.tsx
import { useEditorShortcuts } from '@/hooks/use-editor-shortcuts'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useState } from 'react'
export function MessageEditor() {
const [isFocused, setIsFocused] = useState(false)
const editor = useEditor({
extensions: [StarterKit],
content: '',
})
// Formatting shortcuts (Cmd+B, Cmd+I, etc.)
useEditorShortcuts({
editor,
isFocused,
})
return (
<EditorContent
editor={editor}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
)
}-
Press
?- Opens shortcuts modal -
Press
Cmd+K- Quick switcher -
Press
Cmd+/- Focus message input -
Press
Escape- Close modal - Go to Settings → Keyboard - Customize shortcuts
| Action | Shortcut | Category |
|---|---|---|
| Quick Switcher | Cmd+K |
Navigation |
| Search | Cmd+F |
Navigation |
| Next Channel | Alt+↓ |
Navigation |
| Previous Channel | Alt+↑ |
Navigation |
| Reply | R |
Messages |
| React | E |
Messages |
| Bold | Cmd+B |
Formatting |
| Italic | Cmd+I |
Formatting |
| Show Shortcuts | ? |
UI |
| Close Modal | Esc |
UI |
See full list in shortcuts modal (?)
Users can customize shortcuts in Settings:
- Navigate to Settings → Keyboard
- Click the keyboard icon next to any shortcut
- Press desired key combination
- Click Save
import { useHotkey } from '@/hooks/use-hotkey'
// Simple custom shortcut
useHotkey(
'mod+shift+x',
() => {
console.log('Custom action!')
},
{
preventDefault: true,
}
)import { getShortcutManager } from '@/lib/shortcuts/shortcut-manager'
const manager = getShortcutManager()
// Register multiple shortcuts
manager.registerMultiple([
{
id: 'action-1',
key: 'mod+1',
handler: () => console.log('Action 1'),
priority: 100,
},
{
id: 'action-2',
key: 'mod+2',
handler: () => console.log('Action 2'),
priority: 90,
},
])import { useShortcutStore } from '@/lib/keyboard/shortcut-store'
function MyComponent() {
const conflicts = useShortcutStore((state) => state.conflicts)
if (conflicts.length > 0) {
console.warn('Conflicts detected:', conflicts)
}
}-
Check if shortcuts are enabled:
const enabled = useShortcutStore((state) => state.shortcutsEnabled)
-
Check for conflicts in Settings → Keyboard
-
Verify scope is active:
useScopedKeyboard('my-scope', isActive)
- Make sure no input field is focused
- Try clicking outside modal first
- Check browser console for errors
-
Full Documentation: See
/docs/Keyboard-Shortcuts-System.md -
Examples: See
/docs/examples/keyboard-shortcuts-integration.tsx - API Reference: Check JSDoc comments in source files
You now have:
- ✅ Shortcuts modal (press
?) - ✅ Global shortcuts registered
- ✅ Settings page for customization
- ✅ Ready to use in components
That's it! Start using keyboard shortcuts in your app. 🎉