Add workspace auto-rename branch hint

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-05-31 20:27:45 -07:00
co-authored by Orca
parent c5ba94ce96
commit 54c3fb9aa5
2 changed files with 110 additions and 5 deletions
@@ -9,7 +9,8 @@ import {
FolderPlus,
LoaderCircle,
PlugZap,
Settings2
Settings2,
Sparkles
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
@@ -32,6 +33,7 @@ import SparseCheckoutPresetSelect from '@/components/sparse/SparseCheckoutPreset
import SmartWorkspaceNameField, {
type SmartWorkspaceNameSelection
} from '@/components/new-workspace/SmartWorkspaceNameField'
import AutoRenameBranchHint from '@/components/new-workspace/AutoRenameBranchHint'
import type { SetupConfig } from '@/lib/new-workspace'
import type { WorkspaceCreateErrorDisplay } from '@/lib/workspace-create-error-format'
import type { SshConnectionStatus } from '../../../shared/ssh-types'
@@ -254,6 +256,7 @@ export default function NewWorkspaceComposerCard({
const defaultTuiAgent = useAppStore((s) => s.settings?.defaultTuiAgent ?? null)
const disabledTuiAgents = useAppStore((s) => s.settings?.disabledTuiAgents ?? [])
const updateSettings = useAppStore((s) => s.updateSettings)
const autoRenameBranchFromWork = useAppStore((s) => s.settings?.autoRenameBranchFromWork ?? false)
const nameInputFocusFrameRef = React.useRef<number | null>(null)
const submitShortcutModifierLabel = getScreenSubmitModifierLabel()
const selectedRepoName = React.useMemo(() => {
@@ -436,10 +439,23 @@ export default function NewWorkspaceComposerCard({
</div>
<div className="min-w-0 space-y-1">
<label className="text-xs font-medium text-muted-foreground">
{selectedRepoIsGit ? "Name or 'Create From'" : 'Workspace name'}{' '}
<span className="text-muted-foreground/70">[Optional]</span>
</label>
<div className="flex items-center justify-between gap-2">
<label className="min-w-0 truncate text-xs font-medium text-muted-foreground">
{selectedRepoIsGit ? "Name or 'Create From'" : 'Workspace name'}{' '}
<span className="text-muted-foreground/70">[Optional]</span>
</label>
{selectedRepoIsGit ? (
<div className="flex min-w-0 items-center justify-end gap-1.5">
{autoRenameBranchFromWork ? (
<span className="flex min-w-0 items-center gap-1 truncate text-[11px] text-muted-foreground">
<Sparkles className="size-3 shrink-0" />
<span className="truncate">Auto-named if left blank</span>
</span>
) : null}
<AutoRenameBranchHint />
</div>
) : null}
</div>
<SmartWorkspaceNameField
inputRef={nameInputRef}
repos={eligibleRepos}
@@ -0,0 +1,89 @@
import React from 'react'
import { ChevronRight, Settings2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { useAppStore } from '@/store'
import { cn } from '@/lib/utils'
/**
* Gear affordance on the workspace Name label row. Its popover explains that a
* blank name lets Orca auto-rename the branch from the work, and lets the user
* flip the `autoRenameBranchFromWork` setting inline without leaving the
* composer. Only relevant for git repos, where a branch exists to rename.
*/
export default function AutoRenameBranchHint(): React.JSX.Element {
const autoRenameBranchFromWork = useAppStore((s) => s.settings?.autoRenameBranchFromWork ?? false)
const updateSettings = useAppStore((s) => s.updateSettings)
const openSettingsPage = useAppStore((s) => s.openSettingsPage)
const openSettingsTarget = useAppStore((s) => s.openSettingsTarget)
const closeModal = useAppStore((s) => s.closeModal)
const handleOpenSettings = React.useCallback((): void => {
// Why: the setting lives in the Git pane; closing the composer first keeps
// the settings page from rendering behind the modal.
closeModal()
openSettingsTarget({ pane: 'git', repoId: null })
openSettingsPage()
}, [closeModal, openSettingsPage, openSettingsTarget])
return (
<Popover>
<PopoverTrigger asChild>
<Button
type="button"
variant="ghost"
size="icon-xs"
// Why: detour from the Name → Agent tab flow, so keep it off the tab
// order like the adjacent agent-settings gear.
tabIndex={-1}
className="size-5 shrink-0 rounded-sm text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
aria-label="Auto-rename branch settings"
>
<Settings2 className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent align="end" side="bottom" sideOffset={6} className="w-72 p-3">
<div className="space-y-2.5">
<div className="space-y-1">
<div className="flex items-center justify-between gap-3">
<span className="text-sm font-medium text-foreground">Auto-rename branch</span>
<button
type="button"
role="switch"
aria-checked={autoRenameBranchFromWork}
aria-label="Auto-rename branch"
onClick={() =>
updateSettings({ autoRenameBranchFromWork: !autoRenameBranchFromWork })
}
className={cn(
'relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-colors',
autoRenameBranchFromWork ? 'bg-foreground' : 'bg-muted-foreground/30'
)}
>
<span
className={cn(
'pointer-events-none block size-3.5 rounded-full bg-background shadow-sm transition-transform',
autoRenameBranchFromWork ? 'translate-x-4' : 'translate-x-0.5'
)}
/>
</button>
</div>
<p className="text-xs text-muted-foreground">
When you leave the name blank, Orca renames the branch to match the work once an agent
starts.
</p>
</div>
<button
type="button"
onClick={handleOpenSettings}
className="flex items-center gap-0.5 rounded-sm text-xs text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
Open settings
<ChevronRight className="size-3" />
</button>
</div>
</PopoverContent>
</Popover>
)
}