feat(desktop): quick-create profile from rail + pin rail on empty sidebar

- Add a "+" in the profile rail that opens a self-contained CreateProfileDialog
  (name + clone toggle + optional SOUL.md); extract it and ActionStatus from
  the profiles view so both surfaces share one flow.
- Keep the profile rail pinned to the bottom when a profile has no sessions by
  rendering a flex-1 spacer (previously the rail floated up to the nav).
This commit is contained in:
Brooklyn Nicholson
2026-06-04 16:55:16 -05:00
parent b94b3622b5
commit 5df732a355
5 changed files with 209 additions and 161 deletions
@@ -732,6 +732,8 @@ export function ChatSidebar({
/>
)}
{sidebarOpen && !showSessionSections && <div className="min-h-0 flex-1" />}
{multiProfile && sidebarOpen && (
<div className="shrink-0 px-0.5 pb-1 pt-0.5">
<ProfileRail />
@@ -1,5 +1,5 @@
import { useStore } from '@nanostores/react'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Button } from '@/components/ui/button'
@@ -18,6 +18,7 @@ import {
setShowAllProfiles
} from '@/store/profile'
import { CreateProfileDialog } from '../../profiles/create-profile-dialog'
import { PROFILES_ROUTE } from '../../routes'
// Arc-Spaces-style profile rail at the sidebar foot: a default↔all toggle pinned
@@ -30,6 +31,8 @@ export function ProfileRail() {
const gatewayProfile = useStore($activeGatewayProfile)
const navigate = useNavigate()
const [createOpen, setCreateOpen] = useState(false)
const isAll = scope === ALL_PROFILES
const activeKey = normalizeProfileKey(gatewayProfile)
const defaultProfile = profiles.find(profile => profile.is_default)
@@ -70,9 +73,22 @@ export function ProfileRail() {
onSelect={() => selectProfile(profile.name)}
/>
))}
<Tip label="New profile">
<button
aria-label="New profile"
className="grid size-5 shrink-0 place-items-center rounded-[3px] text-(--ui-text-tertiary) opacity-55 transition hover:bg-(--ui-control-hover-background) hover:text-foreground hover:opacity-100"
onClick={() => setCreateOpen(true)}
type="button"
>
<Codicon name="add" size="0.75rem" />
</button>
</Tip>
</div>
<ProfilePill active={false} glyph="ellipsis" label="Manage profiles…" onSelect={() => navigate(PROFILES_ROUTE)} />
<CreateProfileDialog onClose={() => setCreateOpen(false)} onCreated={refreshActiveProfile} open={createOpen} />
</div>
)
}