Refactor renamed the component groups to something less obtuse:
Elements -> Groups -> Screens -> Views
This commit is contained in:
parent
ca6de91a96
commit
dd46acba87
2 changed files with 151 additions and 144 deletions
|
|
@ -0,0 +1,99 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { fn } from "storybook/test";
|
||||
import { ToolDetailPanel } from "./ToolDetailPanel";
|
||||
|
||||
const meta: Meta<typeof ToolDetailPanel> = {
|
||||
title: "Groups/ToolDetailPanel",
|
||||
component: ToolDetailPanel,
|
||||
args: {
|
||||
onFormChange: fn(),
|
||||
onExecute: fn(),
|
||||
onCancel: fn(),
|
||||
formValues: {},
|
||||
isExecuting: false,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ToolDetailPanel>;
|
||||
|
||||
export const SimpleStringParam: Story = {
|
||||
args: {
|
||||
name: "send_message",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
message: { type: "string", description: "The message to send" },
|
||||
},
|
||||
required: ["message"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const MultipleParams: Story = {
|
||||
args: {
|
||||
name: "create_record",
|
||||
description: "Creates a new record with the given parameters",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
title: { type: "string", description: "Record title" },
|
||||
count: { type: "number", description: "Number of items" },
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
description: "Whether the record is active",
|
||||
},
|
||||
},
|
||||
required: ["title"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WithAnnotations: Story = {
|
||||
args: {
|
||||
name: "delete_records",
|
||||
description: "Deletes records matching the given criteria",
|
||||
annotations: {
|
||||
audience: "admin",
|
||||
readOnly: true,
|
||||
destructive: true,
|
||||
},
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
pattern: { type: "string", description: "Pattern to match records" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Executing: Story = {
|
||||
args: {
|
||||
name: "long_query",
|
||||
description: "Runs a long database query",
|
||||
isExecuting: true,
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string", description: "SQL query to execute" },
|
||||
},
|
||||
},
|
||||
formValues: { query: "SELECT * FROM users" },
|
||||
},
|
||||
};
|
||||
|
||||
export const WithProgress: Story = {
|
||||
args: {
|
||||
name: "batch_process",
|
||||
description: "Processes items in batch",
|
||||
isExecuting: true,
|
||||
progress: { percent: 60, description: "Processing step 3 of 5" },
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
batchSize: { type: "number", description: "Number of items per batch" },
|
||||
},
|
||||
},
|
||||
formValues: { batchSize: 100 },
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
import { Button, Divider, Group, Stack, Text } from "@mantine/core";
|
||||
import { AnnotationBadge } from "../../elements/AnnotationBadge/AnnotationBadge";
|
||||
import { ProgressDisplay } from "../../elements/ProgressDisplay/ProgressDisplay";
|
||||
import { SchemaForm } from "../SchemaForm/SchemaForm";
|
||||
import type { JsonSchema } from "../SchemaForm/SchemaForm";
|
||||
|
||||
export interface ToolAnnotations {
|
||||
audience?: string;
|
||||
readOnly?: boolean;
|
||||
destructive?: boolean;
|
||||
longRunning?: boolean;
|
||||
hints?: string;
|
||||
}
|
||||
|
||||
export interface ToolDetailPanelProps {
|
||||
name: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
annotations?: ToolAnnotations;
|
||||
schema: JsonSchema;
|
||||
formValues: Record<string, unknown>;
|
||||
isExecuting: boolean;
|
||||
progress?: { percent: number; description?: string };
|
||||
onFormChange: (values: Record<string, unknown>) => void;
|
||||
onExecute: () => void;
|
||||
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,
|
||||
description,
|
||||
annotations,
|
||||
schema,
|
||||
formValues,
|
||||
isExecuting,
|
||||
progress,
|
||||
onFormChange,
|
||||
onExecute,
|
||||
onCancel,
|
||||
}: ToolDetailPanelProps) {
|
||||
return (
|
||||
<Stack gap="md" miw={0}>
|
||||
<ToolTitle>{resolveTitle(name, title)}</ToolTitle>
|
||||
{hasAnyAnnotation(annotations) && annotations && (
|
||||
<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 && <HintsText>{annotations.hints}</HintsText>}
|
||||
</Group>
|
||||
)}
|
||||
|
||||
{description && <DescriptionText>{description}</DescriptionText>}
|
||||
|
||||
<Divider />
|
||||
|
||||
<SchemaForm
|
||||
schema={schema}
|
||||
values={formValues}
|
||||
onChange={onFormChange}
|
||||
disabled={isExecuting}
|
||||
/>
|
||||
|
||||
{progress && (
|
||||
<ProgressDisplay
|
||||
progress={progress.percent}
|
||||
description={progress.description}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Group>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={onExecute}
|
||||
disabled={isExecuting}
|
||||
loading={isExecuting}
|
||||
>
|
||||
Execute Tool
|
||||
</Button>
|
||||
{isExecuting && <CancelButton onClick={onCancel}>Cancel</CancelButton>}
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue