Feedback sweep: spinners on every async button, toasts for action outcomes, top activity bar, loading states on every page, terminal connecting overlay, dashboard save indicator, task pane pinned above the package list with auto-scroll and completion toast

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-09-17 18:04:45 -07:00
co-authored by Claude Fable 5.1
parent d08b246b5f
commit 724f30c02b
13 changed files with 261 additions and 93 deletions
+4 -3
View File
@@ -1,17 +1,18 @@
import { useState } from 'react'
import { Term } from './api'
import { Spinner } from './ui'
// A group is either a page (clicking the head opens it — Dashboard) or a folder of
// leaves (Terminal). `soon` groups are inert placeholders for the roadmap.
export interface Group { id: string; label: string; icon: string; soon?: boolean; page?: boolean }
interface Props {
groups: Group[]; terms: Term[]; active: string | null; view: string
groups: Group[]; terms: Term[]; active: string | null; view: string; creating?: boolean
onSelect: (id: string) => void; onView: (id: string) => void; onNew: () => void
onRename: (t: Term) => void; onClose: (t: Term) => void
}
export default function Rail({ groups, terms, active, view, onSelect, onView, onNew, onRename, onClose }: Props) {
export default function Rail({ groups, terms, active, view, creating, onSelect, onView, onNew, onRename, onClose }: Props) {
const [open, setOpen] = useState<string>('terminal')
return (
<nav className="rail">
@@ -45,7 +46,7 @@ export default function Rail({ groups, terms, active, view, onSelect, onView, on
</div>
)
})}
<button className="leaf new" onClick={onNew}>+ New Terminal</button>
<button className="leaf new" disabled={creating} onClick={onNew}>{creating ? <><Spinner /> creating…</> : '+ New Terminal'}</button>
</div>
)}
</div>