Files
stack/packages/cli/src/tui/components/top-bar.tsx
Jason Woltje b0515d34ff fix(cli): preserve two-space gaps in mosaic icon tiles
Extract gap string to const to prevent prettier from collapsing
the double-space literals between icon tiles.
2026-03-15 14:42:00 -05: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}>
<MosaicIcon />
<Box flexDirection="column">
<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>
);
}