From 81a3d1fab3797a0ddc0a7b4cda9c3cb498b1b103 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 01:23:01 +0000 Subject: [PATCH 1/2] feat(spec): add userActions.refresh toggle to ListView (objectui#2634) The ListView UserActionsConfig exposed toolbar toggles for sort / search / filter / rowHeight but had no toggle for a manual data-refresh action, so consumers had no spec-canonical way to reload a list without a full page reload (objectui#2634). Add `refresh: boolean` (default true) alongside the existing toggles. objectui's ListView reads `userActions.refresh` to gate its toolbar Refresh button; the liveness note for `userActions` is updated to record the new live sub-key. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01C7Z2cbcb14wb99upTD6LNw --- packages/spec/liveness/view.json | 2 +- packages/spec/src/ui/view.test.ts | 3 +++ packages/spec/src/ui/view.zod.ts | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/spec/liveness/view.json b/packages/spec/liveness/view.json index 4c021e60ab..c3b7ce7447 100644 --- a/packages/spec/liveness/view.json +++ b/packages/spec/liveness/view.json @@ -41,7 +41,7 @@ "conditionalFormatting": { "status": "live", "note": "objectui: ObjectGrid.tsx (audit L15)." }, "inlineEdit": { "status": "live", "note": "objectui: ObjectGrid.tsx (audit L15)." }, "exportOptions": { "status": "live", "note": "objectui: ObjectGrid.tsx (audit L15)." }, - "userActions": { "status": "live", "note": "objectui: ListView.tsx:374 toolbarFlags (search/sort/filters/density/hide-fields/group/color + addRecordForm). Sub-key userActions.buttons has NO reader (audit L20, re-verified objectui@fb35e48) — dead sub-surface, enforce-or-remove worklist." }, + "userActions": { "status": "live", "note": "objectui: ListView.tsx:374 toolbarFlags (search/sort/filters/refresh/density/hide-fields/group/color + addRecordForm). Sub-key userActions.refresh drives the manual toolbar Refresh button (objectui#2634). Sub-key userActions.buttons has NO reader (audit L20, re-verified objectui@fb35e48) — dead sub-surface, enforce-or-remove worklist." }, "appearance": { "status": "live", "note": "objectui: allowedVisualizations gates the view-type switcher (audit L15); showDescription gates ListView.tsx:1728." }, "tabs": { "status": "live", "note": "objectui: TabBar.tsx — icon/visible/pinned/filter wired (audit L15). Sub-key tabs[].order is NOT used for sorting (audit L20) — dead sub-surface." }, "addRecord": { "status": "live", "note": "objectui: ListView.tsx:374 (addRecord + userActions.addRecordForm drive the add-record flow). Sub-keys addRecord.mode / addRecord.formView have NO reader (audit L20, re-verified objectui@fb35e48) — dead sub-surface." }, diff --git a/packages/spec/src/ui/view.test.ts b/packages/spec/src/ui/view.test.ts index b1aa3ab651..68226aa6d1 100644 --- a/packages/spec/src/ui/view.test.ts +++ b/packages/spec/src/ui/view.test.ts @@ -2126,6 +2126,7 @@ describe('UserActionsConfigSchema', () => { expect(config.sort).toBe(true); expect(config.search).toBe(true); expect(config.filter).toBe(true); + expect(config.refresh).toBe(true); expect(config.rowHeight).toBe(true); expect(config.addRecordForm).toBe(false); expect(config.editInline).toBe(false); @@ -2335,11 +2336,13 @@ describe('ListViewSchema — Airtable Interface parity fields', () => { sort: true, search: true, filter: false, + refresh: false, rowHeight: false, }, }); expect(listView.userActions?.sort).toBe(true); expect(listView.userActions?.filter).toBe(false); + expect(listView.userActions?.refresh).toBe(false); }); it('should accept list view with appearance', () => { diff --git a/packages/spec/src/ui/view.zod.ts b/packages/spec/src/ui/view.zod.ts index 9911185fa5..cc57372e9c 100644 --- a/packages/spec/src/ui/view.zod.ts +++ b/packages/spec/src/ui/view.zod.ts @@ -240,6 +240,7 @@ export const UserActionsConfigSchema = lazySchema(() => z.object({ sort: z.boolean().default(true).describe('Allow users to sort records'), search: z.boolean().default(true).describe('Allow users to search records'), filter: z.boolean().default(true).describe('Allow users to filter records'), + refresh: z.boolean().default(true).describe('Allow users to reload the view data from the backend without a full page reload'), rowHeight: z.boolean().default(true).describe('Allow users to toggle row height/density'), addRecordForm: z.boolean().default(false).describe('Add records through a form instead of inline'), editInline: z.boolean().default(false).describe('Allow users to edit records inline — click a cell to edit it with the field\'s type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.'), From 77b630ab85252100fb78143508dfca2c250d302a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 01:26:22 +0000 Subject: [PATCH 2/2] docs(spec): regenerate ui reference docs for userActions.refresh `content/docs/references/ui/{view,page}.mdx` are generated from the spec (gen:schema + gen:docs). Adding `userActions.refresh` made them drift; this regenerates them so `check:docs` passes. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01C7Z2cbcb14wb99upTD6LNw --- content/docs/references/ui/page.mdx | 2 +- content/docs/references/ui/view.mdx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/content/docs/references/ui/page.mdx b/content/docs/references/ui/page.mdx index 1d9afd6bea..184b37d26a 100644 --- a/content/docs/references/ui/page.mdx +++ b/content/docs/references/ui/page.mdx @@ -56,7 +56,7 @@ Interface-level page configuration (Airtable parity) | **sourceView** | `string` | optional | @deprecated Legacy named-view inheritance. Define columns/sort/filterBy on the page instead. | | **appearance** | `{ showDescription: boolean; allowedVisualizations?: Enum<'grid' \| 'kanban' \| 'gallery' \| 'calendar' \| 'timeline' \| 'gantt' \| 'map' \| 'chart' \| 'tree'>[] }` | optional | Appearance and visualization configuration | | **userFilters** | `{ element: Enum<'dropdown' \| 'tabs' \| 'toggle'>; fields?: { field: string; label?: string; type?: Enum<'select' \| 'multi-select' \| 'boolean' \| 'date-range' \| 'text'>; options?: { value: string \| number \| boolean; label: string; color?: string }[]; … }[]; tabs?: { name: string; label?: string; icon?: string; view?: string; … }[]; showAllRecords?: boolean }` | optional | End-user quick-filter bar for this page (overrides the source view's userFilters) | -| **userActions** | `{ sort: boolean; search: boolean; filter: boolean; rowHeight: boolean; … }` | optional | User action toggles | +| **userActions** | `{ sort: boolean; search: boolean; filter: boolean; refresh: boolean; … }` | optional | User action toggles | | **addRecord** | `{ enabled: boolean; position: Enum<'top' \| 'bottom' \| 'both'>; mode: Enum<'inline' \| 'form' \| 'modal'>; formView?: string }` | optional | Add record entry point configuration | | **buttons** | `string[]` | optional | Toolbar buttons — names of the source object's actions to surface in the page toolbar | | **recordAction** | `Enum<'drawer' \| 'page' \| 'modal' \| 'none'>` | optional | How clicking a record opens its detail (drawer \| page \| modal \| none). Default: drawer | diff --git a/content/docs/references/ui/view.mdx b/content/docs/references/ui/view.mdx index 145d9460c4..bfd8fd3248 100644 --- a/content/docs/references/ui/view.mdx +++ b/content/docs/references/ui/view.mdx @@ -374,7 +374,7 @@ List chart view configuration | **conditionalFormatting** | `{ condition: string \| { dialect: Enum<'cel' \| 'js' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }; style: Record }[]` | optional | Conditional formatting rules for list rows | | **inlineEdit** | `boolean` | optional | Allow inline editing of records directly in the list view | | **exportOptions** | `Enum<'csv' \| 'xlsx' \| 'pdf' \| 'json'>[]` | optional | Available export format options | -| **userActions** | `{ sort?: boolean; search?: boolean; filter?: boolean; rowHeight?: boolean; … }` | optional | User action toggles for the view toolbar | +| **userActions** | `{ sort?: boolean; search?: boolean; filter?: boolean; refresh?: boolean; … }` | optional | User action toggles for the view toolbar | | **appearance** | `{ showDescription?: boolean; allowedVisualizations?: Enum<'grid' \| 'kanban' \| 'gallery' \| 'calendar' \| 'timeline' \| 'gantt' \| 'map' \| 'chart' \| 'tree'>[] }` | optional | Appearance and visualization configuration | | **tabs** | `{ name: string; label?: string; icon?: string; view?: string; … }[]` | optional | Tab definitions for multi-tab view interface | | **addRecord** | `{ enabled?: boolean; position?: Enum<'top' \| 'bottom' \| 'both'>; mode?: Enum<'inline' \| 'form' \| 'modal'>; formView?: string }` | optional | Add record entry point configuration | @@ -462,7 +462,7 @@ List chart view configuration | **conditionalFormatting** | `{ condition: string \| { dialect: Enum<'cel' \| 'js' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }; style: Record }[]` | optional | Conditional formatting rules for list rows | | **inlineEdit** | `boolean` | optional | Allow inline editing of records directly in the list view | | **exportOptions** | `Enum<'csv' \| 'xlsx' \| 'pdf' \| 'json'>[]` | optional | Available export format options | -| **userActions** | `{ sort?: boolean; search?: boolean; filter?: boolean; rowHeight?: boolean; … }` | optional | User action toggles for the view toolbar | +| **userActions** | `{ sort?: boolean; search?: boolean; filter?: boolean; refresh?: boolean; … }` | optional | User action toggles for the view toolbar | | **appearance** | `{ showDescription?: boolean; allowedVisualizations?: Enum<'grid' \| 'kanban' \| 'gallery' \| 'calendar' \| 'timeline' \| 'gantt' \| 'map' \| 'chart' \| 'tree'>[] }` | optional | Appearance and visualization configuration | | **tabs** | `{ name: string; label?: string; icon?: string; view?: string; … }[]` | optional | Tab definitions for multi-tab view interface | | **addRecord** | `{ enabled?: boolean; position?: Enum<'top' \| 'bottom' \| 'both'>; mode?: Enum<'inline' \| 'form' \| 'modal'>; formView?: string }` | optional | Add record entry point configuration | @@ -584,6 +584,7 @@ User action toggles for the view toolbar | **sort** | `boolean` | ✅ | Allow users to sort records | | **search** | `boolean` | ✅ | Allow users to search records | | **filter** | `boolean` | ✅ | Allow users to filter records | +| **refresh** | `boolean` | ✅ | Allow users to reload the view data from the backend without a full page reload | | **rowHeight** | `boolean` | ✅ | Allow users to toggle row height/density | | **addRecordForm** | `boolean` | ✅ | Add records through a form instead of inline | | **editInline** | `boolean` | ✅ | Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in. |