Skip to content

Commit eb1b2d9

Browse files
OyaAIProdclaude
andcommitted
studio: rebuild playground with React Flow + Tailwind theme; add docs
Studio (apps/playground): - Tailwind v4 + OKLCH dark theme (signature blue @ hue 250), glassmorphism, mesh glow, Inter + JetBrains Mono - DAG rebuilt on @xyflow/react: glass nodes with kind-colored chips, status rings (running=blue-pulse, done=green), animated smoothstep edges - page.tsx restyled with the new design system Docs: - guide/creating-agents, guide/sandbox, guide/studio - fix repo URL (oya-labs -> OyaAIProd), wire new pages into the sidebar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f4b975a commit eb1b2d9

11 files changed

Lines changed: 936 additions & 242 deletions

File tree

apps/playground/app/globals.css

Lines changed: 153 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,155 @@
1-
:root{
2-
--ink:#0a0c11; --panel:#0e1117; --panel2:#11151c; --line:#1b212c; --line2:#252c39;
3-
--tx:#e9ebf2; --mut:#8a93a6; --faint:#5a6374;
4-
--coral:#ff6a3d; --coral-dim:#ff6a3d33;
5-
--opaque:#6b7380; --summary:#f5b740; --transp:#46d6a0;
6-
}
7-
*{box-sizing:border-box}
8-
html,body{height:100%;margin:0}
9-
body{
10-
background:var(--ink);color:var(--tx);
11-
font-family:"Hanken Grotesk",system-ui,sans-serif;font-size:14px;
12-
background-image:linear-gradient(var(--line) 1px,transparent 1px),linear-gradient(90deg,var(--line) 1px,transparent 1px);
13-
background-size:34px 34px;background-position:-1px -1px;
14-
}
15-
.app{display:grid;grid-template-columns:236px 1fr 460px;height:100vh}
16-
.col{display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--line);background:rgba(10,12,17,.72);backdrop-filter:blur(6px)}
17-
.col:last-child{border-right:0;border-left:1px solid var(--line)}
18-
.brand{padding:18px 18px 14px;border-bottom:1px solid var(--line);display:flex;align-items:baseline;gap:8px}
19-
.brand .logo{font-family:"Instrument Serif",serif;font-size:30px;line-height:1}
20-
.brand .logo b{color:var(--coral);font-style:italic}
21-
.brand .tag{font-size:11px;color:var(--faint);font-style:italic;font-family:"Instrument Serif",serif}
22-
.navsec{padding:14px 12px 4px;font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--faint)}
23-
.item{display:flex;align-items:center;gap:9px;margin:2px 8px;padding:8px 10px;border-radius:9px;cursor:pointer;color:var(--mut);transition:.12s}
24-
.item:hover{background:var(--panel2);color:var(--tx)}
25-
.item.on{background:var(--coral-dim);color:var(--tx);box-shadow:inset 0 0 0 1px #ff6a3d44}
26-
.item .pip{width:7px;height:7px;border-radius:50%;background:var(--coral);box-shadow:0 0 8px var(--coral)}
27-
.item .mono{font-family:"JetBrains Mono",monospace;font-size:12px}
28-
.item .sub{margin-left:auto;font:500 11px "JetBrains Mono",monospace;color:var(--faint)}
29-
.runrow{display:flex;flex-direction:column;gap:2px;margin:2px 8px;padding:8px 10px;border-radius:9px;cursor:pointer;border:1px solid transparent}
30-
.runrow:hover{background:var(--panel2)} .runrow.on{border-color:var(--line2);background:var(--panel2)}
31-
.runrow .t{font-size:13px;color:var(--tx);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
32-
.runrow .m{font:500 10px "JetBrains Mono",monospace;color:var(--faint);display:flex;gap:8px}
33-
.spacer{flex:1}
34-
.foot{padding:12px 16px;border-top:1px solid var(--line);font:500 10px "JetBrains Mono",monospace;color:var(--faint)}
1+
@import "tailwindcss";
352

36-
.chead{padding:16px 22px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:12px}
37-
.chead .nm{font-family:"Instrument Serif",serif;font-size:24px}
38-
.chead .ds{font-size:12px;color:var(--mut)}
39-
.scroll{flex:1;overflow:auto;padding:22px 22px 8px}
40-
.msg{max-width:760px;margin:0 auto 18px;display:flex;gap:12px}
41-
.msg .who{flex:none;width:26px;height:26px;border-radius:7px;display:grid;place-items:center;font:700 11px "JetBrains Mono",monospace;margin-top:2px}
42-
.msg.user .who{background:#1b2230;color:var(--mut)} .msg.bot .who{background:var(--coral);color:#1a0a05}
43-
.msg .body{flex:1;line-height:1.6;white-space:pre-wrap;cursor:default}
44-
.empty{max-width:520px;margin:12vh auto;text-align:center;color:var(--mut)}
45-
.empty h1{font-family:"Instrument Serif",serif;font-weight:400;font-size:34px;color:var(--tx);margin:0 0 6px}
46-
.suggest{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:18px}
47-
.chip{border:1px solid var(--line2);border-radius:20px;padding:7px 13px;cursor:pointer;font-size:13px;color:var(--mut)}
48-
.chip:hover{border-color:var(--coral);color:var(--tx)}
49-
.composer{padding:14px 22px 20px;border-top:1px solid var(--line)}
50-
.box{max-width:760px;margin:0 auto;display:flex;gap:10px;background:var(--panel);border:1px solid var(--line2);border-radius:14px;padding:8px 8px 8px 16px;align-items:flex-end}
51-
.box:focus-within{border-color:#ff6a3d66}
52-
textarea{flex:1;background:transparent;border:0;outline:0;color:var(--tx);font:inherit;resize:none;max-height:160px;padding:8px 0}
53-
.send{flex:none;width:38px;height:38px;border:0;border-radius:10px;background:var(--coral);color:#1a0a05;font-size:17px;cursor:pointer}
54-
.send:disabled{opacity:.4;cursor:default}
3+
/* ── design tokens (OKLCH, dark, signature blue @ hue 250) ─────────────────── */
4+
@theme {
5+
--color-bg: oklch(0.1 0.005 250);
6+
--color-surface: oklch(0.14 0.012 250);
7+
--color-surface2: oklch(0.18 0.014 250);
8+
--color-fg: oklch(0.98 0.002 250);
9+
--color-muted: oklch(0.68 0.012 250);
10+
--color-faint: oklch(0.52 0.012 250);
11+
--color-line: oklch(0.28 0.012 250 / 0.55);
12+
--color-brand: oklch(0.62 0.19 250);
13+
--color-brand-fg: oklch(0.14 0.01 250);
5514

56-
.rhead{padding:14px 16px 0;border-bottom:1px solid var(--line)}
57-
.rtitle{display:flex;align-items:center;gap:8px;margin-bottom:10px}
58-
.rtitle .t{font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--faint)}
59-
.status{margin-left:auto;font:600 10px "JetBrains Mono",monospace;padding:3px 8px;border-radius:20px}
60-
.status.streaming{color:var(--coral);background:var(--coral-dim)} .status.done{color:var(--transp);background:#46d6a022} .status.idle{color:var(--faint);background:var(--panel2)} .status.error{color:#ff5d5d;background:#ff5d5d22}
61-
.tabs{display:flex;gap:2px}
62-
.tab{padding:8px 12px;font:600 11px "JetBrains Mono",monospace;color:var(--faint);cursor:pointer;border-bottom:2px solid transparent}
63-
.tab:hover{color:var(--mut)} .tab.on{color:var(--tx);border-bottom-color:var(--coral)}
64-
.rbody{flex:1;overflow:auto;position:relative}
65-
.pane{padding:16px}
66-
svg.dag{display:block}
67-
.edge{fill:none;stroke:var(--line2);stroke-width:1.5}
68-
.edge.live{stroke:var(--coral);stroke-width:2}
69-
.node rect{fill:var(--panel2);stroke:var(--line2);transition:.2s}
70-
.node .id{font:700 12px "JetBrains Mono",monospace;fill:var(--tx)}
71-
.node .knd{font:500 10px "JetBrains Mono",monospace;fill:var(--mut)}
72-
.node.pending rect{opacity:.55}
73-
.node.running rect{stroke:var(--coral);fill:#1a1410;filter:drop-shadow(0 0 10px var(--coral-dim))}
74-
.node.done rect{stroke:var(--transp)}
75-
.node.sel rect{stroke:#fff}
76-
.node{cursor:pointer}
77-
.ndot.pending{fill:var(--opaque)}.ndot.running{fill:var(--coral)}.ndot.done{fill:var(--transp)}
78-
.log{font:500 12px/1.7 "JetBrains Mono",monospace;white-space:pre-wrap}
79-
.log .ts{color:var(--faint)} .log b{color:var(--tx)}
80-
.lvl{font:700 9px "JetBrains Mono",monospace;letter-spacing:.06em;padding:2px 6px;border-radius:5px;margin-right:8px}
81-
.lvl.OPAQUE{background:#6b738022;color:var(--opaque)} .lvl.SUMMARY{background:#f5b74022;color:var(--summary)} .lvl.TRANSPARENT{background:#46d6a022;color:var(--transp)}
82-
.hrow{padding:9px 0;border-bottom:1px solid var(--line)}
83-
.hrow .nm{font:700 12px "JetBrains Mono",monospace}
84-
.hrow .v{margin-top:5px;font:500 12px/1.5 "JetBrains Mono",monospace;color:var(--mut);white-space:pre-wrap;word-break:break-word}
85-
.hrow .v.hidden{color:var(--faint);font-style:italic}
86-
.muted{color:var(--faint);padding:18px;text-align:center;font-size:13px}
87-
.answer{margin-top:16px;line-height:1.6;color:var(--tx);white-space:pre-wrap}
15+
/* projection levels — oya's own semantics */
16+
--color-opaque: oklch(0.62 0.02 250);
17+
--color-summary: oklch(0.8 0.14 85);
18+
--color-transp: oklch(0.78 0.15 165);
19+
--color-danger: oklch(0.66 0.2 20);
20+
21+
--radius: 0.75rem;
22+
--font-sans: var(--font-inter), system-ui, sans-serif;
23+
--font-mono: var(--font-mono-jb), ui-monospace, "SF Mono", monospace;
24+
25+
--shadow-glow: 0 0 22px oklch(0.62 0.19 250 / 0.35);
26+
--shadow-glow-green: 0 0 18px oklch(0.78 0.15 165 / 0.3);
27+
}
28+
29+
* {
30+
border-color: var(--color-line);
31+
}
32+
33+
html,
34+
body {
35+
height: 100%;
36+
}
37+
38+
body {
39+
margin: 0;
40+
background: var(--color-bg);
41+
color: var(--color-fg);
42+
font-family: var(--font-sans);
43+
font-size: 14px;
44+
-webkit-font-smoothing: antialiased;
45+
/* subtle full-page mesh glow */
46+
background-image:
47+
radial-gradient(at 0% 0%, oklch(0.62 0.19 250 / 0.08) 0px, transparent 45%),
48+
radial-gradient(at 100% 100%, oklch(0.62 0.19 290 / 0.06) 0px, transparent 45%);
49+
background-attachment: fixed;
50+
}
51+
52+
/* ── reusable surface treatments ──────────────────────────────────────────── */
53+
.glass {
54+
background: oklch(0.14 0.012 250 / 0.72);
55+
backdrop-filter: blur(14px) saturate(140%);
56+
}
57+
.glow {
58+
box-shadow: var(--shadow-glow);
59+
}
60+
.mono {
61+
font-family: var(--font-mono);
62+
}
63+
.scrollbar-thin::-webkit-scrollbar {
64+
width: 8px;
65+
height: 8px;
66+
}
67+
.scrollbar-thin::-webkit-scrollbar-thumb {
68+
background: var(--color-line);
69+
border-radius: 999px;
70+
}
71+
.scrollbar-thin::-webkit-scrollbar-track {
72+
background: transparent;
73+
}
74+
75+
/* projection badges */
76+
.lvl {
77+
font-family: var(--font-mono);
78+
font-weight: 700;
79+
font-size: 9px;
80+
letter-spacing: 0.06em;
81+
padding: 2px 6px;
82+
border-radius: 5px;
83+
}
84+
.lvl-OPAQUE {
85+
background: oklch(0.62 0.02 250 / 0.16);
86+
color: var(--color-opaque);
87+
}
88+
.lvl-SUMMARY {
89+
background: oklch(0.8 0.14 85 / 0.16);
90+
color: var(--color-summary);
91+
}
92+
.lvl-TRANSPARENT {
93+
background: oklch(0.78 0.15 165 / 0.16);
94+
color: var(--color-transp);
95+
}
96+
97+
/* ── React Flow theming ───────────────────────────────────────────────────── */
98+
.react-flow {
99+
--xy-background-color: transparent;
100+
--xy-edge-stroke-default: var(--color-line);
101+
--xy-edge-stroke-selected: var(--color-brand);
102+
}
103+
.react-flow__attribution {
104+
display: none;
105+
}
106+
.react-flow__handle {
107+
width: 7px;
108+
height: 7px;
109+
background: var(--color-brand);
110+
border: none;
111+
opacity: 0.85;
112+
}
113+
.react-flow__edge-path {
114+
stroke-width: 1.6;
115+
}
116+
.react-flow__edge.animated .react-flow__edge-path {
117+
stroke-dasharray: 5;
118+
animation: dashflow 0.6s linear infinite;
119+
}
120+
@keyframes dashflow {
121+
to {
122+
stroke-dashoffset: -10;
123+
}
124+
}
125+
.react-flow__controls {
126+
background: oklch(0.14 0.012 250 / 0.8);
127+
backdrop-filter: blur(8px);
128+
border: 1px solid var(--color-line);
129+
border-radius: 10px;
130+
overflow: hidden;
131+
box-shadow: none;
132+
}
133+
.react-flow__controls-button {
134+
background: transparent;
135+
border-bottom: 1px solid var(--color-line);
136+
color: var(--color-muted);
137+
fill: var(--color-muted);
138+
}
139+
.react-flow__controls-button:hover {
140+
background: var(--color-surface2);
141+
color: var(--color-fg);
142+
}
143+
144+
@keyframes breathe {
145+
0%,
146+
100% {
147+
box-shadow: 0 0 0 0 oklch(0.62 0.19 250 / 0.35);
148+
}
149+
50% {
150+
box-shadow: 0 0 0 6px oklch(0.62 0.19 250 / 0);
151+
}
152+
}
153+
.animate-breathe {
154+
animation: breathe 1.8s ease-in-out infinite;
155+
}

apps/playground/app/layout.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
import type { ReactNode } from "react";
2+
import { Inter, JetBrains_Mono } from "next/font/google";
3+
import "@xyflow/react/dist/style.css";
24
import "./globals.css";
35

6+
const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap" });
7+
const jetbrains = JetBrains_Mono({ subsets: ["latin"], variable: "--font-mono-jb", display: "swap" });
8+
49
export const metadata = {
510
title: "oya studio",
6-
description: "Plan-don't-react agent studio.",
11+
description: "Plan-don't-react agent studio — watch each plan execute, every value at its projection level.",
712
};
813

914
export default function RootLayout({ children }: { children: ReactNode }) {
1015
return (
11-
<html lang="en">
12-
<head>
13-
<link rel="preconnect" href="https://fonts.googleapis.com" />
14-
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
15-
<link
16-
href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500;700&family=Hanken+Grotesk:wght@400;500;600;700&display=swap"
17-
rel="stylesheet"
18-
/>
19-
</head>
16+
<html lang="en" className={`dark ${inter.variable} ${jetbrains.variable}`}>
2017
<body>{children}</body>
2118
</html>
2219
);

0 commit comments

Comments
 (0)