web: server-screen, footer, monitoring-sidebar, and responsive-header polish (#1683)
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled
Closes #1682 Server-screen, footer, monitoring-sidebar, and responsive-header polish: connected-card highlight/scroll + Failed status, footer row + MCP-docs tooltip, Servers box, card-surface refresh (gray-0 entry cards + white code), monitoring-sidebar layout, a 1280px responsive floor honored by the header (always-icon Disconnect, always-SegmentedControl tabs, 1500px status text, always-available sidebar), a horizontally-scrollable long resource URI in the compact Protocol entry, and copy buttons beside resource URIs / network URLs. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
parent
590359abc5
commit
8d33e76f97
6 changed files with 707 additions and 274 deletions
|
|
@ -4,14 +4,14 @@ import { Text } from "@mantine/core";
|
|||
export const COPYRIGHT_NOTICE =
|
||||
"Copyright © Model Context Protocol a Series of LF Projects, LLC.";
|
||||
|
||||
// The `copyrightBadge` variant (src/theme/Text.ts) pins it to the lower-right
|
||||
// corner in grey, on the same row as the version badge, and non-interactive.
|
||||
// The `copyrightBadge` variant (src/theme/Text.ts) styles it as a small grey
|
||||
// single-line label; the footer row positions it at the right (#1682).
|
||||
const CopyrightText = Text.withProps({ variant: "copyrightBadge" });
|
||||
|
||||
/**
|
||||
* The project copyright notice, fixed to the lower-right corner of the screen
|
||||
* (#1639) — the grey, non-interactive twin of the lower-left version badge,
|
||||
* sharing its row.
|
||||
* The project copyright notice, shown at the right of the footer row (#1682,
|
||||
* superseding the fixed lower-right badge of #1639) — the grey twin of the
|
||||
* left-aligned version badge, sharing the footer.
|
||||
*/
|
||||
export function CopyrightBadge() {
|
||||
return <CopyrightText>{COPYRIGHT_NOTICE}</CopyrightText>;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ 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)";
|
||||
"calc(100vh - var(--app-shell-header-height, 0px) - var(--app-shell-footer-height, 0px) - 150px)";
|
||||
|
||||
export interface EmbeddableScrollAreaProps {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,6 +28,17 @@ export const Disconnected: Story = {
|
|||
},
|
||||
};
|
||||
|
||||
// A failed connection settles the status back to "disconnected", but the
|
||||
// `failed` flag surfaces it as a red "Failed" instead of the grey
|
||||
// "Disconnected" (#1682).
|
||||
export const Failed: Story = {
|
||||
args: {
|
||||
status: "disconnected",
|
||||
failed: true,
|
||||
showLabel: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
status: "error",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,27 @@ describe("ServerStatusIndicator", () => {
|
|||
expect(screen.getByText("Error")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders 'Failed' with the error color when failed, overriding the disconnected status (#1682)", () => {
|
||||
const { container } = renderWithMantine(
|
||||
<ServerStatusIndicator status="disconnected" failed showLabel />,
|
||||
);
|
||||
expect(screen.getByText("Failed")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Disconnected")).not.toBeInTheDocument();
|
||||
// The dot uses the error color, not the disconnected grey.
|
||||
const dot = container.querySelector(".mantine-Paper-root");
|
||||
expect(dot?.getAttribute("style") ?? "").toContain(
|
||||
"inspector-status-error",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show 'Failed' when the failed flag is unset (a deliberate disconnect)", () => {
|
||||
renderWithMantine(
|
||||
<ServerStatusIndicator status="disconnected" showLabel />,
|
||||
);
|
||||
expect(screen.getByText("Disconnected")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Failed")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("hides label and uses title when showLabel is false", () => {
|
||||
renderWithMantine(
|
||||
<ServerStatusIndicator
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ export interface ServerStatusIndicatorProps {
|
|||
status: ConnectionStatus;
|
||||
latencyMs?: number;
|
||||
retryCount?: number;
|
||||
/**
|
||||
* True when the server's last connection attempt failed (#1682). The
|
||||
* indicator then shows a red dot + "Failed" instead of the settled
|
||||
* grey "Disconnected", so a failed connect reads distinctly from a
|
||||
* deliberate disconnect. Overrides `status` for the label and color.
|
||||
*/
|
||||
failed?: boolean;
|
||||
// Override for the default viewport-based label visibility. Useful when
|
||||
// the indicator renders inside a constrained container (sidebar, card)
|
||||
// where the global media query doesn't reflect available space.
|
||||
|
|
@ -46,16 +53,30 @@ export function ServerStatusIndicator({
|
|||
status,
|
||||
latencyMs,
|
||||
retryCount,
|
||||
failed = false,
|
||||
showLabel: showLabelProp,
|
||||
}: ServerStatusIndicatorProps) {
|
||||
const wideViewport = useMediaQuery("(min-width: 1200px)");
|
||||
// Drop the text label below 1500px. "Connected (Nms)" is the header's widest
|
||||
// optional element, so shedding it first — earlier than the Disconnect control,
|
||||
// which collapses at the 1280px floor (see ViewHeader) — keeps the tab row from
|
||||
// crowding. Below the breakpoint the indicator is a dot only, with the label
|
||||
// moved to its `title` tooltip.
|
||||
const wideViewport = useMediaQuery("(min-width: 1500px)");
|
||||
const showLabel = showLabelProp ?? wideViewport;
|
||||
const label = getLabel(status, latencyMs, retryCount);
|
||||
// A failed connection settles the status back to "disconnected"; the `failed`
|
||||
// flag distinguishes it as a failure (red + "Failed") from a deliberate
|
||||
// disconnect (grey), overriding the status-derived label and color.
|
||||
const label = failed ? "Failed" : getLabel(status, latencyMs, retryCount);
|
||||
const color = failed
|
||||
? "var(--inspector-status-error)"
|
||||
: statusColorVar[status];
|
||||
return (
|
||||
<Group gap="xs">
|
||||
<Dot
|
||||
bg={statusColorVar[status]}
|
||||
className={status === "connecting" ? "inspector-pulse" : undefined}
|
||||
bg={color}
|
||||
className={
|
||||
!failed && status === "connecting" ? "inspector-pulse" : undefined
|
||||
}
|
||||
title={showLabel ? undefined : label}
|
||||
/>
|
||||
{showLabel && <Text size="sm">{label}</Text>}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ export interface VersionBadgeProps {
|
|||
version?: string;
|
||||
}
|
||||
|
||||
// The `versionBadge` variant (src/theme/Text.ts) pins it to the lower-left
|
||||
// corner in grey and makes it non-interactive.
|
||||
// The `versionBadge` variant (src/theme/Text.ts) styles it as a small grey
|
||||
// single-line label; the footer row positions it at the left (#1682).
|
||||
const VersionText = Text.withProps({ variant: "versionBadge" });
|
||||
|
||||
/**
|
||||
* A small, unobtrusive build-version label fixed to the lower-left corner of
|
||||
* the screen (#1639). Sourced from the root `package.json` via the backend's
|
||||
* `GET /api/config`; renders nothing until the version is known (or on a legacy
|
||||
* backend that omits it).
|
||||
* A small, unobtrusive build-version label shown at the left of the footer row
|
||||
* (#1682, superseding the fixed lower-left badge of #1639). Sourced from the
|
||||
* root `package.json` via the backend's `GET /api/config`; renders nothing until
|
||||
* the version is known (or on a legacy backend that omits it).
|
||||
*/
|
||||
export function VersionBadge({ version }: VersionBadgeProps) {
|
||||
if (!version) return null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue