feat(sidebar): promote Projects to first section + move profile chip under server name

Two small UX tweaks to the macOS sidebar:

* Reorder sections so Projects is the top section above Monitor.
  Reflects how users actually start sessions in Scarf — they pick a
  project first, then drill into chat / sessions / etc. The previous
  order put the read-mostly Dashboard at the top, which made
  Projects feel like a secondary surface.
* Move the active-profile chip out of the top header HStack (where
  it competed for horizontal space with the server-name pill) and
  drop it into a second row right-aligned under the server name.
  Top row stays clean: `[icon] Scarf       <server>`. Second row:
  `                              profile: <name>` only on local
  contexts. Same click target, same .help, just better-anchored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-04 14:37:29 +02:00
parent 2a368a04f7
commit 5afd391838
+33 -21
View File
@@ -44,8 +44,11 @@ struct SidebarView: View {
manage.append(contentsOf: [.health, .logs, .settings])
return [
Section(title: "Monitor", items: [.dashboard, .insights, .sessions, .activity]),
// Projects sits first now promoting it to a first-class
// entry point reflects how users actually open Scarf
// (start with a project, not the dashboard).
Section(title: "Projects", items: [.projects]),
Section(title: "Monitor", items: [.dashboard, .insights, .sessions, .activity]),
Section(title: "Interact", items: interact),
Section(title: "Configure", items: [.platforms, .personalities, .quickCommands, .credentialPools, .plugins, .webhooks, .profiles]),
Section(title: "Manage", items: manage),
@@ -83,31 +86,40 @@ struct SidebarView: View {
// MARK: - Header
private var header: some View {
HStack(spacing: ScarfSpace.s2) {
Image(nsImage: sidebarIconImage)
.resizable()
.interpolation(.high)
.frame(width: 22, height: 22)
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
Text("Scarf")
.scarfStyle(.bodyEmph)
.foregroundStyle(ScarfColor.foregroundPrimary)
VStack(alignment: .leading, spacing: ScarfSpace.s1) {
HStack(spacing: ScarfSpace.s2) {
Image(nsImage: sidebarIconImage)
.resizable()
.interpolation(.high)
.frame(width: 22, height: 22)
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
Text("Scarf")
.scarfStyle(.bodyEmph)
.foregroundStyle(ScarfColor.foregroundPrimary)
Spacer()
Text(serverContext.displayName.lowercased())
.font(ScarfFont.caption2)
.foregroundStyle(ScarfColor.foregroundFaint)
}
// Active-profile chip local contexts only. Remote
// ServerContexts don't read this Mac's active_profile
// file, so the chip would be misleading there.
// file, so the chip would be misleading there. Anchored
// to the trailing edge so it sits visually under the
// server name in the row above; saves horizontal space
// in the top row when the server name + chip would
// otherwise compete.
if !serverContext.isRemote {
Button {
coordinator.selectedSection = .profiles
} label: {
ScarfBadge("profile: \(activeProfileName)", kind: .brand)
HStack(spacing: 0) {
Spacer()
Button {
coordinator.selectedSection = .profiles
} label: {
ScarfBadge("profile: \(activeProfileName)", kind: .brand)
}
.buttonStyle(.plain)
.help("Active Hermes profile — click to manage")
}
.buttonStyle(.plain)
.help("Active Hermes profile — click to manage")
}
Spacer()
Text(serverContext.displayName.lowercased())
.font(ScarfFont.caption2)
.foregroundStyle(ScarfColor.foregroundFaint)
}
.padding(.horizontal, ScarfSpace.s4)
.padding(.top, 19) // Half the original 38 px traffic-light clearance.