* feat(web): single header MonitoringToggle + Prompts-style Tools results (#1661) Consolidate the monitoring column's open/close affordances into one header toggle, and align the Tools/Prompts result panes and the sidebar log layout. - Add a single `MonitoringToggle` in the header, to the right of the theme icon. It opens/closes the monitoring column and only shows when a server is connected OR a connect attempt failed (wide viewport + a monitor tab available) — the same availability rule the column uses. - Remove the scattered pin/close icons: delete `PinColumnButton`; drop `onPin` from the Logs/Protocol/Network/Console screens and their stream panels; drop `onOpenMonitor` from the server list; remove the close button from `MonitoringControls`/`MonitoringScreen`. - Tools screen: remove the "Results will appear here" placeholder pane. Results now replace the input form in a single content pane (the Prompts pattern), with a top-left X (ToolResultPanel) that dismisses them back to the form; form values are preserved for a re-run. - Prompts screen: the argument form fills the content pane width (drop the 40% cap), matching the Tools input. - LogEntry: add a `compact` two-line layout (time/level/logger on line one, message wrapping below) used by the embedded monitoring-column Logs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015sMW1YZXkM7fDkdPtHpE95 * polish(web): tooltips on icon buttons + rename "monitoring column" → "monitoring sidebar" (#1661) - Add Mantine `Tooltip`s to the icon-only controls: Client settings, Theme (dynamic light/dark label), the monitoring-sidebar toggle, the list-level and per-entry Expand/Collapse toggles, the Pin/Unpin toggle, and the Replay button. Labels mirror each control's existing aria-label. - Rename the feature term "monitoring column" → "monitoring sidebar" across the user-facing labels (Open/Close/Resize), comments, and tests, so the UI calls it a sidebar consistently. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015sMW1YZXkM7fDkdPtHpE95 * review: consistent sidebar wording + reuse MonitoringToggleProps (#1661) Address the two optional notes from the PR #1662 review: - Make the MonitoringToggle JSDoc voice consistent ("sidebar" throughout, no lingering "column"). - Drop ViewHeader's duplicate `MonitorToggleProps` and reuse the element's exported `MonitoringToggleProps` as the single source of truth. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015sMW1YZXkM7fDkdPtHpE95 * feat(web): slide-in/out animation for the monitoring-sidebar toggle (#1661) The header MonitoringToggle now animates in/out via a Mantine Transition whose in/out styles drive width + margin-left (plus opacity/translateX): as its slot grows from 0 → the 36px icon, the flex-end header row reflows and pushes the theme + client-settings buttons one slot to the left; the exit reverses and they slide back over. A negative margin-left while collapsed cancels the row gap so the theme icon stays flush-right when the toggle is absent. Only appearance/ disappearance (connect / disconnect / narrow viewport) animates — opening or closing the sidebar leaves the toggle in place. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015sMW1YZXkM7fDkdPtHpE95 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
2.6 KiB
TypeScript
75 lines
2.6 KiB
TypeScript
import type { ReactNode, Ref } from "react";
|
|
import { ScrollArea, Stack } from "@mantine/core";
|
|
|
|
// Full-size, the monitor stream panels bound their scroll to the viewport
|
|
// minus the header and the panel's own chrome.
|
|
const FULLSIZE_MAH =
|
|
"calc(100vh - var(--app-shell-header-height, 0px) - 150px)";
|
|
|
|
export interface EmbeddableScrollAreaProps {
|
|
/**
|
|
* True when rendered inside the pinned monitoring sidebar (#1616): the scroll
|
|
* region fills its flex parent instead of using the viewport calc. A
|
|
* `flex:1 / mih:0` wrapper caps the inner `ScrollArea` at the space remaining
|
|
* below the column's controls (via `mah:100%`), so no viewport math is needed
|
|
* and the final rows never clip.
|
|
*/
|
|
embedded: boolean;
|
|
viewportRef: Ref<HTMLDivElement>;
|
|
children: ReactNode;
|
|
/**
|
|
* Constrain the scrolled content to the viewport width instead of letting it
|
|
* grow to its own `max-content`. Mantine's ScrollArea `content` slot defaults
|
|
* to `min-width: max-content`, so a row with non-wrapping content (e.g. a long
|
|
* network URL) stretches every card past the column and it bleeds out (#1623).
|
|
* When true, the content can shrink to the viewport and each row must manage
|
|
* its own overflow (the Network URL scrolls inside its own inner ScrollArea).
|
|
* Left off for panels whose rows already wrap/truncate (Logs, Protocol), where
|
|
* the default lets a long line scroll the list horizontally instead.
|
|
*/
|
|
constrainContentWidth?: boolean;
|
|
}
|
|
|
|
// Relax the `content` slot's default `min-width: max-content` so the list can't
|
|
// grow wider than its viewport; see `constrainContentWidth`.
|
|
const CONSTRAIN_CONTENT_STYLES = { content: { minWidth: 0 } } as const;
|
|
|
|
/**
|
|
* The scroll region shared by the Logs / Protocol / Network stream panels, which
|
|
* render both full-size (their own tab) and embedded (the monitoring sidebar).
|
|
* Centralizes the one layout difference between those two hosts.
|
|
*/
|
|
export function EmbeddableScrollArea({
|
|
embedded,
|
|
viewportRef,
|
|
children,
|
|
constrainContentWidth = false,
|
|
}: EmbeddableScrollAreaProps) {
|
|
const styles = constrainContentWidth ? CONSTRAIN_CONTENT_STYLES : undefined;
|
|
if (embedded) {
|
|
return (
|
|
<Stack flex={1} mih={0} gap={0}>
|
|
<ScrollArea.Autosize
|
|
viewportRef={viewportRef}
|
|
mah="100%"
|
|
type="scroll"
|
|
offsetScrollbars
|
|
styles={styles}
|
|
>
|
|
{children}
|
|
</ScrollArea.Autosize>
|
|
</Stack>
|
|
);
|
|
}
|
|
return (
|
|
<ScrollArea.Autosize
|
|
viewportRef={viewportRef}
|
|
mah={FULLSIZE_MAH}
|
|
type="scroll"
|
|
offsetScrollbars
|
|
styles={styles}
|
|
>
|
|
{children}
|
|
</ScrollArea.Autosize>
|
|
);
|
|
}
|