SessionRail

import { SessionRail, StatusDot } from '@hanzo/ui/chat'

The rail

New, the surface's places, the recents with their status, and the account. Collapse is an explicit toggle the host keeps.

export function Default() {
const [active, setActive] = useState<string | null>(null)
const [collapsed, setCollapsed] = useState(false)
return (
<XStack height={440}>
<SessionRail onNew={() => setActive(null)} fresh={active === null} links={[ { id: 'artifacts', label: 'Artifacts', icon: <Box size={16} /> }, { id: 'customize', label: 'Customize', icon: <Wrench size={16} /> }, ]} more={[{ id: 'projects', label: 'Projects', icon: <Box size={16} /> }]} recents={RECENTS} active={active} onOpen={setActive} onSort={() => {}} account={{ name: '[email protected]', onPress: () => {} }} onSettings={() => {}} onSearch={() => {}} collapsed={collapsed} onCollapse={setCollapsed} />
</XStack>
)
}

Types

export type SessionStatus = 'running' | 'paused' | 'done' | 'stopped' | 'error' | 'idle'
export interface RailSession {
id: string
title: string
status?: SessionStatus
}
export interface RailLink {
id: string
label: string
icon: ReactNode
onPress?: () => void
/** This place is the current view. */
active?: boolean
}
export interface RailAccount {
/** The line shown — an email or a name. */
name: string
/** Avatar slot. Falls back to the first letter of `name`. */
avatar?: ReactNode
/** The caret beside the name: the account menu. */
onPress?: () => void
}
export interface SessionRailProps extends Col {
/** Starts a new session. */
onNew?: () => void
newLabel?: string
/** The fresh pane IS the current view, so New draws as the active row. */
fresh?: boolean
/** The surface's own places, under New. */
links?: RailLink[]
/** Behind the "More" disclosure. None, and there is no More row. */
more?: RailLink[]
moreLabel?: string
/** The sessions, newest first. */
recents: RailSession[]
recentsLabel?: string
/** The open session's id. */
active?: string | null
onOpen: (id: string) => void
/** The sort/filter control beside the Recents label. None, no control. */
onSort?: () => void
sortLabel?: string
/** Shown in place of the list when there are no recents. */
empty?: ReactNode
/** Drawn above the account row — a notice, a setup card. */
notice?: ReactNode
account?: RailAccount
onSettings?: () => void
onSearch?: () => void
/** Collapsed to the icon rail. The host owns and persists it. */
collapsed?: boolean
onCollapse?: (collapsed: boolean) => void
/** The rail's top row when collapsed — a surface's mark. It is the expand control. */
mark?: ReactNode
/** Below `md`: the drawer is open. */
open?: boolean
onOpenChange?: (open: boolean) => void
/** The landmark's name. */
label?: string
/** Expanded width, px. */
width?: number
}

Exports

SessionRailStatusDottype RailAccounttype RailLinktype RailSessiontype SessionRailPropstype SessionStatus