Skip to content

feat(plugin-list): an empty list offers "Clear filters" when the reader's own filter emptied it - #29047

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-ayrsgr
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-ayrsgr

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #28908

Clause-②: yes (widening)
Metadata-protocol: none

维护者速读

  • 改了什么:列表被读者自己加的筛选(筛选面板的条件、「在队列中」开关)筛空时,空状态现在把「清除筛选」作为主按钮,「添加记录」降为次按钮;点一下清掉读者的整套查询(面板条件、队列开关、搜索词),工具栏筛选角标归零,记录回来。只有搜索时保持原样(「清除搜索」+ 主按钮「添加记录」)。视图自己声明的筛选永远不清,只被它筛空时不出现清除按钮。新增一条界面文案 list.clearFilters(十个语言包)。
  • 为什么改:今天文案说「试试调整或清除它们」,唯一按钮却是「添加记录」,读者得回去找工具栏的小角标;在筛选状态下点「添加记录」还会新建记录。
  • 风险与回滚:低。只改空状态的按钮与一个清除回调;清空的面板条件走与面板编辑相同的 onFilterChange,宿主存下的是空条件组。用户筛选标签(chips)不在本次范围内,各自就地清除。回滚即回退本 PR。
  • 先看:ui/packages/plugin-list/src/ListView.tsx(handleClearReaderQuery 与传给 ListEmptyState 的 onClearFilters 判定);ui/packages/plugin-list/src/ListEmptyState.tsx(主次按钮与「只出现一个清除按钮」);新测试 ListView.emptyStateClearFilters-28908.test.tsx。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/plugin-list/src/__tests__/ListView.emptyStateClearFilters-28908.test.tsx,预期 7 个用例全部通过;第一个用例断言主按钮是「Clear filters」、点击后空状态消失、角标不再显示 active。
  • 需要你做的:无,席位落地。

What changes

The empty state's clear action covers the reader's filters. ListView hands ListEmptyState a new onClearFilters callback whenever a filter the reader applied is part of the empty query: the filter panel's finished conditions (the same predicate hasUserQuery already reads) or the "In a queue" toggle. The callback, handleClearReaderQuery, removes the reader's whole query:

  • the panel group is emptied (conditions: [], id and logic kept) through the same emit as a panel edit, so the toolbar badge clears and a host that stores the group through onFilterChange stores the empty group;
  • the "In a queue" toggle is released;
  • the search box is cleared through handleSearchChange('') when it holds anything, so onSearchChange('') reaches the host as it does for "Clear search".

The view's declared filter is never touched: it is not the reader's query, and buildEffectiveFilter still ANDs it into the next fetch.

One clear action, leading. ListEmptyState gains the onClearFilters prop. Supplied, it draws "Clear filters" (data-testid="empty-state-clear-filters", the default button variant) and the add-record action steps down to the outline variant; it replaces "Clear search" rather than sitting beside it, since it clears the search too. Not supplied, the actions are exactly as before: a search alone draws the outline "Clear search" beside the primary "Add record". ListEmptyState is module-internal (not exported from the package barrel), so the prop widens no public surface.

Copy. One new string, list.clearFilters, in all ten built-in locale packs and in plugin-list's LIST_DEFAULT_TRANSLATIONS (en "Clear filters", zh 清除筛选). Each translation matches the wording the same locale already uses for the Gantt quick-filter's clear action.

Tests

ui/packages/plugin-list/src/__tests__/ListView.emptyStateClearFilters-28908.test.tsx (new), 7 cases, mounted on a data source that answers zero rows for the reader's miss and one lead otherwise:

  • a panel filter that empties the list: "Clear filters" is primary, "Add record" secondary, no "Clear search"; the click empties the group through onFilterChange, the next fetch carries no miss, the empty state is gone and the filter trigger's label no longer reads active;
  • a search alone: "Clear search" (outline) beside the primary "Add record", and the click reaches onSearchChange('');
  • a filter and a search together: one clear action, which clears both;
  • the "In a queue" toggle: "Clear filters" releases it and the rows come back;
  • a view emptied by its declared filter alone: the view-filter copy and no clear action;
  • a reader filter over a declared filter: the click removes the reader's part only, and the next fetch still carries the declared filter;
  • a list emptied by a user-filter chip alone: the "your filters or search" copy and no clear action.

