first commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Card } from "@heroui/react";
|
||||
import { StateChip } from "@/components/StatusChip";
|
||||
import { relTime } from "@/lib/format";
|
||||
import type { SessionView } from "@/protocol";
|
||||
|
||||
/**
|
||||
* Only rendered when more than one session is live. With a single workspace the Now card
|
||||
* already says everything, and an extra list is just noise on a small screen.
|
||||
*/
|
||||
export function SessionsCard({
|
||||
sessions,
|
||||
selectedId,
|
||||
onSelect,
|
||||
now,
|
||||
}: {
|
||||
sessions: SessionView[];
|
||||
selectedId: string | null;
|
||||
onSelect: (id: string | null) => void;
|
||||
now: number;
|
||||
}) {
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<Card.Title className="text-base">Sessions</Card.Title>
|
||||
<Card.Description className="text-xs">
|
||||
Tap one to filter the activity list.
|
||||
</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content className="px-0">
|
||||
<ul className="flex flex-col">
|
||||
<li className="border-b border-separator">
|
||||
<Row active={selectedId === null} onPress={() => onSelect(null)}>
|
||||
<span className="text-sm">All sessions</span>
|
||||
<span className="text-xs text-muted">{sessions.length}</span>
|
||||
</Row>
|
||||
</li>
|
||||
{sessions.map((session) => (
|
||||
<li key={session.id} className="border-b border-separator last:border-b-0">
|
||||
<Row
|
||||
active={selectedId === session.id}
|
||||
onPress={() => onSelect(session.id === selectedId ? null : session.id)}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate text-sm">{session.label}</span>
|
||||
<span className="shrink-0 text-[11px] text-muted">
|
||||
{relTime(session.lastActivity, now)}
|
||||
</span>
|
||||
<StateChip state={session.state} />
|
||||
</Row>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function Row({
|
||||
active,
|
||||
onPress,
|
||||
children,
|
||||
}: {
|
||||
active: boolean;
|
||||
onPress: () => void;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onPress}
|
||||
aria-pressed={active}
|
||||
className={`flex w-full items-center gap-2 px-4 py-3 text-left transition-colors ${
|
||||
active ? "bg-surface-secondary" : "hover:bg-surface-hover"
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user