Skip to content

Commit ad55327

Browse files
os-zhuangclaude
andcommitted
feat(spec): ADR-0047 — list pages hide region/data-context, interface section prominent
Page form (page.form.ts) reorg so interface/list pages get a lean, relevant panel instead of the generic page-form dump: • Data Context + Layout sections gain visibleOn data.type != 'list' (region designer / page object don't apply to a list surface) • Interface section: collapsed:false (primary content), name for i18n • interfaceConfig sub-fields reordered (common first, rare last); source gets the ref:object picker; sourceView/userActions/etc. helpText • type field helpText notes 'list' = interface page Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b9ceaa4 commit ad55327

1 file changed

Lines changed: 22 additions & 11 deletions

File tree

packages/spec/src/ui/page.form.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@ export const pageForm = defineForm({
1919
{ field: 'name', required: true, colSpan: 1, helpText: 'Unique identifier (snake_case)' },
2020
{ field: 'label', required: true, colSpan: 1, helpText: 'Page title shown to users' },
2121
{ field: 'icon', colSpan: 1, helpText: 'Icon for navigation menu' },
22-
{ field: 'type', colSpan: 1, helpText: 'Page type (record, home, app, dashboard, etc.)' },
22+
{ field: 'type', colSpan: 1, helpText: 'Page type — "list" for an interface/list page; also record, home, app, dashboard, etc.' },
2323
{ field: 'template', colSpan: 2, helpText: 'Layout template (e.g., "header-sidebar-main")' },
2424
{ field: 'description', widget: 'textarea', colSpan: 2, helpText: 'Page description for navigation' },
2525
],
2626
},
2727
{
2828
label: 'Data Context',
2929
description: 'Record binding and page-local state.',
30+
// Interface/list pages bind their data via the Interface section
31+
// (source/sourceView), not a page-level object — hide this to keep
32+
// the panel lean (the region/record machinery doesn't apply).
33+
visibleOn: "data.type != 'list'",
3034
fields: [
3135
{ field: 'object', widget: 'ref:object', helpText: 'Bound object (for Record pages)' },
3236
{ field: 'variables', type: 'repeater', helpText: 'Local page state variables' },
@@ -35,43 +39,50 @@ export const pageForm = defineForm({
3539
{
3640
label: 'Layout',
3741
description: 'Page regions and components placed within them.',
42+
// List pages render a curated list surface, not free-form regions —
43+
// the region designer is irrelevant here, so hide it for list pages.
44+
visibleOn: "data.type != 'list'",
3845
fields: [
3946
{ field: 'regions', type: 'repeater', required: true, helpText: 'Layout regions (header, main, sidebar, footer) with components' },
4047
],
4148
},
4249
{
50+
name: 'interface',
4351
label: 'Interface (list pages)',
4452
description: 'ADR-0047 interface mode: bind a source view and curate the end-user surface — quick filters, locked visualizations, toolbar actions (Airtable Interfaces parity).',
4553
collapsible: true,
46-
collapsed: true,
54+
// Primary content for a list page — open by default (still collapsible).
55+
collapsed: false,
4756
visibleOn: "data.type == 'list'",
4857
fields: [
4958
{
5059
field: 'interfaceConfig',
5160
type: 'composite',
5261
helpText:
5362
'source/sourceView bind the object view (columns, base filter and sort are inherited — the iron rule); appearance.allowedVisualizations whitelists renderers (one entry = locked); userActions toggles the toolbar.',
63+
// Order: common authoring controls first, rarely-used ones last.
5464
// Explicit sub-fields so `userFilters` can use the dedicated
5565
// filter-mode selector (None / Tabs / Dropdown, ADR-0047 §3.4a).
5666
// None maps to ABSENCE of userFilters — the protocol stores
5767
// "no filter bar" as omission, not a literal element: 'none'.
5868
// (`element: 'toggle'` stays valid but deprecated — not offered.)
5969
// Keep this list in sync with InterfacePageConfigSchema.
6070
fields: [
61-
{ field: 'source' },
62-
{ field: 'sourceView' },
63-
{ field: 'levels' },
64-
{ field: 'filterBy', type: 'repeater' },
65-
{ field: 'appearance', type: 'composite' },
71+
{ field: 'source', widget: 'ref:object', helpText: 'Object this list reads from' },
72+
{ field: 'sourceView', helpText: 'Named list view to inherit columns/filter/sort from (blank = object default)' },
73+
{ field: 'appearance', type: 'composite', helpText: 'Allowed visualizations (Grid / Kanban / Calendar / …) and description visibility' },
6674
{
6775
field: 'userFilters',
6876
widget: 'filter-mode',
6977
helpText: 'End-user filter bar: None (no bar) / Tabs (named presets) / Dropdown (per-field). None removes the config.',
7078
},
71-
{ field: 'userActions', type: 'composite' },
72-
{ field: 'addRecord', type: 'composite' },
73-
{ field: 'showRecordCount' },
74-
{ field: 'allowPrinting' },
79+
{ field: 'userActions', type: 'composite', helpText: 'Toolbar toggles (search, sort, filter, row height)' },
80+
{ field: 'addRecord', type: 'composite', helpText: 'Add-record entry point' },
81+
{ field: 'showRecordCount', helpText: 'Show the record count bar' },
82+
// Less-common — kept last.
83+
{ field: 'filterBy', type: 'repeater', helpText: 'Always-on page filter (in addition to the source view)' },
84+
{ field: 'levels', helpText: 'Hierarchy levels to display (tree-like sources)' },
85+
{ field: 'allowPrinting', helpText: 'Allow users to print this page' },
7586
],
7687
},
7788
],

0 commit comments

Comments
 (0)