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
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.siteMatch exists;
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
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
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-visible styling;
- adequate contrast;
- an accessible name.
Acceptance criteria
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
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
@connect warning;
- 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-
@connect warnings should keep their normal contrast;
- versions and source should remain readable;
- the Disabled badge should be the main status cue.
Acceptance criteria
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
@connect domains;
- 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
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:
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.
Summary
The batch update page in current
mainis a substantial improvement over the implementation at741b0bd2ec2f75a7e84c62fbe02654ce6bc41543. 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
741b0bd.../src/pages/batchupdate/App.tsxd6cc48b.../src/pages/batchupdate/logic.tscomponents.tsxmobile.tsxdocs/references/design-patterns.mdWhat should be preserved from current main
These are clear improvements and should remain:
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:
That distinction was especially useful when the batch update page was opened because the user navigated to a site with relevant updates.
Current
mainstill 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.commay see:example.com;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
siteparameter exists.A good implementation could use either grouped sections or an equally clear scoped treatment:
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:
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
?site=example.comis present, the UI visibly identifies updates that matchexample.com.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:
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:
Another acceptable design is a denser two-line desktop list row rather than a traditional six-column table.
Do not solve this by
Acceptance criteria
@connectinformation remains discoverable.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-visiblering, 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: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:
focus-visiblestyling;Acceptance criteria
body.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:
size="icon-sm"(32 px in the shared Button primitive);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:
Acceptance criteria
5. Do not dim security-relevant update information when a script is disabled
Background
The current row/card applies
opacity-55to much of the content for a disabled script.That visual treatment also reduces emphasis on:
@connectwarning;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:
@connectwarnings should keep their normal contrast;Acceptance criteria
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:
@connectdomains;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:
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
@connectadditions cannot be hidden only inside off-screen rows before a bulk update.Interaction/state considerations
Please preserve the current state model while implementing the UI changes:
Suggested information hierarchy
Desktop
Mobile
Testing / verification
Please add or update tests for the behavior rather than only snapshotting markup.
Suggested coverage:
siteparameter renders visible current-site context.siteparameter keeps the generic list behavior.@connectmetadata.Design intent
The main principle is:
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.