Add keyboard shortcuts system with reusable hint components
- Implement centralized keyboard registry with 20+ shortcuts - Add instance navigation (Cmd+[1-9], Cmd+[/]) - Add session navigation (Cmd+Shift+[1-9], Cmd+Shift+[/]) - Add agent/model cycling (Tab, Cmd+Shift+M) - Add input shortcuts (Cmd+P focus, Cmd+K clear, ↑↓ history) - Add command palette (Cmd+Shift+P) with 8 MVP commands - Implement message history per folder in IndexedDB (max 100) - Create reusable Kbd and HintRow components - Replace all keyboard hint rendering with consistent components - Use text-based shortcuts (Cmd+Shift+M) for clarity
This commit is contained in:
54
src/components/kbd.tsx
Normal file
54
src/components/kbd.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Component, JSX, For } from "solid-js"
|
||||
import { isMac } from "../lib/keyboard-utils"
|
||||
|
||||
interface KbdProps {
|
||||
children?: JSX.Element
|
||||
shortcut?: string
|
||||
class?: string
|
||||
}
|
||||
|
||||
const Kbd: Component<KbdProps> = (props) => {
|
||||
const parts = () => {
|
||||
if (props.children) return [{ text: props.children, isModifier: false }]
|
||||
if (!props.shortcut) return []
|
||||
|
||||
const result: { text: string | JSX.Element; isModifier: boolean }[] = []
|
||||
const shortcut = props.shortcut.toLowerCase()
|
||||
const tokens = shortcut.split("+")
|
||||
|
||||
tokens.forEach((token, i) => {
|
||||
const trimmed = token.trim()
|
||||
|
||||
if (trimmed === "cmd" || trimmed === "command") {
|
||||
result.push({ text: isMac() ? "Cmd" : "Ctrl", isModifier: false })
|
||||
} else if (trimmed === "shift") {
|
||||
result.push({ text: "Shift", isModifier: false })
|
||||
} else if (trimmed === "alt" || trimmed === "option") {
|
||||
result.push({ text: isMac() ? "Option" : "Alt", isModifier: false })
|
||||
} else if (trimmed === "ctrl") {
|
||||
result.push({ text: "Ctrl", isModifier: false })
|
||||
} else {
|
||||
result.push({ text: trimmed.toUpperCase(), isModifier: false })
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
return (
|
||||
<kbd
|
||||
class={`font-mono bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-xs inline-flex items-center gap-0.5 ${props.class || ""}`}
|
||||
>
|
||||
<For each={parts()}>
|
||||
{(part, index) => (
|
||||
<>
|
||||
{index() > 0 && <span class="opacity-50">+</span>}
|
||||
<span>{part.text}</span>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
</kbd>
|
||||
)
|
||||
}
|
||||
|
||||
export default Kbd
|
||||
Reference in New Issue
Block a user