Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changeset/lucky-worms-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---

---
9 changes: 8 additions & 1 deletion packages/genui/a2ui-playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import { DemosListPage } from './pages/DemosListPage.js';
import { DemosPage } from './pages/DemosPage.js';
import { OpenUIComponentsPage } from './pages/OpenUIComponentsPage.js';
import { OpenUIDemosPage } from './pages/OpenUIDemosPage.js';
import { PlaybackPage } from './pages/PlaybackPage.js';
import type { Protocol, ProtocolName } from './utils/protocol.js';
import { DEFAULT_PROTOCOL, getProtocol } from './utils/protocol.js';

type Tab = 'create' | 'examples' | 'components';
type Tab = 'create' | 'examples' | 'components' | 'playback';

interface TabDef {
id: Tab;
Expand All @@ -29,6 +30,7 @@ const A2UI_TABS: TabDef[] = [
{ id: 'create', label: 'Create' },
{ id: 'examples', label: 'Examples' },
{ id: 'components', label: 'Components' },
{ id: 'playback', label: 'Playback' },
];

const OPENUI_TABS: TabDef[] = [
Expand Down Expand Up @@ -68,6 +70,9 @@ function parseHash(hash: string): Route {
if (rest[0] === 'chat' || rest[0] === 'create') {
return { protocol, tab: 'create' };
}
if (rest[0] === 'playback') {
return { protocol, tab: 'playback' };
}
Comment thread
HuJean marked this conversation as resolved.
// OpenUI has no create tab, default to examples.
if (protocol.name === 'openui') return { protocol, tab: 'examples' };
return { protocol, tab: 'create' };
Expand Down Expand Up @@ -162,6 +167,8 @@ export function App() {
theme={theme}
/>
);
case 'playback':
return <PlaybackPage key='playback' protocol={protocol} />;
default:
return <AIChatPage key='create' protocol={protocol} />;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/genui/a2ui-playground/src/demos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,5 @@ export const SUPPORTED_COMPONENTS = tagsFromMessages([
...STATIC_DEMOS.flatMap((d) => d.messages as unknown[]),
...DYNAMIC_PRESETS.flatMap((d) => d.messages as unknown[]),
]);

export const PLAYBACK_SCENARIOS = [...EXTENDED_STATIC_DEMOS];
156 changes: 156 additions & 0 deletions packages/genui/a2ui-playground/src/pages/AIChatPage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/* ═══════════════════════════════════════════
Create Page
═══════════════════════════════════════════ */

.chatPage {
display: flex;
flex: 1;
overflow: hidden;
}

.chatPage.resizing {
user-select: none;
}

.chatPanel {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}

.chatHeader {
padding: 12px 20px;
border-bottom: 1px solid var(--geist-border);
background: var(--geist-background);
flex-shrink: 0;
}

.chatHeaderTitleRow {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}

.chatHeaderTitle {
font-size: 15px;
font-weight: 600;
margin: 0;
}

.constructionBadge {
display: inline-flex;
align-items: center;
height: 20px;
padding: 0 8px;
border: 1px solid var(--geist-border);
border-radius: 999px;
background: var(--geist-surface);
color: var(--geist-secondary);
font-size: 11px;
font-weight: 600;
line-height: 1;
white-space: nowrap;
}

.chatHeaderSub {
font-size: 12px;
color: var(--geist-secondary);
margin: 2px 0 0;
}

.chatMessages {
flex: 1;
overflow-y: auto;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
}

.chatMessage {
max-width: 80%;
padding: 10px 14px;
border-radius: var(--geist-radius-lg);
font-size: 14px;
line-height: 1.5;
word-break: break-word;
}
Comment thread
HuJean marked this conversation as resolved.

.chatMessageUser {
align-self: flex-end;
background: var(--geist-accent);
color: var(--geist-accent-foreground);
border-bottom-right-radius: 4px;
}

.chatMessageAI {
align-self: flex-start;
background: var(--geist-surface);
border: 1px solid var(--geist-border);
border-bottom-left-radius: 4px;
}

.chatInputArea {
padding: 12px 20px;
border-top: 1px solid var(--geist-border);
background: var(--geist-background);
display: flex;
gap: 8px;
flex-shrink: 0;
}

.chatInput {
flex: 1;
height: 40px;
padding: 0 14px;
border: 1px solid var(--geist-border);
border-radius: var(--geist-radius-md);
font-size: 14px;
background: var(--geist-background);
color: var(--geist-foreground);
outline: none;
transition: border-color var(--geist-transition);
}

.chatInput:focus {
border-color: var(--geist-foreground);
}

.chatInput::placeholder {
color: var(--geist-secondary);
}

.chatSendBtn {
height: 40px;
padding: 0 20px;
border: none;
border-radius: var(--geist-radius-md);
background: var(--geist-accent);
color: var(--geist-accent-foreground);
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: opacity var(--geist-transition);
flex-shrink: 0;
}

.chatSendBtn:hover {
opacity: 0.85;
}

.chatSendBtn:active {
transform: scale(0.97);
}

@media (max-width: 980px) {
.chatPage {
flex-direction: column;
}

.chatPanel {
min-height: 400px;
flex: 0 0 auto;
}
}
2 changes: 2 additions & 0 deletions packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// LICENSE file in the root directory of this source tree.
import { useCallback, useEffect, useRef, useState } from 'react';

import './AIChatPage.css';

import { useResizablePanels } from '../hooks/useResizablePanels.js';
import type { Protocol } from '../utils/protocol.js';

Expand Down
Loading
Loading