Add new components, typography, badge contrast, and screen layout refactors

New element components:
- ListToggle: expand/collapse button using react-icons (RiExpandVerticalLine/RiCollapseVerticalLine)
- LogLevelBadge: extracted from LogEntry, handles all 8 log levels with filled variant and dark/light text contrast

New group components:
- ViewHeader: shared header bar for ConnectedView and UnconnectedView with discriminated union on `connected` prop; MCP logo links to modelcontextprotocol.io
- ServerListControls: combines ListToggle and AddServerMenu, hides toggle when no servers
- LogStreamPanel: extracted from LoggingScreen with scroll containment, filtering by visible levels and search text
- HistoryControls: vertical sidebar with search, method filter, export, and clear
- HistoryListPanel: extracted from HistoryScreen with ListToggle compact mode, filtering by method and search text

Badge contrast improvements:
- AnnotationBadge: filled variant for both dark/light modes; black text in dark, white text in light
- LogLevelBadge: same contrast approach; bold weight for alert/emergency levels
- Badge theme default weight reduced from 700 to 600

Typography:
- Added Fredoka (300-700) as body and heading font
- Added Roboto Mono as monospace font
- Google Fonts loaded in index.html and Storybook previewHead
- Heading weight set to 600

Screen layout refactors:
- LoggingScreen: owns filterText and visibleLevels state; passes to LogControls and LogStreamPanel; removed controls prop in favor of flat props
- HistoryScreen: owns searchText and methodFilter state; passes to HistoryControls and HistoryListPanel for filtering
- Both screens use new ScreenLayout (Flex variant="screen") and Sidebar subcomponents
- Added Flex theme with "screen" variant (overflow: hidden)
- Added Paper theme "panel" variant (flex column, overflow hidden)

Component enhancements:
- ServerCard: added compact prop showing only header row
- HistoryEntry: renamed isExpanded to isListExpanded; internal useState syncs via useEffect; individual entries toggle independently
- LogControls: Select All / Deselect All toggle for level checkboxes; nowrap on level selector group
- ConnectionToggle: LoadingOverlay with rounded corners for connecting state
- ConnectedView: ThemeToggle ActionIcon matched to DisconnectButton height (36px) and border color (outline variant)
- Storybook preview: fullscreen layout wrapper with 100vh overflow hidden

New stories:
- UnconnectedView: Connecting and ManyServers (12 servers for scroll testing)
- ServerCard: CompactConnected and CompactDisconnected
- All new components have corresponding stories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-03-28 20:38:04 -04:00
commit 961dc283fc
5 changed files with 1602 additions and 790 deletions

View file

@ -4,5 +4,6 @@ export const ThemeBadge = Badge.extend({
defaultProps: {
size: "sm",
radius: "sm",
fw: 600,
},
});

View file

@ -0,0 +1,14 @@
import { Flex } from "@mantine/core";
export const ThemeFlex = Flex.extend({
styles: (_theme, props) => {
if (props.variant === "screen") {
return {
root: {
overflow: "hidden",
},
};
}
return { root: {} };
},
});

View file

@ -25,6 +25,16 @@ export const ThemePaper = Paper.extend({
},
};
}
if (props.variant === "panel") {
return {
root: {
display: "flex",
flexDirection: "column" as const,
overflow: "hidden",
minHeight: 0,
},
};
}
return { root: {} };
},
});

View file

@ -5,6 +5,7 @@ export { ThemeBadge } from "./Badge";
export { ThemeButton } from "./Button";
export { ThemeCard } from "./Card";
export { ThemeCode } from "./Code";
export { ThemeFlex } from "./Flex";
export { ThemePaper } from "./Paper";
export { ThemeSelect } from "./Select";
export { ThemeSwitch } from "./Switch";

View file

@ -7,6 +7,7 @@ import {
ThemeButton,
ThemeCard,
ThemeCode,
ThemeFlex,
ThemePaper,
ThemeSelect,
ThemeSwitch,
@ -25,11 +26,10 @@ export const theme = createTheme({
cursorType: "pointer",
/* ── Typography ─────────────────────────────────────────── */
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
fontFamilyMonospace:
'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
fontFamily: '"Fredoka", sans-serif',
fontFamilyMonospace: '"Roboto Mono", monospace',
headings: {
fontFamily: '"Fredoka", sans-serif',
fontWeight: "600",
},
@ -42,6 +42,7 @@ export const theme = createTheme({
Button: ThemeButton,
Card: ThemeCard,
Code: ThemeCode,
Flex: ThemeFlex,
Paper: ThemePaper,
Select: ThemeSelect,
Switch: ThemeSwitch,