Moving the library or queue cursor with the keyboard (j/k, page keys,
first/last) updated the selection but never scrolled the list, so the
selected row could slide out of the scroll box and disappear.
Each pane now runs an effect that re-scrolls its `.selected` row into
view whenever the cursor moves. The queue cursor is its own signal, so
this fires on moves but not on every stream-driven queue refresh; the
library cursor lives in the library pane signal. The scroll is deferred
to the next animation frame (the freshly-rendered row must be in the
DOM) and uses `block: nearest`, so an already-visible row does not jump.
Click/drag selection needs no help -- the pointer is already on-screen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
crabidy-server now serves a browser client with the same functionality
as the TUI at its own address, behind the default-on web-ui feature.
The new cbd-web crate is a client-side Leptos/WASM app talking gRPC-web
(tonic-web-wasm-client) over the same crabidy-core client and proto the
TUI uses, so parity is structural: library browsing, search terms,
marks, bookmarks/captures with live progress and confirmed deletion,
the full queue and playback controls, and the update stream with
reconnect. Keys mirror the TUI; every key also has a clickable control.
Styling is hand-written modern CSS with a single crab orange-red accent
and light/dark themes.
The server wraps its existing gRPC service in tonic-web and composes one
axum router (auth layer -> grpc-web -> service, web bundle as fallback);
axum::serve replaces tonic transport, and native gRPC (h2c) still works.
The bundle is embedded via include_dir behind a build.rs that falls back
to a placeholder so a plain cargo build needs no wasm toolchain. To make
crabidy-core build for wasm, tonic is codegen-only there (transport
generation disabled) and native config loading is target-gated.
devenv gains the wasm toolchain and build-web/serve-web scripts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>