hmgill commited on
Commit
5ae17f7
·
verified ·
1 Parent(s): 44e2a4a

Update public/elements/FossilGallery.jsx

Browse files
Files changed (1) hide show
  1. public/elements/FossilGallery.jsx +38 -25
public/elements/FossilGallery.jsx CHANGED
@@ -1,10 +1,16 @@
1
- // Example gallery. Each card is a SPECIMEN — a set of views — not one image,
2
- // because that is the pipeline's unit of work. The thumbnails are stacked so the
3
- // card shows at a glance how many angles the case has.
4
  //
5
- // Clicking a card ARMS the specimen and prefills its prompt into the composer.
6
- // It deliberately does not run the agent: the prompt is the interesting part and
7
- // the user should get to edit it first.
 
 
 
 
 
 
8
  import { useState } from "react";
9
  import { Button } from "@/components/ui/button";
10
 
@@ -15,11 +21,12 @@ export default function FossilGallery() {
15
  setArmed(ex.id);
16
  callAction({ name: "arm_example", payload: { example_id: ex.id } });
17
  const box =
18
- document.querySelector("#chat-input") ||
19
- document.querySelector("textarea");
20
  if (box) {
21
  const setter = Object.getOwnPropertyDescriptor(
22
- window.HTMLTextAreaElement.prototype, "value").set;
 
 
23
  setter.call(box, ex.prompt);
24
  box.dispatchEvent(new Event("input", { bubbles: true }));
25
  box.focus();
@@ -32,39 +39,45 @@ export default function FossilGallery() {
32
  };
33
 
34
  return (
35
- <div className="w-full">
36
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
37
  {props.examples.map((ex) => (
38
  <button
39
  key={ex.id}
40
  onClick={() => arm(ex)}
41
- className={`text-left rounded-xl border p-3 transition hover:shadow-md ${
42
- armed === ex.id
43
- ? "border-emerald-500 ring-2 ring-emerald-200 bg-emerald-50"
44
- : "border-neutral-200 bg-white hover:border-neutral-300"
45
- }`}
46
  >
47
- <div className="flex gap-1 mb-2">
48
  {ex.thumbs.slice(0, 4).map((t, i) => (
49
- <img key={i} src={t} alt=""
50
- className="w-1/4 aspect-square object-cover rounded-md border border-neutral-200" />
 
 
 
 
51
  ))}
52
  </div>
53
- <div className="font-medium text-sm">{ex.title}</div>
54
- <div className="text-xs text-neutral-500 mt-0.5">
55
  {ex.n_views} view{ex.n_views === 1 ? "" : "s"}
56
- {ex.n_views === 1 && " — the far side will be invented"}
57
  </div>
58
- <div className="text-xs text-neutral-400 mt-1 line-clamp-2">{ex.prompt}</div>
 
 
59
  </button>
60
  ))}
61
  </div>
 
62
  {armed && (
63
- <div className="mt-3 flex items-center gap-2 text-xs text-neutral-600">
64
  <span>Prompt prefilled — edit it if you like, then press send.</span>
65
- <Button size="sm" variant="outline" onClick={clear}>Clear</Button>
 
 
66
  </div>
67
  )}
68
  </div>
69
  );
70
- }
 
1
+ // Example gallery. Each card is a SPECIMEN — a set of views — not one image, because
2
+ // that is the pipeline's unit of work. Thumbnails are laid side by side so the card
3
+ // shows at a glance how many angles the case has.
4
  //
5
+ // Clicking a card ARMS the specimen and prefills its prompt into the composer. It
6
+ // deliberately does not run: the prompt is the interesting part and the user should
7
+ // get to edit it first.
8
+ //
9
+ // THEMING: this used hardcoded `bg-white` / `text-neutral-*`, which produced a glaring
10
+ // white card with unreadable gray text on the dark theme. Everything now uses the
11
+ // app's own theme tokens (`bg-card`, `text-foreground`, `text-muted-foreground`,
12
+ // `border-border`, `ring-primary`), so it follows whatever theme is selected instead
13
+ // of fighting it.
14
  import { useState } from "react";
15
  import { Button } from "@/components/ui/button";
16
 
 
21
  setArmed(ex.id);
22
  callAction({ name: "arm_example", payload: { example_id: ex.id } });
23
  const box =
24
+ document.querySelector("#chat-input") || document.querySelector("textarea");
 
25
  if (box) {
26
  const setter = Object.getOwnPropertyDescriptor(
27
+ window.HTMLTextAreaElement.prototype,
28
+ "value"
29
+ ).set;
30
  setter.call(box, ex.prompt);
31
  box.dispatchEvent(new Event("input", { bubbles: true }));
32
  box.focus();
 
39
  };
40
 
41
  return (
42
+ <div className="w-full bg-transparent">
43
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
44
  {props.examples.map((ex) => (
45
  <button
46
  key={ex.id}
47
  onClick={() => arm(ex)}
48
+ className={`text-left rounded-xl border p-3 transition bg-card text-card-foreground
49
+ hover:border-primary/60 hover:shadow-md
50
+ ${armed === ex.id ? "border-primary ring-2 ring-primary/40" : "border-border"}`}
 
 
51
  >
52
+ <div className="flex gap-1.5 mb-2.5">
53
  {ex.thumbs.slice(0, 4).map((t, i) => (
54
+ <img
55
+ key={i}
56
+ src={t}
57
+ alt=""
58
+ className="flex-1 min-w-0 aspect-square object-cover rounded-md border border-border"
59
+ />
60
  ))}
61
  </div>
62
+ <div className="font-medium text-sm text-foreground">{ex.title}</div>
63
+ <div className="text-xs text-muted-foreground mt-0.5">
64
  {ex.n_views} view{ex.n_views === 1 ? "" : "s"}
 
65
  </div>
66
+ <div className="text-xs text-muted-foreground/80 mt-1 line-clamp-2">
67
+ {ex.prompt}
68
+ </div>
69
  </button>
70
  ))}
71
  </div>
72
+
73
  {armed && (
74
+ <div className="mt-3 flex items-center gap-2 text-xs text-muted-foreground">
75
  <span>Prompt prefilled — edit it if you like, then press send.</span>
76
+ <Button size="sm" variant="outline" onClick={clear}>
77
+ Clear
78
+ </Button>
79
  </div>
80
  )}
81
  </div>
82
  );
83
+ }