style: modern dark UI refresh
- design-token palette (:root vars): deeper #0e0f13 base, indigo #7c8cff accent, layered surfaces, softer borders, shadow + radius scale - tabs as floating rounded chips (active = elevated surface); refined dots - key bar as rounded chips with gaps; Esc gets the accent tint - toolbar icon buttons with rounded hover - overlays (history/dashboard/qr/search/settings) get backdrop-blur + card + shadow; indigo primary buttons; consistent inputs with accent focus ring - chrome uses a system UI font (terminal stays monospace) - xterm dark theme + meta theme-color + manifest + app icon synced to the palette (indigo-gradient icon, accent cursor) 216 tests green; tsc + build clean.
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||
<rect width="512" height="512" rx="96" fill="#1a1a1a"/>
|
||||
<g fill="none" stroke="#3fb950" stroke-width="34" stroke-linecap="round" stroke-linejoin="round">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#1a1c26"/>
|
||||
<stop offset="1" stop-color="#0e0f13"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#9d7cff"/>
|
||||
<stop offset="1" stop-color="#7c8cff"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="112" fill="url(#bg)"/>
|
||||
<g fill="none" stroke="url(#fg)" stroke-width="36" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="150,196 226,256 150,316"/>
|
||||
<line x1="268" y1="320" x2="372" y2="320"/>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 721 B |
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<title>Web Terminal</title>
|
||||
<link rel="manifest" href="./manifest.webmanifest">
|
||||
<meta name="theme-color" content="#1a1a1a">
|
||||
<meta name="theme-color" content="#0e0f13">
|
||||
<link rel="apple-touch-icon" href="./icon.svg">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"scope": "./",
|
||||
"display": "standalone",
|
||||
"orientation": "any",
|
||||
"background_color": "#1a1a1a",
|
||||
"theme_color": "#1a1a1a",
|
||||
"background_color": "#0e0f13",
|
||||
"theme_color": "#0e0f13",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./icon.svg",
|
||||
|
||||
@@ -13,14 +13,19 @@ export interface Settings {
|
||||
}
|
||||
|
||||
export const THEMES: Record<string, ITheme> = {
|
||||
dark: { background: '#1a1a1a', foreground: '#e8e8e8', cursor: '#e8e8e8' },
|
||||
light: {
|
||||
background: '#f5f5f5',
|
||||
foreground: '#1a1a1a',
|
||||
cursor: '#1a1a1a',
|
||||
selectionBackground: '#bcd3f5',
|
||||
dark: {
|
||||
background: '#0e0f13',
|
||||
foreground: '#e7e8ec',
|
||||
cursor: '#7c8cff',
|
||||
selectionBackground: 'rgba(124,140,255,0.28)',
|
||||
},
|
||||
solarized: { background: '#002b36', foreground: '#93a1a1', cursor: '#93a1a1' },
|
||||
light: {
|
||||
background: '#f6f7f9',
|
||||
foreground: '#1a1d24',
|
||||
cursor: '#5b6cff',
|
||||
selectionBackground: '#cdd6ff',
|
||||
},
|
||||
solarized: { background: '#002b36', foreground: '#93a1a1', cursor: '#268bd2' },
|
||||
}
|
||||
|
||||
const KEY = 'web-terminal:settings'
|
||||
|
||||
778
public/style.css
778
public/style.css
@@ -1,113 +1,357 @@
|
||||
/* Web Terminal Styling */
|
||||
/* Web Terminal — modern dark UI */
|
||||
|
||||
:root {
|
||||
/* Key bar is shown on ALL devices (clickable shortcut buttons). Touch
|
||||
devices get a taller bar with bigger tap targets. */
|
||||
--tabbar-h: 36px;
|
||||
--keybar-h: 42px;
|
||||
/* palette (design tokens) */
|
||||
--bg: #0e0f13; /* terminal / deepest surface */
|
||||
--surface-1: #15161c; /* tab bar, key bar */
|
||||
--surface-2: #1c1e26; /* tabs, buttons, cards */
|
||||
--surface-3: #252834; /* hover / active */
|
||||
--border: rgba(255, 255, 255, 0.07);
|
||||
--border-strong: rgba(255, 255, 255, 0.13);
|
||||
--text: #e7e8ec;
|
||||
--text-dim: #9aa0ad;
|
||||
--text-faint: #6b7080;
|
||||
--accent: #7c8cff; /* indigo */
|
||||
--accent-2: #9d7cff;
|
||||
--accent-soft: rgba(124, 140, 255, 0.16);
|
||||
--green: #46d07f;
|
||||
--amber: #f5b14c;
|
||||
--red: #ff6b6b;
|
||||
--shadow: 0 10px 40px rgba(0, 0, 0, 0.55);
|
||||
--radius: 9px;
|
||||
--radius-lg: 14px;
|
||||
|
||||
--tabbar-h: 40px;
|
||||
--keybar-h: 46px;
|
||||
|
||||
--ui-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Touch devices: bigger tap targets for tabs and the key bar. */
|
||||
@media (pointer: coarse) {
|
||||
:root {
|
||||
--tabbar-h: 44px;
|
||||
--keybar-h: 58px;
|
||||
--tabbar-h: 48px;
|
||||
--keybar-h: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #1a1a1a;
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: var(--ui-font);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── Tab bar (top) ───────────────────────────────────────────────── */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--surface-3) transparent;
|
||||
}
|
||||
|
||||
/* ── Tab bar ─────────────────────────────────────────────────────── */
|
||||
#tabbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
inset: 0 0 auto 0;
|
||||
height: var(--tabbar-h);
|
||||
background-color: #222;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
background: linear-gradient(180deg, #181a22, var(--surface-1));
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* tabs: scrollable; toolbar: fixed cluster on the right */
|
||||
#tabs {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 0 4px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
#tabs::-webkit-scrollbar {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* tabs as floating rounded chips */
|
||||
.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
height: calc(var(--tabbar-h) - 12px);
|
||||
padding: 0 4px 0 10px;
|
||||
border-radius: 8px;
|
||||
color: var(--text-dim);
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
max-width: 220px;
|
||||
transition:
|
||||
background 0.12s ease,
|
||||
color 0.12s ease;
|
||||
}
|
||||
.tab:hover {
|
||||
background: var(--surface-2);
|
||||
color: var(--text);
|
||||
}
|
||||
.tab.active {
|
||||
background: var(--surface-3);
|
||||
color: #fff;
|
||||
box-shadow: inset 0 0 0 1px var(--border-strong);
|
||||
}
|
||||
|
||||
.tab-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
flex: none;
|
||||
background: var(--text-faint);
|
||||
}
|
||||
.dot-connected {
|
||||
background: var(--green);
|
||||
box-shadow: 0 0 6px rgba(70, 208, 127, 0.5);
|
||||
}
|
||||
.dot-connecting,
|
||||
.dot-reconnecting {
|
||||
background: var(--amber);
|
||||
}
|
||||
.dot-exited {
|
||||
background: var(--red);
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
padding-right: 4px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tab-rename {
|
||||
width: 120px;
|
||||
margin: 0 4px;
|
||||
padding: 3px 6px;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--accent);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* unread / Claude-waiting accents */
|
||||
.tab.unread .tab-dot {
|
||||
box-shadow: 0 0 0 3px var(--accent-soft);
|
||||
}
|
||||
.tab.unread .tab-label {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
.tab-claude {
|
||||
margin-right: 4px;
|
||||
font-size: 12px;
|
||||
flex: none;
|
||||
}
|
||||
.tab.claude-waiting {
|
||||
background: rgba(245, 177, 76, 0.14);
|
||||
box-shadow: inset 0 0 0 1px rgba(245, 177, 76, 0.5);
|
||||
}
|
||||
|
||||
.tab.dragging {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.tab.drag-over {
|
||||
box-shadow: inset 3px 0 0 var(--accent);
|
||||
}
|
||||
|
||||
.tab-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-faint);
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
padding: 3px 6px;
|
||||
border-radius: 6px;
|
||||
flex: none;
|
||||
}
|
||||
.tab-close:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
}
|
||||
@media (pointer: fine) {
|
||||
.tab:not(.active):not(:hover) .tab-close {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-add {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
padding: 0 10px;
|
||||
flex: none;
|
||||
border-radius: 7px;
|
||||
}
|
||||
.tab-add:hover {
|
||||
color: #fff;
|
||||
background: var(--surface-2);
|
||||
}
|
||||
|
||||
/* toolbar */
|
||||
#toolbar {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-left: 1px solid #3a3a3a;
|
||||
gap: 2px;
|
||||
padding: 0 6px;
|
||||
border-left: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.toolbtn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #aaa;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
padding: 0 12px;
|
||||
height: 100%;
|
||||
padding: 7px 9px;
|
||||
border-radius: 8px;
|
||||
line-height: 1;
|
||||
transition: background 0.12s ease;
|
||||
}
|
||||
.toolbtn:hover {
|
||||
color: #fff;
|
||||
background-color: #2a2a2a;
|
||||
background: var(--surface-2);
|
||||
}
|
||||
|
||||
/* ── Terminal area ───────────────────────────────────────────────── */
|
||||
#term {
|
||||
position: absolute;
|
||||
inset: var(--tabbar-h) 0 var(--keybar-h) 0;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
}
|
||||
.term-pane {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 6px 8px 0;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── Key bar (rounded chips) ─────────────────────────────────────── */
|
||||
#keybar {
|
||||
position: fixed;
|
||||
inset: auto 0 0 0;
|
||||
height: var(--keybar-h);
|
||||
background: var(--surface-1);
|
||||
border-top: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 0 6px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
z-index: 1000;
|
||||
}
|
||||
#keybar::-webkit-scrollbar {
|
||||
height: 0;
|
||||
}
|
||||
#keybar button {
|
||||
flex: 1 0 auto;
|
||||
min-width: 46px;
|
||||
height: calc(var(--keybar-h) - 14px);
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface-2);
|
||||
color: var(--text);
|
||||
font-family: var(--ui-font);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
transition:
|
||||
background 0.1s ease,
|
||||
transform 0.05s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
#keybar button:hover {
|
||||
background: var(--surface-3);
|
||||
}
|
||||
#keybar button:active {
|
||||
transform: translateY(1px);
|
||||
background: var(--surface-3);
|
||||
}
|
||||
#keybar button.keybar-btn-primary {
|
||||
background: var(--accent-soft);
|
||||
color: #cdd4ff;
|
||||
border-color: rgba(124, 140, 255, 0.4);
|
||||
font-weight: 600;
|
||||
min-width: 54px;
|
||||
}
|
||||
#keybar button.keybar-btn-primary:hover {
|
||||
background: rgba(124, 140, 255, 0.26);
|
||||
}
|
||||
|
||||
/* ── Shared: overlays, cards, inputs, buttons ────────────────────── */
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1200;
|
||||
display: flex;
|
||||
background: rgba(8, 9, 12, 0.6);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
/* Search box overlay (M1) */
|
||||
#searchbox {
|
||||
position: fixed;
|
||||
top: calc(var(--tabbar-h) + 6px);
|
||||
right: 8px;
|
||||
top: calc(var(--tabbar-h) + 8px);
|
||||
right: 10px;
|
||||
z-index: 1100;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 6px;
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
gap: 5px;
|
||||
padding: 7px;
|
||||
background: var(--surface-2);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 10px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.search-input {
|
||||
width: 180px;
|
||||
padding: 4px 6px;
|
||||
width: 190px;
|
||||
padding: 5px 8px;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
background: #111;
|
||||
border: 1px solid #444;
|
||||
border-radius: 3px;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 7px;
|
||||
outline: none;
|
||||
}
|
||||
.search-input:focus {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
#searchbox button {
|
||||
background: #333;
|
||||
border: 1px solid #444;
|
||||
color: #ddd;
|
||||
background: var(--surface-3);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
padding: 0 8px;
|
||||
border-radius: 7px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
#searchbox button:hover {
|
||||
background: #555;
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
/* QR connect modal (M5) */
|
||||
/* QR modal */
|
||||
#qrmodal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -115,145 +359,106 @@ html, body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
background: rgba(8, 9, 12, 0.6);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
.qr-card {
|
||||
background: #fff;
|
||||
color: #111;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
background: var(--surface-2);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 22px;
|
||||
text-align: center;
|
||||
max-width: 90vw;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.qr-card canvas {
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
padding: 8px;
|
||||
}
|
||||
.qr-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.qr-url {
|
||||
margin-top: 10px;
|
||||
margin-top: 12px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
color: var(--accent);
|
||||
word-break: break-all;
|
||||
}
|
||||
.qr-note {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
color: var(--text-dim);
|
||||
max-width: 240px;
|
||||
}
|
||||
.qr-close {
|
||||
margin-top: 14px;
|
||||
padding: 6px 18px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: #1a1a1a;
|
||||
margin-top: 16px;
|
||||
padding: 8px 20px;
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 8px;
|
||||
background: var(--surface-3);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
}
|
||||
.qr-close:hover {
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
/* Settings panel (M3) */
|
||||
/* Settings panel */
|
||||
#settingspanel {
|
||||
position: fixed;
|
||||
top: calc(var(--tabbar-h) + 6px);
|
||||
right: 8px;
|
||||
top: calc(var(--tabbar-h) + 8px);
|
||||
right: 10px;
|
||||
z-index: 1100;
|
||||
background: #2a2a2a;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
min-width: 210px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
color: #ddd;
|
||||
background: var(--surface-2);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
min-width: 220px;
|
||||
box-shadow: var(--shadow);
|
||||
color: var(--text);
|
||||
}
|
||||
.settings-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin: 6px 0;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.settings-label {
|
||||
width: 48px;
|
||||
color: #aaa;
|
||||
color: var(--text-dim);
|
||||
font-size: 13px;
|
||||
}
|
||||
.settings-opt {
|
||||
background: #333;
|
||||
border: 1px solid #444;
|
||||
color: #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 4px 9px;
|
||||
background: var(--surface-3);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
border-radius: 7px;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
transition: background 0.1s ease;
|
||||
}
|
||||
.settings-opt:hover {
|
||||
background: var(--surface-1);
|
||||
}
|
||||
.settings-opt.active {
|
||||
background: #4a9eff;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: #4a9eff;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.settings-size {
|
||||
min-width: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Dashboard (M7) */
|
||||
#dashboard {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1200;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 56px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.dash-card {
|
||||
background: #222;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 10px;
|
||||
min-width: 320px;
|
||||
max-width: 90vw;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.dash-title {
|
||||
padding: 12px 16px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
.dash-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 16px;
|
||||
cursor: pointer;
|
||||
color: #ddd;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
}
|
||||
.dash-row:hover {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
.dash-row.active {
|
||||
background: #1a1a1a;
|
||||
box-shadow: inset 3px 0 0 #4a9eff;
|
||||
}
|
||||
.dash-name {
|
||||
flex: 1;
|
||||
}
|
||||
.dash-claude {
|
||||
color: #aaa;
|
||||
font-size: 13px;
|
||||
}
|
||||
.dash-claude.pending {
|
||||
color: #ffcf8f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* History / resume modal (O2) */
|
||||
/* Dashboard + history share the centered-card look */
|
||||
#dashboard,
|
||||
#historymodal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -261,35 +466,65 @@ html, body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 56px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
padding-top: 60px;
|
||||
background: rgba(8, 9, 12, 0.6);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
.dash-card,
|
||||
.hist-card {
|
||||
background: #222;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 10px;
|
||||
min-width: 360px;
|
||||
background: var(--surface-2);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius-lg);
|
||||
min-width: 340px;
|
||||
max-width: 92vw;
|
||||
max-height: 72vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.dash-title,
|
||||
.hist-title {
|
||||
padding: 12px 16px;
|
||||
padding: 14px 18px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
.hist-empty {
|
||||
padding: 16px;
|
||||
color: #aaa;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.dash-row,
|
||||
.hist-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
padding: 11px 18px;
|
||||
cursor: pointer;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
transition: background 0.1s ease;
|
||||
}
|
||||
.dash-row:hover,
|
||||
.hist-row:hover {
|
||||
background: var(--surface-3);
|
||||
}
|
||||
.dash-row.active {
|
||||
box-shadow: inset 3px 0 0 var(--accent);
|
||||
}
|
||||
.dash-name {
|
||||
flex: 1;
|
||||
}
|
||||
.dash-claude {
|
||||
color: var(--text-dim);
|
||||
font-size: 13px;
|
||||
}
|
||||
.dash-claude.pending {
|
||||
color: var(--amber);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hist-empty {
|
||||
padding: 18px;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.hist-row {
|
||||
cursor: default;
|
||||
}
|
||||
.hist-main {
|
||||
flex: 1 1 auto;
|
||||
@@ -300,7 +535,7 @@ html, body {
|
||||
font-size: 13px;
|
||||
}
|
||||
.hist-prev {
|
||||
color: #aaa;
|
||||
color: var(--text-dim);
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -308,93 +543,32 @@ html, body {
|
||||
}
|
||||
.hist-resume {
|
||||
flex: none;
|
||||
background: #2ea043;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 6px 14px;
|
||||
border-radius: 8px;
|
||||
padding: 7px 15px;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
font-weight: 500;
|
||||
transition: background 0.1s ease;
|
||||
}
|
||||
.hist-resume:hover {
|
||||
background: #3fb950;
|
||||
background: var(--accent-2);
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px 0 12px;
|
||||
color: #aaa;
|
||||
background-color: #2a2a2a;
|
||||
border-right: 1px solid #1a1a1a;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
background-color: #1a1a1a;
|
||||
color: #fff;
|
||||
box-shadow: inset 0 -2px 0 #4a9eff; /* active underline accent */
|
||||
}
|
||||
|
||||
/* Status dot — color reflects connection state. */
|
||||
.tab-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
flex: none;
|
||||
background-color: #666;
|
||||
}
|
||||
.dot-connected {
|
||||
background-color: #3fb950; /* green */
|
||||
}
|
||||
.dot-connecting,
|
||||
.dot-reconnecting {
|
||||
background-color: #d29922; /* amber */
|
||||
}
|
||||
.dot-exited {
|
||||
background-color: #f85149; /* red */
|
||||
}
|
||||
|
||||
/* Unread: an inactive tab got new output — blue ring + brighter label. */
|
||||
.tab.unread .tab-dot {
|
||||
box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.6);
|
||||
}
|
||||
.tab.unread .tab-label {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Claude Code activity glyph (H2/H4) */
|
||||
.tab-claude {
|
||||
margin-right: 6px;
|
||||
font-size: 12px;
|
||||
flex: none;
|
||||
}
|
||||
/* A background tab that needs approval gets an amber outline. */
|
||||
.tab.claude-waiting {
|
||||
background-color: #3a2a10;
|
||||
box-shadow: inset 0 -2px 0 #d29922;
|
||||
}
|
||||
|
||||
/* Approve/reject banner (H3) — sits just above the key bar. */
|
||||
/* Approval banner (H3) */
|
||||
#approvalbar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: var(--keybar-h);
|
||||
inset: auto 0 var(--keybar-h) 0;
|
||||
z-index: 1050;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 12px;
|
||||
background: #3a2a10;
|
||||
border-top: 1px solid #d29922;
|
||||
color: #ffcf8f;
|
||||
padding: 10px 14px;
|
||||
background: linear-gradient(180deg, rgba(245, 177, 76, 0.16), rgba(245, 177, 76, 0.08));
|
||||
border-top: 1px solid rgba(245, 177, 76, 0.5);
|
||||
color: #ffe0ad;
|
||||
font-size: 14px;
|
||||
}
|
||||
.approval-label {
|
||||
@@ -403,157 +577,17 @@ html, body {
|
||||
#approvalbar button {
|
||||
flex: none;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 7px 16px;
|
||||
border-radius: 8px;
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
}
|
||||
.approval-yes {
|
||||
background: #2ea043;
|
||||
color: #fff;
|
||||
background: var(--green);
|
||||
color: #06210f;
|
||||
}
|
||||
.approval-no {
|
||||
background: #c93c37;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Drag-to-reorder feedback. */
|
||||
.tab.dragging {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.tab.drag-over {
|
||||
box-shadow: inset 3px 0 0 #4a9eff; /* drop-position indicator */
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
padding-right: 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Inline rename input (double-click a tab) */
|
||||
.tab-rename {
|
||||
width: 110px;
|
||||
margin: 0 4px;
|
||||
padding: 2px 4px;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
background: #111;
|
||||
border: 1px solid #4a9eff;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.tab-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
line-height: 1;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tab-close:hover {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Desktop (mouse): reveal × on hover/active to reduce clutter.
|
||||
Touch devices keep × always visible (no hover). */
|
||||
@media (pointer: fine) {
|
||||
.tab:not(.active):not(:hover) .tab-close {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-add {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #aaa;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
padding: 0 14px;
|
||||
user-select: none;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tab-add:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ── Terminal area (holds one .term-pane per tab) ────────────────── */
|
||||
#term {
|
||||
position: absolute;
|
||||
top: var(--tabbar-h);
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: var(--keybar-h);
|
||||
background-color: #1a1a1a;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.term-pane {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── Shortcut key bar (bottom) — shown on ALL devices ────────────── */
|
||||
#keybar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: var(--keybar-h);
|
||||
background-color: #2a2a2a;
|
||||
border-top: 1px solid #3a3a3a;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
z-index: 1000;
|
||||
gap: 0;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
#keybar button {
|
||||
flex: 1 0 auto;
|
||||
min-width: 48px;
|
||||
height: var(--keybar-h);
|
||||
padding: 0 8px;
|
||||
border: 1px solid #444;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
background-color: #333;
|
||||
color: #ddd;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
border-radius: 0;
|
||||
transition: background-color 0.12s;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
#keybar button:active {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
/* Esc is the most-used (interrupt) — make it prominent. */
|
||||
#keybar button.keybar-btn-primary {
|
||||
background-color: #5a3a12;
|
||||
color: #ffcf8f;
|
||||
font-weight: 600;
|
||||
min-width: 56px;
|
||||
}
|
||||
|
||||
#keybar button.keybar-btn-primary:active {
|
||||
background-color: #7a4f18;
|
||||
background: var(--red);
|
||||
color: #2a0808;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export class TerminalSession {
|
||||
this.term = new Terminal({
|
||||
scrollback: 5000,
|
||||
fontFamily: 'Menlo, Consolas, monospace',
|
||||
theme: { background: '#1a1a1a', foreground: '#e8e8e8', cursor: '#e8e8e8' },
|
||||
theme: { background: '#0e0f13', foreground: '#e7e8ec', cursor: '#7c8cff' },
|
||||
})
|
||||
this.fitAddon = new FitAddon()
|
||||
this.term.loadAddon(this.fitAddon)
|
||||
|
||||
Reference in New Issue
Block a user