Skip to content

Comments

feat: ViewConfigPanel responsive overlay, ARIA accessibility, auto-close on view switch#663

Merged
hotlong merged 3 commits intomainfrom
copilot/optimize-edit-view-page
Feb 21, 2026
Merged

feat: ViewConfigPanel responsive overlay, ARIA accessibility, auto-close on view switch#663
hotlong merged 3 commits intomainfrom
copilot/optimize-edit-view-page

Conversation

Copy link
Contributor

Copilot AI commented Feb 20, 2026

  • Understand existing codebase and implementation
  • Improve ViewConfigPanel responsive behavior (mobile overlay: full-width absolute on mobile, relative sidebar on desktop)
  • Add accessibility attributes (ARIA role=complementary, aria-label, focus management via ref)
  • Auto-close ViewConfigPanel on view tab switch
  • Add tests for ARIA attributes and responsive CSS classes (2 new tests, 29 total passing)
  • Update ROADMAP.md and ROADMAP_CONSOLE.md with Phase 20 details and milestone
  • Fix CI build failure: CRM example objectstack compile Zod double-parse bug on form.sections.columns
  • Run tests and verify changes (28 pass, 1 pre-existing skip)
Original prompt

This section details on the original issue you should resolve

<issue_title>优化编辑视图页面,支持Airtable风格的右侧配置面板(Inline ViewDesigner)</issue_title>
<issue_description>## 背景
目前ObjectUI的"编辑视图"功能需要跳转到专门的ViewDesignerPage,体验与Airtable等主流NoCode平台相比有较大差距。Airtable等系统,支持在主列表视图页面直接通过右侧配置面板(Inline/Slide Panel)进行字段、过滤、外观等配置,极大提升了易用性与效率。

见下方截图:
Airtable 编辑视图示例

主要优化目标

  • 支持在ObjectView页面直接弹出/收起"视图配置"侧边栏,无需跳转
  • 右侧面板提供:页面(标题/描述)、数据源、外观设定、用户过滤器、交互按钮、导出/打印等配置,风格类比Airtable交互
  • 切换不同的视图Tab,右侧面板自动切换对应内容
  • 管理员操作项(如新建/编辑视图)整合到页面当前内容,更流畅的设计工具体验

建议实现方案

  1. apps/console/src/components/ObjectView.tsx中实现本地State(如showViewConfigPanel),点击"编辑视图"Icon时触发;
  2. 侧边栏参考MetadataPanelViewDesigner面板结构,抽取为可复用组件ViewConfigPanel
  3. 面板内信息分区(页面、数据、外观、用户过滤器、操作等),并自动同步当前视图配置;
  4. 原跳转"视图设计器"菜单替换为本地弹窗/侧栏,所有编辑均为所见即所得(WYSIWYG),保存后即时刷新主列表;
  5. 新建视图、切换视图类型与现有逻辑复用,侧边栏自动闭合或切换;
  6. 需要考虑Panel与主视图Responsive布局兼容;

其他优化项

  • 标题支持"面包屑+描述"展示;
  • 主内容底部可显示当前"记录总数"footer

开发完成需运行相关test,评估对roadmap的影响,并及时修订roadmap。

子任务 Sub-Tasks

  • 设计/出稿 ViewConfigPanel 结构和交互
  • 实现 ObjectView 与 Panel 的集成及状态切换
  • 支持Tab切换和Panel动态内容
  • 替换原"编辑视图"菜单跳转为右侧Panel弹出
  • 优化Responsive兼容性和可访问性
  • 添加主页面footer显示"记录总数"
  • 更新/新增测试用例,完善测试
  • 更新 Roadmap

如有需要可细化面板内各分区配置项。</issue_description>

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


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@vercel
Copy link

vercel bot commented Feb 20, 2026

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

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 20, 2026 4:13pm
objectui-demo Ready Ready Preview, Comment Feb 20, 2026 4:13pm
objectui-storybook Ready Ready Preview, Comment Feb 20, 2026 4:13pm

Request Review

… auto-close on view switch

