diff --git a/app/api/themes/[name]/route.ts b/app/api/themes/[name]/route.ts new file mode 100644 index 000000000..5db73f2fe --- /dev/null +++ b/app/api/themes/[name]/route.ts @@ -0,0 +1,33 @@ +import { NextRequest, NextResponse } from "next/server"; +import { resolveTheme, type ThemeVariant } from "@/lib/theme"; + +export async function GET( + request: NextRequest, + { params }: { params: Promise<{ name: string }> }, +) { + try { + const { name } = await params; + const { searchParams } = new URL(request.url); + const mode = (searchParams.get("mode") || "dark") as ThemeVariant; + + const resolved = resolveTheme( + decodeURIComponent(name), + mode === "light" ? "light" : "dark", + ); + + if (!resolved) { + return NextResponse.json( + { error: `Theme "${name}" variant "${mode}" not found` }, + { status: 404 }, + ); + } + + return NextResponse.json(resolved); + } catch (error) { + console.error("Failed to resolve theme:", error); + return NextResponse.json( + { error: "Failed to resolve theme" }, + { status: 500 }, + ); + } +} diff --git a/app/api/themes/route.ts b/app/api/themes/route.ts new file mode 100644 index 000000000..8e2829d70 --- /dev/null +++ b/app/api/themes/route.ts @@ -0,0 +1,16 @@ +import { NextResponse } from "next/server"; +import { listThemeSets } from "@/lib/theme"; + +export async function GET() { + try { + const themeSets = listThemeSets(); + + return NextResponse.json({ themeSets }); + } catch (error) { + console.error("Failed to list themes:", error); + return NextResponse.json( + { error: "Failed to list themes" }, + { status: 500 }, + ); + } +} diff --git a/app/globals.css b/app/globals.css index 1c0e917bd..df4f55e05 100644 --- a/app/globals.css +++ b/app/globals.css @@ -23,12 +23,18 @@ --bg-panel: #f5f5f5; --bg-hover: #eeeeee; --bg-selected: #e8e8e8; + --bg-sidebar: #eeeeee; --border: #e0e0e0; --text: #1a1a1a; --text-muted: #6b7280; --text-dim: #9ca3af; --accent: #2563eb; --accent-hover: #1d4ed8; + /* 语法高亮语义色(prism-theme 引用;主题 JSON 映射会覆盖) */ + --accent-blue: #2563eb; + --accent-red: #dc2626; + --accent-green: #16a34a; + --accent-orange: #d97706; --user-bg: #eff6ff; --assistant-bg: #ffffff; --tool-bg: #f9fafb; @@ -40,12 +46,18 @@ html.dark { --bg-panel: #242424; --bg-hover: #2e2e2e; --bg-selected: #383838; + --bg-sidebar: #2e2e2e; --border: #3a3a3a; --text: #e8e8e8; --text-muted: #9ca3af; --text-dim: #6b7280; --accent: #60a5fa; --accent-hover: #93c5fd; + /* 语法高亮语义色(prism-theme 引用;主题 JSON 映射会覆盖) */ + --accent-blue: #60a5fa; + --accent-red: #f87171; + --accent-green: #4ade80; + --accent-orange: #fb923c; --user-bg: #1e293b; --assistant-bg: #1a1a1a; --tool-bg: #1f2937; diff --git a/app/layout.tsx b/app/layout.tsx index 054989f56..60ed55931 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -63,7 +63,7 @@ export default function RootLayout({