mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-03 01:40:59 -07:00
feat(ui): add Tokyo Night theme (#24054)
Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com>
This commit is contained in:
BIN
docs/assets/theme-tokyonight-dark.png
Normal file
BIN
docs/assets/theme-tokyonight-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -19,6 +19,7 @@ using the `/theme` command within Gemini CLI:
|
||||
- `Holiday`
|
||||
- `Shades Of Purple`
|
||||
- `Solarized Dark`
|
||||
- `Tokyo Night`
|
||||
- **Light themes:**
|
||||
- `ANSI Light`
|
||||
- `Ayu Light`
|
||||
@@ -252,6 +253,10 @@ identify their source, for example: `shades-of-green (green-extension)`.
|
||||
|
||||
<img src="/docs/assets/theme-solarized-dark.png" alt="Solarized Dark theme" width="600">
|
||||
|
||||
### Tokyo Night
|
||||
|
||||
<img src="/docs/assets/theme-tokyonight-dark.png" alt="Tokyo Night theme" width="600">
|
||||
|
||||
## Light themes
|
||||
|
||||
### ANSI Light
|
||||
|
||||
@@ -27,6 +27,10 @@ import {
|
||||
} from '../hooks/useConfirmingTool.js';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('ink-spinner', () => ({
|
||||
default: () => <Text>⠋</Text>,
|
||||
}));
|
||||
|
||||
const mockUseSettings = vi.fn().mockReturnValue({
|
||||
merged: {
|
||||
ui: {
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Focuse
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 11 │
|
||||
│ Line 12 │
|
||||
@@ -24,7 +24,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Unfocu
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 11 │
|
||||
│ Line 12 │
|
||||
@@ -43,7 +43,7 @@ AppHeader(full)
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Constrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ ... first 11 lines hidden (Ctrl+O to show) ... │
|
||||
│ Line 12 │
|
||||
@@ -62,7 +62,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Con
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Unconstrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 1 │
|
||||
│ Line 2 │
|
||||
|
||||
@@ -14,9 +14,9 @@ exports[`Initial Theme Selection > should default to a dark theme when terminal
|
||||
│ 7. Holiday Dark │ 6 return a │ │
|
||||
│ 8. Shades Of Purple Dark │ │ │
|
||||
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
|
||||
│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. Ayu Light │ │ │
|
||||
│ 12. Default Light └─────────────────────────────────────────────────┘ │
|
||||
│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. ANSI Light │ │ │
|
||||
│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ │
|
||||
│ (Use Enter to select, Tab to configure scope, Esc to close) │
|
||||
@@ -64,9 +64,9 @@ exports[`Initial Theme Selection > should use the theme from settings even if te
|
||||
│ 7. Holiday Dark │ 6 return a │ │
|
||||
│ 8. Shades Of Purple Dark │ │ │
|
||||
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
|
||||
│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. Ayu Light │ │ │
|
||||
│ 12. Default Light └─────────────────────────────────────────────────┘ │
|
||||
│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. ANSI Light │ │ │
|
||||
│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ │
|
||||
│ (Use Enter to select, Tab to configure scope, Esc to close) │
|
||||
@@ -103,9 +103,9 @@ exports[`ThemeDialog Snapshots > should render correctly in theme selection mode
|
||||
│ 7. Holiday Dark │ 6 return a │ │
|
||||
│ 8. Shades Of Purple Dark │ │ │
|
||||
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
|
||||
│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. Ayu Light │ │ │
|
||||
│ 12. Default Light └─────────────────────────────────────────────────┘ │
|
||||
│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. ANSI Light │ │ │
|
||||
│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ │
|
||||
│ (Use Enter to select, Tab to configure scope, Esc to close) │
|
||||
@@ -128,9 +128,9 @@ exports[`ThemeDialog Snapshots > should render correctly in theme selection mode
|
||||
│ 7. Holiday Dark │ 6 return a │ │
|
||||
│ 8. Shades Of Purple Dark │ │ │
|
||||
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
|
||||
│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. Ayu Light │ │ │
|
||||
│ 12. Default Light └─────────────────────────────────────────────────┘ │
|
||||
│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. ANSI Light │ │ │
|
||||
│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ╭─────────────────────────────────────────────────╮ │
|
||||
│ │ DEVELOPER TOOLS (Not visible to users) │ │
|
||||
|
||||
155
packages/cli/src/ui/themes/builtin/dark/tokyonight-dark.ts
Normal file
155
packages/cli/src/ui/themes/builtin/dark/tokyonight-dark.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { type ColorsTheme, Theme } from '../../theme.js';
|
||||
import { interpolateColor } from '../../color-utils.js';
|
||||
|
||||
const palette = {
|
||||
bg: '#1a1b26',
|
||||
bg_dark: '#16161e',
|
||||
bg_dark1: '#0C0E14',
|
||||
bg_highlight: '#292e42',
|
||||
blue: '#7aa2f7',
|
||||
blue0: '#3d59a1',
|
||||
blue1: '#2ac3de',
|
||||
blue2: '#0db9d7',
|
||||
blue5: '#89ddff',
|
||||
blue6: '#b4f9f8',
|
||||
blue7: '#394b70',
|
||||
comment: '#565f89',
|
||||
cyan: '#7dcfff',
|
||||
fg: '#c0caf5',
|
||||
fg_dark: '#a9b1d6',
|
||||
fg_gutter: '#3b4261',
|
||||
green: '#9ece6a',
|
||||
green1: '#73daca',
|
||||
green2: '#41a6b5',
|
||||
magenta: '#bb9af7',
|
||||
magenta2: '#ff007c',
|
||||
orange: '#ff9e64',
|
||||
purple: '#9d7cd8',
|
||||
red: '#f7768e',
|
||||
red1: '#db4b4b',
|
||||
teal: '#1abc9c',
|
||||
yellow: '#e0af68',
|
||||
diff: {
|
||||
add: '#243e4a',
|
||||
change: '#1f2231',
|
||||
delete: '#4a272f',
|
||||
},
|
||||
};
|
||||
|
||||
const tokyoNightColors: ColorsTheme = {
|
||||
type: 'dark',
|
||||
Background: palette.bg,
|
||||
Foreground: palette.fg,
|
||||
LightBlue: palette.purple,
|
||||
AccentBlue: palette.magenta,
|
||||
AccentPurple: palette.blue,
|
||||
AccentCyan: palette.cyan,
|
||||
AccentGreen: palette.teal,
|
||||
AccentYellow: palette.yellow,
|
||||
AccentRed: palette.red1,
|
||||
DiffAdded: palette.diff.add,
|
||||
DiffRemoved: palette.diff.delete,
|
||||
Comment: palette.comment,
|
||||
Gray: palette.fg_dark,
|
||||
DarkGray: palette.fg_gutter,
|
||||
FocusColor: palette.blue,
|
||||
GradientColors: [palette.blue, palette.magenta, palette.cyan],
|
||||
};
|
||||
|
||||
export const TokyoNight: Theme = new Theme(
|
||||
'Tokyo Night',
|
||||
'dark',
|
||||
{
|
||||
hljs: {
|
||||
display: 'block',
|
||||
overflowX: 'auto',
|
||||
padding: '0.5em',
|
||||
background: palette.bg,
|
||||
color: palette.fg,
|
||||
},
|
||||
'hljs-addition': { background: palette.diff.add },
|
||||
'hljs-attr': { color: palette.green1 },
|
||||
'hljs-attribute': { color: palette.green1 },
|
||||
'hljs-brace': { color: palette.fg_dark },
|
||||
'hljs-built_in': { color: palette.blue1 },
|
||||
'hljs-builtin-symbol': { color: palette.blue1 },
|
||||
'hljs-bullet': {
|
||||
color: palette.orange,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
'hljs-char': { color: palette.green },
|
||||
'hljs-char-escape': { color: palette.magenta },
|
||||
'hljs-character': { color: palette.green },
|
||||
'hljs-class': { color: palette.blue1 },
|
||||
'hljs-class-title': { color: palette.blue1 },
|
||||
'hljs-code': { color: palette.green },
|
||||
'hljs-comment': {
|
||||
color: palette.comment,
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
'hljs-computation-expression': { color: palette.cyan },
|
||||
'hljs-deletion': { background: palette.diff.delete },
|
||||
'hljs-doctag': { color: palette.yellow },
|
||||
'hljs-emphasis': { fontStyle: 'italic' },
|
||||
'hljs-function': { color: palette.blue },
|
||||
'hljs-function-dispatch': { color: palette.blue },
|
||||
'hljs-keyword': {
|
||||
color: palette.magenta,
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
'hljs-label': { color: palette.blue },
|
||||
'hljs-link': { color: palette.teal },
|
||||
'hljs-literal': { color: palette.orange },
|
||||
'hljs-message-name': { color: palette.blue },
|
||||
'hljs-meta': { color: palette.cyan },
|
||||
'hljs-meta-prompt': { color: palette.fg_dark },
|
||||
'hljs-name': { color: palette.magenta },
|
||||
'hljs-named-character': { color: palette.blue1 },
|
||||
'hljs-number': { color: palette.orange },
|
||||
'hljs-operator': { color: palette.blue5 },
|
||||
'hljs-params': { color: palette.yellow },
|
||||
'hljs-property': { color: palette.green1 },
|
||||
'hljs-punctuation': { color: palette.fg_dark },
|
||||
'hljs-quote': {
|
||||
color: palette.comment,
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
'hljs-regex': { color: palette.blue6 },
|
||||
'hljs-regexp': { color: palette.blue6 },
|
||||
'hljs-rest_arg': {
|
||||
color: interpolateColor(palette.yellow, palette.fg, 0.8),
|
||||
},
|
||||
'hljs-section': {
|
||||
color: palette.blue,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
'hljs-selector-attr': { color: palette.cyan },
|
||||
'hljs-selector-class': { color: palette.green1 },
|
||||
'hljs-selector-id': { color: palette.green1 },
|
||||
'hljs-selector-pseudo': { color: palette.cyan },
|
||||
'hljs-selector-tag': { color: palette.magenta },
|
||||
'hljs-string': { color: palette.green },
|
||||
'hljs-strong': { fontWeight: 'bold' },
|
||||
'hljs-subst': { color: palette.blue5 },
|
||||
'hljs-symbol': { color: palette.magenta },
|
||||
'hljs-tag': { color: palette.blue1 },
|
||||
'hljs-template-tag': { color: palette.blue5 },
|
||||
'hljs-template-variable': { color: palette.fg },
|
||||
'hljs-title': { color: palette.blue },
|
||||
'hljs-title-class': { color: palette.blue1 },
|
||||
'hljs-title-class-inherited': { color: palette.blue1 },
|
||||
'hljs-title-function': { color: palette.blue },
|
||||
'hljs-title-function-invoke': { color: palette.blue },
|
||||
'hljs-type': { color: palette.blue1 },
|
||||
'hljs-variable': { color: palette.fg },
|
||||
'hljs-variable-constant': { color: palette.orange },
|
||||
'hljs-variable-language': { color: palette.red },
|
||||
},
|
||||
tokyoNightColors,
|
||||
);
|
||||
@@ -18,6 +18,7 @@ import { ShadesOfPurple } from './builtin/dark/shades-of-purple-dark.js';
|
||||
import { SolarizedDark } from './builtin/dark/solarized-dark.js';
|
||||
import { SolarizedLight } from './builtin/light/solarized-light.js';
|
||||
import { XCode } from './builtin/light/xcode-light.js';
|
||||
import { TokyoNight } from './builtin/dark/tokyonight-dark.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import type { Theme, ThemeType, ColorsTheme, CustomTheme } from './theme.js';
|
||||
@@ -84,6 +85,7 @@ class ThemeManager {
|
||||
SolarizedDark,
|
||||
SolarizedLight,
|
||||
XCode,
|
||||
TokyoNight,
|
||||
ANSI,
|
||||
ANSILight,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user