Skip to content

feat(flow-designer): localize palette headings + cloud-sync recents + guide#2553

Merged
os-zhuang merged 1 commit into
mainfrom
claude/flow-palette-followups
Jul 16, 2026
Merged

feat(flow-designer): localize palette headings + cloud-sync recents + guide#2553
os-zhuang merged 1 commit into
mainfrom
claude/flow-palette-followups

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Three follow-ups to the add-node palette search (#1943, shipped in #2543). Each is independent; grouped here as one cohesive PR since they share the palette surface.

1. Localize the category headings

The palette's section headings (Data / Logic / Human / Integration / Flow) rendered as hardcoded English while the same popover's search placeholder / empty state / "Recently used" heading were already localized. Now translated via five new engine.flowPalette.category.* keys (en + zh) — e.g. 数据 / 逻辑 / 人工 / 集成 / 流程.

The NodeCategory literals, NODE_CATEGORY_ORDER, and nodeCategory() returns are unchanged — they're the in-memory bucket keys / render-order tokens / React keys (not persisted, never sent to the server). Only the CommandGroup heading render is translated, so bucketing and the server-merge are untouched.

2. Cloud-sync the "Recently used" list

Upgrades the MRU from browser-local storage to per-user cloud sync, reusing the existing sys_user_preference stack:

  • New FlowPaletteRecentsProvider / useFlowPaletteRecents() (context/), modeled on RecentItemsProvider: localStorage-first for instant paint, hydrates from a UserDataAdapter<string> when attached, debounced write-through, cross-tab sync, silent offline degrade. Cap 5.
  • Wired into ConsoleShell's UserStateBridge (new ui.flow.palette.recents key via createObjectStackUserStateAdapter) and provider stack; new UserStateKind 'flowPaletteRecents'.
  • One-shot migration folds the legacy unscoped flow-palette-recents key (the localStorage-only version) into the signed-in user's scoped list, then removes it.
  • NodePalette consumes the hook, which falls back to the localStorage module outside a provider (unit tests, the dev preview gallery) — so the pre-cloud-sync behavior is preserved with no provider wiring. flowPaletteRecents.ts is kept as that fallback + the migration source.

3. Flow Designer guide

New content/docs/guide/flow-designer.md (registered in guide/meta.json) covering the canvas, the searchable palette (search / keyboard / recents / server-merged plugin nodes), the node inspector, and validation/simulation. user-state-persistence.md extended with the new provider/hook/cap.

Testing

  • NodePalette.test.tsx (13 cases): added a zh-locale test asserting localized headings render and the English literals are gone; existing cases stay green (recents run through the hook's localStorage fallback).
  • New FlowPaletteRecentsProvider.test.tsx (8 cases): sync localStorage hydration, dedup-to-front, cap 5, user-scoped persistence, legacy-key migration + clear, adapter hydration overriding local, debounced save(), and the no-provider fallback.
  • pnpm vitest run packages/app-shell/src/context packages/app-shell/src/views/metadata-admin/previews → 247 passed. turbo run build --filter=@object-ui/app-shell (tsc, 29 pkgs) passes; eslint on touched files: 0 errors.
  • Docs: apps/site next build exits 0 and generates docs/guide/flow-designer; meta.json valid.
  • Verified end-to-end in a real browser (console /preview-gallery.html?only=flow + Playwright): category headings render, ArrowDown+Enter inserts a node, reopen shows "Recently used" with the freshly-inserted type (fallback path), query resets, scr filter works. Only console errors are the palette's GET /api/v1/automation/actions fetch failing with no backend — the expected offline-fallback path, not from the new hook/provider.

Note: turbo run build --filter=@object-ui/site surfaces pre-existing tsc errors in plugin-form / plugin-grid / plugin-view (files untouched here, identical to main) under this worktree's type resolution; the site's own next build passes. Unrelated to this change.

🤖 Generated with Claude Code

https://claude.ai/code/session_011j35dppNPaEp1ULzHoUxYn


Generated by Claude Code

… guide (#1943)

Three follow-ups to the add-node palette search (#1943 / #2543):

1. Localize the palette section headings (Data / Logic / Human /
   Integration / Flow) to the active console language via five new
   engine.flowPalette.category.* keys (en + zh). The NodeCategory
   literals stay English — they remain the in-memory bucket keys /
   render order tokens; only the CommandGroup heading is translated.

2. Cloud-sync the 'Recently used' list. New FlowPaletteRecentsProvider /
   useFlowPaletteRecents persist a per-user MRU of node types to
   sys_user_preference (key ui.flow.palette.recents) via the existing
   createObjectStackUserStateAdapter stack, mirroring RecentItemsProvider:
   localStorage-first, debounced write-through, cross-tab sync, silent
   offline degrade. A one-shot migration folds the legacy unscoped
   'flow-palette-recents' key into the signed-in user's scoped list.
   NodePalette consumes the hook, which falls back to the localStorage
   module outside a provider (tests, the dev preview gallery), so the
   pre-cloud-sync behavior is preserved.

3. Add a Flow Designer guide (content/docs/guide/flow-designer.md,
   registered in guide/meta.json) covering the canvas, the searchable
   palette (search / keyboard / recents / server-merged plugin nodes),
   the inspector, and validation/simulation. Extend
   user-state-persistence.md with the new provider/hook/cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011j35dppNPaEp1ULzHoUxYn
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Jul 16, 2026 1:49am

Request Review

@github-actions github-actions Bot added the tests label Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 27.6 KB 350 KB
Entry file index-DpefogzY.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.17KB 2.95KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 21.70KB 4.21KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.12KB 3.41KB
auth (LoginForm.js) 17.12KB 5.00KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.63KB 2.15KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 30.17KB 7.28KB
auth (createAuthenticatedFetch.js) 3.93KB 1.55KB
auth (index.js) 1.83KB 0.79KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.86KB 0.85KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (PresenceProvider.js) 2.42KB 0.96KB
collaboration (index.js) 1.25KB 0.53KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 444.81KB 96.19KB
core (index.js) 1.69KB 0.60KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 113.70KB 28.15KB
fields (index.js) 202.59KB 49.53KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.46KB 0.96KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 5.37KB 1.72KB
i18n (useObjectLabel.js) 21.22KB 4.69KB
i18n (useSafeTranslation.js) 2.68KB 0.98KB
layout (index.js) 38.45KB 10.67KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 4.42KB 1.27KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 1.77KB 0.77KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 5.90KB 2.15KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.46KB 1.03KB
permissions (evaluator.js) 4.00KB 1.23KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.50KB 0.70KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 45.12KB 12.34KB
plugin-charts (index.js) 46.31KB 13.06KB
plugin-chatbot (index.js) 176.76KB 42.28KB
plugin-dashboard (index.js) 108.35KB 26.87KB
plugin-designer (index.js) 213.89KB 43.03KB
plugin-detail (index.js) 209.27KB 50.98KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 104.26KB 25.24KB
plugin-gantt (index.js) 149.17KB 37.17KB
plugin-grid (index.js) 171.50KB 45.28KB
plugin-kanban (index.js) 47.17KB 12.85KB
plugin-list (index.js) 97.92KB 23.14KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 37.82KB 9.96KB
plugin-timeline (index.js) 25.37KB 7.20KB
plugin-tree (index.js) 8.36KB 2.81KB
plugin-view (index.js) 85.69KB 20.85KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.55KB 0.67KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 3.19KB 1.38KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 18.70KB 6.09KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 0.79KB 0.43KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 2.16KB 0.94KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
tenant (TenantContext.js) 0.31KB 0.25KB
tenant (TenantGuard.js) 1.04KB 0.43KB
tenant (TenantProvider.js) 2.76KB 0.98KB
tenant (TenantScopedQuery.js) 0.77KB 0.44KB
tenant (index.js) 0.75KB 0.38KB
tenant (resolver.js) 2.64KB 0.76KB
tenant (useTenant.js) 0.50KB 0.32KB
tenant (useTenantBranding.js) 0.62KB 0.39KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 0.77KB 0.41KB
types (disclosure.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (index.js) 1.54KB 0.68KB
types (layout.js) 0.20KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.26KB 1.96KB
types (tenant.js) 0.20KB 0.18KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 0.75KB 0.46KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 02:26
@os-zhuang
os-zhuang merged commit 77b40db into main Jul 16, 2026
10 checks passed
@os-zhuang
os-zhuang deleted the claude/flow-palette-followups branch July 16, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants