Optimize object detail page with Power Apps-inspired tabbed layout#1200
Optimize object detail page with Power Apps-inspired tabbed layout#1200
Conversation
Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/32d509ca-9783-48ab-a16a-0182b122bfc7 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/32d509ca-9783-48ab-a16a-0182b122bfc7 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/32d509ca-9783-48ab-a16a-0182b122bfc7 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
❌ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
There was a problem hiding this comment.
Pull request overview
Updates the Console’s object detail page to reduce visual clutter by replacing the previous 6-section vertical stack with a single tabbed container, keeping the detail page schema PageSchema-driven while reorganizing content into four logical areas.
Changes:
- Replaced the object detail page body schema with a single
object-detail-tabswidget node. - Added and registered
ObjectDetailTabsWidgetto render 4 tabs (Details, Fields, Relationships, Data) and delegate to existing widgets. - Refined existing object detail widgets’ UI to a cleaner sectioned layout and adjusted MetadataDetailPage tests for the new entry widget.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/console/src/schemas/objectDetailPageSchema.ts | Switches object detail schema body to a single tabbed widget node. |
| apps/console/src/components/schema/registerObjectDetailWidgets.ts | Registers the new object-detail-tabs widget type in the ComponentRegistry. |
| apps/console/src/components/schema/objectDetailWidgets.tsx | Refactors styling/structure of properties/relationships/keys/data widgets for the new layout. |
| apps/console/src/components/schema/ObjectDetailTabsWidget.tsx | Introduces the tabbed container widget orchestrating the object detail sections. |
| apps/console/src/tests/MetadataDetailPage.test.tsx | Updates tests to register/assert the new tabbed widget. |
| import { | ||
| ObjectPropertiesWidget, | ||
| ObjectRelationshipsWidget, | ||
| ObjectKeysWidget, | ||
| ObjectDataExperienceWidget, | ||
| ObjectDataPreviewWidget, | ||
| } from './objectDetailWidgets'; | ||
| import { ObjectFieldDesignerWidget } from './ObjectFieldDesignerWidget'; | ||
|
|
There was a problem hiding this comment.
ObjectDetailTabsWidget composes object detail sections by importing and rendering the widget components directly. This bypasses SchemaRenderer features (expression evaluation, per-node error boundary, debug attributes/ARIA extraction) and prevents swapping/overriding implementations via ComponentRegistry. Consider rendering the per-tab child nodes via <SchemaRenderer schema={...} /> instead of direct component imports, and keep only SchemaNodes in this widget.
| import { | |
| ObjectPropertiesWidget, | |
| ObjectRelationshipsWidget, | |
| ObjectKeysWidget, | |
| ObjectDataExperienceWidget, | |
| ObjectDataPreviewWidget, | |
| } from './objectDetailWidgets'; | |
| import { ObjectFieldDesignerWidget } from './ObjectFieldDesignerWidget'; | |
| import { SchemaRenderer } from '@object-ui/react'; | |
| const ObjectPropertiesWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); | |
| const ObjectRelationshipsWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); | |
| const ObjectKeysWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); | |
| const ObjectDataExperienceWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); | |
| const ObjectDataPreviewWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); | |
| const ObjectFieldDesignerWidget = ({ schema }: { schema: SchemaNode }) => ( | |
| <SchemaRenderer schema={schema} /> | |
| ); |
| <div className="space-y-1.5"> | ||
| <label className="text-xs font-medium text-muted-foreground">Display Name</label> | ||
| <p className="text-sm font-medium">{object.label}</p> | ||
| </div> | ||
| )} | ||
| {object.group && ( | ||
| <div> | ||
| <span className="text-muted-foreground">Group</span> | ||
| <p className="mt-0.5">{object.group}</p> | ||
| <div className="space-y-1.5"> | ||
| <label className="text-xs font-medium text-muted-foreground">API Name</label> | ||
| <p className="text-sm font-mono bg-muted/50 rounded px-2 py-1">{object.name}</p> | ||
| </div> |
There was a problem hiding this comment.
The read-only label/value layout uses <label> elements without associated form controls (htmlFor). This is semantically incorrect and can confuse screen readers. Prefer non-form semantics like <div>/<span> or a <dl> with <dt>/<dd> for definition-style readouts.
| <div className="space-y-1.5"> | ||
| <label className="text-xs font-medium text-muted-foreground">Field Count</label> | ||
| <p className="text-sm font-medium">{object.fieldCount ?? fields.length} fields</p> | ||
| </div> |
There was a problem hiding this comment.
Field Count always renders "{n} fields", which produces incorrect grammar for singular (e.g., "1 fields"). Consider pluralizing based on the count ("1 field" vs "N fields").
| <div className="grid grid-cols-1 sm:grid-cols-3 gap-4"> | ||
| <div className="rounded-lg border p-6 text-center hover:bg-accent/50 transition-colors cursor-pointer" data-testid="data-experience-forms"> | ||
| <PanelTop className="h-8 w-8 mx-auto mb-3 text-muted-foreground" /> | ||
| <p className="text-sm font-semibold mb-1">Forms</p> | ||
| <p className="text-xs text-muted-foreground">Design forms for data entry</p> | ||
| </div> | ||
| <div className="rounded-lg border p-6 text-center hover:bg-accent/50 transition-colors cursor-pointer" data-testid="data-experience-views"> | ||
| <LayoutList className="h-8 w-8 mx-auto mb-3 text-muted-foreground" /> | ||
| <p className="text-sm font-semibold mb-1">Views</p> | ||
| <p className="text-xs text-muted-foreground">Configure list and detail views</p> | ||
| </div> | ||
| <div className="rounded-lg border p-6 text-center hover:bg-accent/50 transition-colors cursor-pointer" data-testid="data-experience-dashboards"> | ||
| <BarChart3 className="h-8 w-8 mx-auto mb-3 text-muted-foreground" /> | ||
| <p className="text-sm font-semibold mb-1">Dashboards</p> | ||
| <p className="text-xs text-muted-foreground">Build visual dashboards</p> | ||
| </div> |
There was a problem hiding this comment.
The Data Experience cards use cursor-pointer and hover styling but have no click handler or interactive semantics. Either remove the pointer/hover affordance for non-interactive placeholders, or render them as accessible interactive elements (e.g., buttons/links with keyboard support) when navigation is implemented.
|
@copilot fix all |
…ML, pluralization, remove false affordance Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/f45bbfad-453a-42a8-9f55-09107853caaa Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
All 4 review comments addressed in 05d7e5c:
|
The object management record detail page displayed all configuration sections in a single vertical stack of 6 cards, creating visual clutter and poor information hierarchy.
Changes
Tabbed Navigation
ObjectDetailTabsWidgetwith 4 logical tabs:Visual Refinement
Architecture
buildObjectDetailPageSchema()now returns singleobject-detail-tabswidgetObjectDetailTabsWidgetorchestrates tab rendering and delegates to existing widgetsUpdated
MetadataDetailPage.test.tsxto register and validate the new tabs widget.