evOo-local/apps/web/e2e/fixtures/oo-gallery.tsx
cynarAI 9f4991abe0
feat(avatar): draw every bot as a living Oo on web (#136)
Bots now render as an Oo rig built once in core: nine species, styled
Oo eyes, eyewear, headwear, neckwear, arms and moment props, with a
level of detail per size. A shared animation frame loop moves only
visible avatars and holds still under reduced motion.


Claude-Session: https://claude.ai/code/session_01EKuME5CgL1ddGGN7LGvtBj

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-04 22:40:12 +02:00

63 lines
2.4 KiB
TypeScript

import type { OoMoment } from "@rakazo/core";
import { BotAvatar } from "@rakazo/ui-web";
import { createRoot } from "react-dom/client";
import "../../src/styles.css";
const params = new URLSearchParams(location.search);
document.documentElement.dataset.theme = params.get("theme") === "dark" ? "dark" : "light";
const crew: { name: string; look: string; moment: OoMoment }[] = [
{ name: "Classic", look: "#8B5CF6::shape_3", moment: "idle" },
{
name: "Miso",
look: "oo1:c=FF8A33;sp=cat;la=soft;li=wing;ir=green;ew=round;pl=0.80",
moment: "working",
},
{ name: "Bruno", look: "oo1:c=B38559;sp=dog;ar=paw;ck=peach;nk=scarf", moment: "cooking" },
{
name: "Luna",
look: "oo1:c=FFFFFF;sp=bunny;la=full;es=rose;ir=violet;sk=heart;ck=pink;ew=heart",
moment: "success",
},
{ name: "Teddy", look: "oo1:c=C98A5A;sp=bear;ar=paw;hd=beanie", moment: "reading" },
{
name: "Pixel",
look: "oo1:c=A7B1C2;sp=robot;ar=robot;sk=star;hd=headphones",
moment: "listening",
},
{ name: "Boo", look: "oo1:c=CDB8FF;sp=ghost;en=0.80", moment: "autopilot" },
{ name: "Kermi", look: "oo1:c=7BD389;sp=frog;ew=nerd;nk=bowtie", moment: "thinking" },
{ name: "Pingu", look: "oo1:c=3A4A6B;sp=penguin;hd=crown;ew=monocle", moment: "offering" },
{ name: "Waiting", look: "oo1:c=10B981;br=fine;hd=flower", moment: "waiting" },
{ name: "Worried", look: "oo1:c=F59E0B;sp=bunny;ew=reading", moment: "concerned" },
{ name: "Sleepy", look: "oo1:c=3D8BFF;sp=cat;nk=bell;hd=party", moment: "asleep" },
];
createRoot(document.getElementById("root")!).render(
<main className="min-h-screen bg-background p-6 text-foreground">
<div data-testid="oo-gallery" className="grid grid-cols-4 gap-4">
{crew.map(({ name, look, moment }) => (
<figure
key={name}
className="flex flex-col items-center gap-1 rounded-xl border border-border bg-card p-2"
>
<BotAvatar color={look} identity={name} size={120} moment={moment} still />
<figcaption className="text-ui-body-sm text-muted-foreground">{moment}</figcaption>
</figure>
))}
</div>
<div data-testid="oo-sizes" className="mt-6 flex items-end gap-4">
{[20, 28, 44, 72].map((size) => (
<BotAvatar
key={size}
color={crew[1]!.look}
identity="sizes"
size={size}
status="running"
still
/>
))}
</div>
</main>,
);