feat: replace top-level New Session button with contextual buttons

Remove the single New Session button from the sidebar top and replace it
with contextual creation buttons scoped to each section:

- Scratchpad section: 'New Scratchpad' button that auto-creates a
  scratchpad session with the first available single-agent pattern
- Project groups: 'New Session' button that opens the pattern picker
  modal pre-scoped to that project
- WelcomePane: primary action updated to 'New Scratchpad'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-24 19:05:50 +01:00
co-authored by Copilot
parent a79787735a
commit 30733ae59a
3 changed files with 51 additions and 26 deletions
+26 -8
View File
@@ -22,7 +22,7 @@ import {
resolveReasoningEffort,
} from '@shared/domain/models';
import type { PatternDefinition } from '@shared/domain/pattern';
import { isScratchpadProject } from '@shared/domain/project';
import { isScratchpadProject, SCRATCHPAD_PROJECT_ID } from '@shared/domain/project';
import { applyScratchpadSessionConfig } from '@shared/domain/session';
import type { LspProfileDefinition, McpServerDefinition } from '@shared/domain/tooling';
import type { WorkspaceState } from '@shared/domain/workspace';
@@ -89,7 +89,7 @@ export default function App() {
const [isRefreshingCapabilities, setIsRefreshingCapabilities] = useState(false);
const [showSettings, setShowSettings] = useState(false);
const [showNewSession, setShowNewSession] = useState(false);
const [newSessionProjectId, setNewSessionProjectId] = useState<string>();
// Load workspace on mount
useEffect(() => {
@@ -201,6 +201,21 @@ export default function App() {
}
};
const handleCreateScratchpad = () => {
const singlePatterns = workspace.patterns
.filter((p) => p.mode === 'single' && p.availability !== 'unavailable')
.sort((a, b) => {
if (a.isFavorite && !b.isFavorite) return -1;
if (!a.isFavorite && b.isFavorite) return 1;
return 0;
});
const defaultPattern = singlePatterns[0];
if (defaultPattern) {
void api.createSession({ projectId: SCRATCHPAD_PROJECT_ID, patternId: defaultPattern.id });
}
};
// Determine main content
let content: React.ReactNode;
let detailPanel: React.ReactNode | undefined;
@@ -253,7 +268,7 @@ export default function App() {
<WelcomePane
hasProjects={hasUserProjects}
onAddProject={() => void api.addProject()}
onNewSession={() => setShowNewSession(true)}
onNewScratchpad={() => handleCreateScratchpad()}
onOpenSettings={() => setShowSettings(true)}
/>
);
@@ -309,7 +324,10 @@ export default function App() {
sidebar={
<Sidebar
onAddProject={() => void api.addProject()}
onNewSession={() => setShowNewSession(true)}
onCreateScratchpad={() => handleCreateScratchpad()}
onNewProjectSession={(projectId) => {
setNewSessionProjectId(projectId);
}}
onOpenSettings={() => setShowSettings(true)}
onProjectSelect={(projectId) => {
void api.selectProject(projectId);
@@ -337,12 +355,12 @@ export default function App() {
}
/>
{showNewSession && (
{newSessionProjectId && (
<NewSessionModal
defaultProjectId={workspace.selectedProjectId}
onClose={() => setShowNewSession(false)}
defaultProjectId={newSessionProjectId}
onClose={() => setNewSessionProjectId(undefined)}
onCreate={(projectId, patternId) => {
setShowNewSession(false);
setNewSessionProjectId(undefined);
void api.createSession({ projectId, patternId });
}}
onTogglePatternFavorite={(patternId, isFavorite) => {
+21 -14
View File
@@ -35,7 +35,8 @@ import type { WorkspaceState } from '@shared/domain/workspace';
interface SidebarProps {
workspace: WorkspaceState;
onAddProject: () => void;
onNewSession: () => void;
onCreateScratchpad: () => void;
onNewProjectSession: (projectId: string) => void;
onProjectSelect: (projectId?: string) => void;
onSessionSelect: (sessionId: string) => void;
onOpenSettings: () => void;
@@ -310,6 +311,8 @@ function ProjectGroup({
onRenameSubmit,
onRenameCancel,
onRefreshGitContext,
onNewSession,
newSessionLabel,
}: {
project: ProjectRecord;
sessions: SessionRecord[];
@@ -321,6 +324,8 @@ function ProjectGroup({
onRenameSubmit: (sessionId: string, title: string) => void;
onRenameCancel: () => void;
onRefreshGitContext?: (projectId: string) => void;
onNewSession?: () => void;
newSessionLabel?: string;
}){
const [expanded, setExpanded] = useState(true);
const isScratchpad = isScratchpadProject(project);
@@ -414,6 +419,16 @@ function ProjectGroup({
/>
))
)}
{onNewSession && (
<button
className="flex w-full items-center justify-center gap-1.5 rounded-md border border-dashed border-zinc-700/60 bg-zinc-800/20 px-2.5 py-1.5 text-[12px] font-medium text-zinc-500 transition hover:border-indigo-500/40 hover:bg-indigo-500/5 hover:text-indigo-300"
onClick={onNewSession}
type="button"
>
<Plus className="size-3.5" />
{newSessionLabel ?? 'New Session'}
</button>
)}
</div>
)}
</div>
@@ -425,7 +440,8 @@ function ProjectGroup({
export function Sidebar({
workspace,
onAddProject,
onNewSession,
onCreateScratchpad,
onNewProjectSession,
onProjectSelect,
onSessionSelect,
onOpenSettings,
@@ -537,18 +553,6 @@ export function Sidebar({
</div>
</div>
{/* New session CTA */}
<div className="px-3 pt-2 pb-1">
<button
className="flex w-full items-center justify-center gap-2 rounded-lg border border-dashed border-zinc-700 bg-zinc-800/30 px-3 py-2 text-[13px] font-medium text-zinc-400 transition hover:border-indigo-500/40 hover:bg-indigo-500/5 hover:text-indigo-300"
onClick={onNewSession}
type="button"
>
<Plus className="size-4" />
New Session
</button>
</div>
{/* Session list */}
<div
className="flex-1 overflow-y-auto px-2 py-2"
@@ -600,6 +604,8 @@ export function Sidebar({
project={scratchpadProject}
selectedSessionId={workspace.selectedSessionId}
sessions={workspace.sessions.filter((session) => session.projectId === scratchpadProject.id)}
onNewSession={onCreateScratchpad}
newSessionLabel="New Scratchpad"
/>
</div>
)}
@@ -646,6 +652,7 @@ export function Sidebar({
project={project}
selectedSessionId={workspace.selectedSessionId}
sessions={workspace.sessions.filter((session) => session.projectId === project.id)}
onNewSession={() => onNewProjectSession(project.id)}
/>
))}
</div>
+4 -4
View File
@@ -2,14 +2,14 @@ import { MessageSquare, Plus, Settings } from 'lucide-react';
interface WelcomePaneProps {
hasProjects: boolean;
onNewSession: () => void;
onNewScratchpad: () => void;
onAddProject: () => void;
onOpenSettings: () => void;
}
export function WelcomePane({
hasProjects,
onNewSession,
onNewScratchpad,
onAddProject,
onOpenSettings,
}: WelcomePaneProps) {
@@ -31,11 +31,11 @@ export function WelcomePane({
<div className="flex flex-col items-center gap-2">
<button
className="flex items-center gap-2 rounded-lg bg-indigo-600 px-5 py-2.5 text-sm font-medium text-white transition hover:bg-indigo-500"
onClick={onNewSession}
onClick={onNewScratchpad}
type="button"
>
<Plus className="size-4" />
New Session
New Scratchpad
</button>
{!hasProjects && (
<button