Skip to content

Commit d2cb8b8

Browse files
Copilothotlong
andcommitted
feat: complete console engine schema integration (AppHeader, SidebarNav stories, docs, ROADMAP)
- AppHeader: import BreadcrumbItemType from engine types for schema alignment - Add SidebarNav Storybook stories with badges, nested items, groups, and search - Update layout.md docs for enhanced SidebarNav props (badges, children, search, NavGroup) - Update view-switcher.mdx docs for allowCreateView/viewActions - Update ROADMAP.md with P1.14 Console Engine Schema Integration section - Verify Airtable UX defaults propagation (no overrides in Console ObjectView) - Verify i18n consistency across en/zh locales Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 46b969f commit d2cb8b8

5 files changed

Lines changed: 273 additions & 7 deletions

File tree

ROADMAP.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind + Shadcn. It renders JSON metadata from the @objectstack/spec protocol into pixel-perfect, accessible, and interactive enterprise interfaces.
1515

16-
**Where We Are:** Foundation is **solid and shipping** — 35 packages, 99+ components, 6,700+ tests, 80 Storybook stories, 43/43 builds passing, ~85% protocol alignment. SpecBridge, Expression Engine, Action Engine, data binding, all view plugins (Grid/Kanban/Calendar/Gantt/Timeline/Map/Gallery), Record components, Report engine, Dashboard BI features, mobile UX, i18n (11 locales), WCAG AA accessibility, Console through Phase 20 (L3), **AppShell Navigation Renderer** (P0.1), **Flow Designer** (P2.4), **Feed/Chatter UI** (P1.5), **App Creation & Editing Flow** (P1.11), **System Settings & App Management** (P1.12), **Page/Dashboard Editor Console Integration** (P1.11), and **Right-Side Visual Editor Drawer** (P1.11) — all ✅ complete. **ViewDesigner** has been removed — its capabilities (drag-to-reorder, undo/redo) are now provided by the ViewConfigPanel (right-side config panel).
16+
**Where We Are:** Foundation is **solid and shipping** — 35 packages, 99+ components, 6,700+ tests, 80 Storybook stories, 43/43 builds passing, ~85% protocol alignment. SpecBridge, Expression Engine, Action Engine, data binding, all view plugins (Grid/Kanban/Calendar/Gantt/Timeline/Map/Gallery), Record components, Report engine, Dashboard BI features, mobile UX, i18n (11 locales), WCAG AA accessibility, Console through Phase 20 (L3), **AppShell Navigation Renderer** (P0.1), **Flow Designer** (P2.4), **Feed/Chatter UI** (P1.5), **App Creation & Editing Flow** (P1.11), **System Settings & App Management** (P1.12), **Page/Dashboard Editor Console Integration** (P1.11), **Right-Side Visual Editor Drawer** (P1.11), and **Console Engine Schema Integration** (P1.14) — all ✅ complete. **ViewDesigner** has been removed — its capabilities (drag-to-reorder, undo/redo) are now provided by the ViewConfigPanel (right-side config panel).
1717

1818
**What Remains:** The gap to **Airtable-level UX** is primarily in:
1919
1. ~~**AppShell** — No dynamic navigation renderer from spec JSON (last P0 blocker)~~ ✅ Complete
@@ -792,6 +792,31 @@ ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind
792792
- [x] Empty tables show 3 ghost placeholder rows with skeleton-like appearance
793793
- [x] Ghost rows use varying widths for visual variety
794794

