From a4411c21b6687e7392447da08dbaec2dc530075f Mon Sep 17 00:00:00 2001
From: Adam <2363879+adamdotdevin@users.noreply.github.com>
Date: Sun, 28 Dec 2025 15:47:05 -0600
Subject: feat(desktop): theme preview

---
 packages/app/src/context/command.tsx | 37 ++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

(limited to 'packages/app/src/context/command.tsx')

diff --git a/packages/app/src/context/command.tsx b/packages/app/src/context/command.tsx
index f91a1cf05..626bfdbe4 100644
--- a/packages/app/src/context/command.tsx
+++ b/packages/app/src/context/command.tsx
@@ -3,6 +3,7 @@ import { createSimpleContext } from "@opencode-ai/ui/context"
 import { useDialog } from "@opencode-ai/ui/context/dialog"
 import { Dialog } from "@opencode-ai/ui/dialog"
 import { List } from "@opencode-ai/ui/list"
+import { useTheme } from "@opencode-ai/ui/theme"
 
 const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform)
 
@@ -115,6 +116,34 @@ export function formatKeybind(config: string): string {
 
 function DialogCommand(props: { options: CommandOption[] }) {
   const dialog = useDialog()
+  const theme = useTheme()
+  let committed = false
+
+  const handleMove = (option: CommandOption | undefined) => {
+    if (!option) return
+    if (option.id.startsWith("theme.set.")) {
+      const id = option.id.replace("theme.set.", "")
+      theme.previewTheme(id)
+    } else if (option.id.startsWith("theme.scheme.") && !option.id.includes("cycle")) {
+      const scheme = option.id.replace("theme.scheme.", "") as "light" | "dark" | "system"
+      theme.previewColorScheme(scheme)
+    }
+  }
+
+  const handleSelect = (option: CommandOption | undefined) => {
+    if (option) {
+      theme.commitPreview()
+      committed = true
+      dialog.close()
+      option.onSelect?.("palette")
+    }
+  }
+
+  onCleanup(() => {
+    if (!committed) {
+      theme.cancelPreview()
+    }
+  })
 
   return (
     <Dialog title="Commands">
@@ -125,12 +154,8 @@ function DialogCommand(props: { options: CommandOption[] }) {
         key={(x) => x?.id}
         filterKeys={["title", "description", "category"]}
         groupBy={(x) => x.category ?? ""}
-        onSelect={(option) => {
-          if (option) {
-            dialog.close()
-            option.onSelect?.("palette")
-          }
-        }}
+        onMove={handleMove}
+        onSelect={handleSelect}
       >
         {(option) => (
           <div class="w-full flex items-center justify-between gap-4">
-- 
cgit v1.2.3

