Zotero page UX: smoother collection selection and friendlier sync feedback
#4,961 opened on Jul 4, 2026
Repository metrics
- Stars
- (8,787 stars)
- PR merge metrics
- (PR metrics pending)
Description
Summary
The Zotero integration (#4723, #4960) works end-to-end, but parts of the page UX are still clunky — especially how collections are chosen. Plenty of self-contained, UI-only improvements here; a good place to make a first contribution.
Current behavior (what feels clunky)
- Choosing collections is fiddly. Collections live in a plain comma-separated text field of opaque keys (e.g.
W63I9K8W) inside the "Advanced options" section. The picker is a separate card at the bottom of the page: clicking a key appends it to the text field back at the top. Removing a collection means hand-editing the comma list. There are no checkboxes, no names next to the selected keys, no visual link between the picker and the field. - The sync-status table shows raw collection keys, not names — "W63I9K8W" instead of "test". Users have to remember what a key means.
- The group picker has the same shape: a separate bottom card that silently rewrites two fields in Advanced.
- Feedback is split across two channels: the app-wide banner (autosave results) and an inline message area under the action buttons (test/sync/picker results). Users have to watch two places.
- Sync results are thin: after a sync you see status/item-count per collection, but the imported/skipped/errors counts from the run are only visible in server logs.
Suggested direction
Replace the text-field + bottom-card pattern with an inline, name-based multi-select directly under the Collections field (see the implementation notes in the first comment). Show collection names in the status table. Fold group selection into the library-type row. Surface the last sync's imported/skipped/errors counts in the status area.
Small, independent slices — each bullet above is shippable on its own.
Constraints to respect
- All dynamic values inserted via
innerHTMLmust go through the page'sesc()helper (XSS). - CSS classes must carry the
ldr-prefix (pre-commit enforces this). - Autosave is gated on
configLoadState === 'ready'— new controls must save throughautosave()and respect that gate. - The API key is write-only; nothing may echo it back to the page.
tests/ui_tests/test_zotero_integration_ci.jspins element ids and page structure — update it in lockstep with any markup changes.