storybook component fixes and improvements
- Add @storybook/addon-actions for action logging in stories - Add onTestCapability callback to ExperimentalFeaturesPanel - Use CopyButton overlay in ResourcePreviewPanel and ResultPanel - Replace includeContext checkbox with badge in SamplingRequestPanel - Add LongServerName story for ServerCard - Fix long tool name overflow with truncation and contained Paper variant - Add optional title prop to ToolListItem and ToolDetailPanel - Move tool annotations from list to detail panel form - Vertically center static text in ResourceTemplateInput - Fix InlineError blank space when no details Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4a4818e933
commit
1da76c53ef
18 changed files with 167 additions and 110 deletions
|
|
@ -7,6 +7,7 @@ const config: StorybookConfig = {
|
||||||
],
|
],
|
||||||
"addons": [
|
"addons": [
|
||||||
"@chromatic-com/storybook",
|
"@chromatic-com/storybook",
|
||||||
|
"@storybook/addon-actions",
|
||||||
"@storybook/addon-vitest",
|
"@storybook/addon-vitest",
|
||||||
"@storybook/addon-a11y",
|
"@storybook/addon-a11y",
|
||||||
"@storybook/addon-docs",
|
"@storybook/addon-docs",
|
||||||
|
|
|
||||||
12
clients/web/package-lock.json
generated
12
clients/web/package-lock.json
generated
|
|
@ -20,6 +20,7 @@
|
||||||
"@chromatic-com/storybook": "^5.0.1",
|
"@chromatic-com/storybook": "^5.0.1",
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@storybook/addon-a11y": "^10.2.19",
|
"@storybook/addon-a11y": "^10.2.19",
|
||||||
|
"@storybook/addon-actions": "^9.0.8",
|
||||||
"@storybook/addon-docs": "^10.2.19",
|
"@storybook/addon-docs": "^10.2.19",
|
||||||
"@storybook/addon-onboarding": "^10.2.19",
|
"@storybook/addon-onboarding": "^10.2.19",
|
||||||
"@storybook/addon-vitest": "^10.2.19",
|
"@storybook/addon-vitest": "^10.2.19",
|
||||||
|
|
@ -1695,6 +1696,17 @@
|
||||||
"storybook": "^10.2.19"
|
"storybook": "^10.2.19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@storybook/addon-actions": {
|
||||||
|
"version": "9.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-9.0.8.tgz",
|
||||||
|
"integrity": "sha512-LFePu7PPnWN0Il/uoUpmA5T0J0C7d6haJIbg0pXrjxW2MQVSYXE4S4LSUz8fOImltBDV3xAl6tLPYHFj6VcrOA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/storybook"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@storybook/addon-docs": {
|
"node_modules/@storybook/addon-docs": {
|
||||||
"version": "10.2.19",
|
"version": "10.2.19",
|
||||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.2.19.tgz",
|
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.2.19.tgz",
|
||||||
|
|
|
||||||
|
|
@ -23,30 +23,31 @@
|
||||||
"react-dom": "^19.2.4"
|
"react-dom": "^19.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@chromatic-com/storybook": "^5.0.1",
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
|
"@storybook/addon-a11y": "^10.2.19",
|
||||||
|
"@storybook/addon-actions": "^9.0.8",
|
||||||
|
"@storybook/addon-docs": "^10.2.19",
|
||||||
|
"@storybook/addon-onboarding": "^10.2.19",
|
||||||
|
"@storybook/addon-vitest": "^10.2.19",
|
||||||
|
"@storybook/react-vite": "^10.2.19",
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vitejs/plugin-react": "^6.0.0",
|
"@vitejs/plugin-react": "^6.0.0",
|
||||||
|
"@vitest/browser-playwright": "^4.1.0",
|
||||||
|
"@vitest/coverage-v8": "^4.1.0",
|
||||||
"eslint": "^9.39.4",
|
"eslint": "^9.39.4",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.2",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
|
"eslint-plugin-storybook": "^10.2.19",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.4.0",
|
||||||
|
"playwright": "^1.58.2",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"storybook": "^10.2.19",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"typescript-eslint": "^8.56.1",
|
"typescript-eslint": "^8.56.1",
|
||||||
"prettier": "^3.8.1",
|
|
||||||
"vite": "^8.0.0",
|
"vite": "^8.0.0",
|
||||||
"storybook": "^10.2.19",
|
"vitest": "^4.1.0"
|
||||||
"@storybook/react-vite": "^10.2.19",
|
|
||||||
"@chromatic-com/storybook": "^5.0.1",
|
|
||||||
"@storybook/addon-vitest": "^10.2.19",
|
|
||||||
"@storybook/addon-a11y": "^10.2.19",
|
|
||||||
"@storybook/addon-docs": "^10.2.19",
|
|
||||||
"@storybook/addon-onboarding": "^10.2.19",
|
|
||||||
"eslint-plugin-storybook": "^10.2.19",
|
|
||||||
"vitest": "^4.1.0",
|
|
||||||
"playwright": "^1.58.2",
|
|
||||||
"@vitest/browser-playwright": "^4.1.0",
|
|
||||||
"@vitest/coverage-v8": "^4.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ const meta: Meta<typeof ExperimentalFeaturesPanel> = {
|
||||||
onRemoveHeader: fn(),
|
onRemoveHeader: fn(),
|
||||||
onHeaderChange: fn(),
|
onHeaderChange: fn(),
|
||||||
onCopyResponse: fn(),
|
onCopyResponse: fn(),
|
||||||
|
onTestCapability: fn(),
|
||||||
clientCapabilities: [
|
clientCapabilities: [
|
||||||
{ name: "experimental/customSampling", enabled: false },
|
{ name: "experimental/customSampling", enabled: false },
|
||||||
{ name: "experimental/batchRequests", enabled: true },
|
{ name: "experimental/batchRequests", enabled: true },
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ export interface ExperimentalFeaturesPanelProps {
|
||||||
onRemoveHeader: (index: number) => void;
|
onRemoveHeader: (index: number) => void;
|
||||||
onHeaderChange: (index: number, key: string, value: string) => void;
|
onHeaderChange: (index: number, key: string, value: string) => void;
|
||||||
onCopyResponse: () => void;
|
onCopyResponse: () => void;
|
||||||
|
onTestCapability: (name: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExperimentalFeaturesPanel({
|
export function ExperimentalFeaturesPanel({
|
||||||
|
|
@ -67,6 +68,7 @@ export function ExperimentalFeaturesPanel({
|
||||||
onRemoveHeader,
|
onRemoveHeader,
|
||||||
onHeaderChange,
|
onHeaderChange,
|
||||||
onCopyResponse,
|
onCopyResponse,
|
||||||
|
onTestCapability,
|
||||||
}: ExperimentalFeaturesPanelProps) {
|
}: ExperimentalFeaturesPanelProps) {
|
||||||
return (
|
return (
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
|
|
@ -94,7 +96,11 @@ export function ExperimentalFeaturesPanel({
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Group>
|
<Group>
|
||||||
<Button size="xs" variant="light">
|
<Button
|
||||||
|
size="xs"
|
||||||
|
variant="light"
|
||||||
|
onClick={() => onTestCapability(cap.name)}
|
||||||
|
>
|
||||||
Test →
|
Test →
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ const meta: Meta<typeof ResourcePreviewPanel> = {
|
||||||
title: "Molecules/ResourcePreviewPanel",
|
title: "Molecules/ResourcePreviewPanel",
|
||||||
component: ResourcePreviewPanel,
|
component: ResourcePreviewPanel,
|
||||||
args: {
|
args: {
|
||||||
onCopy: fn(),
|
|
||||||
onSubscribe: fn(),
|
onSubscribe: fn(),
|
||||||
onUnsubscribe: fn(),
|
onUnsubscribe: fn(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ export interface ResourcePreviewPanelProps {
|
||||||
content: string;
|
content: string;
|
||||||
lastUpdated?: string;
|
lastUpdated?: string;
|
||||||
isSubscribed: boolean;
|
isSubscribed: boolean;
|
||||||
onCopy: () => void;
|
|
||||||
onSubscribe: () => void;
|
onSubscribe: () => void;
|
||||||
onUnsubscribe: () => void;
|
onUnsubscribe: () => void;
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +25,6 @@ export function ResourcePreviewPanel({
|
||||||
content,
|
content,
|
||||||
lastUpdated,
|
lastUpdated,
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
onCopy,
|
|
||||||
onSubscribe,
|
onSubscribe,
|
||||||
onUnsubscribe,
|
onUnsubscribe,
|
||||||
}: ResourcePreviewPanelProps) {
|
}: ResourcePreviewPanelProps) {
|
||||||
|
|
@ -61,11 +59,9 @@ export function ResourcePreviewPanel({
|
||||||
type={resolveContentType(mimeType)}
|
type={resolveContentType(mimeType)}
|
||||||
content={content}
|
content={content}
|
||||||
mimeType={mimeType}
|
mimeType={mimeType}
|
||||||
|
copyable
|
||||||
/>
|
/>
|
||||||
<Group>
|
<Group>
|
||||||
<Button variant="light" size="sm" onClick={onCopy}>
|
|
||||||
Copy
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
variant="light"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export function ResourceTemplateInput({
|
||||||
<Group gap="xs" align="flex-end">
|
<Group gap="xs" align="flex-end">
|
||||||
{parts.map((part, index) =>
|
{parts.map((part, index) =>
|
||||||
part.type === "static" ? (
|
part.type === "static" ? (
|
||||||
<Text key={index} size="sm">
|
<Text key={index} size="sm" pb={6}>
|
||||||
{part.value}
|
{part.value}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ const meta: Meta<typeof ResultPanel> = {
|
||||||
title: "Molecules/ResultPanel",
|
title: "Molecules/ResultPanel",
|
||||||
component: ResultPanel,
|
component: ResultPanel,
|
||||||
args: {
|
args: {
|
||||||
onCopy: fn(),
|
|
||||||
onClear: fn(),
|
onClear: fn(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,10 @@ export interface ResultContentItem {
|
||||||
|
|
||||||
export interface ResultPanelProps {
|
export interface ResultPanelProps {
|
||||||
content: ResultContentItem[];
|
content: ResultContentItem[];
|
||||||
onCopy: () => void;
|
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ResultPanel({ content, onCopy, onClear }: ResultPanelProps) {
|
export function ResultPanel({ content, onClear }: ResultPanelProps) {
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Title order={4}>Results</Title>
|
<Title order={4}>Results</Title>
|
||||||
|
|
@ -29,6 +28,7 @@ export function ResultPanel({ content, onCopy, onClear }: ResultPanelProps) {
|
||||||
key={index}
|
key={index}
|
||||||
type={item.type === "text" ? "text" : "json"}
|
type={item.type === "text" ? "text" : "json"}
|
||||||
content={item.text}
|
content={item.text}
|
||||||
|
copyable
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -47,9 +47,6 @@ export function ResultPanel({ content, onCopy, onClear }: ResultPanelProps) {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Group>
|
<Group>
|
||||||
<Button variant="light" size="sm" onClick={onCopy}>
|
|
||||||
Copy
|
|
||||||
</Button>
|
|
||||||
<Button variant="light" size="sm" onClick={onClear}>
|
<Button variant="light" size="sm" onClick={onClear}>
|
||||||
Clear
|
Clear
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
|
||||||
Divider,
|
Divider,
|
||||||
Group,
|
Group,
|
||||||
Paper,
|
Paper,
|
||||||
|
|
@ -134,11 +133,10 @@ export function SamplingRequestPanel({
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{includeContext && (
|
{includeContext && (
|
||||||
<Checkbox
|
<Group gap="xs">
|
||||||
label={`Include Context: ${includeContext}`}
|
<Text size="sm">Include Context:</Text>
|
||||||
checked
|
<Badge>{includeContext}</Badge>
|
||||||
readOnly
|
</Group>
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tools && tools.length > 0 && (
|
{tools && tools.length > 0 && (
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,19 @@ export const WithClientFeatures: Story = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LongServerName: Story = {
|
||||||
|
args: {
|
||||||
|
name: "my-organization-super-long-experimental-mcp-server-with-many-features-v2",
|
||||||
|
version: "1.0.0-beta.42",
|
||||||
|
transport: "stdio",
|
||||||
|
connectionMode: "Subprocess",
|
||||||
|
command:
|
||||||
|
"npx -y @my-organization/super-long-experimental-mcp-server-with-many-features-v2",
|
||||||
|
status: "connected",
|
||||||
|
canTestClientFeatures: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const HttpDirect: Story = {
|
export const HttpDirect: Story = {
|
||||||
args: {
|
args: {
|
||||||
name: "Remote API Server",
|
name: "Remote API Server",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Button, Divider, Group, Stack, Text, Title } from "@mantine/core";
|
import { Button, Divider, Group, Stack, Text } from "@mantine/core";
|
||||||
import { AnnotationBadge } from "../../atoms/AnnotationBadge/AnnotationBadge";
|
import { AnnotationBadge } from "../../atoms/AnnotationBadge/AnnotationBadge";
|
||||||
import { ProgressDisplay } from "../../atoms/ProgressDisplay/ProgressDisplay";
|
import { ProgressDisplay } from "../../atoms/ProgressDisplay/ProgressDisplay";
|
||||||
import { SchemaForm } from "../SchemaForm/SchemaForm";
|
import { SchemaForm } from "../SchemaForm/SchemaForm";
|
||||||
|
|
@ -14,6 +14,7 @@ export interface ToolAnnotations {
|
||||||
|
|
||||||
export interface ToolDetailPanelProps {
|
export interface ToolDetailPanelProps {
|
||||||
name: string;
|
name: string;
|
||||||
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
annotations?: ToolAnnotations;
|
annotations?: ToolAnnotations;
|
||||||
schema: JsonSchema;
|
schema: JsonSchema;
|
||||||
|
|
@ -27,6 +28,7 @@ export interface ToolDetailPanelProps {
|
||||||
|
|
||||||
export function ToolDetailPanel({
|
export function ToolDetailPanel({
|
||||||
name,
|
name,
|
||||||
|
title,
|
||||||
description,
|
description,
|
||||||
annotations,
|
annotations,
|
||||||
schema,
|
schema,
|
||||||
|
|
@ -46,8 +48,39 @@ export function ToolDetailPanel({
|
||||||
annotations.hints);
|
annotations.hints);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="md">
|
<Stack gap="md" miw={0}>
|
||||||
<Title order={4}>Tool: {name}</Title>
|
<Text fw={700} size="lg" truncate="end">
|
||||||
|
{title ?? name}
|
||||||
|
</Text>
|
||||||
|
{title && (
|
||||||
|
<Text size="sm" c="dimmed" truncate="end">
|
||||||
|
{name}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{hasAnnotations && (
|
||||||
|
<Group gap="xs">
|
||||||
|
{annotations.audience && (
|
||||||
|
<AnnotationBadge
|
||||||
|
label={annotations.audience}
|
||||||
|
variant="audience"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{annotations.readOnly && (
|
||||||
|
<AnnotationBadge label="read-only" variant="readOnly" />
|
||||||
|
)}
|
||||||
|
{annotations.destructive && (
|
||||||
|
<AnnotationBadge label="destructive" variant="destructive" />
|
||||||
|
)}
|
||||||
|
{annotations.longRunning && (
|
||||||
|
<AnnotationBadge label="long-run" variant="longRun" />
|
||||||
|
)}
|
||||||
|
{annotations.hints && (
|
||||||
|
<Text size="xs" c="dimmed" fs="italic">
|
||||||
|
{annotations.hints}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
|
||||||
{description && (
|
{description && (
|
||||||
<Text size="sm" c="dimmed">
|
<Text size="sm" c="dimmed">
|
||||||
|
|
@ -55,34 +88,6 @@ export function ToolDetailPanel({
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hasAnnotations && (
|
|
||||||
<>
|
|
||||||
<Text size="sm">Annotations:</Text>
|
|
||||||
<Group gap="xs">
|
|
||||||
{annotations.audience && (
|
|
||||||
<AnnotationBadge
|
|
||||||
label={annotations.audience}
|
|
||||||
variant="audience"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{annotations.readOnly && (
|
|
||||||
<AnnotationBadge label="read-only" variant="readOnly" />
|
|
||||||
)}
|
|
||||||
{annotations.destructive && (
|
|
||||||
<AnnotationBadge label="destructive" variant="destructive" />
|
|
||||||
)}
|
|
||||||
{annotations.longRunning && (
|
|
||||||
<AnnotationBadge label="long-run" variant="longRun" />
|
|
||||||
)}
|
|
||||||
{annotations.hints && (
|
|
||||||
<Text size="xs" c="dimmed" fs="italic">
|
|
||||||
{annotations.hints}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Group>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<SchemaForm
|
<SchemaForm
|
||||||
|
|
|
||||||
|
|
@ -27,27 +27,11 @@ export const Selected: Story = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WithAnnotations: Story = {
|
export const WithTitle: Story = {
|
||||||
args: {
|
args: {
|
||||||
name: "get_weather",
|
name: "get_weather",
|
||||||
|
title: "Get Weather",
|
||||||
selected: false,
|
selected: false,
|
||||||
annotations: [
|
|
||||||
{ label: "user", variant: "audience" },
|
|
||||||
{ label: "read-only", variant: "readOnly" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MultipleAnnotations: Story = {
|
|
||||||
args: {
|
|
||||||
name: "update_database",
|
|
||||||
selected: false,
|
|
||||||
annotations: [
|
|
||||||
{ label: "user", variant: "audience" },
|
|
||||||
{ label: "read-only", variant: "readOnly" },
|
|
||||||
{ label: "destructive", variant: "destructive" },
|
|
||||||
{ label: "long-run", variant: "longRun" },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,15 @@
|
||||||
import { Group, Stack, Text, UnstyledButton } from "@mantine/core";
|
import { Stack, Text, UnstyledButton } from "@mantine/core";
|
||||||
import { AnnotationBadge } from "../../atoms/AnnotationBadge/AnnotationBadge";
|
|
||||||
import type { AnnotationVariant } from "../../atoms/AnnotationBadge/AnnotationBadge";
|
|
||||||
|
|
||||||
export interface ToolAnnotation {
|
|
||||||
label: string;
|
|
||||||
variant?: AnnotationVariant;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ToolListItemProps {
|
export interface ToolListItemProps {
|
||||||
name: string;
|
name: string;
|
||||||
annotations?: ToolAnnotation[];
|
title?: string;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolListItem({
|
export function ToolListItem({
|
||||||
name,
|
name,
|
||||||
annotations,
|
title,
|
||||||
selected,
|
selected,
|
||||||
onClick,
|
onClick,
|
||||||
}: ToolListItemProps) {
|
}: ToolListItemProps) {
|
||||||
|
|
@ -28,18 +21,14 @@ export function ToolListItem({
|
||||||
style={{ borderRadius: "var(--mantine-radius-md)" }}
|
style={{ borderRadius: "var(--mantine-radius-md)" }}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<Stack gap="xs">
|
<Stack gap={2}>
|
||||||
<Text fw={500}>{name}</Text>
|
<Text fw={500} truncate>
|
||||||
{annotations && annotations.length > 0 && (
|
{title ?? name}
|
||||||
<Group gap="xs">
|
</Text>
|
||||||
{annotations.map((annotation) => (
|
{title && (
|
||||||
<AnnotationBadge
|
<Text size="xs" c="dimmed" truncate>
|
||||||
key={annotation.label}
|
{name}
|
||||||
label={annotation.label}
|
</Text>
|
||||||
variant={annotation.variant}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Group>
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</UnstyledButton>
|
</UnstyledButton>
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,26 @@ export default meta;
|
||||||
type Story = StoryObj<typeof ToolsScreen>;
|
type Story = StoryObj<typeof ToolsScreen>;
|
||||||
|
|
||||||
const sampleTools: ToolListItemProps[] = [
|
const sampleTools: ToolListItemProps[] = [
|
||||||
{ name: "send_message", selected: false, onClick: fn() },
|
{
|
||||||
|
name: "send_message",
|
||||||
|
title: "Send Message",
|
||||||
|
selected: false,
|
||||||
|
onClick: fn(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "create_record",
|
name: "create_record",
|
||||||
annotations: [{ label: "read-only" }],
|
title: "Create Record",
|
||||||
selected: false,
|
selected: false,
|
||||||
onClick: fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "delete_records",
|
name: "delete_records",
|
||||||
annotations: [{ label: "destructive", variant: "destructive" }],
|
|
||||||
selected: false,
|
selected: false,
|
||||||
onClick: fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
{ name: "list_users", selected: false, onClick: fn() },
|
{ name: "list_users", selected: false, onClick: fn() },
|
||||||
{
|
{
|
||||||
name: "batch_process",
|
name: "batch_process",
|
||||||
annotations: [{ label: "long-run", variant: "longRun" }],
|
|
||||||
selected: false,
|
selected: false,
|
||||||
onClick: fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
|
|
@ -45,6 +48,7 @@ const sampleTools: ToolListItemProps[] = [
|
||||||
|
|
||||||
const selectedToolData: ToolDetailPanelProps = {
|
const selectedToolData: ToolDetailPanelProps = {
|
||||||
name: "create_record",
|
name: "create_record",
|
||||||
|
title: "Create Record",
|
||||||
description: "Creates a new record with the given parameters",
|
description: "Creates a new record with the given parameters",
|
||||||
schema: {
|
schema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
|
|
@ -79,7 +83,6 @@ const resultData: ResultPanelProps = {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onCopy: fn(),
|
|
||||||
onClear: fn(),
|
onClear: fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -111,6 +114,51 @@ export const WithResult: Story = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LongToolName: Story = {
|
||||||
|
args: {
|
||||||
|
tools: [
|
||||||
|
...sampleTools,
|
||||||
|
{
|
||||||
|
name: "organization_internal_database_complex_multi_table_join_query_with_aggregation_and_filtering",
|
||||||
|
selected: true,
|
||||||
|
onClick: fn(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selectedTool: {
|
||||||
|
name: "organization_internal_database_complex_multi_table_join_query_with_aggregation_and_filtering",
|
||||||
|
annotations: {
|
||||||
|
readOnly: true,
|
||||||
|
longRunning: true,
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
"Executes a complex multi-table join query across the organization's internal database with support for aggregation functions, nested filtering, and pagination of large result sets.",
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
primary_table_name: {
|
||||||
|
type: "string",
|
||||||
|
description: "The main table to query from",
|
||||||
|
},
|
||||||
|
join_configuration: {
|
||||||
|
type: "string",
|
||||||
|
description: "JSON configuration for table joins",
|
||||||
|
},
|
||||||
|
aggregation_functions: {
|
||||||
|
type: "string",
|
||||||
|
description: "Comma-separated list of aggregation functions to apply",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["primary_table_name"],
|
||||||
|
},
|
||||||
|
formValues: {},
|
||||||
|
isExecuting: false,
|
||||||
|
onFormChange: fn(),
|
||||||
|
onExecute: fn(),
|
||||||
|
onCancel: fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const WithListChanged: Story = {
|
export const WithListChanged: Story = {
|
||||||
args: {
|
args: {
|
||||||
tools: sampleTools,
|
tools: sampleTools,
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ export function ToolsScreen({
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
|
||||||
<Grid.Col span={5}>
|
<Grid.Col span={5}>
|
||||||
<Paper withBorder p="md">
|
<Paper withBorder p="md" variant="contained">
|
||||||
{selectedTool ? (
|
{selectedTool ? (
|
||||||
<ToolDetailPanel {...selectedTool} />
|
<ToolDetailPanel {...selectedTool} />
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,14 @@ export const ThemePaper = Paper.extend({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (props.variant === "contained") {
|
||||||
|
return {
|
||||||
|
root: {
|
||||||
|
overflow: "hidden",
|
||||||
|
minWidth: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
return { root: {} };
|
return { root: {} };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue