inspector/clients/web/src/components/screens/ResourcesScreen/ResourcesScreen.stories.tsx
cliffhall a0e763a315 Redesign Resources screen: template panel, subscriptions, hover states, and callback architecture
- Rename ResourceTemplateInput to ResourceTemplatePanel with panel layout
  (title header, URI with live variable preview, labeled inputs, Read Resource button)
- ResourceTemplatePanel manages its own variable state via useState;
  single onReadResource(uri) callback returns fully resolved URI
- Extract ResourceSubscribedItem group component with name, timestamp, and
  subtle Unsubscribe button
- Add hover state to listItem variant via theme classNames + App.css pseudo-selector
- Add Refresh button to ResourcePreviewPanel
- Refactor ResourcesScreen callbacks: onSelectUri, onSelectTemplate,
  onReadResource, onSubscribeResource, onUnsubscribeResource replace
  per-item onClick/onUnsubscribe props; screen wires callbacks to children
- Define data-only types (ResourceItem, TemplateListItem, SubscriptionItem,
  SelectedResource, SelectedTemplate) separating data from callbacks
- Extract named .withProps() subcomponents (FooterRow, AnnotationGroup,
  ActionGroup, Spacer) for AGENTS.md compliance
- Update all stories (ResourceTemplatePanel, ResourcesScreen, ConnectedView)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:04:25 -04:00

159 lines
3.6 KiB
TypeScript

import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
import { ResourcesScreen } from "./ResourcesScreen";
import type {
ResourceItem,
TemplateListItem,
SelectedResource,
SelectedTemplate,
} from "./ResourcesScreen";
const meta: Meta<typeof ResourcesScreen> = {
title: "Screens/ResourcesScreen",
component: ResourcesScreen,
parameters: { layout: "fullscreen" },
args: {
searchText: "",
onSearchChange: fn(),
onRefreshList: fn(),
onSelectUri: fn(),
onSelectTemplate: fn(),
onReadResource: fn(),
onSubscribeResource: fn(),
onUnsubscribeResource: fn(),
listChanged: false,
subscriptions: [],
templates: [],
},
};
export default meta;
type Story = StoryObj<typeof ResourcesScreen>;
const sampleResources: ResourceItem[] = [
{
name: "config.json",
uri: "file:///config.json",
annotations: { audience: "developer", priority: 0.8 },
selected: false,
},
{
name: "README.md",
uri: "file:///README.md",
selected: false,
},
{
name: "schema.sql",
uri: "file:///schema.sql",
annotations: { priority: 0.5 },
selected: false,
},
];
const sampleTemplates: TemplateListItem[] = [
{
name: "User Profile",
uriTemplate: "file:///users/{userId}/profile",
selected: false,
},
{
name: "Table Row",
title: "Database Table Row",
uriTemplate: "db://tables/{tableName}/rows/{rowId}",
selected: false,
},
];
const selectedResourceData: SelectedResource = {
uri: "file:///config.json",
mimeType: "application/json",
annotations: { audience: "developer", priority: 0.8 },
content: JSON.stringify(
{
name: "my-project",
version: "1.0.0",
settings: { debug: true, logLevel: "info" },
},
null,
2,
),
lastUpdated: "2026-03-17T10:30:00Z",
isSubscribed: true,
};
const selectedTemplateData: SelectedTemplate = {
name: "User Profile",
uriTemplate: "file:///users/{userId}/profile",
description: "Fetch a user profile by their unique identifier.",
};
export const WithResources: Story = {
args: {
resources: sampleResources,
},
};
export const ResourceSelected: Story = {
args: {
resources: sampleResources.map((r) =>
r.uri === "file:///config.json" ? { ...r, selected: true } : r,
),
selectedResource: selectedResourceData,
subscriptions: [
{
name: "config.json",
uri: "file:///config.json",
lastUpdated: "2026-03-17T10:30:00Z",
},
],
},
};
export const WithTemplates: Story = {
args: {
resources: sampleResources,
templates: sampleTemplates,
},
};
export const TemplateSelected: Story = {
args: {
resources: sampleResources,
templates: sampleTemplates.map((t) =>
t.uriTemplate === "file:///users/{userId}/profile"
? { ...t, selected: true }
: t,
),
selectedTemplate: selectedTemplateData,
},
};
export const TemplateWithResource: Story = {
args: {
resources: sampleResources,
templates: sampleTemplates.map((t) =>
t.uriTemplate === "file:///users/{userId}/profile"
? { ...t, selected: true }
: t,
),
selectedTemplate: selectedTemplateData,
selectedResource: {
uri: "file:///users/42/profile",
mimeType: "application/json",
annotations: { audience: "developer", priority: 0.8 },
content: JSON.stringify(
{ id: 42, name: "Alice", email: "alice@example.com" },
null,
2,
),
lastUpdated: "2026-03-17T11:15:00Z",
isSubscribed: false,
},
},
};
export const Empty: Story = {
args: {
resources: [],
},
};