Expand dark theme coverage across client UI

This commit is contained in:
Shantur Rathore
2025-10-28 18:19:17 +00:00
parent 8858fe052b
commit 1ce5b125a9
12 changed files with 197 additions and 107 deletions

View File

@@ -64,17 +64,19 @@ export default function AgentSelector(props: AgentSelectorProps) {
itemComponent={(itemProps) => (
<Select.Item
item={itemProps.item}
class="px-3 py-2 cursor-pointer hover:bg-gray-100 rounded outline-none focus:bg-gray-100"
class="px-3 py-2 cursor-pointer rounded outline-none transition-colors hover:bg-gray-100 focus:bg-gray-100 dark:hover:bg-gray-800 dark:focus:bg-gray-800"
>
<div class="flex flex-col">
<Select.ItemLabel class="font-medium text-sm text-gray-900 flex items-center gap-2">
<Select.ItemLabel class="font-medium text-sm text-gray-900 dark:text-gray-100 flex items-center gap-2">
<span>{itemProps.item.rawValue.name}</span>
<Show when={itemProps.item.rawValue.mode === "subagent"}>
<span class="text-xs font-normal text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded">subagent</span>
<span class="text-xs font-normal text-blue-600 dark:text-blue-300 bg-blue-50 dark:bg-blue-900/40 px-1.5 py-0.5 rounded">
subagent
</span>
</Show>
</Select.ItemLabel>
<Show when={itemProps.item.rawValue.description}>
<Select.ItemDescription class="text-xs text-gray-600">
<Select.ItemDescription class="text-xs text-gray-600 dark:text-gray-300">
{itemProps.item.rawValue.description.length > 50
? itemProps.item.rawValue.description.slice(0, 50) + "..."
: itemProps.item.rawValue.description}
@@ -86,23 +88,25 @@ export default function AgentSelector(props: AgentSelectorProps) {
>
<Select.Trigger
data-agent-selector
class="inline-flex items-center justify-between gap-2 px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50 outline-none focus:ring-2 focus:ring-blue-500 text-xs min-w-[100px]"
class="inline-flex items-center justify-between gap-2 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 outline-none focus:ring-2 focus:ring-blue-500 text-xs min-w-[100px] transition-colors"
>
<Select.Value<Agent>>
{(state) => <span class="text-gray-700">Agent: {state.selectedOption()?.name ?? "None"}</span>}
{(state) => (
<span class="text-gray-700 dark:text-gray-200">Agent: {state.selectedOption()?.name ?? "None"}</span>
)}
</Select.Value>
<Select.Icon>
<ChevronDown class="w-3 h-3 text-gray-500" />
<ChevronDown class="w-3 h-3 text-gray-500 dark:text-gray-300" />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content class="bg-white border border-gray-300 rounded-md shadow-lg max-h-80 overflow-auto p-1 z-50">
<Select.Listbox />
<Select.Content class="bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md shadow-lg max-h-80 overflow-auto p-1 z-50">
<Select.Listbox class="bg-white dark:bg-gray-800" />
</Select.Content>
</Select.Portal>
</Select>
<span class="text-xs text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500">
<Kbd shortcut="cmd+shift+a" />
</span>
</div>

View File

@@ -30,7 +30,9 @@ const InstanceTab: Component<InstanceTabProps> = (props) => {
<div class="instance-tab-container group">
<button
class={`instance-tab inline-flex items-center gap-2 px-3 py-2 rounded-t-md max-w-[200px] transition-colors ${
props.active ? "bg-blue-500 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"
props.active
? "bg-blue-500 text-white"
: "bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700"
}`}
onClick={props.onSelect}
title={props.instance.folder}
@@ -42,7 +44,7 @@ const InstanceTab: Component<InstanceTabProps> = (props) => {
{props.instance.folder.split("/").pop() || props.instance.folder}
</span>
<span
class="tab-close opacity-0 group-hover:opacity-100 hover:bg-red-500 hover:text-white rounded p-0.5 transition-opacity ml-auto cursor-pointer"
class="tab-close opacity-0 group-hover:opacity-100 hover:bg-red-500 dark:hover:bg-red-600 hover:text-white rounded p-0.5 transition-opacity ml-auto cursor-pointer"
onClick={(e) => {
e.stopPropagation()
props.onClose()

View File

@@ -15,7 +15,7 @@ interface InstanceTabsProps {
const InstanceTabs: Component<InstanceTabsProps> = (props) => {
return (
<div class="instance-tabs bg-gray-50 border-b border-gray-200">
<div class="instance-tabs bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
<div class="tabs-container flex items-center justify-between gap-1 px-2 py-1 overflow-x-auto" role="tablist">
<div class="flex items-center gap-1 overflow-x-auto">
<For each={Array.from(props.instances.entries())}>
@@ -29,7 +29,7 @@ const InstanceTabs: Component<InstanceTabsProps> = (props) => {
)}
</For>
<button
class="new-tab-button inline-flex items-center justify-center w-8 h-8 rounded-md text-gray-600 hover:bg-gray-200 transition-colors"
class="new-tab-button inline-flex items-center justify-center w-8 h-8 rounded-md text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"
onClick={props.onNew}
title="New instance (Cmd/Ctrl+N)"
aria-label="New instance"

View File

@@ -146,14 +146,14 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
}
return (
<div class="flex-1 flex flex-col overflow-hidden bg-gray-50">
<div class="flex-1 flex flex-col overflow-hidden bg-gray-50 dark:bg-gray-950">
<div class="flex-1 flex flex-col lg:flex-row gap-4 p-4 overflow-auto">
<div class="flex-1 flex flex-col gap-4 min-h-0">
<Show
when={parentSessions().length > 0}
fallback={
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 text-center flex-shrink-0">
<div class="text-gray-400 mb-2">
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6 text-center flex-shrink-0">
<div class="text-gray-400 dark:text-gray-500 mb-2">
<svg class="w-12 h-12 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
@@ -163,15 +163,15 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
/>
</svg>
</div>
<p class="text-gray-600 font-medium text-sm">No Previous Sessions</p>
<p class="text-xs text-gray-500">Create a new session below to get started</p>
<p class="text-gray-600 dark:text-gray-200 font-medium text-sm">No Previous Sessions</p>
<p class="text-xs text-gray-500 dark:text-gray-400">Create a new session below to get started</p>
</div>
}
>
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden flex-shrink-0">
<div class="px-4 py-3 border-b border-gray-200 bg-gray-50">
<h2 class="text-base font-semibold text-gray-900">Resume Session</h2>
<p class="text-xs text-gray-500 mt-0.5">
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex-shrink-0">
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900">
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">Resume Session</h2>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
{parentSessions().length} {parentSessions().length === 1 ? "session" : "sessions"} available
</p>
</div>
@@ -180,11 +180,10 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
{(session, index) => (
<button
data-session-index={index()}
class="w-full text-left px-4 py-2.5 border-b border-gray-100 hover:bg-blue-50 transition-all group focus:outline-none"
class="w-full text-left px-4 py-2.5 border-b border-gray-100 dark:border-gray-800 transition-all group focus:outline-none hover:bg-blue-50 dark:hover:bg-blue-900/30"
classList={{
"bg-blue-100 ring-2 ring-blue-500 ring-inset":
"bg-blue-100 dark:bg-blue-900/50 ring-2 ring-blue-500 dark:ring-blue-400 ring-inset":
focusMode() === "sessions" && selectedIndex() === index(),
"hover:bg-blue-50": focusMode() !== "sessions" || selectedIndex() !== index(),
}}
onClick={() => handleSessionSelect(session.id)}
onMouseEnter={() => {
@@ -196,22 +195,23 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2">
<span
class="text-sm font-medium text-gray-900 group-hover:text-blue-700 truncate"
class="text-sm font-medium text-gray-900 dark:text-gray-100 group-hover:text-blue-700 dark:group-hover:text-blue-300 truncate"
classList={{
"text-blue-700": focusMode() === "sessions" && selectedIndex() === index(),
"text-blue-700 dark:text-blue-300":
focusMode() === "sessions" && selectedIndex() === index(),
}}
>
{session.title || "Untitled Session"}
</span>
</div>
<div class="flex items-center gap-3 text-xs text-gray-500 mt-0.5">
<div class="flex items-center gap-3 text-xs text-gray-500 dark:text-gray-400 mt-0.5">
<span>{session.agent}</span>
<span></span>
<span>{formatRelativeTime(session.time.updated)}</span>
</div>
</div>
<Show when={focusMode() === "sessions" && selectedIndex() === index()}>
<kbd class="px-1.5 py-0.5 text-xs font-semibold text-gray-700 bg-white border border-gray-300 rounded flex-shrink-0">
<kbd class="px-1.5 py-0.5 text-xs font-semibold text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded flex-shrink-0">
</kbd>
</Show>
@@ -223,18 +223,23 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
</div>
</Show>
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden flex-shrink-0">
<div class="px-4 py-3 border-b border-gray-200 bg-gray-50">
<h2 class="text-base font-semibold text-gray-900">Start New Session</h2>
<p class="text-xs text-gray-500 mt-0.5">Create a fresh conversation with your chosen agent</p>
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex-shrink-0">
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900">
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">Start New Session</h2>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
Create a fresh conversation with your chosen agent
</p>
</div>
<div class="p-4">
<Show when={agentList().length > 0} fallback={<div class="text-sm text-gray-500">Loading agents...</div>}>
<Show
when={agentList().length > 0}
fallback={<div class="text-sm text-gray-500 dark:text-gray-400">Loading agents...</div>}
>
<div class="space-y-3">
<div>
<label class="block text-xs font-medium text-gray-700 mb-1.5">Agent</label>
<label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1.5">Agent</label>
<select
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm bg-white hover:border-gray-400 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm bg-white dark:bg-gray-800 dark:text-gray-100 hover:border-gray-400 dark:hover:border-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all"
value={selectedAgent()}
onChange={(e) => setSelectedAgent(e.currentTarget.value)}
>
@@ -250,7 +255,7 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
</div>
<button
class="w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-all font-medium flex items-center justify-between text-sm relative group"
class="w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 dark:hover:bg-blue-500 disabled:bg-gray-300 dark:disabled:bg-gray-600 disabled:cursor-not-allowed transition-all font-medium flex items-center justify-between text-sm relative group focus:outline-none focus:ring-2 focus:ring-blue-500/40"
onClick={handleNewSession}
disabled={isCreating() || agentList().length === 0}
>
@@ -276,7 +281,7 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
</svg>
<span>Create Session</span>
</div>
<kbd class="px-1.5 py-0.5 text-xs font-semibold bg-blue-700 border border-blue-500 rounded flex-shrink-0">
<kbd class="px-1.5 py-0.5 text-xs font-semibold bg-blue-700 border border-blue-500 rounded flex-shrink-0 dark:bg-blue-600 dark:border-blue-400">
Cmd+Enter
</kbd>
</Show>
@@ -294,29 +299,45 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
</div>
</div>
<div class="px-4 py-2 bg-white border-t border-gray-200 flex-shrink-0">
<div class="flex items-center justify-center flex-wrap gap-3 text-xs text-gray-500">
<div class="px-4 py-2 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 flex-shrink-0">
<div class="flex items-center justify-center flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400">
<div class="flex items-center gap-1.5">
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs"></kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs"></kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
</kbd>
<span>Navigate</span>
</div>
<div class="flex items-center gap-1.5">
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs">PgUp</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs">PgDn</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
PgUp
</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
PgDn
</kbd>
<span>Jump</span>
</div>
<div class="flex items-center gap-1.5">
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs">Home</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs">End</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
Home
</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
End
</kbd>
<span>First/Last</span>
</div>
<div class="flex items-center gap-1.5">
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded font-mono text-xs">Enter</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
Enter
</kbd>
<span>Resume</span>
</div>
<div class="flex items-center gap-1.5">
<kbd class="px-1.5 py-0.5 bg-gray-100 border border-gray-300 rounded text-xs">Cmd+Enter</kbd>
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded text-xs">
Cmd+Enter
</kbd>
<span>New Session</span>
</div>
</div>

View File

@@ -1,5 +1,5 @@
import { createEffect, createSignal, onMount, onCleanup } from "solid-js"
import { renderMarkdown, onLanguagesLoaded } from "../lib/markdown"
import { renderMarkdown, onLanguagesLoaded, initMarkdown } from "../lib/markdown"
import type { TextPart } from "../types/message"
interface MarkdownProps {
@@ -15,11 +15,16 @@ export function Markdown(props: MarkdownProps) {
createEffect(async () => {
const part = props.part
const text = part.text || ""
const dark = Boolean(props.isDark)
const themeKey = dark ? "dark" : "light"
latestRequestedText = text
if (part.renderCache && part.renderCache.text === text) {
setHtml(part.renderCache.html)
await initMarkdown(dark)
const cache = part.renderCache
if (cache && cache.text === text && cache.theme === themeKey) {
setHtml(cache.html)
return
}
@@ -28,12 +33,13 @@ export function Markdown(props: MarkdownProps) {
if (latestRequestedText === text) {
setHtml(rendered)
part.renderCache = { text, html: rendered }
part.renderCache = { text, html: rendered, theme: themeKey }
}
} catch (error) {
console.error("Failed to render markdown:", error)
if (latestRequestedText === text) {
setHtml(text)
part.renderCache = { text, html: text, theme: themeKey }
}
}
})

View File

@@ -323,11 +323,11 @@ export default function MessageStream(props: MessageStreamProps) {
return (
<div class="message-stream-container">
<div class="connection-status">
<div class="flex items-center gap-2 text-sm font-medium text-gray-700">
<div class="connection-status-text flex items-center gap-2 text-sm font-medium">
<span>{formattedSessionInfo()}</span>
</div>
<div class="flex-1" />
<div class="flex items-center gap-2 text-sm font-medium text-gray-700">
<div class="connection-status-text flex items-center gap-2 text-sm font-medium">
<span>Command Palette</span>
<Kbd shortcut="cmd+shift+p" />
</div>

View File

@@ -78,19 +78,19 @@ export default function ModelSelector(props: ModelSelectorProps) {
itemComponent={(itemProps) => (
<Combobox.Item
item={itemProps.item}
class="px-3 py-2 cursor-pointer hover:bg-blue-50 rounded outline-none data-[highlighted]:bg-blue-100 flex items-start gap-2"
class="px-3 py-2 cursor-pointer rounded outline-none transition-colors hover:bg-blue-50 dark:hover:bg-blue-900/40 data-[highlighted]:bg-blue-100 dark:data-[highlighted]:bg-blue-900/60 flex items-start gap-2"
>
<div class="flex flex-col flex-1 min-w-0">
<Combobox.ItemLabel class="font-medium text-sm text-gray-900">
<Combobox.ItemLabel class="font-medium text-sm text-gray-900 dark:text-gray-100">
{itemProps.item.rawValue.name}
</Combobox.ItemLabel>
<Combobox.ItemDescription class="text-xs text-gray-600">
<Combobox.ItemDescription class="text-xs text-gray-600 dark:text-gray-300">
{itemProps.item.rawValue.providerName} {itemProps.item.rawValue.providerId}/
{itemProps.item.rawValue.id}
</Combobox.ItemDescription>
</div>
<Combobox.ItemIndicator class="flex-shrink-0 mt-0.5">
<svg class="w-4 h-4 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<Combobox.ItemIndicator class="flex-shrink-0 mt-0.5 text-blue-600 dark:text-blue-400">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</Combobox.ItemIndicator>
@@ -101,36 +101,38 @@ export default function ModelSelector(props: ModelSelectorProps) {
<Combobox.Input class="sr-only" data-model-selector />
<Combobox.Trigger
ref={triggerRef}
class="inline-flex items-center justify-between gap-2 px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50 outline-none focus:ring-2 focus:ring-blue-500 text-xs min-w-[180px]"
class="inline-flex items-center justify-between gap-2 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 outline-none focus:ring-2 focus:ring-blue-500 text-xs min-w-[180px] transition-colors"
>
<div class="flex flex-col items-start min-w-0">
<span class="text-gray-700 font-medium">Model: {currentModelValue()?.name ?? "None"}</span>
<span class="text-gray-700 dark:text-gray-200 font-medium">
Model: {currentModelValue()?.name ?? "None"}
</span>
{currentModelValue() && (
<span class="text-gray-500 text-[10px]">
<span class="text-gray-500 dark:text-gray-400 text-[10px]">
{currentModelValue()!.providerId}/{currentModelValue()!.id}
</span>
)}
</div>
<Combobox.Icon class="flex-shrink-0">
<ChevronDown class="w-3 h-3 text-gray-500" />
<ChevronDown class="w-3 h-3 text-gray-500 dark:text-gray-300" />
</Combobox.Icon>
</Combobox.Trigger>
</Combobox.Control>
<Combobox.Portal>
<Combobox.Content class="bg-white border border-gray-300 rounded-md shadow-lg overflow-hidden z-50 min-w-[300px]">
<div class="p-2 border-b border-gray-200">
<Combobox.Content class="bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md shadow-lg overflow-hidden z-50 min-w-[300px]">
<div class="p-2 border-b border-gray-200 dark:border-gray-700">
<Combobox.Input
ref={searchInputRef}
class="w-full px-3 py-1.5 text-xs border border-gray-300 rounded outline-none focus:ring-2 focus:ring-blue-500"
class="w-full px-3 py-1.5 text-xs border border-gray-300 dark:border-gray-600 rounded outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100"
placeholder="Search models..."
/>
</div>
<Combobox.Listbox class="max-h-64 overflow-auto p-1" />
<Combobox.Listbox class="max-h-64 overflow-auto p-1 bg-white dark:bg-gray-800" />
</Combobox.Content>
</Combobox.Portal>
</Combobox>
<span class="text-xs text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500">
<Kbd shortcut="cmd+shift+m" />
</span>
</div>

View File

@@ -66,28 +66,34 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
<Dialog.Portal>
<Dialog.Overlay class="fixed inset-0 bg-black/50 z-50" />
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
<Dialog.Content class="bg-white rounded-lg shadow-2xl w-full max-w-lg p-6">
<Dialog.Title class="text-xl font-semibold text-gray-900 mb-4">
<Dialog.Content class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-2xl w-full max-w-lg p-6">
<Dialog.Title class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-4">
OpenCode {instance()?.folder.split("/").pop()}
</Dialog.Title>
<div class="space-y-6">
<Show
when={parentSessions().length > 0}
fallback={<div class="text-center py-4 text-gray-500 text-sm">No previous sessions</div>}
fallback={
<div class="text-center py-4 text-gray-500 dark:text-gray-400 text-sm">No previous sessions</div>
}
>
<div>
<h3 class="text-sm font-medium text-gray-700 mb-2">Resume a session ({parentSessions().length}):</h3>
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Resume a session ({parentSessions().length}):
</h3>
<div class="space-y-1 max-h-[400px] overflow-y-auto">
<For each={parentSessions()}>
{(session) => (
<button
class="w-full text-left px-3 py-2 rounded hover:bg-gray-100 transition-colors group"
class="w-full text-left px-3 py-2 rounded transition-colors group hover:bg-gray-100 dark:hover:bg-gray-800"
onClick={() => handleSessionSelect(session.id)}
>
<div class="flex justify-between items-start">
<span class="text-sm text-gray-900 truncate flex-1">{session.title || "Untitled"}</span>
<span class="text-xs text-gray-500 ml-2 flex-shrink-0">
<span class="text-sm text-gray-900 dark:text-gray-100 truncate flex-1">
{session.title || "Untitled"}
</span>
<span class="text-xs text-gray-500 dark:text-gray-400 ml-2 flex-shrink-0">
{formatRelativeTime(session.time.updated)}
</span>
</div>
@@ -100,22 +106,22 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300" />
<div class="w-full border-t border-gray-300 dark:border-gray-700" />
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white text-gray-500">or</span>
<span class="px-2 bg-white dark:bg-gray-900 text-gray-500 dark:text-gray-400">or</span>
</div>
</div>
<div>
<h3 class="text-sm font-medium text-gray-700 mb-2">Start new session:</h3>
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Start new session:</h3>
<div class="space-y-3">
<Show
when={agentList().length > 0}
fallback={<div class="text-sm text-gray-500">Loading agents...</div>}
fallback={<div class="text-sm text-gray-500 dark:text-gray-400">Loading agents...</div>}
>
<select
class="w-full px-3 py-2 border border-gray-300 rounded text-sm bg-white hover:border-gray-400 transition-colors"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded text-sm bg-white dark:bg-gray-800 dark:text-gray-100 hover:border-gray-400 dark:hover:border-gray-500 transition-colors"
value={selectedAgent()}
onChange={(e) => setSelectedAgent(e.currentTarget.value)}
>
@@ -124,7 +130,7 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
</Show>
<button
class="w-full px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"
class="w-full px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 dark:hover:bg-blue-500 disabled:bg-gray-300 dark:disabled:bg-gray-600 disabled:cursor-not-allowed transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500/40"
onClick={handleNewSession}
disabled={isCreating() || agentList().length === 0}
>
@@ -135,7 +141,10 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
</div>
<div class="mt-6 flex justify-end">
<button class="px-4 py-2 text-sm text-gray-700 hover:text-gray-900" onClick={handleCancel}>
<button
class="px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
onClick={handleCancel}
>
Cancel
</button>
</div>

View File

@@ -19,7 +19,7 @@ const SessionTabs: Component<SessionTabsProps> = (props) => {
const totalTabs = () => sessionsList().length + 1
return (
<div class="session-tabs bg-white border-b border-gray-200">
<div class="session-tabs bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
<div class="tabs-container flex items-center justify-between gap-1 px-2 py-1 overflow-x-auto" role="tablist">
<div class="flex items-center gap-1 overflow-x-auto">
<For each={sessionsList()}>
@@ -39,7 +39,7 @@ const SessionTabs: Component<SessionTabsProps> = (props) => {
onSelect={() => props.onSelect("info")}
/>
<button
class="new-tab-button inline-flex items-center justify-center w-8 h-8 rounded-md text-gray-600 hover:bg-gray-100 transition-colors"
class="new-tab-button inline-flex items-center justify-center w-8 h-8 rounded-md text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
onClick={props.onNew}
title="New parent session (Cmd/Ctrl+T)"
aria-label="New parent session"