Files
stack/packages/cli/src/tui/components/top-bar.tsx
Jason Woltje 82c10a7b33
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
feat(cli): TUI complete overhaul — components, sidebar, search, branding (#157)
Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
2026-03-15 22:17:19 +00:00

100 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from 'react';
import { Box, Text } from 'ink';
export interface TopBarProps {
gatewayUrl: string;
version: string;
modelName: string | null;
thinkingLevel: string;
contextWindow: number;
agentName: string;
connected: boolean;
connecting: boolean;
}
/** Compact the URL — strip protocol */
function compactHost(url: string): string {
return url.replace(/^https?:\/\//, '');
}
function formatContextWindow(n: number): string {
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(0)}M`;
if (n >= 1_000) return `${(n / 1_000).toFixed(0)}k`;
return String(n);
}
/**
* Mosaic 3×3 icon — brand tiles with black gaps (windmill cross pattern)
*
* Layout:
* blue ·· purple
* ·· pink ··
* amber ·· teal
*/
// Two-space gap between tiles (extracted to avoid prettier collapse)
const GAP = ' ';
function MosaicIcon() {
return (
<Box flexDirection="column" marginRight={2}>
<Text>
<Text color="#2f80ff"></Text>
<Text>{GAP}</Text>
<Text color="#8b5cf6"></Text>
</Text>
<Text>
<Text>{GAP}</Text>
<Text color="#ec4899"></Text>
</Text>
<Text>
<Text color="#f59e0b"></Text>
<Text>{GAP}</Text>
<Text color="#14b8a6"></Text>
</Text>
</Box>
);
}
export function TopBar({
gatewayUrl,
version,
modelName,
thinkingLevel,
contextWindow,
agentName,
connected,
connecting,
}: TopBarProps) {
const host = compactHost(gatewayUrl);
const connectionIndicator = connected ? '●' : '○';
const connectionColor = connected ? 'green' : connecting ? 'yellow' : 'red';
// Build model description line like: "claude-opus-4-6 (1M context) · default"
const modelDisplay = modelName ?? 'awaiting model';
const contextStr = contextWindow > 0 ? ` (${formatContextWindow(contextWindow)} context)` : '';
const thinkingStr = thinkingLevel !== 'off' ? ` · ${thinkingLevel}` : '';
return (
<Box paddingX={1} paddingY={0} marginBottom={1}>
<MosaicIcon />
<Box flexDirection="column" flexGrow={1}>
<Text>
<Text bold color="#56a0ff">
Mosaic Stack
</Text>
<Text dimColor> v{version}</Text>
</Text>
<Text dimColor>
{modelDisplay}
{contextStr}
{thinkingStr} · {agentName}
</Text>
<Text>
<Text color={connectionColor}>{connectionIndicator}</Text>
<Text dimColor> {host}</Text>
</Text>
</Box>
</Box>
);
}