fix: align new-session styling and improve dark theme startup
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { app, BrowserWindow, dialog, ipcMain } from "electron"
|
||||
import { app, BrowserWindow, dialog, ipcMain, nativeTheme } from "electron"
|
||||
import { join } from "path"
|
||||
import { createApplicationMenu } from "./menu"
|
||||
import { setupInstanceIPC } from "./ipc"
|
||||
@@ -10,11 +10,15 @@ setupStorageIPC()
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
function createWindow() {
|
||||
const prefersDark = nativeTheme.shouldUseDarkColors
|
||||
const backgroundColor = prefersDark ? "#1a1a1a" : "#ffffff"
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1400,
|
||||
height: 900,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
backgroundColor,
|
||||
webPreferences: {
|
||||
preload: join(__dirname, "../preload/index.js"),
|
||||
contextIsolation: true,
|
||||
|
||||
@@ -231,11 +231,8 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
|
||||
<p class="panel-subtitle">Create a fresh conversation with your chosen agent</p>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<Show
|
||||
when={agentList().length > 0}
|
||||
fallback={<div class="text-sm text-muted">Loading agents...</div>}
|
||||
>
|
||||
<div class="space-y-3">
|
||||
<div class="space-y-3">
|
||||
<Show when={agentList().length > 0}>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-secondary mb-1.5">Agent</label>
|
||||
<select
|
||||
@@ -253,40 +250,36 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
|
||||
</For>
|
||||
</select>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="selector-button selector-button-primary w-full flex items-center justify-between gap-2 font-medium"
|
||||
onClick={handleNewSession}
|
||||
disabled={isCreating() || agentList().length === 0}
|
||||
>
|
||||
<Show
|
||||
when={!isCreating()}
|
||||
fallback={
|
||||
<div class="flex items-center gap-2 w-full justify-center text-sm">
|
||||
<svg class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
Creating...
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div class="flex items-center gap-2 flex-1 justify-center text-sm">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
<span>Create Session</span>
|
||||
</div>
|
||||
<kbd class="kbd flex-shrink-0">Cmd+Enter</kbd>
|
||||
</Show>
|
||||
</button>
|
||||
</div>
|
||||
</Show>
|
||||
<button
|
||||
type="button"
|
||||
class="button-primary w-full flex items-center justify-center text-sm disabled:cursor-not-allowed"
|
||||
onClick={handleNewSession}
|
||||
disabled={isCreating() || agentList().length === 0}
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
{isCreating() ? (
|
||||
<svg class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
) : (
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
)}
|
||||
<span>{agentList().length === 0 ? "Loading agents..." : "Create Session"}</span>
|
||||
</div>
|
||||
<kbd class="kbd ml-2">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,11 +129,38 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
|
||||
</Show>
|
||||
|
||||
<button
|
||||
class="selector-button selector-button-primary w-full"
|
||||
class="button-primary w-full flex items-center justify-center text-sm disabled:cursor-not-allowed"
|
||||
onClick={handleNewSession}
|
||||
disabled={isCreating() || agentList().length === 0}
|
||||
>
|
||||
{isCreating() ? "Creating..." : "Start"}
|
||||
<div class="flex items-center gap-2">
|
||||
<Show
|
||||
when={!isCreating()}
|
||||
fallback={
|
||||
<svg class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
</Show>
|
||||
<Show
|
||||
when={!isCreating()}
|
||||
fallback={<span>Creating...</span>}
|
||||
>
|
||||
<span>{agentList().length === 0 ? "Loading agents..." : "Create Session"}</span>
|
||||
</Show>
|
||||
</div>
|
||||
<kbd class="kbd ml-2">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,37 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>OpenCode Client</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
background-color: #ffffff;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html,
|
||||
body {
|
||||
background-color: #1a1a1a;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
;(function () {
|
||||
try {
|
||||
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
if (prefersDark) {
|
||||
document.documentElement.setAttribute('data-theme', 'dark')
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-theme')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to apply initial theme', error)
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -76,6 +76,22 @@
|
||||
@apply cursor-not-allowed opacity-50;
|
||||
}
|
||||
|
||||
/* Ensure Tailwind base reset on [type="button"] doesn't remove accent styles */
|
||||
button.button-primary {
|
||||
background-color: var(--accent-primary);
|
||||
color: var(--text-inverted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] button.button-primary {
|
||||
background-color: #3f3f46;
|
||||
color: #f5f6f8;
|
||||
}
|
||||
|
||||
[data-theme="dark"] button.button-primary:hover:not(:disabled) {
|
||||
background-color: #52525b;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
@apply inline-flex items-center justify-center gap-2 rounded-lg px-6 py-3 text-base font-medium transition-colors;
|
||||
background-color: var(--surface-secondary);
|
||||
@@ -378,12 +394,23 @@
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .tab-active {
|
||||
background-color: #3f3f46;
|
||||
color: #f5f6f8;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .tab-active:hover {
|
||||
background-color: #52525b;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .tab-inactive {
|
||||
background-color: var(--surface-muted);
|
||||
background-color: #2a2a31;
|
||||
color: #d4d4d8;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .tab-inactive:hover {
|
||||
background-color: var(--surface-hover);
|
||||
background-color: #3f3f46;
|
||||
color: #f5f6f8;
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
@@ -410,6 +437,15 @@
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .new-tab-button {
|
||||
background-color: #3f3f46;
|
||||
color: #f5f6f8;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .new-tab-button:hover {
|
||||
background-color: #52525b;
|
||||
}
|
||||
|
||||
.new-tab-button:focus-visible {
|
||||
@apply ring-2 ring-offset-1;
|
||||
ring-color: var(--accent-primary);
|
||||
@@ -1201,12 +1237,16 @@
|
||||
}
|
||||
|
||||
.selector-button {
|
||||
@apply px-3 py-1.5 text-sm rounded transition-colors cursor-pointer;
|
||||
@apply px-3 py-1.5 text-sm rounded transition-colors cursor-pointer w-full inline-flex items-center justify-center font-medium;
|
||||
background-color: var(--surface-secondary);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-base);
|
||||
}
|
||||
|
||||
.selector-button-primary {
|
||||
background-color: var(--accent-primary);
|
||||
color: var(--text-inverted);
|
||||
background-color: var(--accent-primary) !important;
|
||||
color: var(--text-inverted) !important;
|
||||
border: 1px solid var(--accent-primary) !important;
|
||||
}
|
||||
|
||||
.selector-button-primary:hover:not(:disabled) {
|
||||
@@ -1374,7 +1414,7 @@
|
||||
}
|
||||
|
||||
.panel-section-header {
|
||||
@apply w-full px-4 py-3 flex items-center justify-between transition-colors cursor-pointer;
|
||||
@apply w-full px-4 py-3 flex items-center justify-center transition-colors cursor-pointer gap-2;
|
||||
background-color: var(--surface-secondary);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,68 @@
|
||||
--line-height-relaxed: 1.6;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
/* Surface tokens */
|
||||
--surface-base: #1a1a1a;
|
||||
--surface-secondary: #2a2a2a;
|
||||
--surface-muted: #212529;
|
||||
--surface-code: #1a1a1a;
|
||||
--surface-hover: #3a3a3a;
|
||||
|
||||
/* Border tokens */
|
||||
--border-base: #3a3a3a;
|
||||
--border-secondary: #3a3a3a;
|
||||
--border-muted: #3a3a3a;
|
||||
|
||||
/* Text tokens */
|
||||
--text-primary: #e0e0e0;
|
||||
--text-secondary: #999999;
|
||||
--text-muted: #999999;
|
||||
--text-inverted: #1a1a1a;
|
||||
|
||||
/* Accent tokens */
|
||||
--accent-primary: #0080ff;
|
||||
--accent-hover: #0066cc;
|
||||
|
||||
/* Status tokens */
|
||||
--status-success: #4caf50;
|
||||
--status-error: #f44336;
|
||||
--status-warning: #ff9800;
|
||||
|
||||
/* Message-specific tokens */
|
||||
--message-user-bg: #1a2332;
|
||||
--message-user-border: #42a5f5;
|
||||
--message-assistant-bg: #251a2e;
|
||||
--message-assistant-border: #ba68c8;
|
||||
--message-tool-bg: #212529;
|
||||
--message-tool-border: #adb5bd;
|
||||
|
||||
/* Typography tokens (same as light theme) */
|
||||
--font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
--font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
||||
|
||||
/* Font weights */
|
||||
--font-weight-regular: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
||||
/* Font sizes */
|
||||
--font-size-xs: 11px;
|
||||
--font-size-sm: 12px;
|
||||
--font-size-base: 14px;
|
||||
--font-size-lg: 16px;
|
||||
--font-size-xl: 18px;
|
||||
--font-size-2xl: 20px;
|
||||
|
||||
/* Line heights */
|
||||
--line-height-tight: 1.25;
|
||||
--line-height-normal: 1.5;
|
||||
--line-height-relaxed: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/* Surface tokens */
|
||||
--surface-base: #1a1a1a;
|
||||
@@ -116,4 +178,4 @@
|
||||
--line-height-tight: 1.25;
|
||||
--line-height-normal: 1.5;
|
||||
--line-height-relaxed: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user