Repository navigation
Improve batch update UI/UX: site context, responsive layout, accessibility, and safer bulk actions #1775
Description
Summary
The batch update page in current main is a substantial improvement over the implementation at 741b0bd2ec2f75a7e84c62fbe02654ce6bc41543. The current version has dedicated desktop/mobile layouts, row-level progress, batch progress, skeleton/loading/error states, explicit retry paths, and much better async feedback.
However, the redesign also removed or weakened several pieces of context that were useful in the older flow, and a few parts of the new layout do not fully follow the repository's own responsive/accessibility design rules.
This issue proposes a focused follow-up pass. The goal is not to revert the new UI. The goal is to keep the stronger state model and visual system in main, while fixing the remaining workflow, responsive, accessibility, and bulk-action problems.
Comparison baseline
- Old implementation:
741b0bd.../src/pages/batchupdate/App.tsx - Current main reviewed:
d6cc48b.../src/pages/batchupdate/ - Current site grouping logic:
logic.ts - Current desktop/shared components:
components.tsx - Current mobile view:
mobile.tsx - Project UI rules:
docs/references/design-patterns.md
What should be preserved from current main
These are clear improvements and should remain:
| Area | Old behavior | Current main | Direction |
|---|---|---|---|
| Async feedback | Mostly global busy state | Per-row queued / updating / success / failure, retry, batch summary | Keep current |
| Loading | Little visible structure while records load | Skeleton table/cards and top progress | Keep current |
| Failure handling | Some failures could look like no-op/success | Dedicated load error, record-expired handling, retry paths | Keep current |
| Mobile | Same general content model as desktop | Dedicated mobile shell and card layout | Keep current |
| Batch control | Group-wide actions only | Explicit selection + selected count | Keep current as the safe base |
| Update detail opening | Limited feedback | Loading state and duplicate-click protection | Keep current |
| Auto close | Page could close itself after a countdown | Removed in #1720 after #1715 | Do not restore auto-close |
The old countdown should not come back. #1720 correctly removed it because users could lose the page before finishing their review.
1. Restore visible site context and make batch scope unambiguous
Background
The older page explicitly separated updates into:
- updates related to the current site;
- updates for other sites;
- ignored updates.
That distinction was especially useful when the batch update page was opened because the user navigated to a site with relevant updates.
Current main still calculates this information:
UpdateItem.siteMatchexists;categorize(records, site)sorts matching items to the top.
But the view never renders siteMatch. The result is that the user sees some rows at the top without any explanation of why they are first.
This is more than a visual detail. The page can be opened with ?site=<domain>, so there is real task context behind that ordering.
Current UX problem
A user entering from example.com may see:
- several rows related to
example.com; - then unrelated updates;
- one global "select all" control.
Nothing in the UI explains where the current-site group ends.
This also changes the meaning of "select all": in the old page, batch actions were scoped to a visible group; in current main, select-all selects every pending update, including unrelated sites.
Required improvement
Make the current-site context visible whenever a site parameter exists.
A good implementation could use either grouped sections or an equally clear scoped treatment:
- For example.com — N updates
- Other updates — M updates
- Ignored updates — K updates
The exact visual treatment can follow the current design system; it does not need to copy the old Collapse component.
Batch-selection behavior
When site context exists, batch scope should be explicit.
Preferred behavior:
- provide a "select all for this site" action or section-level checkbox;
- keep an intentional way to select all pending updates globally;
- never make a site-triggered page silently select unrelated updates.
If the team prefers one global table, add a non-color site marker and a scoped selection action so the boundary remains understandable.
Acceptance criteria
- When
?site=example.comis present, the UI visibly identifies updates that matchexample.com. - The boundary between current-site and other updates is understandable without relying only on ordering.
- A bulk-selection control makes its scope clear.
- Keyboard and screen-reader users receive the same site/group context.
- Without a
siteparameter, the page remains simple and does not show an empty/current-site section.
2. Make the desktop layout truly usable from the 768 px breakpoint upward
Background
The project has one mobile breakpoint: widths below 768 px use the mobile shell. At 768 px and above, batch update uses the desktop table.
In the current desktop row, fixed columns reserve approximately:
| Column | Width |
|---|---|
| Checkbox slot | 36 px |
| Version | 170 px |
| Change | 230 px |
| Source | 160 px |
| Action | 180 px |
| Fixed subtotal | 776 px |
This subtotal is before the script-name column and before the row/container horizontal padding.
At a 768 px viewport, the desktop content area is already narrower than those fixed columns. The name area therefore has no realistic room, and the row can become cramped or overflow-prone.
This is the same general fixed-column problem that other ScriptCat list pages have already been moving away from.
Required improvement
Keep the single 768 px shell breakpoint, but make the desktop row itself adaptive.
Suggested direction:
- keep a stable left anchor for selection + script identity;
- keep the primary action area stable on the right;
- move lower-priority metadata such as source/risk into a secondary line under the script name when horizontal space is tight;
- allow metadata to wrap/truncate intentionally;
- avoid a layout whose fixed columns already exceed the smallest supported desktop width.
Another acceptable design is a denser two-line desktop list row rather than a traditional six-column table.
Do not solve this by
- adding a second JavaScript mobile breakpoint only for this page;
- introducing horizontal scrolling as the normal behavior at ordinary tablet/narrow-desktop widths;
- hiding security-relevant information without another discoverable path.
Acceptance criteria
- At 768 px wide, the desktop shell does not horizontally overflow.
- Script names retain useful readable space at narrow desktop widths.
- Update risk and new-
@connectinformation remains discoverable. - Actions remain aligned and reachable.
- Test at 768, 800, 900, 1024, and 1100 px, in both light and dark themes.
- Include at least one long-locale fixture, as required by the design guidelines.
3. Fix keyboard focus visibility for custom text actions
Background
The repository design guide explicitly notes that the global base layer removes native outlines. Custom buttons must therefore add a visible focus-visible ring, or reuse a shared primitive that already provides one.
The batch update page contains several custom <button> elements that use text/underline styling but do not visibly add the standard focus ring, for example:
- clickable script names;
- Update / Ignore / Restore text actions;
- row Retry;
- "View updated scripts";
- record-expired "Recheck";
- several mobile text actions.
This can leave keyboard users with no visible indication of where focus is.
Required improvement
Prefer a shared text-action/link-button primitive instead of repeating raw button classes.
At minimum, every custom interactive element must have:
- keyboard reachability;
- visible
focus-visiblestyling; - adequate contrast;
- an accessible name.
Acceptance criteria
- Tabbing through every batch-update action always shows a visible focus indicator.
- Focus indication works in both themes.
- Row status changes do not unexpectedly drop keyboard focus to
body. - No action relies on hover alone to reveal essential information.
4. Increase mobile hit areas for frequently used actions
Background
The project design guide targets roughly 44 px touch areas for primary mobile interactions.
Current mobile batch update uses several controls smaller than that:
- top-bar refresh/close use
size="icon-sm"(32 px in the shared Button primitive); - Update / Ignore / Restore are compact text buttons with little or no hit-area padding;
- some inline recovery actions are similarly compact.
These controls are visually clean, but they are easy to miss on a phone.
Required improvement
Keep the visual density, but enlarge the interactive hit area.
Possible approaches:
- use a larger Button size for top-bar controls;
- keep text visually compact while adding vertical/horizontal padding;
- use a pseudo-element/absolute hit target when the visible control must stay small;
- preserve enough spacing that adjacent Update / Ignore actions are not easy to mis-tap.
Acceptance criteria
- Primary mobile actions have approximately 44 px touch targets or equivalent expanded hit areas.
- Update and Ignore cannot be easily mis-tapped as neighboring controls.
- Enlarged hit areas do not cause the card layout to jump or become visually heavy.
- Verify on the narrowest supported mobile width and with long translated labels.
5. Do not dim security-relevant update information when a script is disabled
Background
The current row/card applies opacity-55 to much of the content for a disabled script.
That visual treatment also reduces emphasis on:
- version change;
- code-change risk;
- new
@connectwarning; - source.
A script being disabled is an execution state. It does not make an update's security/review information less important.
The UI already has an explicit Enabled/Disabled badge, so the additional broad opacity reduction is not necessary to communicate status.
Required improvement
De-emphasize only the script's execution status/identity if desired, but keep update-decision information at normal legibility.
In particular:
- risk badges should keep their normal contrast;
- new-
@connectwarnings should keep their normal contrast; - versions and source should remain readable;
- the Disabled badge should be the main status cue.
Acceptance criteria
- Security/risk metadata has the same legibility for enabled and disabled scripts.
- Disabled state remains clear without relying on whole-row opacity.
- Contrast continues to meet the project's WCAG AA target in both themes.
6. Add aggregate risk feedback before a large bulk update
Background
The current row design is much better than the old page at showing risk:
- code-change severity;
- new
@connectdomains; - source;
- version transition.
However, once many scripts are selected, the batch action area only reports the selected count. It does not summarize whether the selection contains high-attention updates.
This matters most when the user uses "select all" and the risky rows are outside the current scroll position.
Required improvement
Before committing a risky batch, surface a compact aggregate risk summary.
For example:
12 selected · 2 major code changes · 1 adds new @connect domains
For ordinary low-risk selections, the current one-click flow can remain.
For a selection containing especially important review signals (at least new @connect; optionally major code changes), add a lightweight confirmation that names the affected scripts and the reason they need attention.
This should not turn every batch update into a modal-heavy flow.
Acceptance criteria
- The batch toolbar/action bar summarizes important risk within the current selection.
- New-
@connectadditions cannot be hidden only inside off-screen rows before a bulk update. - Any confirmation is conditional and focused on meaningful risk, not shown for every normal batch.
- The user can cancel and return to the same selection without losing it.
Interaction/state considerations
Please preserve the current state model while implementing the UI changes:
- row state remains visible for queued / working / success / failure;
- failed rows remain retryable;
- successful rows may exit after the current short confirmation period;
- batch progress remains deterministic;
- record-expired recovery remains explicit;
- checking updates keeps the top progress signal;
- initial loading keeps layout-preserving skeletons;
- load failure must never render as "all scripts are up to date";
- auto-close remains removed.
Suggested information hierarchy
Desktop
- Page title + last-check/checking state + Check updates + Close
- Optional current-site context summary
- Optional record-expired / batch-progress banner
- Scoped selection toolbar
- Adaptive update list
- Ignored updates section
Mobile
- Title + concise status + Refresh + Close
- Optional current-site context
- Optional record-expired / batch-progress banner
- Selection summary
- Update cards
- Ignored section
- Bottom batch action bar with selected count + risk summary
Testing / verification
Please add or update tests for the behavior rather than only snapshotting markup.
Suggested coverage:
-
siteparameter renders visible current-site context. - Current-site and global selection scopes are correct.
- No
siteparameter keeps the generic list behavior. - Desktop layout has no horizontal overflow at 768 px.
- Keyboard focus is visible on every custom action.
- Mobile controls expose adequate hit areas.
- Disabled scripts do not dim risk/new-
@connectmetadata. - Bulk risk summary updates as selection changes.
- Risk confirmation appears only when required.
- Existing batch-progress, retry, skeleton, load-error, record-expired, and no-auto-close tests continue to pass.
Design intent
The main principle is:
Keep the new page's stronger state feedback, but make the user's scope and risk visible before they commit a batch action.
The old UI was clearer about "updates for the site I am on" versus "other updates." The new UI is much better at progress, errors, mobile presentation, and detailed per-row risk. Combining those strengths should make the batch-update flow easier to understand without adding unnecessary visual complexity.
Activity
cyfung1031 commentedon Sep 27, 2026
主要是1 問題 "Restore visible site context and make batch scope unambiguous"
新UI完全沒考慮實際使用的操作
這個問題必須改善
CodFrm commentedon Oct 9, 2026
第一轮改动在 #1788,各点的处理情况如下:
1. 站点上下文(本次主要处理的点):已完成。带
?site=打开且有命中的脚本时,列表分成「{site} 相关」和「其他更新」两段,每段的组头复选框只切换本段;顶部复选框显式标为「全选」,部分选中时显示半选。没有site参数或没有命中时不分段,页面和以前一样。桌面端和移动端都做了。2. 768px 起的桌面布局:已完成。没有加新的断点,而是改成两行行布局:表格只保留「脚本 / 变更 / 操作」三列,版本和来源放到脚本名下面一行,长版本截断后悬停可以看全文。768px 下不再重叠,脚本名有可读宽度。移动端触屏没有悬停,版本单独占一行,折行显示完整内容。
3. 键盘焦点不可见:这一点不成立。
src/index.css的全局规则已经给所有button:focus-visible/[role="button"]:focus-visible加了ring-2 ring-ring/50,用 Tab 切换时这些自定义按钮都有可见的焦点环,所以不改。4. 移动端点击区域:已完成。顶栏的刷新 / 关闭从 32px 改为 44px;卡片里的「更新 / 忽略」和所有复选框的点击区域扩到约 44px,用负外边距和伪元素实现,外观和卡片高度不变,相邻两个按钮的点击区域也不重叠。顺带修了一处不一致:移动端批量进行中卡片复选框没有禁用,现在和桌面端一致了。
5. 禁用脚本不要调暗风险信息:维护者决定保持现状,这次不改。
6. 批量更新前汇总风险:这次先不做,留作后续。
另外,风险标签配色也按讨论调整了:重大改动从危险红改为警示橙,显著改动从主色蓝改为中性灰,轻微改动保持绿色。
这个 issue 先保持打开,第 6 点等后续再处理。
💄 批量更新页按当前站点分段,修正相似度显示,并优化窄屏与移动端布局 (#1788)