1import { cn } from "../../lib/utils";
2import type { ThemeCardPreviewColors } from "./ThemePreviewCircles";
3
4// A simple miniature of the app: sidebar, a short conversation, the
5// composer, and the orchestrator panel floating over the interface as an
6// island with horizontal agent rows.
7function ThemeWireframePane({
8 colors,
9 clip,
10}: {
11 colors: ThemeCardPreviewColors;
12 clip?: "left" | "right" | undefined;
13}) {
14 const line = "rgb(127 127 127 / 0.25)";
15 return (
16 <span
17 className="absolute inset-0"
18 style={
19 clip === undefined
20 ? undefined
21 : {
22 clipPath:
23 clip === "left"
24 ? "polygon(0 0, calc(50% - 1px) 0, calc(50% - 1px) 100%, 0 100%)"
25 : "polygon(calc(50% + 1px) 0, 100% 0, 100% 100%, calc(50% + 1px) 100%)",
26 }
27 }
28 >
29 <span className="absolute inset-0" style={{ backgroundColor: colors.canvas }} />
30 <span
31 className="absolute inset-y-0 left-0 w-[22%]"
32 style={{ backgroundColor: colors.sidebar, boxShadow: `inset -1px 0 0 ${line}` }}
33 />
34
35 {/* Sidebar: search, then thread rows */}
36 <span
37 className="absolute left-[3%] top-[8%] h-[8%] w-[16%] rounded-md"
38 style={{ backgroundColor: colors.surface, boxShadow: `inset 0 0 0 1px ${line}` }}
39 />
40 <span
41 className="absolute left-[3%] top-[22%] h-[7%] w-[16%] rounded-md"
42 style={{ backgroundColor: colors.accentSurface }}
43 />
44 <span
45 className="absolute left-[3%] top-[32%] h-[7%] w-[16%] rounded-md"
46 style={{ backgroundColor: colors.messageSurface, opacity: 0.7 }}
47 />
48 <span
49 className="absolute left-[3%] top-[42%] h-[7%] w-[16%] rounded-md"
50 style={{ backgroundColor: colors.messageSurface, opacity: 0.5 }}
51 />
52
53 {/* Conversation */}
54 <span
55 className="absolute right-[28%] top-[11%] h-[9%] w-[24%] rounded-lg"
56 style={{ backgroundColor: colors.messageSurface }}
57 />
58 <span
59 className="absolute left-[27%] top-[28%] h-[5%] w-[34%] rounded-sm"
60 style={{ backgroundColor: line }}
61 />
62 <span
63 className="absolute left-[27%] top-[38%] h-[5%] w-[26%] rounded-sm"
64 style={{ backgroundColor: line }}
65 />
66
67 {/* Composer */}
68 <span
69 className="absolute bottom-[8%] left-[26%] right-[6%] flex h-[15%] items-center justify-between rounded-md px-1"
70 style={{
71 backgroundColor: colors.surface,
72 boxShadow: `inset 0 0 0 1px ${line}`,
73 }}
74 >
75 <span
76 className="block h-[26%] w-[34%] rounded-full"
77 style={{ backgroundColor: line, opacity: 0.7 }}
78 />
79 <span
80 className="block aspect-square h-[58%] rounded-full"
81 style={{ backgroundColor: colors.messageAction }}
82 />
83 </span>
84
85 {/* Orchestrator island floating over the composer */}
86 <span
87 className="absolute right-[5%] top-[8%] h-[46%] w-[20%] rounded-lg"
88 style={{
89 backgroundColor: colors.surface,
90 boxShadow: `inset 0 0 0 1px ${line}, 0 2px 5px rgb(0 0 0 / 0.14)`,
91 }}
92 >
93 {[0, 1, 2].map((row) => (
94 <span
95 className="absolute left-[11%] right-[11%] flex items-center gap-1"
96 key={row}
97 style={{ top: `${10 + row * 30}%`, height: "20%" }}
98 >
99 <span
100 className="block aspect-square h-[26%] rounded-full"
101 style={{
102 backgroundColor:
103 row === 0 ? "#34d399" : row === 1 ? colors.messageAction : "#fbbf24",
104 opacity: 0.55,
105 }}
106 />
107 <span className="block h-[30%] w-[52%] rounded-sm" style={{ backgroundColor: line }} />
108 </span>
109 ))}
110 </span>
111 </span>
112 );
113}
114
115export function ThemeWireframe({
116 className,
117 panes,
118}: {
119 /** Sizing (height) for the frame; the pane geometry is percentage based. */
120 className?: string;
121 panes: ReadonlyArray<{ colors: ThemeCardPreviewColors; clip?: "left" | "right" }>;
122}) {
123 return (
124 <span
125 aria-hidden
126 className={cn(
127 "relative block w-full overflow-hidden rounded-lg border border-border/60",
128 className,
129 )}
130 >
131 {panes.map((pane) => (
132 <ThemeWireframePane clip={pane.clip} colors={pane.colors} key={pane.clip ?? "pane"} />
133 ))}
134 </span>
135 );
136}