795+
### P1.14 Console Integration — Engine Schema Capabilities ✅
796+
797+
> **Status:** Complete — Console now consumes HeaderBarSchema, ViewSwitcher allowCreateView/viewActions, SidebarNav enhanced props, and Airtable UX defaults.
798+
799+
**ViewSwitcher `allowCreateView` & `viewActions`:**
800+
- [x] Added `allowCreateView` and `viewActions` to `ObjectViewSchema` type
801+
- [x] Engine `ObjectView` passes `allowCreateView`/`viewActions` to `ViewSwitcherSchema` builder
802+
- [x] Engine `ObjectView` accepts and passes `onCreateView`/`onViewAction` callbacks to `ViewSwitcher`
803+
- [x] Console `ObjectView` sets `allowCreateView: isAdmin` and `viewActions` (settings/share/duplicate/delete)
804+
- [x] Console wires `onCreateView` → open ViewConfigPanel in create mode
805+
- [x] Console wires `onViewAction('settings')` → open ViewConfigPanel in edit mode
806+
807+
**AppHeader `HeaderBarSchema` Alignment:**
808+
- [x] Console `AppHeader` breadcrumb items typed as engine `BreadcrumbItem` type
809+
- [x] Breadcrumbs with `siblings` dropdown navigation working
810+
- [x] Search triggers ⌘K command palette (desktop + mobile)
811+
812+
**SidebarNav Enhanced Props:**
813+
- [x] Storybook stories for badges, nested items, NavGroups, search filtering
814+
- [x] Documentation updated for `SidebarNav` enhanced API (badges, badgeVariant, children, searchEnabled, NavGroup)
815+
816+
**Airtable UX Defaults Propagation:**
817+
- [x] Verified: Console `ObjectView` does NOT override `rowHeight`, `density`, or `singleClickEdit`
818+
- [x] Engine defaults (`compact` rows, `singleClickEdit: true`, browser locale dates) flow through correctly
819+
795820
---
796821

797822
## 🧩 P2 — Polish & Advanced Features

apps/console/src/components/AppHeader.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { ActivityFeed, type ActivityItem } from './ActivityFeed';
3636
import type { ConnectionState } from '../dataSource';
3737
import { useAdapter } from '../context/AdapterProvider';
3838
import { useObjectTranslation } from '@object-ui/i18n';
39+
import type { BreadcrumbItem as BreadcrumbItemType } from '@object-ui/types';
3940

4041
/** Convert a slug like "crm_dashboard" or "audit-log" to "Crm Dashboard" / "Audit Log" */
4142
function humanizeSlug(slug: string): string {
@@ -106,8 +107,8 @@ export function AppHeader({ appName, objects, connectionState, presenceUsers, ac
106107
href: `${baseHref}/${o.name}`,
107108
}));
108109

