Skip to content

feat(ui): Library Manager — management settings screen + switcher Manage/status (LM-1/LM-2)#165

Merged
eliotlim merged 3 commits into
mainfrom
feat/library-manager-ui
Jul 14, 2026
Merged

feat(ui): Library Manager — management settings screen + switcher Manage/status (LM-1/LM-2)#165
eliotlim merged 3 commits into
mainfrom
feat/library-manager-ui

Conversation

@eliotlim

Copy link
Copy Markdown
Owner

Problem

A device can be connected to several libraries (server connections), but there was no place to manage them. Editing a library — renaming it, changing its icon, re-pointing its server URL, or removing it — was only possible through the switcher's "add" dialog or the single-server Connection tab. There was no overview of every library this device knows about, and no signal of which ones are actually reachable.

Solution

LM-1 — Libraries settings screen. A new Libraries tab under Settings that lists every library this device can open. Each row reuses LibraryProvider's CRUD (addLibrary / updateLibrary / removeLibrary) to rename, change icon, re-point the server URL, or remove a library, plus an inline "Add a library" row. The local library ("This device") is guarded: its URL is locked and it can't be removed. Two robustness details from the design review:

  • Active-URL edits reconnect. Editing the active library's server URL doesn't just rewrite the stored list (which would silently desync the data client) — it re-points the connection through the same path selectLibrary uses (setServerUrlOverride + reload).
  • Name commits on blur (or Enter), not per keystroke, so a half-cleared field never leaves a nameless card/switcher row; blank falls back to the host label / "Local library".

LM-2 — Switcher Manage entry + status. The library switcher gains a "Manage libraries…" footer (opens the new tab) and a subtle, non-blocking connection-status dot per non-active row. The dot probes each remote's unauthenticated GET /health with a 3s abort, degrading to a neutral "unknown" on timeout/network/CORS so it can never hang or block the menu; the local library is always "reachable" and the active library shows a checkmark instead.

Before / After

Behaviour Before After
Switcher dropdown — status + Manage
Plain list: active checkmark only, no per-library status, no way to manage.

Non-active rows show a status dot (green reachable / amber unreachable), active row keeps its checkmark, and a Manage libraries… footer opens the new tab.
Libraries settings screen (new) Did not exist — no Libraries tab; editing was only in the add-dialog / Connection tab.
New Libraries tab: per-library icon/name/URL editing + add row.
Reachability in settings Did not exist
All three cards: local (green, locked), active "Team server" (green + Active pill), and an amber unreachable remote with a trash button.
Local (this-device) locked card Did not exist
Icon/name editable; URL row shows the locked "This device — always available. It can't be removed or pointed at another server." hint; no trash button.

Capture note: reachability was driven live — the "Team server" remote points at a healthy server (green) and the "Backup host" remote at a server returning 503 (amber). The switcher shows both dots; in the settings screen the amber card sits below the fold in the full-dialog shot, so the dedicated cards-list shot shows all three states together.

Test procedure

  • pnpm --filter @book.dev/sdk build && pnpm --filter @book.dev/ui build — green (build:libs).
  • pnpm --filter @book.dev/ui typecheck / lint — green.
  • pnpm --filter @book.dev/ui test (vitest) — green.
  • Captures produced via the web e2e Playwright harness (seeding a local + two remote libraries) — before = base main, after = this branch.

Operational notes

  • No account/deploy change. This is an MVP layered on the already-synced library list in localStorage; no server, migration, or account-service change.
  • Reachability probes are best-effort and unauthenticated (/health only) — they never block the UI and never claim a server is "down", only "unknown", on any probe failure.
  • Known low-severity a11y follow-ups (design review, accepted): the status dot is exposed via title / aria-label only — it is not keyboard-focusable, so the status isn't reachable by keyboard-only navigation. To be tightened in a follow-up.

Verify: green (build:libs + typecheck + lint + ui vitest).
Gate: design (Devon) — CLEAR WITH NITS, all nits applied (active-URL reconnect, name-on-blur, cross-ref hint, cleanup).

🤖 Generated with Claude Code

https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w

eliotlim and others added 3 commits July 14, 2026 10:39
Add a "Libraries" settings tab that lists every configured library with its
icon, name, host label, and a live reachability dot, and lets you rename,
re-icon, re-point the server URL (validated via isSafeServerUrl), and remove
each one — plus an inline add-a-library row. The local library (this device)
is guarded: its URL is locked and it can't be removed.
Add a "Manage libraries" item to the library switcher that opens the new
Libraries settings tab, and a subtle per-entry connection-status dot: the
active library reads Connected, others get a short, abortable GET /health
probe (the always-open endpoint) that degrades to "unknown" on timeout/CORS
so it never blocks or hangs the menu.
…eanup (design review)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app.book.pub Ready Ready Preview, Comment Jul 14, 2026 3:50am

Request Review

@eliotlim eliotlim merged commit 598e855 into main Jul 14, 2026
10 checks passed
@eliotlim eliotlim deleted the feat/library-manager-ui branch July 14, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant