Extract ResourceControls, refactor ResourcesScreen layout, and add scrollable accordion panels

- Extract ResourceControls group component from ResourcesScreen:
  title, search, list-changed indicator, and three-section accordion
  (URIs, Templates, Subscriptions) with per-panel ScrollArea.Autosize
- Refactor ResourcesScreen to sidebar+panel Flex layout matching
  HistoryScreen/LoggingScreen pattern (ScreenLayout, Sidebar, SidebarCard)
- Each accordion panel dynamically computes max height based on how many
  sections are open, dividing available space evenly
- Accordion uses controlled state (value/onChange) to track open sections
- Sidebar card sizes to content naturally (compact when collapsed,
  grows with open sections, capped by scroll areas)
- Right panel wrapped in ScrollArea.Autosize for long content
- Add AllSections story with 20 URIs, 7 templates, 8 subscriptions
- Add more templates and subscriptions to ConnectedView ResourcesActive
- Add ResourceControls stories (Default, WithSearch, Empty)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-03-31 14:38:02 -04:00
commit eca6cf7665

View file

@ -0,0 +1,72 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
import { ResourceControls } from "./ResourceControls";
const meta: Meta<typeof ResourceControls> = {
title: "Groups/ResourceControls",
component: ResourceControls,
args: {
searchText: "",
onSearchChange: fn(),
onRefreshList: fn(),
onSelectUri: fn(),
onSelectTemplate: fn(),
onUnsubscribeResource: fn(),
listChanged: false,
},
};
export default meta;
type Story = StoryObj<typeof ResourceControls>;
export const Default: Story = {
args: {
resources: [
{
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",
selected: false,
},
],
templates: [
{
name: "User Profile",
uriTemplate: "file:///users/{userId}/profile",
selected: false,
},
],
subscriptions: [
{
name: "config.json",
uri: "file:///config.json",
lastUpdated: "2026-03-17T10:30:00Z",
},
],
},
};
export const WithSearch: Story = {
args: {
...Default.args,
searchText: "config",
},
};
export const Empty: Story = {
args: {
resources: [],
templates: [],
subscriptions: [],
},
};