Skip to content

feat: add live playground for interactive schema demonstration - #8

Merged
huangyiirene merged 6 commits into
mainfrom
copilot/add-live-playground
Jan 13, 2026
Merged

feat: add live playground for interactive schema demonstration#8
huangyiirene merged 6 commits into
mainfrom
copilot/add-live-playground

Conversation

CopilotAI commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

Implements a split-view playground to demonstrate Object UI's schema-driven rendering without requiring backend infrastructure.

Implementation

New Application: apps/playground/

  • Split-view interface: example selector | JSON editor | live preview
  • 7 curated examples across primitives, layouts, and forms
  • Real-time JSON validation with error display
  • Responsive viewport toggles (desktop/tablet/mobile)
  • One-click schema export

Workspace Integration

  • Added apps/* to monorepo configuration
  • New scripts: playground:dev, playground:build, playground:preview

Technical Decisions

  • Textarea editor instead of Monaco (avoids CDN dependencies in restricted environments)
  • Direct SchemaRenderer integration demonstrating standalone usage
  • Tailwind-native examples showing className customization

Examples Structure

// apps/playground/src/data/examples.tsexportconstexamples={'button-variants': `{ "type": "button", "label": "Purple Custom Button", "className": "bg-purple-500 hover:bg-purple-700 text-white" }`,'dashboard': `{ /* KPI cards + responsive grid */ }`,// ... 5 more examples};exportconstexampleCategories={'Primitives': ['simple-page','input-states','button-variants'],'Layouts': ['grid-layout','dashboard','tabs-demo'],'Forms': ['form-demo']};

Screenshots

Dashboard Example
Full playground interface showing JSON editor and live dashboard preview

Button Variants with Custom Tailwind Styling
All Shadcn button variants plus custom purple button

Responsive Preview Modes
Mobile viewport showing layout adjustments

Usage

pnpm playground:dev # http://localhost:5174
pnpm playground:build
Original prompt

This section details on the original issue you should resolve

<issue_title>构建一个 Live Playground (实时演练场) (用于展示引擎能力)</issue_title>
<issue_description>对于 Object UI 这样一个“元数据驱动”的渲染引擎,Examples(示例/演示) 的设计至关重要。

普通的组件库(如 AntD)只需要展示“代码 vs 组件”。
但你需要展示的是 “JSON Schema vs 界面”。

** 构建一个 Live Playground (实时演练场) (用于展示引擎能力)。

我们重点讨论如何构建这个 Live Playground,因为这是你项目的“门面”。


1. 架构位置

建议在 Monorepo 中创建一个独立的 Vite 应用:

packages/
apps/
└── playground/ # 👈 对外发布的演示站点
├── package.json
├── src/
│ ├── data/ # 预置的 JSON 案例
│ ├── layout/ # 演练场的布局框架
│ └── App.tsx
└── vite.config.ts

2. 核心交互设计:Split View (左右分屏)

这是低代码引擎的标准演示形态。

  • 左侧 (Editor): Monaco Editor (VS Code 风格编辑器),显示 JSON/YAML。
  • 右侧 (Preview):<SchemaRenderer /> 渲染结果。
  • 功能:
  • 实时编译: 左侧修改 JSON,右侧毫秒级更新。
  • 错误高亮: 如果 JSON 格式错了,或者 Schema 校验不通过,直接标红。

3. 内容规划:你应该展示哪些 Case?

不要只放几个按钮,要按场景分类,证明你的引擎是“全能”的。

A. 基础原子 (Primitives)

展示你对 Shadcn 的封装能力。

  • input.json: 各种状态的输入框(Required, Disabled, Error)。
  • button.json: 不同 Level (Primary, Ghost, Destructive) 的按钮。

B. 复杂布局 (Layouts) - 这是你的杀手锏

证明你能搞定 B 端复杂的排版。

  • grid-layout.json: 嵌套的 Grid,响应式 (col-span-1 md:col-span-2)。
  • dashboard.json: 上面是 KPI 卡片,下面是图表和表格。
  • tabs.json: 选项卡切换。

C. 数据联动 (Interactivity)

证明你不是静态的,支持数据域 (DataScope)。

  • form-linkage.json:

  • 当“国家”选择“中国”时,“省份”下拉框才显示。

  • 表达式:visibleOn: "${country === 'cn'}"

  • crud-table.json: 一个带搜索栏、分页、操作列的完整表格。


4. 代码实现参考 (The Playground App)

你需要安装 @monaco-editor/react 来实现代码编辑体验。

// apps/playground/src/App.tsximportReact,{useState,useEffect}from'react';importEditorfrom'@monaco-editor/react';import{SchemaRenderer}from'@object-ui/react';import{standardComponents}from'@object-ui/components';import{examples}from'./data';// 预置的案例列表exportdefaultfunctionPlayground(){const[selectedExample,setSelectedExample]=useState('dashboard');const[code,setCode]=useState(examples['dashboard']);const[schema,setSchema]=useState(null);// 实时解析 JSONuseEffect(()=>{try{constparsed=JSON.parse(code);setSchema(parsed);}catch(e){// JSON 语法错误时保持上一次的渲染,或显示错误提示}},[code]);return(<divclassName="flex h-screen w-screen">{/* 1. 侧边栏:选择案例 */}<asideclassName="w-64 bg-slate-50 border-r p-4"><h1className="font-bold mb-4">Object UI Examples</h1>{Object.keys(examples).map(key=>(<buttonkey={key}onClick={()=>{setSelectedExample(key);setCode(examples[key]);}}className={`block w-full text-left px-2 py-1 rounded ${key===selectedExample ? 'bg-blue-100 text-blue-600' : ''}`}>{key}</button>))}</aside>{/* 2. 左侧:代码编辑器 */}<divclassName="w-1/2 h-full border-r"><Editorheight="100%"defaultLanguage="json"value={code}onChange={(val)=>setCode(val||'')}options={{minimap: {enabled: false},fontSize: 14}}/></div>{/* 3. 右侧:实时预览 */}<divclassName="w-1/2 h-full bg-white overflow-auto p-8"><divclassName="max-w-4xl mx-auto border rounded-lg shadow-sm p-6 bg-white">{schema ? (<SchemaRendererschema={schema}components={standardComponents}// 模拟数据源,证明是 Standalone 的dataSource={{find: async()=>[]}}/>) : (<divclassName="text-red-500">Invalid JSON</div>)}</div></div></div>);}

5. 关键卖点植入

在 Playground 里,你还需要通过一些小细节来强化你的产品定位:

  1. Tailwind Class 编辑:
  • 在演示 button.json 时,故意加一行 "className": "bg-purple-500 hover:bg-purple-700"
  • 让用户修改这个字符串,右边按钮颜色立马变。
  • 目的: 展示 "Tailwind Native" 的威力。
  1. 移动端预览模式:
  • 在右侧预览区加一个 [手机/平板/桌面] 的切换按钮,调整容器宽度。
  • 目的: 展示 Responsive Grid 的能力。
  1. Schema 导出:
  • 加一个 "Copy Schema" 按钮。
  • 目的: 方便开发者直接把调好的配置复制到他们的项目中。

总结

你的 apps/playground 是最好的销售工具。
它不需要后端,不需要 ObjectOS。它只需要证明:“给我一段 JSON,我还你一个漂亮的界面。”</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

CopilotAIand others added 4 commits January 13, 2026 18:23
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a Live Playground application for Object UI - a standalone interactive demo environment that showcases the schema-driven rendering engine's capabilities through real-time JSON editing and live preview.

Changes:

  • Created a new Vite-based playground application in apps/playground with split-view interface (example gallery, JSON editor, and live preview)
  • Added 7 curated example schemas organized into three categories: Primitives, Layouts, and Forms
  • Implemented responsive viewport toggles and one-click schema copy functionality
  • Updated workspace configuration to include the new apps/* directory

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
pnpm-workspace.yamlAdded apps/* to workspace packages
package.jsonAdded playground development, build, and preview scripts
apps/playground/vite.config.tsConfigured Vite with path aliases to monorepo packages
apps/playground/tsconfig.jsonTypeScript configuration for the playground app
apps/playground/tailwind.config.jsTailwind CSS configuration matching Shadcn design system
apps/playground/src/main.tsxReact application entry point
apps/playground/src/index.cssTailwind base styles and CSS variables for theming
apps/playground/src/data/examples.tsSeven example schemas demonstrating various UI capabilities
apps/playground/src/App.tsxMain playground component with split-view layout
apps/playground/postcss.config.jsPostCSS configuration for Tailwind processing
apps/playground/package.jsonPlayground dependencies and scripts
apps/playground/index.htmlHTML entry point for the playground
apps/playground/README.mdDocumentation for the playground application
apps/playground/.gitignoreStandard Node.js project ignore patterns
README.mdRemoved trailing empty lines
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment threadapps/playground/README.md Outdated
export default function Playground() {
const [selectedExample, setSelectedExample] = useState<ExampleKey>('dashboard');
const [code, setCode] = useState(examples['dashboard']);
const [schema, setSchema] = useState<any>(null);

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema state uses any type which bypasses TypeScript's type checking. Consider using a more specific type from @object-ui/types or define an interface for the schema structure to maintain type safety.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +4
/**
* Predefined JSON schema examples for the Object UI Playground
* Organized by category to showcase different capabilities
*/

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file defines example schemas as template strings but lacks JSDoc annotations for the individual examples and exported types. According to CodingGuidelineID 1000000, properties in the Schema should have JSDoc documentation to enable auto-generated documentation for the open-source community. Add JSDoc comments for the examples object, ExampleKey type, and exampleCategories to document their purpose and structure.

Copilot generated this review using guidance from repository custom instructions.
}
`}
>
{key.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ')}

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline string transformation logic for converting kebab-case to Title Case is complex and duplicates formatting logic. Extract this into a utility function (e.g., formatExampleName) to improve readability and maintainability.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

CopilotAI changed the title [WIP] Add Live Playground to showcase engine capabilitiesfeat: add live playground for interactive schema demonstrationJan 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

CopilotAI requested a review from hotlongJanuary 13, 2026 18:38
@huangyiirene
huangyiirene marked this pull request as ready for review January 13, 2026 18:39
@huangyiirene
huangyiirene merged commit 8a2c443 into mainJan 13, 2026
1 of 5 checks passed
CopilotAI added a commit that referenced this pull request Jan 24, 2026
- Fix handleExportCSV to guard on gridRef.current?.api (issue #1)
- Add dedicated onContextMenuAction callback instead of overloading onCellClicked (issue #2)
- Remove icon property from customItems to prevent HTML injection (issue #3)
- Remove validation claim from README - only basic AG Grid editing (issue #4)
- Add test assertions for all new inputs (editable, exportConfig, etc.) (issue #5)
- Fix onExport type to only support 'csv' format (issue #6)
- Remove unused ColumnConfig properties (autoSize, groupable) (issue #9)
- Type schema props with proper interfaces instead of 'any' (issue #10)
- Update export description to only mention CSV (issue #11)
- Add AG Grid Community vs Enterprise section to docs (issue #8)
- Update README and docs with new callback and clarifications
All tests pass (8/8), lint clean (0 errors)
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
CopilotAI added a commit that referenced this pull request Feb 20, 2026
…warning, i18n fallback
- Issue #1: Normalize `in`/`not in` operators to backend-compatible `or`/`and` of `=`/`!=`
- Issue #2: Filter merging now validates and filters empty conditions
- Issue #3: CSV export safely serializes arrays (semicolon-separated) and objects (JSON)
- Issue #5: Request counter prevents stale data from overwriting latest results
- Issue #6: PullToRefresh resets pull distance immediately to prevent UI lock
- Issue #7: $top configurable via schema.pagination, data limit warning shown
- Issue #8: Extended i18n fallback translations for all ListView labels
- Issue #9: Defensive null checks in effectiveFields for mismatched objectDef
- Issue #10: Added FilterNormalization, Export, and DataFetch test suites
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
CopilotAI added a commit that referenced this pull request Feb 23, 2026
- #39 showRecordCount: conditionally show/hide record count bar
- #24 rowHeight: add short and extra_tall mapping in ListView + bridge
- #7 sort: parse legacy string format "field desc"
- #22 description: render view description below toolbar
- #40 allowPrinting: add print button with window.print()
- #31 virtualScroll: forward flag to grid view schema
- #35 userActions: wire sort/search/filter/rowHeight to toolbar visibility
- #38 addRecord: render "+ Add Record" button from spec config
- #37 tabs: render tab bar UI for view tabs
- #9 filterableFields: restrict FilterBuilder to whitelist fields
- #8 searchableFields: scope search queries to specified fields
- #36 appearance: wire showDescription and allowedVisualizations
- #16 pageSizeOptions: add page size selector UI in status bar
- #17-21: use spec kanban/calendar/gantt/gallery/timeline configs
- #20 gallery: add typed GalleryConfig to ListViewSchema
- #21 timeline: add typed TimelineConfig to ListViewSchema
- Bridge: add short/extra_tall density mapping, filterableFields pass-through
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
os-zhuang added a commit that referenced this pull request Jul 5, 2026
… — refresh data, don't rebuild UI (#2269) (#2274)
P1 of #2269, plus the P2/P3 guardrails:
- @object-ui/react: notifyDataChanged / useDataInvalidation /
subscribeDataChanges + useMutationInvalidationBridge(dataSource), which
fans every dataSource write (MutationEvent — the bus list views already
use) onto one seam. The bus also dispatches the legacy
objectui:related-changed window event so pre-bus listeners keep working;
notifyRelatedChanged is now a thin alias for writes that bypass the
dataSource (row actions).
- DELETED both refetch-by-remount keys: key={refreshKey} on
RecordDetailView (AppContent) and key={actionRefreshKey} on DetailView.
The schema-path pageRecord fetch and DetailView's self-fetch subscribe
to the bus and refetch IN PLACE; all nine action-success bumps became
precisely-scoped notifyDataChanged calls; undo/redo use the
UndoableOperation's own objectName/recordId.
- RelatedCountStore wired to the bus + snapshot fixed: getSnapshot
returned the same Map reference, so emit() never re-rendered
subscribers (pre-existing latent bug — badges only updated by luck) and
invalidation left them stale. Snapshot is now a monotonic version;
useRelatedCountVersion() drives the probe effect's re-fetch.
- P3: app-shell/src/urlParams.ts — single registry of reserved console
URL params (recordId/form/formObject/formLink/tab/palette/shortcuts);
all literals migrated.
- P2: AGENTS.md Commandment #8 — UI-state classification (addressable →
URL; preference → storage; ephemeral → component) + 'refresh data,
don't rebuild UI'.
Browser-verified (showcase, StrictMode): account edit-save on the
Related tab → name updates in place, tab kept; child create → subtable
refetches via the bridge alone (manual notify removed) and the Related
badge re-probes 11 → 12. Unit: +10 bus tests; suites 1679 green;
type-check 32/32.
Claude-Session: https://claude.ai/code/session_019zKcAtbtxuF9SXYgSzjk9v
Co-authored-by: Claude <noreply@anthropic.com>
@github-actionsgithub-actionsBot mentioned this pull request Jul 5, 2026
@github-actionsgithub-actionsBot mentioned this pull request Jul 5, 2026
@github-actionsgithub-actionsBot mentioned this pull request Jul 5, 2026
os-zhuang added a commit that referenced this pull request Jul 14, 2026
#8) (#2498)
* feat(app-shell,plugin-chatbot,i18n): proactive AI usage indicator in the ChatDock (ADR-0057 #8)
Surfaces remaining AI headroom BEFORE a send hits the 429 wall, instead of only
learning the limit reactively. Consumes the cloud `GET /api/v1/ai/usage` endpoint.
- AiUsageIndicator (app-shell): two meters (build + dataChat) as small progress
rings in the ChatDock header (desktop rail + mobile sheet). Near-full → amber
"running low" + a popover with "resets tonight/next cycle" and the upgrade /
top-up CTA, reusing the 429 deep-link (cloudPricingDeepLink). D5-safe: renders
fractions/qualitative words only, never a token number. Hides itself when the
endpoint is absent (older backend / OSS / no seat) — fail-soft, never broken.
- useAiUsage (app-shell): fetches the D5-safe per-meter fractions; refetches on
the chat engine's post-turn / 429 nudge and on tab re-focus; inert without an
apiBase; fails soft to null on any error.
- useObjectChat (plugin-chatbot): emits AI_USAGE_REFRESH_EVENT on a rejected send
(429) and on the loading→ready turn-finish edge, so the ring moves right after
the user's action. Decoupled window event — no callback threaded through ChatPane.
- i18n: console.ai.usage.* in en + zh-CN.
Depends on cloud PR #824 (the read endpoint) being deployed; until then the
indicator stays hidden.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: add changeset for AI usage indicator
---------
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot mentioned this pull request Jul 14, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

构建一个 **Live Playground (实时演练场)** (用于展示引擎能力)

4 participants

@huangyiirene@hotlong