Acceptance notes

  • User-filter chips are out of scope (claim amendment 6569743409). UserFilters holds its own selection and each chip clears in place; resetting chips from the empty state would need a key remount, which ui/AGENTS.md Convert to monorepo with scoped packages #8 forbids. So a list emptied by a chip alone keeps the "your current filters or search" copy and offers only "Add record". When the panel or the queue toggle is also set, "Clear filters" clears those and the search, and the chip stays.
  • The declaration reads Clause-②: yes (widening) for the one new key on @object-ui/i18n's locale catalogue, as the claim amendment rules; Metadata-protocol: none (no metadata key or option).

Verification

Readings on f44092be (the change) unless named; ceaa4f90 merges origin/main (2ac698ba touched the locale packs with other keys, clean merge), and the scoped re-check after it is named below.

Tests
  • New file alone: 1 file, 7/7 passed.
  • pnpm --dir ui exec vitest run packages/plugin-list/ packages/i18n/ (under the verify lock, --maxWorkers=2): 274 files passed; 3172 tests passed, 13 skipped.
  • pnpm --dir ui exec vitest run scripts/: 169 files passed, 2 skipped; 4900 tests passed.
  • Ablation (one-time, not kept): scripts/ablation-replace.mjs replaced ? handleClearReaderQuery in the onClearFilters handoff with an undefined callback. The new file went 4 failed / 3 passed (the four "Clear filters" cases red; search-only, declared-only and chip-only green, as they pin unchanged behaviour). The restore leg read blob == HEAD and an empty git diff HEAD.
  • After the merge (ceaa4f90): packages/i18n/ plus the 15 plugin-list test files that name the empty state (git grep -l of empty-state, ListEmptyState, clearSearch) and the new file: 109 files passed; 1694 tests passed, 13 skipped. The merge rebuilt the plugin-list closure first (49/49 tasks).
Type-check, lint
  • turbo run type-check --filter=@object-ui/plugin-list --filter=@object-ui/i18n: 51/51 tasks on f44092be; 51/51 tasks again on ceaa4f90.
  • eslint on every changed source, test and locale file: 0 errors (warnings only: two as any data-source casts in the new test, the pattern the neighbouring empty-state tests use, and pre-existing ones).
  • node scripts/check-sdui-manifest.mjs: exit 0 (no component config changed).
  • pnpm check:new-line-citations under ui/: 0 new citations.
Derived gates

node scripts/pm/dispatch-gates.mjs --ran: 34 derived families accounted for, 34 run, 0 NOT MEASURED, every one exit 0. The PR-body gates (check-changeset-no-major, check-closing-keyword-parity, check-partof-closing-keyword, check-adr-0087-registration, check-empty-changeset) ran on this body: exit 0 on each.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QsR2jS5v57GVJJL1k8m1nN


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

席位核对 · ACCEPT · 2026-11-02T06:42Z

Head-sha: ceaa4f909fd488d3839f17ebbe1fe1f80a153e04

  • Shape:
    • The PR is a draft against main. The first card line is Fixes #28908, and no other card sits beside a closing keyword.
    • 14 files, +308 / −5, inside the claimed surface (6569718286, amendment 6569743409): ListView.tsx, ListEmptyState.tsx, one new key in the ten locale packs, the new test and a changeset. No governed path: check-governed-merges --pr 29047 reports NOT governed.
    • Clause-②: yes (widening) and Metadata-protocol: none start their lines in the body and the changeset, as the amendment rules: one new key, list.clearFilters, on @object-ui/i18n's catalogue. The changeset is patch.
  • Read in the diff:
  • Gates (check-runs on this head): 44 success, 11 skipped, 0 failed or pending. mergeable_state is clean.
  • Tests (dev): new emptyStateClearFilters-28908 (7 tests); plugin-list and i18n 274 files, 3172 passed; after merging main, 109 files, 1694 passed; ui scripts/ 4900 passed. Ablation of the clear handoff: 4 red, 3 green, restored. Derived gates 34 of 34.
  • NOT MEASURED: the seat ran no live session.
  • Landing: ordinary queue landing, pr_ready then automerge_enable. Fixes #28908 closes the card on merge. ListView.tsx is also changed by queued PRs fix(plugin-list, app-shell): "Reset to view default" clears the stored list setting instead of copying the view into it #29044 and feat(plugin-list): a phone list offers Sort in the Display panel and a search that expands in place #29054 in separate hunks; a queue conflict is handled by merging main.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 2, 2026 06:43
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 2, 2026 06:43
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit b889c40 Nov 2, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-ayrsgr branch November 2, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

1 participant