diff --git a/packages/agent-playground/app/mock-scenarios.ts b/packages/agent-playground/app/mock-scenarios.ts
new file mode 100644
index 000000000..c873d6266
--- /dev/null
+++ b/packages/agent-playground/app/mock-scenarios.ts
@@ -0,0 +1,238 @@
+import type { AgentSession, Theme } from "../../react-grab/src/types";
+
+interface MockScenario {
+ id: string;
+ name: string;
+ description: string;
+ session: AgentSession;
+ theme: Theme;
+}
+
+export const MOCK_SCENARIOS: MockScenario[] = [
+ {
+ id: "scenario-button-styling",
+ name: "Button Styling",
+ description: "Style a button with colors and effects",
+ session: {
+ id: "playground-session-1",
+ context: {
+ content: [''],
+ prompt:
+ "Make this button stand out with a gradient background and shadow",
+ options: {},
+ },
+ lastStatus: "Ready to apply changes",
+ isStreaming: false,
+ createdAt: Date.now(),
+ lastUpdatedAt: Date.now(),
+ position: { x: 100, y: 100 },
+ selectionBounds: [
+ {
+ x: 50,
+ y: 50,
+ width: 140,
+ height: 45,
+ borderRadius: "8px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "button",
+ componentName: "CTAButton",
+ },
+ theme: {
+ enabled: true,
+ hue: 280,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ },
+ {
+ id: "scenario-card-layout",
+ name: "Card Layout",
+ description: "Adjust card spacing and shadows",
+ session: {
+ id: "playground-session-2",
+ context: {
+ content: [
+ '

Feature Title
Feature description text
',
+ ],
+ prompt:
+ "Improve the card layout with better spacing and a subtle shadow",
+ options: {},
+ },
+ lastStatus: "Changes applied",
+ isStreaming: false,
+ createdAt: Date.now() - 60000,
+ lastUpdatedAt: Date.now() - 55000,
+ position: { x: 200, y: 150 },
+ selectionBounds: [
+ {
+ x: 150,
+ y: 120,
+ width: 300,
+ height: 200,
+ borderRadius: "12px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "div",
+ componentName: "FeatureCard",
+ },
+ theme: {
+ enabled: true,
+ hue: 200,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ },
+ {
+ id: "scenario-form-input",
+ name: "Form Input",
+ description: "Style form input with focus states",
+ session: {
+ id: "playground-session-3",
+ context: {
+ content: [
+ '',
+ ],
+ prompt: "Add focus states and improve the input styling",
+ options: {},
+ },
+ lastStatus: "Streaming updates…",
+ isStreaming: true,
+ createdAt: Date.now() - 10000,
+ lastUpdatedAt: Date.now() - 1000,
+ position: { x: 150, y: 250 },
+ selectionBounds: [
+ {
+ x: 100,
+ y: 220,
+ width: 320,
+ height: 48,
+ borderRadius: "6px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "input",
+ },
+ theme: {
+ enabled: true,
+ hue: 140,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ },
+ {
+ id: "scenario-navigation",
+ name: "Navigation Bar",
+ description: "Responsive navigation with hover effects",
+ session: {
+ id: "playground-session-4",
+ context: {
+ content: [
+ '',
+ ],
+ prompt:
+ "Make this navigation responsive and add smooth hover transitions",
+ options: {},
+ },
+ lastStatus: "Ready to apply",
+ isStreaming: false,
+ createdAt: Date.now() - 120000,
+ lastUpdatedAt: Date.now() - 115000,
+ position: { x: 50, y: 50 },
+ selectionBounds: [
+ {
+ x: 20,
+ y: 20,
+ width: 600,
+ height: 60,
+ borderRadius: "0",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "nav",
+ componentName: "MainNavigation",
+ },
+ theme: {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ },
+ {
+ id: "scenario-minimal-theme",
+ name: "Minimal Theme",
+ description: "Test with minimal UI overlays",
+ session: {
+ id: "playground-session-5",
+ context: {
+ content: ['Minimal Example
'],
+ prompt: "Apply minimal styling with reduced visual noise",
+ options: {},
+ },
+ lastStatus: "Changes applied successfully",
+ isStreaming: false,
+ createdAt: Date.now() - 240000,
+ lastUpdatedAt: Date.now() - 235000,
+ position: { x: 180, y: 120 },
+ selectionBounds: [
+ {
+ x: 120,
+ y: 80,
+ width: 400,
+ height: 100,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "div",
+ componentName: "Container",
+ },
+ theme: {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: false },
+ grabbedBoxes: { enabled: false },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: false },
+ toolbar: { enabled: true },
+ },
+ },
+];
+
+export const getScenarioById = (
+ scenarioId: string,
+): MockScenario | undefined => {
+ return MOCK_SCENARIOS.find((scenario) => scenario.id === scenarioId);
+};
+
+export const getScenarioNames = (): Array<{
+ id: string;
+ name: string;
+ description: string;
+}> => {
+ return MOCK_SCENARIOS.map((scenario) => ({
+ id: scenario.id,
+ name: scenario.name,
+ description: scenario.description,
+ }));
+};
diff --git a/packages/react-grab/e2e/fixtures/session-fixtures.ts b/packages/react-grab/e2e/fixtures/session-fixtures.ts
new file mode 100644
index 000000000..8b58c302c
--- /dev/null
+++ b/packages/react-grab/e2e/fixtures/session-fixtures.ts
@@ -0,0 +1,168 @@
+import type { AgentSession } from "../../src/types";
+
+export const TEST_SESSION_BASIC: AgentSession = {
+ id: "test-session-basic",
+ context: {
+ content: [""],
+ prompt: "Style this button",
+ options: {},
+ },
+ lastStatus: "Completed",
+ isStreaming: false,
+ createdAt: Date.now() - 10000,
+ lastUpdatedAt: Date.now() - 9000,
+ position: { x: 100, y: 100 },
+ selectionBounds: [
+ {
+ x: 50,
+ y: 50,
+ width: 100,
+ height: 40,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "button",
+};
+
+export const TEST_SESSION_STREAMING: AgentSession = {
+ id: "test-session-streaming",
+ context: {
+ content: ['Card Content
'],
+ prompt: "Update card styling",
+ options: {},
+ },
+ lastStatus: "Processing…",
+ isStreaming: true,
+ createdAt: Date.now() - 5000,
+ lastUpdatedAt: Date.now() - 1000,
+ position: { x: 200, y: 150 },
+ selectionBounds: [
+ {
+ x: 150,
+ y: 100,
+ width: 250,
+ height: 150,
+ borderRadius: "8px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "div",
+ componentName: "Card",
+};
+
+export const TEST_SESSION_WITH_ERROR: AgentSession = {
+ id: "test-session-error",
+ context: {
+ content: [''],
+ prompt: "Apply invalid CSS",
+ options: {},
+ },
+ lastStatus: "Failed",
+ isStreaming: false,
+ createdAt: Date.now() - 15000,
+ lastUpdatedAt: Date.now() - 14000,
+ position: { x: 150, y: 250 },
+ selectionBounds: [
+ {
+ x: 100,
+ y: 220,
+ width: 300,
+ height: 45,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "input",
+ error: "Invalid CSS syntax",
+};
+
+export const TEST_SESSION_WITH_COMPONENT: AgentSession = {
+ id: "test-session-component",
+ context: {
+ content: [''],
+ prompt: "Style navigation",
+ options: {},
+ },
+ lastStatus: "Completed successfully",
+ isStreaming: false,
+ createdAt: Date.now() - 30000,
+ lastUpdatedAt: Date.now() - 28000,
+ position: { x: 50, y: 50 },
+ selectionBounds: [
+ {
+ x: 20,
+ y: 20,
+ width: 400,
+ height: 50,
+ borderRadius: "0",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "nav",
+ componentName: "Navigation",
+};
+
+export const TEST_SESSION_NESTED: AgentSession = {
+ id: "test-session-nested",
+ context: {
+ content: ["Nested Text
"],
+ prompt: "Update nested element",
+ options: {},
+ sessionId: "test-session-basic",
+ },
+ lastStatus: "In progress",
+ isStreaming: true,
+ createdAt: Date.now() - 3000,
+ lastUpdatedAt: Date.now() - 500,
+ position: { x: 180, y: 120 },
+ selectionBounds: [
+ {
+ x: 140,
+ y: 90,
+ width: 180,
+ height: 80,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "strong",
+};
+
+export const ALL_TEST_SESSIONS: AgentSession[] = [
+ TEST_SESSION_BASIC,
+ TEST_SESSION_STREAMING,
+ TEST_SESSION_WITH_ERROR,
+ TEST_SESSION_WITH_COMPONENT,
+ TEST_SESSION_NESTED,
+];
+
+export const createTestSession = (
+ overrides: Partial = {},
+): AgentSession => {
+ return {
+ id: `test-session-${Date.now()}`,
+ context: {
+ content: ["Test Element
"],
+ prompt: "Test prompt",
+ options: {},
+ },
+ lastStatus: "Ready",
+ isStreaming: false,
+ createdAt: Date.now(),
+ lastUpdatedAt: Date.now(),
+ position: { x: 100, y: 100 },
+ selectionBounds: [
+ {
+ x: 50,
+ y: 50,
+ width: 200,
+ height: 100,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "div",
+ ...overrides,
+ };
+};
diff --git a/packages/react-grab/e2e/fixtures/theme-fixtures.ts b/packages/react-grab/e2e/fixtures/theme-fixtures.ts
new file mode 100644
index 000000000..1ec10b45e
--- /dev/null
+++ b/packages/react-grab/e2e/fixtures/theme-fixtures.ts
@@ -0,0 +1,102 @@
+import type { Theme } from "../../src/types";
+
+export const TEST_THEME_DEFAULT: Theme = {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+};
+
+export const TEST_THEME_BLUE: Theme = {
+ enabled: true,
+ hue: 200,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+};
+
+export const TEST_THEME_PURPLE: Theme = {
+ enabled: true,
+ hue: 280,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+};
+
+export const TEST_THEME_GREEN: Theme = {
+ enabled: true,
+ hue: 140,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+};
+
+export const TEST_THEME_MINIMAL: Theme = {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: false },
+ grabbedBoxes: { enabled: false },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: false },
+ toolbar: { enabled: true },
+};
+
+export const TEST_THEME_DISABLED: Theme = {
+ enabled: false,
+ hue: 0,
+ selectionBox: { enabled: false },
+ dragBox: { enabled: false },
+ grabbedBoxes: { enabled: false },
+ elementLabel: { enabled: false },
+ crosshair: { enabled: false },
+ toolbar: { enabled: false },
+};
+
+export const TEST_THEME_SELECTION_ONLY: Theme = {
+ enabled: true,
+ hue: 180,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: false },
+ grabbedBoxes: { enabled: false },
+ elementLabel: { enabled: false },
+ crosshair: { enabled: false },
+ toolbar: { enabled: false },
+};
+
+export const ALL_TEST_THEMES: Record = {
+ default: TEST_THEME_DEFAULT,
+ blue: TEST_THEME_BLUE,
+ purple: TEST_THEME_PURPLE,
+ green: TEST_THEME_GREEN,
+ minimal: TEST_THEME_MINIMAL,
+ disabled: TEST_THEME_DISABLED,
+ selectionOnly: TEST_THEME_SELECTION_ONLY,
+};
+
+export const createTestTheme = (overrides: Partial = {}): Theme => {
+ return {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ ...overrides,
+ };
+};
diff --git a/packages/website/lib/mock-data.ts b/packages/website/lib/mock-data.ts
new file mode 100644
index 000000000..6dcf4e9b8
--- /dev/null
+++ b/packages/website/lib/mock-data.ts
@@ -0,0 +1,218 @@
+import type { AgentSession, Theme } from "../../react-grab/src/types";
+import type { ToolbarState } from "../../react-grab/src/components/toolbar/state";
+
+export const isDemoMode = (): boolean => {
+ if (typeof window === "undefined") return false;
+ return window.location.search.includes("demo=true");
+};
+
+export const MOCK_SESSIONS: AgentSession[] = [
+ {
+ id: "session-demo-1",
+ context: {
+ content: [''],
+ prompt: "Make this button blue with rounded corners",
+ options: {},
+ },
+ lastStatus: "Successfully applied style changes",
+ isStreaming: false,
+ createdAt: Date.now() - 300000,
+ lastUpdatedAt: Date.now() - 295000,
+ position: { x: 120, y: 100 },
+ selectionBounds: [
+ {
+ x: 50,
+ y: 50,
+ width: 120,
+ height: 40,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "button",
+ componentName: "SubmitButton",
+ },
+ {
+ id: "session-demo-2",
+ context: {
+ content: [
+ 'Product Title
Product description goes here
',
+ ],
+ prompt: "Add a subtle shadow and increase spacing",
+ options: {},
+ },
+ lastStatus: "Changes applied successfully",
+ isStreaming: false,
+ createdAt: Date.now() - 180000,
+ lastUpdatedAt: Date.now() - 175000,
+ position: { x: 300, y: 200 },
+ selectionBounds: [
+ {
+ x: 200,
+ y: 150,
+ width: 280,
+ height: 160,
+ borderRadius: "8px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "div",
+ componentName: "ProductCard",
+ },
+ {
+ id: "session-demo-3",
+ context: {
+ content: [''],
+ prompt: "Make navigation responsive and add hover effects",
+ options: {},
+ sessionId: "session-demo-2",
+ },
+ lastStatus: "Streaming updates…",
+ isStreaming: true,
+ createdAt: Date.now() - 30000,
+ lastUpdatedAt: Date.now() - 1000,
+ position: { x: 150, y: 50 },
+ selectionBounds: [
+ {
+ x: 20,
+ y: 20,
+ width: 400,
+ height: 50,
+ borderRadius: "0",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "nav",
+ },
+ {
+ id: "session-demo-4",
+ context: {
+ content: [''],
+ prompt: "Style this input with focus states",
+ options: {},
+ },
+ lastStatus: "Failed to apply changes",
+ isStreaming: false,
+ createdAt: Date.now() - 90000,
+ lastUpdatedAt: Date.now() - 85000,
+ position: { x: 250, y: 300 },
+ selectionBounds: [
+ {
+ x: 100,
+ y: 250,
+ width: 300,
+ height: 45,
+ borderRadius: "4px",
+ transform: "translate(0, 0)",
+ },
+ ],
+ tagName: "input",
+ error: "Unable to parse CSS syntax",
+ },
+];
+
+export const MOCK_TOOLBAR_STATES: Record = {
+ bottom: {
+ edge: "bottom",
+ ratio: 0.5,
+ collapsed: false,
+ },
+ top: {
+ edge: "top",
+ ratio: 0.3,
+ collapsed: false,
+ },
+ left: {
+ edge: "left",
+ ratio: 0.4,
+ collapsed: true,
+ },
+ right: {
+ edge: "right",
+ ratio: 0.6,
+ collapsed: false,
+ },
+};
+
+export const MOCK_THEMES: Record = {
+ default: {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ blue: {
+ enabled: true,
+ hue: 200,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ purple: {
+ enabled: true,
+ hue: 280,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ green: {
+ enabled: true,
+ hue: 140,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: true },
+ grabbedBoxes: { enabled: true },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: true },
+ toolbar: { enabled: true },
+ },
+ minimal: {
+ enabled: true,
+ hue: 0,
+ selectionBox: { enabled: true },
+ dragBox: { enabled: false },
+ grabbedBoxes: { enabled: false },
+ elementLabel: { enabled: true },
+ crosshair: { enabled: false },
+ toolbar: { enabled: true },
+ },
+};
+
+export const getMockSessions = (): AgentSession[] => {
+ return isDemoMode() ? MOCK_SESSIONS : [];
+};
+
+export const getMockToolbarState = (
+ key: string = "bottom",
+): ToolbarState | null => {
+ if (!isDemoMode()) return null;
+ return MOCK_TOOLBAR_STATES[key] || MOCK_TOOLBAR_STATES.bottom;
+};
+
+export const getMockTheme = (key: string = "default"): Theme | null => {
+ if (!isDemoMode()) return null;
+ return MOCK_THEMES[key] || MOCK_THEMES.default;
+};
+
+export const initializeDemoMode = (): {
+ sessions: AgentSession[];
+ toolbarState: ToolbarState;
+ theme: Theme;
+} | null => {
+ if (!isDemoMode()) return null;
+
+ return {
+ sessions: MOCK_SESSIONS,
+ toolbarState: MOCK_TOOLBAR_STATES.bottom,
+ theme: MOCK_THEMES.default,
+ };
+};