Skip to content

Commit 2a6d504

Browse files
mishrapraffulclaude
andcommitted
feat: add settings icon and keyboard shortcuts section to sidebar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent dfa7aa6 commit 2a6d504

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

src/renderer/components/Sidebar/Sidebar.tsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
44
import { useSessionShortcuts } from "../../hooks/useChordShortcuts";
55
import { useRepoStore } from "../../stores/repoStore";
66
import { useSessionStore } from "../../stores/sessionStore";
7+
import { useThemeStore } from "../../stores/themeStore";
78
import { NewSessionDialog } from "./NewSessionDialog";
89
import { SessionListItem, type SessionListItemProps } from "./SessionListItem";
910
import { WorktreeDeleteDialog } from "./WorktreeDeleteDialog";
@@ -34,7 +35,10 @@ export function Sidebar() {
3435

3536
const reorderSessions = useSessionStore((state) => state.reorderSessions);
3637

38+
const toggleSettings = useThemeStore((state) => state.toggleSettings);
39+
3740
const [archiveOpen, setArchiveOpen] = useState(false);
41+
const [shortcutsOpen, setShortcutsOpen] = useState(false);
3842
const [metaHeld, setMetaHeld] = useState(false);
3943
const repoPickerRef = useRef<HTMLDivElement>(null);
4044

@@ -259,6 +263,46 @@ export function Sidebar() {
259263
</div>
260264
)}
261265

266+
{/* Keyboard shortcuts panel */}
267+
{shortcutsOpen && (
268+
<div className="border-t border-white/[0.06] px-3 py-2.5 space-y-1.5">
269+
<p className="text-[10px] font-medium text-text-muted uppercase tracking-wide mb-2">Shortcuts</p>
270+
{SHORTCUTS.map(({ keys, label }) => (
271+
<div key={label} className="flex items-center justify-between gap-2">
272+
<span className="text-[11px] text-text-muted">{label}</span>
273+
<kbd className="text-[10px] text-text-muted font-mono bg-white/5 rounded px-1.5 py-0.5 shrink-0">
274+
{keys}
275+
</kbd>
276+
</div>
277+
))}
278+
</div>
279+
)}
280+
281+
{/* Bottom bar: keyboard shortcuts toggle + settings */}
282+
<div className="border-t border-white/[0.06] flex items-center px-2 py-1.5">
283+
<button
284+
type="button"
285+
onClick={() => setShortcutsOpen(!shortcutsOpen)}
286+
className={`w-6 h-6 flex items-center justify-center rounded-md transition-colors ${
287+
shortcutsOpen
288+
? "text-text-primary bg-white/10"
289+
: "text-text-muted hover:text-text-primary hover:bg-white/10"
290+
}`}
291+
title="Keyboard shortcuts"
292+
>
293+
<KeyboardIcon />
294+
</button>
295+
<div className="flex-1" />
296+
<button
297+
type="button"
298+
onClick={toggleSettings}
299+
className="w-6 h-6 flex items-center justify-center rounded-md text-text-muted hover:text-text-primary hover:bg-white/10 transition-colors"
300+
title="Settings (⌘,)"
301+
>
302+
<GearIcon />
303+
</button>
304+
</div>
305+
262306
{/* New session dialog */}
263307
{pendingNewSessionRepo && (
264308
<NewSessionDialog
@@ -283,6 +327,14 @@ export function Sidebar() {
283327
);
284328
}
285329

330+
const SHORTCUTS = [
331+
{ keys: "⌘N", label: "New session" },
332+
{ keys: "⌘,", label: "Settings" },
333+
{ keys: "⌘B", label: "Toggle sidebar" },
334+
{ keys: "⌘1-9", label: "Jump to session" },
335+
{ keys: "Esc×2", label: "Stop agent" },
336+
];
337+
286338
function SortableSessionItem(props: Omit<SessionListItemProps, "sortableProps">) {
287339
const sortable = useSortable({ id: props.session.id });
288340
return <SessionListItem {...props} sortableProps={sortable} />;
@@ -323,3 +375,39 @@ function ChevronIcon({ open }: { open: boolean }) {
323375
</svg>
324376
);
325377
}
378+
379+
function GearIcon() {
380+
return (
381+
<svg
382+
width="14"
383+
height="14"
384+
viewBox="0 0 24 24"
385+
fill="none"
386+
stroke="currentColor"
387+
strokeWidth="2"
388+
strokeLinecap="round"
389+
strokeLinejoin="round"
390+
>
391+
<circle cx="12" cy="12" r="3" />
392+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
393+
</svg>
394+
);
395+
}
396+
397+
function KeyboardIcon() {
398+
return (
399+
<svg
400+
width="14"
401+
height="14"
402+
viewBox="0 0 24 24"
403+
fill="none"
404+
stroke="currentColor"
405+
strokeWidth="2"
406+
strokeLinecap="round"
407+
strokeLinejoin="round"
408+
>
409+
<rect x="2" y="6" width="20" height="12" rx="2" />
410+
<path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M8 14h8" />
411+
</svg>
412+
);
413+
}

0 commit comments

Comments
 (0)