- Add ARIA role=complementary and aria-label to ViewConfigPanel
- Add focus management when panel opens (ref + useEffect)
- Add responsive mobile overlay (full-width on mobile, w-72 on desktop)
- Auto-close config panel when switching view tabs in ObjectView
- Add tests for ARIA attributes and responsive CSS classes
- Update ROADMAP.md and ROADMAP_CONSOLE.md with Phase 20 improvements

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@github-actions github-actions bot added documentation Improvements or additions to documentation apps tests labels Feb 20, 2026
Copilot AI changed the title [WIP] Optimize edit view page to support inline configuration panel feat: ViewConfigPanel responsive overlay, ARIA accessibility, auto-close on view switch Feb 20, 2026
Copilot AI requested a review from hotlong February 20, 2026 15:47
@github-actions
Copy link
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 45.7 KB 60 KB
Entry file index-Bom--ZUS.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 7.36KB 1.78KB
auth (ForgotPasswordForm.js) 4.00KB 1.44KB
auth (LoginForm.js) 4.20KB 1.45KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 5.66KB 1.59KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (createAuthClient.js) 2.78KB 0.98KB
auth (createAuthenticatedFetch.js) 1.24KB 0.60KB
auth (index.js) 1.18KB 0.51KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 1.57KB 0.57KB
collaboration (CommentThread.js) 18.17KB 4.43KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (index.js) 1.04KB 0.47KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 1836.21KB 430.99KB
core (index.js) 0.81KB 0.32KB
create-plugin (index.js) 10.13KB 3.17KB
data-objectstack (index.js) 38.87KB 9.57KB
fields (index.js) 91.24KB 18.29KB
i18n (i18n.js) 2.03KB 0.77KB
i18n (index.js) 1.79KB 0.72KB
i18n (provider.js) 3.21KB 1.09KB
layout (index.js) 16.40KB 5.01KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (index.js) 1.19KB 0.53KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 4.42KB 1.27KB
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 (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.11KB 0.87KB
permissions (evaluator.js) 4.00KB 1.23KB
permissions (index.js) 0.85KB 0.40KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 0.99KB 0.49KB
plugin-aggrid (AddressField-DgyQ0rvP.js) 3.05KB 0.76KB
plugin-aggrid (AgGridImpl-PXsqf13U.js) 7.04KB 2.33KB
plugin-aggrid (AutoNumberField-CfvVFnS6.js) 0.28KB 0.27KB
plugin-aggrid (FileField-By7TkYU4.js) 5.90KB 2.10KB
plugin-aggrid (FormulaField-BH1-S6cR.js) 0.52KB 0.39KB
plugin-aggrid (GeolocationField-DF12n1Oq.js) 4.46KB 1.50KB
plugin-aggrid (GridField-DeP1y9bu.js) 1.71KB 0.68KB
plugin-aggrid (LocationField-Yrf_klbg.js) 0.93KB 0.54KB
plugin-aggrid (MasterDetailField-BVACkcph.js) 3.86KB 1.18KB
plugin-aggrid (ObjectAgGridImpl-vdRgFM8b.js) 919.78KB 203.55KB
plugin-aggrid (ObjectField-C0oaTX1I.js) 1.61KB 0.77KB
plugin-aggrid (QRCodeField-BqSbA7Ze.js) 3.38KB 1.23KB
plugin-aggrid (RichTextField-1ja5qNye.js) 1.16KB 0.59KB
plugin-aggrid (SignatureField-BN33JBE_.js) 3.33KB 1.29KB
plugin-aggrid (SummaryField-DVimg2HJ.js) 0.48KB 0.37KB
plugin-aggrid (UserField-CkLKQN0S.js) 2.44KB 0.93KB
plugin-aggrid (VectorField-Bci33_ds.js) 0.79KB 0.45KB
plugin-aggrid (index-KHEwoOB6.js) 19.95KB 5.03KB
plugin-aggrid (index.js) 0.22KB 0.16KB
plugin-ai (index.js) 25.35KB 6.39KB
plugin-calendar (index.js) 48.96KB 13.31KB
plugin-charts (AdvancedChartImpl-GErbMD6M.js) 126.98KB 26.25KB
plugin-charts (BarChart-C_I0OFbj.js) 542.77KB 135.30KB
plugin-charts (ChartImpl-CnD20l5F.js) 3.19KB 1.10KB
plugin-charts (index-Byep0tj1.js) 15.23KB 4.49KB
plugin-charts (index.js) 0.19KB 0.16KB
plugin-chatbot (index.js) 1140.69KB 333.05KB
plugin-dashboard (index.js) 147.98KB 38.66KB
plugin-designer (index.js) 160.84KB 29.64KB
plugin-detail (AddressField-C2t3j3mD.js) 2.98KB 0.75KB
plugin-detail (AutoNumberField-BxnFqllo.js) 0.28KB 0.26KB
plugin-detail (AvatarField-ylyEZscY.js) 2.62KB 1.07KB
plugin-detail (BooleanField-CK0ulUBE.js) 1.13KB 0.51KB
plugin-detail (CodeField-BmnT-q1_.js) 0.74KB 0.47KB
plugin-detail (ColorField-B-FMmhsz.js) 1.23KB 0.54KB
plugin-detail (CurrencyField-BDwQw36y.js) 1.48KB 0.73KB
plugin-detail (DateField-D0Vnr0uU.js) 0.54KB 0.37KB
plugin-detail (DateTimeField-B8TR6UKY.js) 0.71KB 0.42KB
plugin-detail (EmailField-aypQ_Yjg.js) 0.81KB 0.48KB
plugin-detail (FileField-CXwxaVT2.js) 5.50KB 1.94KB
plugin-detail (FormulaField-CJkkwIK8.js) 0.51KB 0.38KB
plugin-detail (GeolocationField-BkuAOlrN.js) 3.71KB 1.21KB
plugin-detail (GridField-B3n6K9lw.js) 1.67KB 0.67KB
plugin-detail (ImageField-CbaphNBD.js) 2.83KB 1.14KB
plugin-detail (LocationField-CYcDkmKI.js) 0.95KB 0.53KB
plugin-detail (LookupField-DGccABSc.js) 4.00KB 1.38KB
plugin-detail (MasterDetailField-CRwFyfrS.js) 3.40KB 1.00KB
plugin-detail (NumberField-Cbre7Q1v.js) 0.68KB 0.44KB
plugin-detail (ObjectField-CpGLnHmF.js) 1.64KB 0.76KB
plugin-detail (PasswordField-CkHIyXmO.js) 1.21KB 0.62KB
plugin-detail (PercentField-m_Nhyr3-.js) 1.28KB 0.66KB
plugin-detail (PhoneField-cXZBMVNS.js) 0.80KB 0.48KB
plugin-detail (QRCodeField-0WgKvf2V.js) 2.35KB 0.91KB
plugin-detail (RatingField-9h0ClTSf.js) 1.62KB 0.66KB
plugin-detail (RichTextField-DI7ZyX1D.js) 1.15KB 0.59KB
plugin-detail (SelectField-jRBvvYsB.js) 0.90KB 0.49KB
plugin-detail (SignatureField-m079CM_l.js) 2.97KB 1.10KB
plugin-detail (SliderField-DCRv64Kn.js) 1.00KB 0.49KB
plugin-detail (SummaryField-ugYPYxjP.js) 0.47KB 0.36KB
plugin-detail (TextAreaField-BJq6lvT-.js) 1.09KB 0.59KB
plugin-detail (TextField-BiuNlt6U.js) 0.82KB 0.42KB
plugin-detail (TimeField-DrMiCIDu.js) 0.50KB 0.34KB
plugin-detail (UrlField-BqtpZOVz.js) 0.98KB 0.52KB
plugin-detail (UserField-DbcPDoXM.js) 2.33KB 0.90KB
plugin-detail (VectorField-CKg9jdGa.js) 0.78KB 0.44KB
plugin-detail (index-HrTrgcwe.js) 1819.17KB 427.24KB
plugin-detail (index.js) 0.59KB 0.36KB
plugin-editor (MonacoImpl-hfdmoz6k.js) 18.15KB 5.59KB
plugin-editor (index-CuYbY6xb.js) 10.10KB 3.32KB
plugin-editor (index.js) 0.19KB 0.15KB
plugin-form (index.js) 65.63KB 13.72KB
plugin-gantt (index.js) 243.73KB 58.84KB
plugin-grid (index.js) 93.09KB 24.46KB
plugin-kanban (KanbanEnhanced-DvU5XHf-.js) 32.31KB 9.09KB
plugin-kanban (KanbanImpl-4CyDnVUT.js) 14.16KB 4.17KB
plugin-kanban (index-DD747jWd.js) 31.17KB 9.19KB
plugin-kanban (index.js) 0.42KB 0.26KB
plugin-kanban (sortable.esm-CNNHgHk5.js) 71.43KB 18.99KB
plugin-list (index.js) 1796.36KB 423.84KB
plugin-map (index.js) 130.37KB 31.65KB
plugin-map (maplibre-gl-DSpYxujd.js) 1416.27KB 302.72KB
plugin-markdown (MarkdownImpl-DufQ-eRU.js) 256.68KB 64.45KB
plugin-markdown (index-CrmE78vF.js) 9.63KB 3.17KB
plugin-markdown (index.js) 0.19KB 0.15KB
plugin-report (index.js) 65.85KB 13.42KB
plugin-timeline (index.js) 107.96KB 25.07KB
plugin-view (index.js) 132.44KB 33.64KB
plugin-workflow (index.js) 47.05KB 9.69KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 8.21KB 2.56KB
react (index.js) 0.66KB 0.38KB
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.10KB 0.71KB
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.20KB 0.18KB
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.13KB 0.50KB
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 (tenant.js) 0.20KB 0.18KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 0.20KB 0.18KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB
types (workflow.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

@hotlong
Copy link
Contributor

hotlong commented Feb 20, 2026

@copilot fix ci build and test errors

…n form.sections.columns

The `defineStack()` in @objectstack/spec transforms `columns: '2'` (string)
to `columns: 2` (number) via ZodPipe. When `objectstack compile` CLI then
runs safeParse again on the already-transformed data, the number `2` fails
the string enum validation expecting "1"|"2"|"3"|"4".

Fix: pass `{ strict: false }` to `defineStack()` in the CRM example config,
deferring validation to the compile CLI's single safeParse pass.

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@copilot fix ci build and test errors

Fixed in 8d97719. The CI failure was caused by a Zod double-parse bug in the CRM example: defineStack() transforms form.sections.columns from string "2" to number 2 via ZodPipe, then objectstack compile CLI runs safeParse() again on the already-transformed data, and the number 2 fails the string enum validation expecting "1"|"2"|"3"|"4".

Fix: pass { strict: false } to defineStack() in the CRM config, deferring validation to the compile CLI's single safeParse pass. CRM now compiles successfully (8 objects, 108 fields, 8 views, 21 actions).

@hotlong hotlong marked this pull request as ready for review February 21, 2026 00:41
Copilot AI review requested due to automatic review settings February 21, 2026 00:41
@hotlong hotlong merged commit f494b6e into main Feb 21, 2026
5 checks passed
Copy link
Contributor

Copilot AI left a comment

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 enhances the ViewConfigPanel component to provide a responsive, accessible inline view configuration experience similar to Airtable. The changes improve mobile UX by implementing a full-screen overlay on small screens while maintaining the existing inline sidebar on desktop, add proper ARIA accessibility attributes, and automatically close the panel when users switch between views.

Changes:

  • Enhanced ViewConfigPanel with responsive CSS classes (absolute full-width overlay on mobile, relative sidebar on desktop)
  • Added ARIA accessibility attributes (role="complementary", aria-label, tabIndex) and focus management
  • Implemented auto-close behavior when switching views in ObjectView
  • Added workaround comment for CRM example Zod double-parse bug
  • Updated ROADMAP documentation to reflect Phase 20 completion

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/console/src/components/ViewConfigPanel.tsx Added responsive positioning (absolute → relative breakpoint), ARIA attributes (role, aria-label, tabIndex), and focus management via useRef + useEffect
apps/console/src/components/ObjectView.tsx Added auto-close logic for ViewConfigPanel when handleViewChange is called (line 127)
apps/console/src/tests/ViewConfigPanel.test.tsx Added 2 new tests verifying ARIA attributes and responsive CSS classes (29 total tests now)
examples/crm/objectstack.config.ts Added { strict: false } option with explanatory comment about Zod double-parse bug workaround
ROADMAP_CONSOLE.md Updated Phase 20 description with new features (responsive overlay, ARIA, auto-close) and added v2.1.0 milestone
ROADMAP.md Updated Inline View Config Panel feature description with new capabilities

Comment on lines +101 to +106
// Focus the panel when it opens for keyboard accessibility
useEffect(() => {
if (open && panelRef.current) {
panelRef.current.focus();
}
}, [open]);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The focus management effect in useEffect is not covered by tests. Consider adding a test to verify that the panel receives focus when opened, which is important for keyboard navigation and accessibility. This can be done by checking if panelRef.current.focus() was called or by verifying focus programmatically in the test.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +127
// Auto-close the config panel when switching views
setShowViewConfigPanel(false);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The auto-close behavior when switching views is not covered by tests. Consider adding a test in ViewSwitching.test.tsx or ObjectView.test.tsx to verify that showViewConfigPanel is set to false when handleViewChange is called. This ensures the panel closes automatically when users switch between views, which is an important UX behavior mentioned in the PR description.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

优化编辑视图页面,支持Airtable风格的右侧配置面板(Inline ViewDesigner)

2 participants