feat(web): monitoring column search, close-to-fullscreen, and open/close animation (#1616)

- Add a search box to MonitoringControls (right of the tabs). It's a single
  shared search kept across column tab switches, filtering whichever screen is
  shown. Embedded panels apply this text but still ignore the sidebar-only
  filters (levels/categories/directions/method), which have no control there.
- Close button now uses the "collapse sidebar" icon (TbLayoutSidebarRightCollapse),
  the mirror of the pin button's expand icon.
- Closing the column carries its selection to the primary view: the screen the
  user was watching becomes the active header tab (rather than snapping back to
  the pre-pin selection).
- Animate the column open/close: the handle + column slide in from the right and
  fade (reversing on close) via a Mantine Transition.
- HistoryListPanel: drop the redundant "History (N)" header when there are no
  pinned requests (lone unpinned section renders headerless).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-07-08 20:16:15 -04:00
commit c5e064ff71

View file

@ -58,8 +58,11 @@ function matchesFilters(
entry: FetchRequestEntry,
filterText: string,
visibleCategories: Record<FetchRequestCategory, boolean>,
// The embedded column exposes only the search box (no category toggles), so it
// applies the text filter but skips the category filter (#1616).
ignoreCategories: boolean,
): boolean {
if (!visibleCategories[entry.category]) return false;
if (!ignoreCategories && !visibleCategories[entry.category]) return false;
if (filterText) {
const term = filterText.toLowerCase();
const status =
@ -98,13 +101,11 @@ export function NetworkStreamPanel({
}: NetworkStreamPanelProps) {
const viewportRef = useScrollMemory("network-stream");
const filteredEntries = useMemo(() => {
// Embedded column: show the full stream (no filter sidebar to explain a
// mirrored filter). See LogStreamPanel (#1616). `.filter()` returns a fresh
// array, so sorting in-place is safe.
// Embedded column filters by text only (its category toggles live in the
// full-size sidebar). See LogStreamPanel (#1616). `.filter()` returns a
// fresh array, so sorting in-place is safe.
const sorted = entries
.filter(
(e) => embedded || matchesFilters(e, filterText, visibleCategories),
)
.filter((e) => matchesFilters(e, filterText, visibleCategories, embedded))
.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
if (sortDirection === "newest-first") sorted.reverse();
return sorted;