diff --git a/clients/web/src/components/molecules/ElicitationFormPanel/ElicitationFormPanel.tsx b/clients/web/src/components/molecules/ElicitationFormPanel/ElicitationFormPanel.tsx
index 6b6a0fb7..6507ec5f 100644
--- a/clients/web/src/components/molecules/ElicitationFormPanel/ElicitationFormPanel.tsx
+++ b/clients/web/src/components/molecules/ElicitationFormPanel/ElicitationFormPanel.tsx
@@ -12,6 +12,19 @@ export interface ElicitationFormPanelProps {
onCancel: () => void;
}
+const QuotedMessage = Text.withProps({
+ size: "md",
+ fs: "italic",
+});
+
+function formatQuoted(text: string): string {
+ return `\u201C${text}\u201D`;
+}
+
+function formatWarning(serverName: string): string {
+ return `Only provide information you trust this server with. The server \u201C${serverName}\u201D is requesting this data.`;
+}
+
export function ElicitationFormPanel({
message,
schema,
@@ -23,14 +36,11 @@ export function ElicitationFormPanel({
}: ElicitationFormPanelProps) {
return (
-
- “{message}”
-
+ {formatQuoted(message)}
- Only provide information you trust this server with. The server “
- {serverName}” is requesting this data.
+ {formatWarning(serverName)}
-
+
);
}
diff --git a/clients/web/src/components/molecules/ImportServerJsonPanel/ImportServerJsonPanel.tsx b/clients/web/src/components/molecules/ImportServerJsonPanel/ImportServerJsonPanel.tsx
index 1857219b..da19f528 100644
--- a/clients/web/src/components/molecules/ImportServerJsonPanel/ImportServerJsonPanel.tsx
+++ b/clients/web/src/components/molecules/ImportServerJsonPanel/ImportServerJsonPanel.tsx
@@ -54,6 +54,15 @@ const validationIcons: Record<
error: { icon: "\u2717", color: "red" },
};
+const HintText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+function formatPackageLabel(pkg: PackageInfo): string {
+ return `${pkg.registryType}: ${pkg.identifier} (${pkg.runtimeHint})`;
+}
+
export function ImportServerJsonPanel({
jsonContent,
validationResults,
@@ -73,9 +82,7 @@ export function ImportServerJsonPanel({
Import MCP Registry server.json
-
- Paste server.json content or drag and drop a file:
-
+ Paste server.json content or drag and drop a file:
))}
diff --git a/clients/web/src/components/molecules/InlineElicitationRequest/InlineElicitationRequest.tsx b/clients/web/src/components/molecules/InlineElicitationRequest/InlineElicitationRequest.tsx
index d51dcd32..916ba139 100644
--- a/clients/web/src/components/molecules/InlineElicitationRequest/InlineElicitationRequest.tsx
+++ b/clients/web/src/components/molecules/InlineElicitationRequest/InlineElicitationRequest.tsx
@@ -24,6 +24,37 @@ export interface InlineElicitationRequestProps {
onCancel: () => void;
}
+const RequestContainer = Paper.withProps({
+ p: "md",
+ withBorder: true,
+});
+
+const QueueLabel = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+});
+
+const ItalicMessage = Text.withProps({
+ size: "sm",
+ fs: "italic",
+});
+
+const ActionsRow = Group.withProps({
+ justify: "flex-end",
+ gap: "xs",
+});
+
+const CompactButton = Button.withProps({
+ size: "xs",
+ variant: "light",
+});
+
+function getBadgeLabel(mode: "form" | "url"): string {
+ return mode === "form"
+ ? "elicitation/create (form)"
+ : "elicitation/create (url)";
+}
+
export function InlineElicitationRequest({
mode,
message,
@@ -36,22 +67,15 @@ export function InlineElicitationRequest({
onSubmit,
onCancel,
}: InlineElicitationRequestProps) {
- const badgeLabel =
- mode === "form" ? "elicitation/create (form)" : "elicitation/create (url)";
-
return (
-
+
- {badgeLabel}
-
- {queuePosition}
-
+ {getBadgeLabel(mode)}
+ {queuePosition}
-
- {message}
-
+ {message}
{mode === "form" && schema && (
)}
-
-
- Cancel
-
+
+ Cancel
{mode === "form" && (
Submit
)}
-
+
-
+
);
}
diff --git a/clients/web/src/components/molecules/InlineSamplingRequest/InlineSamplingRequest.tsx b/clients/web/src/components/molecules/InlineSamplingRequest/InlineSamplingRequest.tsx
index 72b2622e..182e08e9 100644
--- a/clients/web/src/components/molecules/InlineSamplingRequest/InlineSamplingRequest.tsx
+++ b/clients/web/src/components/molecules/InlineSamplingRequest/InlineSamplingRequest.tsx
@@ -19,6 +19,47 @@ export interface InlineSamplingRequestProps {
onViewDetails: () => void;
}
+const RequestContainer = Paper.withProps({
+ p: "md",
+ withBorder: true,
+});
+
+const QueueLabel = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+});
+
+const PreviewText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+ lineClamp: 2,
+});
+
+const DetailButton = Button.withProps({
+ variant: "subtle",
+ size: "xs",
+});
+
+const ActionsRow = Group.withProps({
+ justify: "flex-end",
+ gap: "xs",
+});
+
+const CompactButton = Button.withProps({
+ size: "xs",
+ variant: "light",
+});
+
+const RejectButton = Button.withProps({
+ size: "xs",
+ variant: "light",
+ color: "red",
+});
+
+function formatModelHints(hints: string[]): string {
+ return `Model hints: ${hints.join(", ")}`;
+}
+
export function InlineSamplingRequest({
queuePosition,
modelHints,
@@ -30,26 +71,18 @@ export function InlineSamplingRequest({
onViewDetails,
}: InlineSamplingRequestProps) {
return (
-
+
sampling/createMessage
-
- {queuePosition}
-
+ {queuePosition}
- {modelHints && (
- Model hints: {modelHints.join(", ")}
- )}
+ {modelHints && {formatModelHints(modelHints)}}
-
- {messagePreview}
-
+ {messagePreview}
-
- View Details
-
+ View Details
-
-
- Auto-respond
-
-
- Edit & Send
-
-
- Reject
-
-
+
+ Auto-respond
+ Edit & Send
+ Reject
+
-
+
);
}
diff --git a/clients/web/src/components/molecules/LogControls/LogControls.tsx b/clients/web/src/components/molecules/LogControls/LogControls.tsx
index c9c840e8..859ab7e6 100644
--- a/clients/web/src/components/molecules/LogControls/LogControls.tsx
+++ b/clients/web/src/components/molecules/LogControls/LogControls.tsx
@@ -31,6 +31,11 @@ const LEVEL_COLORS: Record = {
emergency: { c: "red", fw: 900 },
};
+const ToolbarButton = Button.withProps({
+ variant: "light",
+ size: "sm",
+});
+
export interface LogControlsProps {
currentLevel: string;
filterText: string;
@@ -93,12 +98,8 @@ export function LogControls({
})}
-
- Clear
-
-
- Export
-
+ Clear
+ Export
);
diff --git a/clients/web/src/components/molecules/PendingClientRequests/PendingClientRequests.tsx b/clients/web/src/components/molecules/PendingClientRequests/PendingClientRequests.tsx
index 4cf4b6d4..c3aa78cd 100644
--- a/clients/web/src/components/molecules/PendingClientRequests/PendingClientRequests.tsx
+++ b/clients/web/src/components/molecules/PendingClientRequests/PendingClientRequests.tsx
@@ -6,16 +6,16 @@ export interface PendingClientRequestsProps {
children: ReactNode;
}
+function formatTitle(count: number): string {
+ return `Pending Client Requests (${count})`;
+}
+
export function PendingClientRequests({
count,
children,
}: PendingClientRequestsProps) {
return (
-
+
{children}
);
diff --git a/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx b/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx
index 48205cce..7ab97194 100644
--- a/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx
+++ b/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx
@@ -21,6 +21,15 @@ export interface PromptArgumentsFormProps {
onGetPrompt: () => void;
}
+const DescriptionText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+function formatPlaceholder(name: string): string {
+ return `Enter ${name}...`;
+}
+
export function PromptArgumentsForm({
prompts,
selectedPrompt,
@@ -46,9 +55,7 @@ export function PromptArgumentsForm({
placeholder="Choose a prompt..."
/>
{selectedPrompt && selectedPromptInfo?.description && (
-
- {selectedPromptInfo.description}
-
+ {selectedPromptInfo.description}
)}
{promptArguments.length > 0 && (
<>
@@ -58,7 +65,7 @@ export function PromptArgumentsForm({
label={arg.name}
withAsterisk={arg.required}
description={arg.description}
- placeholder={`Enter ${arg.name}...`}
+ placeholder={formatPlaceholder(arg.name)}
value={argumentValues[arg.name] || ""}
onChange={(event) =>
onArgumentChange(arg.name, event.currentTarget.value)
diff --git a/clients/web/src/components/molecules/PromptMessagesDisplay/PromptMessagesDisplay.tsx b/clients/web/src/components/molecules/PromptMessagesDisplay/PromptMessagesDisplay.tsx
index 641e2135..dfad1b7f 100644
--- a/clients/web/src/components/molecules/PromptMessagesDisplay/PromptMessagesDisplay.tsx
+++ b/clients/web/src/components/molecules/PromptMessagesDisplay/PromptMessagesDisplay.tsx
@@ -8,6 +8,11 @@ export interface PromptMessage {
audioContent?: { data: string; mimeType: string };
}
+const CopyAllButton = Button.withProps({
+ variant: "light",
+ size: "sm",
+});
+
export interface PromptMessagesDisplayProps {
messages: PromptMessage[];
onCopyAll?: () => void;
@@ -22,9 +27,7 @@ export function PromptMessagesDisplay({
Messages
{onCopyAll && messages.length > 0 && (
-
- Copy All
-
+ Copy All
)}
{messages.length === 0 ? (
diff --git a/clients/web/src/components/molecules/ResourceListItem/ResourceListItem.tsx b/clients/web/src/components/molecules/ResourceListItem/ResourceListItem.tsx
index 4628e8c0..9b4a93d1 100644
--- a/clients/web/src/components/molecules/ResourceListItem/ResourceListItem.tsx
+++ b/clients/web/src/components/molecules/ResourceListItem/ResourceListItem.tsx
@@ -22,8 +22,8 @@ export function ResourceListItem({
{name}
diff --git a/clients/web/src/components/molecules/ResourcePreviewPanel/ResourcePreviewPanel.tsx b/clients/web/src/components/molecules/ResourcePreviewPanel/ResourcePreviewPanel.tsx
index 69c9c2c6..a243e107 100644
--- a/clients/web/src/components/molecules/ResourcePreviewPanel/ResourcePreviewPanel.tsx
+++ b/clients/web/src/components/molecules/ResourcePreviewPanel/ResourcePreviewPanel.tsx
@@ -1,4 +1,4 @@
-import { Group, Stack, Text, Title } from "@mantine/core";
+import { Flex, Group, Stack, Text, Title } from "@mantine/core";
import { AnnotationBadge } from "../../atoms/AnnotationBadge/AnnotationBadge";
import { ContentViewer } from "../../atoms/ContentViewer/ContentViewer";
import { CopyButton } from "../../atoms/CopyButton/CopyButton";
@@ -27,6 +27,41 @@ function resolveContentType(mimeType: string): "json" | "image" | "text" {
return "text";
}
+function formatLastUpdated(lastUpdated: string): string {
+ return `Last updated: ${lastUpdated}`;
+}
+
+const HeaderRow = Group.withProps({
+ justify: "space-between",
+ wrap: "nowrap",
+});
+
+const UriGroup = Group.withProps({
+ gap: "xs",
+ wrap: "nowrap",
+});
+
+const UriText = Text.withProps({
+ size: "sm",
+ c: "blue",
+ truncate: "end",
+});
+
+const MetaRow = Group.withProps({
+ justify: "space-between",
+ wrap: "nowrap",
+});
+
+const TimestampText = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+});
+
+const MimeText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
export function ResourcePreviewPanel({
uri,
mimeType,
@@ -39,33 +74,27 @@ export function ResourcePreviewPanel({
}: ResourcePreviewPanelProps) {
return (
-
+
Resource
-
-
- {uri}
-
+
+ {uri}
-
-
+
+
-
+
{lastUpdated ? (
-
- Last updated: {lastUpdated}
-
+ {formatLastUpdated(lastUpdated)}
) : (
-
+
)}
-
- {mimeType}
-
-
+ {mimeType}
+
{annotations?.audience && (
diff --git a/clients/web/src/components/molecules/ResourceTemplateInput/ResourceTemplateInput.tsx b/clients/web/src/components/molecules/ResourceTemplateInput/ResourceTemplateInput.tsx
index 2f04603e..c639e0da 100644
--- a/clients/web/src/components/molecules/ResourceTemplateInput/ResourceTemplateInput.tsx
+++ b/clients/web/src/components/molecules/ResourceTemplateInput/ResourceTemplateInput.tsx
@@ -36,6 +36,11 @@ function parseTemplate(template: string): TemplatePart[] {
return parts;
}
+const StaticPart = Text.withProps({
+ size: "sm",
+ pb: 6,
+});
+
export function ResourceTemplateInput({
template,
variables,
@@ -48,9 +53,7 @@ export function ResourceTemplateInput({
{parts.map((part, index) =>
part.type === "static" ? (
-
- {part.value}
-
+ {part.value}
) : (
void;
}
+const ClearButton = Button.withProps({
+ variant: "light",
+ size: "sm",
+});
+
+function resolveTextType(type: string): "text" | "json" {
+ return type === "text" ? "text" : "json";
+}
+
+function resolveMediaType(mimeType?: string): "image" | "audio" {
+ return mimeType?.startsWith("image") ? "image" : "audio";
+}
+
export function ResultPanel({ content, onClear }: ResultPanelProps) {
return (
@@ -26,7 +39,7 @@ export function ResultPanel({ content, onClear }: ResultPanelProps) {
return (
@@ -36,7 +49,7 @@ export function ResultPanel({ content, onClear }: ResultPanelProps) {
return (
@@ -47,9 +60,7 @@ export function ResultPanel({ content, onClear }: ResultPanelProps) {
>
)}
-
- Clear
-
+ Clear
);
diff --git a/clients/web/src/components/molecules/RootsTable/RootsTable.tsx b/clients/web/src/components/molecules/RootsTable/RootsTable.tsx
index 7d8f138c..0cad2d39 100644
--- a/clients/web/src/components/molecules/RootsTable/RootsTable.tsx
+++ b/clients/web/src/components/molecules/RootsTable/RootsTable.tsx
@@ -27,6 +27,21 @@ export interface RootsTableProps {
onBrowse: () => void;
}
+const HintText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+const RemoveIcon = ActionIcon.withProps({
+ color: "red",
+ variant: "subtle",
+});
+
+const AddRootButton = Button.withProps({
+ variant: "light",
+ fullWidth: true,
+});
+
export function RootsTable({
roots,
newRootName,
@@ -40,9 +55,7 @@ export function RootsTable({
return (
Roots Configuration
-
- Filesystem roots exposed to the connected server:
-
+ Filesystem roots exposed to the connected server:
{roots.length > 0 && (
@@ -59,13 +72,9 @@ export function RootsTable({
{root.name}
{root.uri}
- onRemoveRoot(root.uri)}
- >
+ onRemoveRoot(root.uri)}>
X
-
+
))}
@@ -73,9 +82,7 @@ export function RootsTable({
)}
-
- + Add Root
-
+ + Add Root
diff --git a/clients/web/src/components/molecules/SamplingRequestPanel/SamplingRequestPanel.tsx b/clients/web/src/components/molecules/SamplingRequestPanel/SamplingRequestPanel.tsx
index 86ff02a0..b63bd151 100644
--- a/clients/web/src/components/molecules/SamplingRequestPanel/SamplingRequestPanel.tsx
+++ b/clients/web/src/components/molecules/SamplingRequestPanel/SamplingRequestPanel.tsx
@@ -54,6 +54,39 @@ function formatPriority(value: number): string {
return `high (${value})`;
}
+function formatOptional(value: unknown, fallback: string): string {
+ return value !== undefined ? String(value) : fallback;
+}
+
+function serializeJson(value: unknown): string {
+ return JSON.stringify(value);
+}
+
+const HintText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+const PreferencesContainer = Paper.withProps({
+ p: "sm",
+ withBorder: true,
+});
+
+const ToolCard = Paper.withProps({
+ p: "xs",
+ withBorder: true,
+});
+
+const ToolName = Text.withProps({
+ size: "sm",
+ fw: 600,
+});
+
+const RejectButton = Button.withProps({
+ variant: "light",
+ color: "red",
+});
+
export function SamplingRequestPanel({
messages,
modelHints,
@@ -78,9 +111,7 @@ export function SamplingRequestPanel({
}: SamplingRequestPanelProps) {
return (
-
- The server is requesting an LLM completion.
-
+ The server is requesting an LLM completion.
Messages:
{messages.map((message, index) => (
@@ -94,7 +125,7 @@ export function SamplingRequestPanel({
))}
{modelHints && modelHints.length > 0 && (
-
+
Model Preferences:
@@ -119,17 +150,19 @@ export function SamplingRequestPanel({
)}
-
+
)}
Parameters:
- Max Tokens: {maxTokens ?? "not specified"}
- Stop Sequences:{" "}
- {stopSequences ? JSON.stringify(stopSequences) : "not specified"}
+ Max Tokens: {formatOptional(maxTokens, "not specified")}
- Temperature: {temperature !== undefined ? temperature : "not specified"}
+ Stop Sequences:{" "}
+ {stopSequences ? serializeJson(stopSequences) : "not specified"}
+
+
+ Temperature: {formatOptional(temperature, "not specified")}
{includeContext && (
@@ -143,12 +176,10 @@ export function SamplingRequestPanel({
<>
Available Tools:
{tools.map((tool) => (
-
-
- {tool.name}
-
+
+ {tool.name}
{tool.description && {tool.description}}
-
+
))}
>
)}
@@ -181,9 +212,7 @@ export function SamplingRequestPanel({
Auto-respond
-
- Reject
-
+ Reject
Send Response
diff --git a/clients/web/src/components/molecules/SchemaForm/SchemaForm.tsx b/clients/web/src/components/molecules/SchemaForm/SchemaForm.tsx
index bd5a50c1..f72d5f62 100644
--- a/clients/web/src/components/molecules/SchemaForm/SchemaForm.tsx
+++ b/clients/web/src/components/molecules/SchemaForm/SchemaForm.tsx
@@ -27,6 +27,20 @@ export interface JsonSchema {
format?: string;
}
+const FieldLabel = Text.withProps({
+ fw: 500,
+ size: "sm",
+});
+
+const FieldDescription = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+});
+
+function serializeJson(value: unknown): string {
+ return JSON.stringify(value, null, 2);
+}
+
export interface SchemaFormProps {
schema: JsonSchema;
values: Record;
@@ -182,14 +196,8 @@ export function SchemaForm({
if (fieldSchema.type === "object" && fieldSchema.properties) {
return (
-
- {label}
-
- {description && (
-
- {description}
-
- )}
+ {label}
+ {description && {description}}
{
try {
handleFieldChange(fieldName, JSON.parse(val));
diff --git a/clients/web/src/components/molecules/ServerCard/ServerCard.tsx b/clients/web/src/components/molecules/ServerCard/ServerCard.tsx
index 709b38bb..cb0d1e33 100644
--- a/clients/web/src/components/molecules/ServerCard/ServerCard.tsx
+++ b/clients/web/src/components/molecules/ServerCard/ServerCard.tsx
@@ -39,6 +39,27 @@ const ActionsRow = Group.withProps({
gap: "xs",
});
+const ServerName = Text.withProps({
+ fw: 600,
+ size: "lg",
+});
+
+const ModeText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+const SubtleButton = Button.withProps({
+ variant: "subtle",
+ size: "xs",
+});
+
+const RemoveButton = Button.withProps({
+ variant: "subtle",
+ size: "xs",
+ color: "red.6",
+});
+
export function ServerCard({
name,
version,
@@ -68,9 +89,7 @@ export function ServerCard({
-
- {name}
-
+ {name}
{version && {version}}
@@ -86,9 +105,7 @@ export function ServerCard({
-
- {connectionMode}
-
+ {connectionMode}
@@ -103,29 +120,17 @@ export function ServerCard({
-
- Clone
-
-
- Edit
-
-
- Remove
-
+ Clone
+ Edit
+ Remove
-
- Server Info
-
-
- Settings
-
+ Server Info
+ Settings
{canTestClientFeatures && (
))}
>
@@ -126,17 +141,11 @@ export function ServerSettingsForm({
Custom Headers
-
- + Add Header
-
+ + Add Header
-
- Headers sent with every HTTP request to this server
-
+ Headers sent with every HTTP request to this server
{headers.length === 0 ? (
-
- No custom headers configured
-
+ No custom headers configured
) : (
Request Metadata
-
- + Add Metadata
-
+ + Add Metadata
-
+
Metadata sent with every MCP request (included in _meta field)
-
+
{metadata.length === 0 ? (
-
- No request metadata configured
-
+ No request metadata configured
) : (
OAuth Settings
-
+
Pre-configure OAuth credentials for servers requiring authentication
-
+
= {
cancelled: "yellow",
};
+const TaskContainer = Card.withProps({
+ withBorder: true,
+ padding: "md",
+});
+
+const TaskIdText = Text.withProps({
+ size: "sm",
+ ff: "monospace",
+});
+
+const DetailText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+const ValueSpan = Text.withProps({
+ component: "span",
+ fw: 600,
+});
+
+const ProgressNote = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+ fs: "italic",
+});
+
+const SubtleButton = Button.withProps({
+ variant: "subtle",
+ size: "xs",
+});
+
+const CancelButton = Button.withProps({
+ variant: "subtle",
+ color: "red",
+ size: "xs",
+});
+
+function formatTaskId(taskId: string): string {
+ return `Task: ${taskId}`;
+}
+
+function formatTimeline(
+ startedAt: string,
+ completedAt?: string,
+ elapsed?: string,
+): string {
+ let result = `Started: ${startedAt}`;
+ if (completedAt) result += ` | Completed: ${completedAt}`;
+ if (elapsed) result += ` | Elapsed: ${elapsed}`;
+ return result;
+}
+
export function TaskCard({
taskId,
status,
@@ -52,46 +104,34 @@ export function TaskCard({
const isActive = status === "waiting" || status === "running";
return (
-
+
-
- Task: {taskId}
-
+ {formatTaskId(taskId)}
{status}
{progress !== undefined && }
-
- Method:{" "}
-
- {method}
-
-
+
+ Method: {method}
+
{target && (
-
- Tool/Resource:{" "}
-
- {target}
-
-
+
+ Tool/Resource: {target}
+
)}
{startedAt && (
-
- Started: {startedAt}
- {completedAt && <> | Completed: {completedAt}>}
- {elapsed && <> | Elapsed: {elapsed}>}
-
+
+ {formatTimeline(startedAt, completedAt, elapsed)}
+
)}
{progressDescription && (
-
- {progressDescription}
-
+ {progressDescription}
)}
{error && (
@@ -103,25 +143,17 @@ export function TaskCard({
{isActive ? (
<>
-
- View Details
-
-
- Cancel
-
+ View Details
+ Cancel
>
) : (
<>
-
- View Result
-
-
- Dismiss
-
+ View Result
+ Dismiss
>
)}
-
+
);
}
diff --git a/clients/web/src/components/molecules/ToolDetailPanel/ToolDetailPanel.tsx b/clients/web/src/components/molecules/ToolDetailPanel/ToolDetailPanel.tsx
index 2955830a..69927bab 100644
--- a/clients/web/src/components/molecules/ToolDetailPanel/ToolDetailPanel.tsx
+++ b/clients/web/src/components/molecules/ToolDetailPanel/ToolDetailPanel.tsx
@@ -26,6 +26,43 @@ export interface ToolDetailPanelProps {
onCancel: () => void;
}
+const ToolTitle = Text.withProps({
+ fw: 700,
+ size: "lg",
+ truncate: "end",
+});
+
+const HintsText = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+ fs: "italic",
+});
+
+const DescriptionText = Text.withProps({
+ size: "sm",
+ c: "dimmed",
+});
+
+const CancelButton = Button.withProps({
+ variant: "light",
+ color: "red",
+});
+
+function resolveTitle(name: string, title?: string): string {
+ return title ?? name;
+}
+
+function hasAnyAnnotation(annotations?: ToolAnnotations): boolean {
+ return !!(
+ annotations &&
+ (annotations.audience ||
+ annotations.readOnly ||
+ annotations.destructive ||
+ annotations.longRunning ||
+ annotations.hints)
+ );
+}
+
export function ToolDetailPanel({
name,
title,
@@ -39,20 +76,10 @@ export function ToolDetailPanel({
onExecute,
onCancel,
}: ToolDetailPanelProps) {
- const hasAnnotations =
- annotations &&
- (annotations.audience ||
- annotations.readOnly ||
- annotations.destructive ||
- annotations.longRunning ||
- annotations.hints);
-
return (
-
- {title ?? name}
-
- {hasAnnotations && (
+ {resolveTitle(name, title)}
+ {hasAnyAnnotation(annotations) && annotations && (
{annotations.audience && (
@@ -66,19 +93,11 @@ export function ToolDetailPanel({
{annotations.longRunning && (
)}
- {annotations.hints && (
-
- {annotations.hints}
-
- )}
+ {annotations.hints && {annotations.hints}}
)}
- {description && (
-
- {description}
-
- )}
+ {description && {description}}
@@ -105,11 +124,7 @@ export function ToolDetailPanel({
>
Execute Tool
- {isExecuting && (
-
- Cancel
-
- )}
+ {isExecuting && Cancel}
);
diff --git a/clients/web/src/components/molecules/ToolListItem/ToolListItem.tsx b/clients/web/src/components/molecules/ToolListItem/ToolListItem.tsx
index f54b6c3e..bbe8c427 100644
--- a/clients/web/src/components/molecules/ToolListItem/ToolListItem.tsx
+++ b/clients/web/src/components/molecules/ToolListItem/ToolListItem.tsx
@@ -7,6 +7,21 @@ export interface ToolListItemProps {
onClick: () => void;
}
+const ItemLabel = Text.withProps({
+ fw: 500,
+ truncate: true,
+});
+
+const ItemSubLabel = Text.withProps({
+ size: "xs",
+ c: "dimmed",
+ truncate: true,
+});
+
+function resolveLabel(name: string, title?: string): string {
+ return title ?? name;
+}
+
export function ToolListItem({
name,
title,
@@ -17,19 +32,13 @@ export function ToolListItem({
-
- {title ?? name}
-
- {title && (
-
- {name}
-
- )}
+ {resolveLabel(name, title)}
+ {title && {name}}
);
diff --git a/clients/web/src/theme/UnstyledButton.ts b/clients/web/src/theme/UnstyledButton.ts
new file mode 100644
index 00000000..bc2641cd
--- /dev/null
+++ b/clients/web/src/theme/UnstyledButton.ts
@@ -0,0 +1,10 @@
+import { UnstyledButton } from "@mantine/core";
+
+export const ThemeUnstyledButton = UnstyledButton.extend({
+ styles: (_theme, props) => {
+ if (props.variant === "listItem") {
+ return { root: { borderRadius: "var(--mantine-radius-md)" } };
+ }
+ return { root: {} };
+ },
+});
diff --git a/clients/web/src/theme/index.ts b/clients/web/src/theme/index.ts
index 4d1d198a..1736ef0a 100644
--- a/clients/web/src/theme/index.ts
+++ b/clients/web/src/theme/index.ts
@@ -9,3 +9,4 @@ export { ThemePaper } from "./Paper";
export { ThemeSelect } from "./Select";
export { ThemeSwitch } from "./Switch";
export { ThemeTextInput } from "./TextInput";
+export { ThemeUnstyledButton } from "./UnstyledButton";
diff --git a/clients/web/src/theme/theme.ts b/clients/web/src/theme/theme.ts
index 9363d36d..42ca6e95 100644
--- a/clients/web/src/theme/theme.ts
+++ b/clients/web/src/theme/theme.ts
@@ -11,6 +11,7 @@ import {
ThemeSelect,
ThemeSwitch,
ThemeTextInput,
+ ThemeUnstyledButton,
} from "./index";
export const theme = createTheme({
@@ -45,5 +46,6 @@ export const theme = createTheme({
Select: ThemeSelect,
Switch: ThemeSwitch,
TextInput: ThemeTextInput,
+ UnstyledButton: ThemeUnstyledButton,
},
});