Terminal sessions move from the rail into a tab strip on the terminal page

The rail is now a flat list of pages; Terminal is one of them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-09-18 22:10:22 -07:00
co-authored by Claude Fable 5.1
parent 7eb00d089f
commit 91b7f4f009
5 changed files with 92 additions and 85 deletions
+14 -13
View File
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import { api, Me, Term } from './api'
import Rail, { Group } from './Rail'
import TerminalPane, { TermHandle } from './TerminalPane'
import TermTabs from './TermTabs'
import KeyBar from './KeyBar'
import Dashboard from './Dashboard'
import Services from './Services'
@@ -26,16 +27,16 @@ const FolderIcon = (
)
const GROUPS: Group[] = [
{ id: 'dashboard', label: 'Dashboard', icon: '◔', page: true },
{ id: 'procs', label: 'Processes', icon: '≡', page: true },
{ id: 'dashboard', label: 'Dashboard', icon: '◔' },
{ id: 'procs', label: 'Processes', icon: '≡' },
{ id: 'terminal', label: 'Terminal', icon: '>_' },
{ id: 'services', label: 'Services', icon: '◈', page: true },
{ id: 'cron', label: 'Cron', icon: '⏱', page: true },
{ id: 'updates', label: 'Updates', icon: '⇪', page: true },
{ id: 'disks', label: 'Disks', icon: '▤', page: true },
{ id: 'files', label: 'Files', icon: FolderIcon, page: true },
{ id: 'machines', label: 'Machines', icon: '⌂', page: true },
{ id: 'settings', label: 'Settings', icon: '⚙', page: true },
{ id: 'services', label: 'Services', icon: '◈' },
{ id: 'cron', label: 'Cron', icon: '⏱' },
{ id: 'updates', label: 'Updates', icon: '⇪' },
{ id: 'disks', label: 'Disks', icon: '▤' },
{ id: 'files', label: 'Files', icon: FolderIcon },
{ id: 'machines', label: 'Machines', icon: '⌂' },
{ id: 'settings', label: 'Settings', icon: '⚙' },
]
type View = 'terminal' | 'dashboard' | 'services' | 'cron' | 'updates' | 'disks' | 'files' | 'procs' | 'machines' | 'settings'
@@ -167,11 +168,9 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
</header>
<div className="body">
<Rail groups={GROUPS} terms={terms} active={active} view={view} creating={creating}
<Rail groups={GROUPS} view={view}
header={<MachineSwitcher hub={hubMe.host} current={machine} machines={machines} onChange={switchMachine} onManage={() => { setView('machines'); setDrawer(false) }} />}
onSelect={(id) => { setActive(id); setView('terminal'); setDrawer(false) }}
onView={(id) => { setView(id as View); setDrawer(false) }}
onNew={create} onRename={rename} onClose={close} />
onView={(id) => { setView(id as View); setDrawer(false) }} />
<div className="backdrop" onClick={() => setDrawer(false)} />
<main className="main" key={machine ?? 'hub'}>
@@ -184,6 +183,8 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
{view === 'updates' && <Updates />}
{view === 'disks' && <Disks />}
{view === 'files' && <Files onOpenInTerminal={runInTerminal} />}
{termView && <TermTabs terms={terms} active={active} creating={creating}
onSelect={setActive} onNew={create} onRename={rename} onClose={close} />}
{termView && terms.length === 0 && (
<div className="center muted">
<div>No terminals.</div>