Skip to content

Commit 8fd4a69

Browse files
feat: rich theme preview with mini-app mockup showing markdown, code blocks, syntax colors, accent dots, and glow
1 parent 0737c49 commit 8fd4a69

1 file changed

Lines changed: 136 additions & 39 deletions

File tree

crates/tauri-app/frontend/src/components/settings/ThemeSelector.tsx

Lines changed: 136 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -120,23 +120,58 @@ export function ThemeSelector(props?: { inline?: boolean }) {
120120
<div class="theme-grid">
121121
<For each={themes()}>
122122
{(theme) => (
123-
<button
123+
<div
124124
class="theme-card"
125125
classList={{ active: activeId() === theme.id }}
126126
onClick={() => selectTheme(theme.id)}
127127
>
128-
<div class="theme-preview" style={{ background: theme.vars["--bg-base"] || theme.preview[0] }}>
129-
<div class="theme-preview-sidebar" style={{ background: theme.vars["--bg-surface"] || theme.preview[1] }}>
130-
<div class="theme-preview-sidebar-line" style={{ background: theme.vars["--text-tertiary"] || "#888" }} />
131-
<div class="theme-preview-sidebar-line" style={{ background: theme.vars["--primary"] || theme.preview[2], opacity: "0.7" }} />
132-
<div class="theme-preview-sidebar-line" style={{ background: theme.vars["--text-tertiary"] || "#888" }} />
128+
<div class="tp" style={{ background: theme.vars["--bg-base"] || "#0f1012" }}>
129+
<div class="tp-side" style={{ background: theme.vars["--bg-surface"] || "#18181c", "border-right": `1px solid ${theme.vars["--border"] || "rgba(255,255,255,0.06)"}` }}>
130+
<div class="tp-sln" style={{ background: theme.vars["--primary"] || "#6b7cff", opacity: "0.7" }} />
131+
<div class="tp-sln" style={{ background: theme.vars["--bg-accent"] || "#222", height: "4px" }} />
132+
<div class="tp-sln" style={{ background: theme.vars["--text-tertiary"] || "#888", opacity: "0.2" }} />
133+
<div class="tp-sln" style={{ background: theme.vars["--text-tertiary"] || "#888", opacity: "0.15" }} />
133134
</div>
134-
<div class="theme-preview-main">
135-
<div class="theme-preview-topbar" style={{ background: theme.vars["--text-tertiary"] || "#888" }} />
136-
<div class="theme-preview-msg-user" style={{ background: theme.vars["--primary"] || theme.preview[2] }} />
137-
<div class="theme-preview-msg-bot" style={{ background: theme.vars["--text"] || "#fff" }} />
138-
<div class="theme-preview-composer" style={{ background: theme.vars["--text"] || "#fff" }} />
135+
<div class="tp-body">
136+
<div class="tp-tabbar" style={{ background: theme.vars["--bg-surface"] || "#18181c" }}>
137+
<div class="tp-tab-a" style={{ background: theme.vars["--bg-base"] || "#0f1012", border: `1px solid ${theme.vars["--border"] || "rgba(255,255,255,0.06)"}` }} />
138+
<div class="tp-tab-i" style={{ background: theme.vars["--text-tertiary"] || "#888", opacity: "0.2" }} />
139+
</div>
140+
<div class="tp-msgs">
141+
<div class="tp-u" style={{ background: `${theme.vars["--primary"] || "#6b7cff"}15`, border: `1px solid ${theme.vars["--primary"] || "#6b7cff"}20` }}>
142+
<div class="tp-l" style={{ background: theme.vars["--text"] || "#eee", width: "70%" }} />
143+
</div>
144+
<div class="tp-a">
145+
<div class="tp-l tp-h" style={{ background: theme.vars["--text"] || "#eee", width: "35%" }} />
146+
<div class="tp-l" style={{ background: theme.vars["--text-secondary"] || "#aaa", width: "88%" }} />
147+
<div class="tp-l" style={{ background: theme.vars["--text-secondary"] || "#aaa", width: "55%" }} />
148+
<div class="tp-cb" style={{ background: theme.vars["--bg-card"] || "#151518", border: `1px solid ${theme.vars["--border"] || "rgba(255,255,255,0.06)"}` }}>
149+
<div class="tp-l" style={{ background: theme.vars["--hljs-keyword"] || "#c678dd", width: "30%" }} />
150+
<div class="tp-l" style={{ background: theme.vars["--hljs-string"] || "#98c379", width: "50%" }} />
151+
<div class="tp-l" style={{ background: theme.vars["--hljs-function"] || "#61afef", width: "38%" }} />
152+
</div>
153+
<div class="tp-il">
154+
<div class="tp-l" style={{ background: theme.vars["--text-secondary"] || "#aaa", width: "22%" }} />
155+
<div class="tp-ic" style={{ background: `${theme.vars["--text"] || "#fff"}14` }}>
156+
<div style={{ background: theme.vars["--hljs-keyword"] || "#dda0f7", height: "2px", "border-radius": "1px" }} />
157+
</div>
158+
<div class="tp-l" style={{ background: theme.vars["--text-secondary"] || "#aaa", width: "18%" }} />
159+
</div>
160+
</div>
161+
<div class="tp-dots">
162+
<div class="tp-d" style={{ background: theme.vars["--primary"] || "#6b7cff" }} />
163+
<div class="tp-d" style={{ background: theme.vars["--green"] || "#4cd694" }} />
164+
<div class="tp-d" style={{ background: theme.vars["--amber"] || "#f0b840" }} />
165+
<div class="tp-d" style={{ background: theme.vars["--red"] || "#f25f67" }} />
166+
<div class="tp-d" style={{ background: theme.vars["--purple"] || "#b47aff" }} />
167+
</div>
168+
</div>
169+
<div class="tp-comp" style={{ background: theme.vars["--bg-card"] || "#151518", border: `1px solid ${theme.vars["--border"] || "rgba(255,255,255,0.06)"}` }}>
170+
<div class="tp-comp-in" style={{ background: theme.vars["--text-tertiary"] || "#888", opacity: "0.12" }} />
171+
<div class="tp-comp-btn" style={{ background: theme.vars["--primary"] || "#6b7cff" }} />
172+
</div>
139173
</div>
174+
<div class="tp-glow" style={{ background: `radial-gradient(ellipse at 65% 30%, ${theme.vars["--primary-glow"] || "rgba(107,124,255,0.12)"} 0%, transparent 70%)` }} />
140175
</div>
141176
<div class="theme-info">
142177
<span class="theme-name">{theme.name}</span>
@@ -171,7 +206,7 @@ export function ThemeSelector(props?: { inline?: boolean }) {
171206
</button>
172207
)}
173208
</div>
174-
</button>
209+
</div>
175210
)}
176211
</For>
177212
</div>
@@ -285,55 +320,117 @@ if (!document.getElementById("theme-selector-styles")) {
285320
border-color: var(--primary);
286321
box-shadow: 0 0 0 1px var(--primary-glow);
287322
}
288-
.theme-preview {
323+
/* Rich theme preview — mini app mockup */
324+
.tp {
289325
display: flex;
290-
height: 80px;
326+
height: 120px;
291327
border-radius: 6px;
292328
overflow: hidden;
293-
border: 1px solid rgba(128,128,128,0.15);
329+
border: 1px solid rgba(128,128,128,0.12);
330+
position: relative;
294331
}
295-
.theme-preview-sidebar {
296-
width: 22%;
332+
.tp-side {
333+
width: 20%;
297334
display: flex;
298335
flex-direction: column;
299336
gap: 3px;
300-
padding: 4px 3px;
337+
padding: 5px 3px;
301338
}
302-
.theme-preview-sidebar-line {
303-
height: 3px;
304-
border-radius: 1px;
305-
opacity: 0.5;
339+
.tp-sln { height: 3px; border-radius: 1px; }
340+
.tp-body {
341+
flex: 1;
342+
display: flex;
343+
flex-direction: column;
344+
min-width: 0;
345+
}
346+
.tp-tabbar {
347+
display: flex;
348+
gap: 2px;
349+
padding: 2px 3px;
350+
align-items: flex-end;
351+
height: 10px;
306352
}
307-
.theme-preview-main {
353+
.tp-tab-a { width: 20px; height: 6px; border-radius: 2px 2px 0 0; }
354+
.tp-tab-i { width: 14px; height: 3px; border-radius: 1px; margin-bottom: 1px; }
355+
.tp-msgs {
308356
flex: 1;
309357
display: flex;
310358
flex-direction: column;
311359
padding: 4px 5px;
312360
gap: 3px;
361+
overflow: hidden;
313362
}
314-
.theme-preview-topbar {
315-
height: 4px;
363+
.tp-u {
364+
align-self: flex-end;
365+
padding: 2px 4px;
366+
border-radius: 3px;
367+
max-width: 55%;
368+
}
369+
.tp-a {
370+
display: flex;
371+
flex-direction: column;
372+
gap: 2px;
373+
}
374+
.tp-l {
375+
height: 2px;
316376
border-radius: 1px;
317-
opacity: 0.3;
318377
}
319-
.theme-preview-msg-user {
320-
height: 6px;
321-
border-radius: 3px;
322-
align-self: flex-end;
323-
width: 50%;
324-
opacity: 0.15;
378+
.tp-h {
379+
height: 3px;
380+
margin-bottom: 1px;
325381
}
326-
.theme-preview-msg-bot {
327-
height: 10px;
382+
.tp-cb {
383+
padding: 3px 4px;
328384
border-radius: 3px;
329-
width: 70%;
330-
opacity: 0.08;
385+
display: flex;
386+
flex-direction: column;
387+
gap: 2px;
388+
margin: 1px 0;
331389
}
332-
.theme-preview-composer {
390+
.tp-il {
391+
display: flex;
392+
align-items: center;
393+
gap: 2px;
394+
}
395+
.tp-ic {
396+
padding: 1px 3px;
397+
border-radius: 2px;
398+
}
399+
.tp-dots {
400+
display: flex;
401+
gap: 3px;
333402
margin-top: auto;
334-
height: 8px;
403+
padding-top: 2px;
404+
}
405+
.tp-d {
406+
width: 4px;
407+
height: 4px;
408+
border-radius: 50%;
409+
}
410+
.tp-comp {
411+
display: flex;
412+
gap: 3px;
413+
padding: 3px 4px;
414+
margin: 0 4px 4px;
335415
border-radius: 4px;
336-
opacity: 0.12;
416+
align-items: center;
417+
}
418+
.tp-comp-in {
419+
flex: 1;
420+
height: 4px;
421+
border-radius: 2px;
422+
}
423+
.tp-comp-btn {
424+
width: 6px;
425+
height: 6px;
426+
border-radius: 50%;
427+
flex-shrink: 0;
428+
}
429+
.tp-glow {
430+
position: absolute;
431+
inset: 0;
432+
pointer-events: none;
433+
opacity: 0.5;
337434
}
338435
.theme-info {
339436
display: flex;

0 commit comments

Comments
 (0)