wraith/frontend/composables/useTerminalThemes.ts
Vantz Stockwell 3b14a7c1d1 feat: Termius-inspired UI — right sidebar, host counts, terminal themes
Left sidebar:
- Groups now show recursive host count badges
- Hosts in tree show up to 3 tags inline

Right sidebar (Host Details panel):
- Click any host card to open details panel on the right
- Shows address, port, protocol, group, credential, tags, color, notes
- Connect, Edit, Delete action buttons at bottom
- Selected card gets ring highlight

Terminal themes (10 prebuilt):
- Wraith (default), Dracula, Nord, Solarized Dark, Monokai, One Dark,
  Gruvbox Dark, Tokyo Night, Catppuccin Mocha, Cyberpunk
- Visual theme picker in Settings with color preview + sample text
- Persisted to /api/settings and localStorage for immediate use
- useTerminal reads theme on terminal creation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:19:57 -04:00

286 lines
6.7 KiB
TypeScript

import type { ITheme } from '@xterm/xterm'
export interface TerminalTheme {
name: string
id: string
theme: ITheme
}
export const terminalThemes: TerminalTheme[] = [
{
name: 'Wraith',
id: 'wraith',
theme: {
background: '#0a0a0f',
foreground: '#e4e4ef',
cursor: '#5c7cfa',
cursorAccent: '#0a0a0f',
selectionBackground: '#364fc744',
black: '#1a1a2e',
red: '#e94560',
green: '#0cce6b',
yellow: '#ffc145',
blue: '#5c7cfa',
magenta: '#c77dff',
cyan: '#56d4e0',
white: '#e4e4ef',
brightBlack: '#3a3a4e',
brightRed: '#ff6b81',
brightGreen: '#2ee89a',
brightYellow: '#ffd366',
brightBlue: '#7c9cfa',
brightMagenta: '#d9a0ff',
brightCyan: '#7aecf5',
brightWhite: '#ffffff',
},
},
{
name: 'Dracula',
id: 'dracula',
theme: {
background: '#282a36',
foreground: '#f8f8f2',
cursor: '#f8f8f2',
cursorAccent: '#282a36',
selectionBackground: '#44475a',
black: '#21222c',
red: '#ff5555',
green: '#50fa7b',
yellow: '#f1fa8c',
blue: '#bd93f9',
magenta: '#ff79c6',
cyan: '#8be9fd',
white: '#f8f8f2',
brightBlack: '#6272a4',
brightRed: '#ff6e6e',
brightGreen: '#69ff94',
brightYellow: '#ffffa5',
brightBlue: '#d6acff',
brightMagenta: '#ff92df',
brightCyan: '#a4ffff',
brightWhite: '#ffffff',
},
},
{
name: 'Nord',
id: 'nord',
theme: {
background: '#2e3440',
foreground: '#d8dee9',
cursor: '#d8dee9',
cursorAccent: '#2e3440',
selectionBackground: '#434c5e',
black: '#3b4252',
red: '#bf616a',
green: '#a3be8c',
yellow: '#ebcb8b',
blue: '#81a1c1',
magenta: '#b48ead',
cyan: '#88c0d0',
white: '#e5e9f0',
brightBlack: '#4c566a',
brightRed: '#bf616a',
brightGreen: '#a3be8c',
brightYellow: '#ebcb8b',
brightBlue: '#81a1c1',
brightMagenta: '#b48ead',
brightCyan: '#8fbcbb',
brightWhite: '#eceff4',
},
},
{
name: 'Solarized Dark',
id: 'solarized-dark',
theme: {
background: '#002b36',
foreground: '#839496',
cursor: '#839496',
cursorAccent: '#002b36',
selectionBackground: '#073642',
black: '#073642',
red: '#dc322f',
green: '#859900',
yellow: '#b58900',
blue: '#268bd2',
magenta: '#d33682',
cyan: '#2aa198',
white: '#eee8d5',
brightBlack: '#586e75',
brightRed: '#cb4b16',
brightGreen: '#586e75',
brightYellow: '#657b83',
brightBlue: '#839496',
brightMagenta: '#6c71c4',
brightCyan: '#93a1a1',
brightWhite: '#fdf6e3',
},
},
{
name: 'Monokai',
id: 'monokai',
theme: {
background: '#272822',
foreground: '#f8f8f2',
cursor: '#f8f8f0',
cursorAccent: '#272822',
selectionBackground: '#49483e',
black: '#272822',
red: '#f92672',
green: '#a6e22e',
yellow: '#f4bf75',
blue: '#66d9ef',
magenta: '#ae81ff',
cyan: '#a1efe4',
white: '#f8f8f2',
brightBlack: '#75715e',
brightRed: '#f92672',
brightGreen: '#a6e22e',
brightYellow: '#f4bf75',
brightBlue: '#66d9ef',
brightMagenta: '#ae81ff',
brightCyan: '#a1efe4',
brightWhite: '#f9f8f5',
},
},
{
name: 'One Dark',
id: 'one-dark',
theme: {
background: '#282c34',
foreground: '#abb2bf',
cursor: '#528bff',
cursorAccent: '#282c34',
selectionBackground: '#3e4451',
black: '#282c34',
red: '#e06c75',
green: '#98c379',
yellow: '#e5c07b',
blue: '#61afef',
magenta: '#c678dd',
cyan: '#56b6c2',
white: '#abb2bf',
brightBlack: '#5c6370',
brightRed: '#e06c75',
brightGreen: '#98c379',
brightYellow: '#e5c07b',
brightBlue: '#61afef',
brightMagenta: '#c678dd',
brightCyan: '#56b6c2',
brightWhite: '#ffffff',
},
},
{
name: 'Gruvbox Dark',
id: 'gruvbox-dark',
theme: {
background: '#282828',
foreground: '#ebdbb2',
cursor: '#ebdbb2',
cursorAccent: '#282828',
selectionBackground: '#3c3836',
black: '#282828',
red: '#cc241d',
green: '#98971a',
yellow: '#d79921',
blue: '#458588',
magenta: '#b16286',
cyan: '#689d6a',
white: '#a89984',
brightBlack: '#928374',
brightRed: '#fb4934',
brightGreen: '#b8bb26',
brightYellow: '#fabd2f',
brightBlue: '#83a598',
brightMagenta: '#d3869b',
brightCyan: '#8ec07c',
brightWhite: '#ebdbb2',
},
},
{
name: 'Tokyo Night',
id: 'tokyo-night',
theme: {
background: '#1a1b26',
foreground: '#a9b1d6',
cursor: '#c0caf5',
cursorAccent: '#1a1b26',
selectionBackground: '#33467c',
black: '#15161e',
red: '#f7768e',
green: '#9ece6a',
yellow: '#e0af68',
blue: '#7aa2f7',
magenta: '#bb9af7',
cyan: '#7dcfff',
white: '#a9b1d6',
brightBlack: '#414868',
brightRed: '#f7768e',
brightGreen: '#9ece6a',
brightYellow: '#e0af68',
brightBlue: '#7aa2f7',
brightMagenta: '#bb9af7',
brightCyan: '#7dcfff',
brightWhite: '#c0caf5',
},
},
{
name: 'Catppuccin Mocha',
id: 'catppuccin-mocha',
theme: {
background: '#1e1e2e',
foreground: '#cdd6f4',
cursor: '#f5e0dc',
cursorAccent: '#1e1e2e',
selectionBackground: '#45475a',
black: '#45475a',
red: '#f38ba8',
green: '#a6e3a1',
yellow: '#f9e2af',
blue: '#89b4fa',
magenta: '#f5c2e7',
cyan: '#94e2d5',
white: '#bac2de',
brightBlack: '#585b70',
brightRed: '#f38ba8',
brightGreen: '#a6e3a1',
brightYellow: '#f9e2af',
brightBlue: '#89b4fa',
brightMagenta: '#f5c2e7',
brightCyan: '#94e2d5',
brightWhite: '#a6adc8',
},
},
{
name: 'Cyberpunk',
id: 'cyberpunk',
theme: {
background: '#0d0221',
foreground: '#0abdc6',
cursor: '#ff2079',
cursorAccent: '#0d0221',
selectionBackground: '#541388',
black: '#0d0221',
red: '#ff2079',
green: '#0abdc6',
yellow: '#f3e600',
blue: '#711c91',
magenta: '#ea00d9',
cyan: '#0abdc6',
white: '#d7d7d7',
brightBlack: '#541388',
brightRed: '#ff4492',
brightGreen: '#33e1ed',
brightYellow: '#f5ed37',
brightBlue: '#9945b5',
brightMagenta: '#ff00ff',
brightCyan: '#33e1ed',
brightWhite: '#ffffff',
},
},
]
export function getTerminalTheme(id: string): ITheme {
const found = terminalThemes.find(t => t.id === id)
return found?.theme || terminalThemes[0].theme
}