109-
// Determine breadcrumb items with optional siblings for dropdown
110-
const breadcrumbItems: { label: string; href?: string; siblings?: { label: string; href: string }[] }[] = [
110+
// Determine breadcrumb items using engine BreadcrumbItem type for schema alignment
111+
const breadcrumbItems: BreadcrumbItemType[] = [
111112
{ label: appName, href: baseHref }
112113
];
113114

@@ -151,6 +152,10 @@ export function AppHeader({ appName, objects, connectionState, presenceUsers, ac
151152
}
152153
}
153154

155+
// HeaderBarSchema alignment: breadcrumbItems typed as engine BreadcrumbItemType.
156+
// Console-specific concerns (presence, activity, connection) rendered as JSX below.
157+
// Future: delegate full rendering to SchemaRenderer with header-bar schema.
158+
154159
return (
155160
<div className="flex items-center justify-between w-full h-full px-2 sm:px-3 md:px-4 gap-1.5 sm:gap-2">
156161
<div className="flex items-center gap-1.5 sm:gap-2 min-w-0 flex-1">

content/docs/components/complex/view-switcher.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,10 @@ interface ViewSwitcherSchema {
7878
onViewChange?: string;
7979
persistPreference?: boolean;
8080
storageKey?: string;
81+
allowCreateView?: boolean; // Show "+" button to create views
82+
viewActions?: Array<{ // Per-view action icons
83+
type: 'share' | 'settings' | 'duplicate' | 'delete';
84+
icon?: string;
85+
}>;
8186
}
8287
```

content/docs/guide/layout.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,24 +291,32 @@ The `SidebarNav` provides a collapsible navigation sidebar with menu items.
291291
href?: string,
292292
icon?: string,
293293
badge?: string | number,
294-
items?: Array<...>, // Nested menu items
294+
badgeVariant?: 'default' | 'destructive' | 'outline',
295+
items?: Array<...>, // Nested menu items (collapsible children)
295296
active?: boolean,
296297
disabled?: boolean
297298
}>,
298299

300+
// Items can also be grouped using NavGroup:
301+
// items: Array<{ label: string, items: NavItem[] }>
302+
299303
collapsible?: boolean,
300304
defaultOpen?: boolean,
305+
searchEnabled?: boolean, // Show search input to filter navigation
306+
searchPlaceholder?: string, // Placeholder for search input
301307

302308
className?: string
303309
}
304310
```
305311

306312
### Features
307313

308-
- Nested menu items (2 levels)
309-
- Active state highlighting
314+
- Nested menu items (2 levels) with collapsible expand/collapse
315+
- Active state highlighting via React Router
310316
- Icon support (Lucide icons)
311-
- Badge/counter support
317+
- Badge/counter support with variant styling (`default`, `destructive`, `outline`)
318+
- NavGroup support for grouped navigation sections
319+
- Built-in search filtering (`searchEnabled`) across all items and children
312320
- Collapse/expand animation
313321

314322
## Common Layout Patterns
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
import React from 'react';
3+
import { MemoryRouter } from 'react-router-dom';
4+
import { SidebarNav, type NavItem, type NavGroup } from '../SidebarNav';
5+
import { SidebarProvider } from '@object-ui/components';
6+
import {
7+
Home,
8+
Users,
9+
FolderOpen,
10+
BarChart,
11+
Settings,
12+
HelpCircle,
13+
Mail,
14+
Calendar,
15+
FileText,
16+
Shield,
17+
} from 'lucide-react';
18+
19+
/**
20+
* SidebarNav stories demonstrating badges, nested items, search, and NavGroups.
21+
*
22+
* Part of Console integration: consume new engine schema capabilities
23+
* (HeaderBar, ViewSwitcher, SidebarNav, Airtable UX).
24+
*/
25+
const meta = {
26+
title: 'Layout/SidebarNav',
27+
component: SidebarNav,
28+
decorators: [
29+
(Story) => (
30+
<MemoryRouter initialEntries={['/dashboard']}>
31+
<SidebarProvider defaultOpen style={{ height: '600px', border: '1px solid hsl(var(--border))' }}>
32+
<Story />
33+
</SidebarProvider>
34+
</MemoryRouter>
35+
),
36+
],
37+
parameters: {
38+
layout: 'fullscreen',
39+
docs: {
40+
description: {
41+
component:
42+
'Navigation sidebar with React Router integration. Supports badges, nested collapsible items, grouped navigation, and built-in search filtering.',
43+
},
44+
},
45+
},
46+
tags: ['autodocs'],
47+
} satisfies Meta<typeof SidebarNav>;
48+
49+
export default meta;
50+
type Story = StoryObj<typeof meta>;
51+
52+
// ---------------------------------------------------------------------------
53+
// Basic flat items
54+
// ---------------------------------------------------------------------------
55+
const basicItems: NavItem[] = [
56+
{ title: 'Dashboard', href: '/dashboard', icon: Home },
57+
{ title: 'Contacts', href: '/contacts', icon: Users },
58+
{ title: 'Projects', href: '/projects', icon: FolderOpen },
59+
{ title: 'Reports', href: '/reports', icon: BarChart },
60+
{ title: 'Settings', href: '/settings', icon: Settings },
61+
];
62+
63+
export const Default: Story = {
64+
args: {
65+
items: basicItems,
66+
title: 'My App',
67+
},
68+
};
69+
70+
// ---------------------------------------------------------------------------
71+
// With Badges
72+
// ---------------------------------------------------------------------------
73+
const itemsWithBadges: NavItem[] = [
74+
{ title: 'Dashboard', href: '/dashboard', icon: Home },
75+
{ title: 'Inbox', href: '/inbox', icon: Mail, badge: 12, badgeVariant: 'destructive' },
76+
{ title: 'Contacts', href: '/contacts', icon: Users, badge: 342 },
77+
{ title: 'Projects', href: '/projects', icon: FolderOpen, badge: '3 new', badgeVariant: 'outline' },
78+
{ title: 'Calendar', href: '/calendar', icon: Calendar },
79+
{ title: 'Settings', href: '/settings', icon: Settings },
80+
];
81+
82+
export const WithBadges: Story = {
83+
args: {
84+
items: itemsWithBadges,
85+
title: 'CRM App',
86+
},
87+
};
88+
89+
// ---------------------------------------------------------------------------
90+
// Nested Items (collapsible children)
91+
// ---------------------------------------------------------------------------
92+
const nestedItems: NavItem[] = [
93+
{ title: 'Dashboard', href: '/dashboard', icon: Home },
94+
{
95+
title: 'Projects',
96+
href: '/projects',
97+
icon: FolderOpen,
98+
badge: 5,
99+
children: [
100+
{ title: 'Active', href: '/projects/active' },
101+
{ title: 'Archived', href: '/projects/archived' },
102+
{ title: 'Templates', href: '/projects/templates', badge: 2 },
103+
],
104+
},
105+
{
106+
title: 'Reports',
107+
href: '/reports',
108+
icon: BarChart,
109+
children: [
110+
{ title: 'Sales', href: '/reports/sales' },
111+
{ title: 'Marketing', href: '/reports/marketing', badge: 'New', badgeVariant: 'outline' },
112+
{ title: 'Finance', href: '/reports/finance' },
113+
],
114+
},
115+
{ title: 'Settings', href: '/settings', icon: Settings },
116+
];
117+
118+
export const NestedItems: Story = {
119+
args: {
120+
items: nestedItems,
121+
title: 'Enterprise App',
122+
},
123+
};
124+
125+
// ---------------------------------------------------------------------------
126+
// NavGroup — grouped navigation
127+
// ---------------------------------------------------------------------------
128+
const groupedItems: NavGroup[] = [
129+
{
130+
label: 'Main',
131+
items: [
132+
{ title: 'Dashboard', href: '/dashboard', icon: Home },
133+
{ title: 'Inbox', href: '/inbox', icon: Mail, badge: 5, badgeVariant: 'destructive' },
134+
],
135+
},
136+
{
137+
label: 'Content',
138+
items: [
139+
{ title: 'Documents', href: '/documents', icon: FileText, badge: 23 },
140+
{ title: 'Projects', href: '/projects', icon: FolderOpen },
141+
{ title: 'Calendar', href: '/calendar', icon: Calendar },
142+
],
143+
},
144+
{
145+
label: 'Admin',
146+
items: [
147+
{ title: 'Users', href: '/admin/users', icon: Users },
148+
{ title: 'Permissions', href: '/admin/permissions', icon: Shield },
149+
{ title: 'Settings', href: '/settings', icon: Settings },
150+
],
151+
},
152+
];
153+
154+
export const GroupedNavigation: Story = {
155+
args: {
156+
items: groupedItems,
157+
},
158+
};
159+
160+
// ---------------------------------------------------------------------------
161+
// Search Enabled
162+
// ---------------------------------------------------------------------------
163+
export const WithSearch: Story = {
164+
args: {
165+
items: groupedItems,
166+
searchEnabled: true,
167+
searchPlaceholder: 'Filter navigation...',
168+
},
169+
};
170+
171+
// ---------------------------------------------------------------------------
172+
// Full featured: badges + nested + groups + search
173+
// ---------------------------------------------------------------------------
174+
const fullFeaturedGroups: NavGroup[] = [
175+
{
176+
label: 'Workspace',
177+
items: [
178+
{ title: 'Dashboard', href: '/dashboard', icon: Home },
179+
{ title: 'Inbox', href: '/inbox', icon: Mail, badge: 8, badgeVariant: 'destructive' },
180+
{
181+
title: 'Projects',
182+
href: '/projects',
183+
icon: FolderOpen,
184+
badge: 3,
185+
children: [
186+
{ title: 'Design System', href: '/projects/design' },
187+
{ title: 'API v2', href: '/projects/api', badge: 'WIP', badgeVariant: 'outline' },
188+
{ title: 'Mobile App', href: '/projects/mobile' },
189+
],
190+
},
191+
],
192+
},
193+
{
194+
label: 'Analytics',
195+
items: [
196+
{
197+
title: 'Reports',
198+
href: '/reports',
199+
icon: BarChart,
200+
children: [
201+
{ title: 'Revenue', href: '/reports/revenue' },
202+
{ title: 'Users', href: '/reports/users', badge: 'New', badgeVariant: 'outline' },
203+
],
204+
},
205+
{ title: 'Calendar', href: '/calendar', icon: Calendar },
206+
],
207+
},
208+
{
209+
label: 'System',
210+
items: [
211+
{ title: 'Settings', href: '/settings', icon: Settings },
212+
{ title: 'Help', href: '/help', icon: HelpCircle },
213+
],
214+
},
215+
];
216+
217+
export const FullFeatured: Story = {
218+
args: {
219+
items: fullFeaturedGroups,
220+
searchEnabled: true,
221+
searchPlaceholder: 'Search navigation...',
222+
},
223+
};

0 commit comments

Comments
 (0)