feat(tui): add ASCII art banner on startup

This commit is contained in:
William Valentin
2026-02-10 13:11:32 -08:00
parent f204ff1dd7
commit f892bbe6ca
4 changed files with 43 additions and 2 deletions
+32
View File
@@ -0,0 +1,32 @@
// ASCII art banner for Flynn TUI startup
/**
* Flynn ASCII art banner using block characters.
* Raw art lines without any color codes — callers apply their own styling.
*/
export const FLYNN_BANNER = `
███████╗██╗ ██╗ ██╗███╗ ██╗███╗ ██╗
██╔════╝██║ ╚██╗ ██╔╝████╗ ██║████╗ ██║
█████╗ ██║ ╚████╔╝ ██╔██╗ ██║██╔██╗ ██║
██╔══╝ ██║ ╚██╔╝ ██║╚██╗██║██║╚██╗██║
██║ ███████╗ ██║ ██║ ╚████║██║ ╚████║
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝`;
/**
* Returns the banner with ANSI color codes for terminal output.
* Uses orange (208) for the art and dim for the box frame.
*/
export function getColoredBanner(): string {
const orange = '\x1b[38;5;208m';
const reset = '\x1b[0m';
return `${orange}${FLYNN_BANNER}${reset}`;
}
/**
* Returns plain banner lines for use in Ink/React components.
* Each line is returned individually for flexible rendering.
*/
export function getBannerLines(): string[] {
return FLYNN_BANNER.split('\n').filter((line) => line.length > 0);
}
+7 -1
View File
@@ -3,6 +3,7 @@ import { Box, Text, Static } from 'ink';
import type { Message } from '../../../models/types.js';
import { getMessageText } from '../../../models/media.js';
import { renderMarkdown } from '../markdown.js';
import { getBannerLines } from '../banner.js';
export interface MessageListProps {
messages: Message[];
@@ -80,7 +81,12 @@ export const MessageList = memo(function MessageList({
return (
<Box flexDirection="column" flexGrow={1} paddingX={1} overflowY="hidden">
{visibleMessages.length === 0 && !streamingContent ? (
<Text color="gray">No messages yet. Start typing to chat with Flynn.</Text>
<Box flexDirection="column" alignItems="center" justifyContent="center" flexGrow={1}>
{getBannerLines().map((line, i) => (
<Text key={i} color="#ff8c00">{line}</Text>
))}
<Text color="gray">{'\n'}Start typing to chat with Flynn.</Text>
</Box>
) : (
<>
<Static items={visibleMessages}>
+1
View File
@@ -13,5 +13,6 @@ export {
export { renderMarkdown } from './markdown.js';
export { parseCommand as parseCommandUtil, getHelpText, resolveModelAlias } from './commands.js';
export { FLYNN_BANNER, getColoredBanner, getBannerLines } from './banner.js';
export { App, StatusBar, MessageList, InputBar } from './components/index.js';
+3 -1
View File
@@ -10,6 +10,7 @@ import { OllamaClient, LlamaCppClient } from '../../models/index.js';
import { createClientFromConfig } from '../../daemon/index.js';
import { loginGitHub } from '../../auth/index.js';
import type { PairingManager } from '../../channels/pairing.js';
import { getColoredBanner } from './banner.js';
export { parseCommand, type Command };
@@ -125,7 +126,8 @@ export class MinimalTui {
readline.emitKeypressEvents(process.stdin);
}
console.log(`${colors.orange}${colors.bold}Flynn TUI${colors.reset} ${colors.dim}(minimal mode)${colors.reset}`);
console.log(getColoredBanner());
console.log(`\n${colors.orange}${colors.bold}Flynn TUI${colors.reset} ${colors.dim}(minimal mode)${colors.reset}`);
console.log(`${colors.gray}Type /help for commands, /fullscreen for panel mode${colors.reset}\n`);
await this.promptLoop();