From 0162cf5195f8f96d97f4f8156b0ba8cc4017a463 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:01:03 +0000 Subject: [PATCH 1/4] Initial plan From 9888510f50b4aa45b4c9bdb5ca7b8147c4472418 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:13:46 +0000 Subject: [PATCH 2/4] Rename "examples" to "stories" in component manifest format - Updated type definitions in types.ts files to rename Example to Story - Updated format-manifest.ts to use story terminology (story, story_name, story_description, story_code) - Updated all fixture JSON files to use "stories" instead of "examples" - Updated test files and descriptions to use "stories" terminology - Updated test snapshots to reflect the new XML output format - All tests passing, build and typecheck successful Co-authored-by: JReinhold <5678122+JReinhold@users.noreply.github.com> --- packages/mcp/fixtures/button.fixture.json | 2 +- packages/mcp/fixtures/card.fixture.json | 2 +- .../mcp/fixtures/full-manifest.fixture.json | 6 +- packages/mcp/fixtures/input.fixture.json | 2 +- .../mcp/fixtures/small-manifest.fixture.json | 6 +- .../tools/get-component-documentation.test.ts | 84 +++---- packages/mcp/src/types.ts | 4 +- .../format-manifest.test.ts.snap | 210 +++++++++--------- .../mcp/src/utils/format-manifest.test.ts | 148 ++++++------ packages/mcp/src/utils/format-manifest.ts | 36 +-- packages/mcp/types.ts | 4 +- 11 files changed, 252 insertions(+), 252 deletions(-) diff --git a/packages/mcp/fixtures/button.fixture.json b/packages/mcp/fixtures/button.fixture.json index 16e9103e..91cd3c0e 100644 --- a/packages/mcp/fixtures/button.fixture.json +++ b/packages/mcp/fixtures/button.fixture.json @@ -76,7 +76,7 @@ } } }, - "examples": [ + "stories": [ { "id": "button--primary", "name": "Primary", diff --git a/packages/mcp/fixtures/card.fixture.json b/packages/mcp/fixtures/card.fixture.json index 8fc300f7..a436418b 100644 --- a/packages/mcp/fixtures/card.fixture.json +++ b/packages/mcp/fixtures/card.fixture.json @@ -74,7 +74,7 @@ } } }, - "examples": [ + "stories": [ { "id": "card--basic", "name": "Basic", diff --git a/packages/mcp/fixtures/full-manifest.fixture.json b/packages/mcp/fixtures/full-manifest.fixture.json index 65da7641..b2e02ba6 100644 --- a/packages/mcp/fixtures/full-manifest.fixture.json +++ b/packages/mcp/fixtures/full-manifest.fixture.json @@ -78,7 +78,7 @@ } } }, - "examples": [ + "stories": [ { "id": "button--primary", "name": "Primary", @@ -244,7 +244,7 @@ } } }, - "examples": [ + "stories": [ { "id": "card--basic", "name": "Basic", @@ -429,7 +429,7 @@ } } }, - "examples": [ + "stories": [ { "id": "input--basic", "name": "Basic", diff --git a/packages/mcp/fixtures/input.fixture.json b/packages/mcp/fixtures/input.fixture.json index e0d192e6..8cd6fbc3 100644 --- a/packages/mcp/fixtures/input.fixture.json +++ b/packages/mcp/fixtures/input.fixture.json @@ -89,7 +89,7 @@ } } }, - "examples": [ + "stories": [ { "id": "input--basic", "name": "Basic", diff --git a/packages/mcp/fixtures/small-manifest.fixture.json b/packages/mcp/fixtures/small-manifest.fixture.json index fc62ba50..70c0838b 100644 --- a/packages/mcp/fixtures/small-manifest.fixture.json +++ b/packages/mcp/fixtures/small-manifest.fixture.json @@ -6,7 +6,7 @@ "path": "src/components/Button.tsx", "name": "Button", "summary": "A simple button component", - "examples": [ + "stories": [ { "name": "Primary", "description": "The primary button variant.", @@ -19,7 +19,7 @@ "path": "src/components/Card.tsx", "name": "Card", "description": "A container component for grouping related content.", - "examples": [ + "stories": [ { "name": "Basic", "description": "A basic card with content.", @@ -32,7 +32,7 @@ "path": "src/components/Input.tsx", "name": "Input", "description": "A text input component with validation support.", - "examples": [ + "stories": [ { "name": "Basic", "description": "A basic text input.", diff --git a/packages/mcp/src/tools/get-component-documentation.test.ts b/packages/mcp/src/tools/get-component-documentation.test.ts index 8d07306a..f2950dc6 100644 --- a/packages/mcp/src/tools/get-component-documentation.test.ts +++ b/packages/mcp/src/tools/get-component-documentation.test.ts @@ -72,15 +72,15 @@ describe('getComponentDocumentationTool', () => { "text": " button Button - - Primary - + + Primary + The primary button variant. - - + + const Primary = () => - - + + ", "type": "text", }, @@ -111,15 +111,15 @@ describe('getComponentDocumentationTool', () => { "text": " button Button - - Primary - + + Primary + The primary button variant. - - + + const Primary = () => - - + + ", "type": "text", }, @@ -130,20 +130,20 @@ describe('getComponentDocumentationTool', () => { A container component for grouping related content. - - Basic - + + Basic + A basic card with content. - - + + const Basic = () => (

Title

Content

) -
-
+ + ", "type": "text", }, @@ -154,15 +154,15 @@ describe('getComponentDocumentationTool', () => { A text input component with validation support. - - Basic - + + Basic + A basic text input. - - + + const Basic = () => - - + + ", "type": "text", }, @@ -220,15 +220,15 @@ describe('getComponentDocumentationTool', () => { "text": " button Button - - Primary - + + Primary + The primary button variant. - - + + const Primary = () => - - + + ", "type": "text", }, @@ -239,20 +239,20 @@ describe('getComponentDocumentationTool', () => { A container component for grouping related content. - - Basic - + + Basic + A basic card with content. - - + + const Basic = () => (

Title

Content

) -
-
+ + ", "type": "text", }, diff --git a/packages/mcp/src/types.ts b/packages/mcp/src/types.ts index 1e2305cd..d13998d3 100644 --- a/packages/mcp/src/types.ts +++ b/packages/mcp/src/types.ts @@ -50,7 +50,7 @@ const BaseManifest = v.object({ ), }); -const Example = v.object({ +const Story = v.object({ ...BaseManifest.entries, snippet: v.optional(v.string()), }); @@ -60,7 +60,7 @@ export const ComponentManifest = v.object({ id: v.string(), path: v.string(), summary: v.optional(v.string()), - examples: v.optional(v.array(Example)), + stories: v.optional(v.array(Story)), // loose schema for react-docgen types, as they are pretty complex reactDocgen: v.optional(v.custom(() => true)), }); diff --git a/packages/mcp/src/utils/__snapshots__/format-manifest.test.ts.snap b/packages/mcp/src/utils/__snapshots__/format-manifest.test.ts.snap index d546dff7..10feea6f 100644 --- a/packages/mcp/src/utils/__snapshots__/format-manifest.test.ts.snap +++ b/packages/mcp/src/utils/__snapshots__/format-manifest.test.ts.snap @@ -13,9 +13,9 @@ The Button component is a fundamental building block for user interactions. It c Buttons should be used for actions that affect the current page or trigger operations. For navigation, consider using a Link component instead. - -Primary - + +Primary + The primary button variant is used for the main call-to-action on a page. It has the highest visual prominence and should be used sparingly to guide users toward the most important action. ## Best Practices @@ -23,34 +23,34 @@ The primary button variant is used for the main call-to-action on a page. It has - Use only one primary button per section - Keep button text concise and action-oriented - Ensure sufficient contrast for accessibility - - + + import { Button } from '@storybook/design-system'; const Primary = () => - - - -Secondary - + + + +Secondary + The secondary button variant is used for secondary actions that are still important but not the primary focus of the page. Secondary buttons have less visual weight than primary buttons and can be used multiple times on a page. - - + + import { Button } from '@storybook/design-system'; const Secondary = () => - - - -With Sizes - + + + +With Sizes + Buttons are available in three sizes: small, medium (default), and large. Choose the appropriate size based on the context and hierarchy of actions. Larger buttons are more prominent and easier to tap on mobile devices. - - + + import { Button } from '@storybook/design-system'; const WithSizes = () => ( @@ -60,34 +60,34 @@ const WithSizes = () => ( ) - - - -Loading - + + + +Loading + The loading state provides visual feedback when an async operation is in progress. When loading is true, the button displays a spinner and is automatically disabled to prevent multiple submissions. The button text remains visible to maintain layout stability. - - + + import { Button } from '@storybook/design-system'; const Loading = () => - - - -Danger - + + + +Danger + The danger variant is used for destructive actions that cannot be easily undone, such as deleting data or canceling subscriptions. Use this variant to draw attention to the serious nature of the action. Consider adding a confirmation dialog for critical operations. - - + + import { Button } from '@storybook/design-system'; const Danger = () => - - + + variant @@ -170,14 +170,14 @@ The Card component provides a consistent way to present information in a contain - Use elevation to indicate interactive vs static cards - Keep content hierarchy clear with proper use of typography - -Basic - + +Basic + A basic card with just content. The default elevated variant provides subtle depth through shadow, making the card appear to float above the page. This is ideal for creating visual hierarchy and grouping related information. - - + + import { Card } from '@storybook/design-system'; const Basic = () => ( @@ -186,16 +186,16 @@ const Basic = () => (

This is some card content that provides information to the user.

) -
-
- -With Header And Footer - + + + +With Header And Footer + A card with distinct header and footer sections. Headers typically contain titles, subtitles, or avatars. Footers often contain actions like buttons or metadata like timestamps. The header and footer are visually separated from the main content area. - - + + import { Card } from '@storybook/design-system'; const WithHeaderAndFooter = () => ( @@ -206,11 +206,11 @@ const WithHeaderAndFooter = () => (

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

) -
-
- -Clickable - + + + +Clickable + An interactive card that responds to clicks. Clickable cards add hover effects and cursor changes to indicate interactivity. This pattern is useful for navigation cards, product cards, or any scenario where the entire card acts as a single interactive element. @@ -218,8 +218,8 @@ Clickable cards add hover effects and cursor changes to indicate interactivity. ## Accessibility Clickable cards are rendered as buttons with proper keyboard support and ARIA attributes. - - + + import { Card } from '@storybook/design-system'; const Clickable = () => ( @@ -228,11 +228,11 @@ const Clickable = () => (

Click anywhere on this card to view details.

) -
-
- -Variants - + + + +Variants + Different visual variants of the card component. - **Elevated**: Default variant with shadow for depth @@ -240,8 +240,8 @@ Different visual variants of the card component. - **Flat**: No border or shadow, minimal visual separation Choose variants based on your design system and the level of emphasis needed. - - + + import { Card } from '@storybook/design-system'; const Variants = () => ( @@ -257,16 +257,16 @@ const Variants = () => ( ) - - - -User Profile - + + + +User Profile + A real-world example of a user profile card. This example demonstrates how to compose the Card component with other design system components to create a complete, functional UI element. It includes an avatar, user information, stats, and action buttons. - - + + import { Card, Avatar, Button } from '@storybook/design-system'; const UserProfile = () => ( @@ -294,8 +294,8 @@ const UserProfile = () => ( ) - - + + variant @@ -373,53 +373,53 @@ The Input component is a foundational form element that wraps the native HTML in The Input component automatically manages ARIA attributes for labels, descriptions, and error messages to ensure screen reader compatibility. - -Basic - + +Basic + A basic text input with a label. This is the most common use case for the Input component. Always include a label for accessibility, even if it's visually hidden in your design. - - + + import { Input } from '@storybook/design-system'; const Basic = () => - - - -With Error - + + + +With Error + An input displaying an error state with an error message. Error messages should be clear, concise, and provide actionable guidance to help users fix the issue. The input border and message text are styled in red to indicate the error state. - - + + import { Input } from '@storybook/design-system'; const WithError = () => - - - -With Helper Text - + + + +With Helper Text + An input with helper text providing additional context or instructions. Helper text appears below the input and provides guidance without being an error. Use it to clarify format expectations, character limits, or provide helpful hints. - - + + import { Input } from '@storybook/design-system'; const WithHelperText = () => - - - -Types - + + + +Types + Different input types for various data formats. Using the correct input type improves the user experience by showing appropriate mobile keyboards and enabling browser validation features. - - + + import { Input } from '@storybook/design-system'; const Types = () => ( @@ -430,21 +430,21 @@ const Types = () => ( ) - - - -Disabled - + + + +Disabled + A disabled input that cannot be interacted with. Disabled inputs are useful for displaying non-editable data in forms or for inputs that become available only after certain conditions are met. - - + + import { Input } from '@storybook/design-system'; const Disabled = () => - - + + type diff --git a/packages/mcp/src/utils/format-manifest.test.ts b/packages/mcp/src/utils/format-manifest.test.ts index 7d065788..448d6368 100644 --- a/packages/mcp/src/utils/format-manifest.test.ts +++ b/packages/mcp/src/utils/format-manifest.test.ts @@ -102,14 +102,14 @@ describe('formatComponentManifest', () => { }); }); - describe('examples section', () => { - it('should format a single example', () => { + describe('stories section', () => { + it('should format a single story', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', import: 'import { Button } from "@/components";', - examples: [ + stories: [ { name: 'Primary', description: 'A primary button variant', @@ -124,28 +124,28 @@ describe('formatComponentManifest', () => { " button Button - - Primary - + + Primary + A primary button variant - - + + import { Button } from "@/components"; - - + + " `); }); - it('should format multiple examples', () => { + it('should format multiple stories', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', import: 'import { Button } from "@/components";', - examples: [ + stories: [ { name: 'Primary', snippet: '', @@ -163,32 +163,32 @@ describe('formatComponentManifest', () => { " button Button - - Primary - + + Primary + import { Button } from "@/components"; - - - - Secondary - + + + + Secondary + import { Button } from "@/components"; - - + + " `); }); - it('should format PascalCase example names correctly', () => { + it('should format PascalCase story names correctly', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', - examples: [ + stories: [ { name: 'WithIcon', snippet: '', @@ -206,29 +206,29 @@ describe('formatComponentManifest', () => { " button Button - - With Icon - + + With Icon + - - - - Disabled State - + + + + Disabled State + - - + + " `); }); - it('should use example import over component import when provided', () => { + it('should use story import over component import when provided', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', import: 'import { Button } from "@/components";', - examples: [ + stories: [ { name: 'WithCustomImport', import: 'import { Button } from "@/custom-path";', @@ -243,24 +243,24 @@ describe('formatComponentManifest', () => { " button Button - - With Custom Import - + + With Custom Import + import { Button } from "@/custom-path"; - - + + " `); }); - it('should handle examples without description', () => { + it('should handle stories without description', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', - examples: [ + stories: [ { name: 'Simple', snippet: '', @@ -274,22 +274,22 @@ describe('formatComponentManifest', () => { " button Button - - Simple - + + Simple + - - + + " `); }); - it('should handle examples without import', () => { + it('should handle stories without import', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', - examples: [ + stories: [ { name: 'NoImport', snippet: '', @@ -303,17 +303,17 @@ describe('formatComponentManifest', () => { " button Button - - No Import - + + No Import + - - + + " `); }); - it('should omit examples when no examples are provided', () => { + it('should omit stories when no stories are provided', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', @@ -334,12 +334,12 @@ describe('formatComponentManifest', () => { `); }); - it('should omit examples when examples array is empty', () => { + it('should omit stories when stories array is empty', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', path: 'src/components/Button.tsx', - examples: [], + stories: [], }; const result = formatComponentManifest(manifest); @@ -354,7 +354,7 @@ describe('formatComponentManifest', () => { }); describe('complete component', () => { - it('should format a complete component with description and multiple examples', () => { + it('should format a complete component with description and multiple stories', () => { const manifest: ComponentManifest = { id: 'button', name: 'Button', @@ -363,7 +363,7 @@ describe('formatComponentManifest', () => { 'A versatile button component.\n\nSupports multiple variants, sizes, and states.', summary: 'A button for user interactions', import: 'import { Button } from "@storybook/design-system";', - examples: [ + stories: [ { name: 'Primary', description: 'The primary button variant.', @@ -390,23 +390,23 @@ describe('formatComponentManifest', () => { Supports multiple variants, sizes, and states. - - Primary - + + Primary + The primary button variant. - - + + import { Button } from "@storybook/design-system"; const Primary = () => - - - - With Sizes - + + + + With Sizes + Buttons in different sizes. - - + + import { Button } from "@storybook/design-system"; const Sizes = () => ( @@ -415,8 +415,8 @@ describe('formatComponentManifest', () => { ) - - + + " `); }); diff --git a/packages/mcp/src/utils/format-manifest.ts b/packages/mcp/src/utils/format-manifest.ts index effd7cdb..31c9dd5a 100644 --- a/packages/mcp/src/utils/format-manifest.ts +++ b/packages/mcp/src/utils/format-manifest.ts @@ -19,34 +19,34 @@ export function formatComponentManifest( `); } - // Examples section - only if there are examples - if (componentManifest.examples && componentManifest.examples.length > 0) { - for (const example of componentManifest.examples) { - if (!example.snippet) { + // Stories section - only if there are stories + if (componentManifest.stories && componentManifest.stories.length > 0) { + for (const story of componentManifest.stories) { + if (!story.snippet) { continue; } - const exampleParts: string[] = []; + const storyParts: string[] = []; // Convert PascalCase to Human Readable Case // "WithSizes" -> "With Sizes" - exampleParts.push(dedent` - ${example.name.replace(/([A-Z])/g, ' $1').trim()}`); + storyParts.push(dedent` + ${story.name.replace(/([A-Z])/g, ' $1').trim()}`); - if (example.description) { - exampleParts.push(dedent` - ${example.description} - `); + if (story.description) { + storyParts.push(dedent` + ${story.description} + `); } - exampleParts.push(''); - const importStatement = example.import || componentManifest.import; + storyParts.push(''); + const importStatement = story.import || componentManifest.import; if (importStatement) { - exampleParts.push(`${importStatement}\n`); + storyParts.push(`${importStatement}\n`); } - exampleParts.push(dedent`${example.snippet} - - `); + storyParts.push(dedent`${story.snippet} + + `); - parts.push(exampleParts.join('\n')); + parts.push(storyParts.join('\n')); } } diff --git a/packages/mcp/types.ts b/packages/mcp/types.ts index 7b28f63b..908886d6 100644 --- a/packages/mcp/types.ts +++ b/packages/mcp/types.ts @@ -23,7 +23,7 @@ const BaseManifest = v.object({ jsDocTags: v.exactOptional(v.array(JSDocTag)), }); -const Example = v.object({ +const Story = v.object({ ...BaseManifest.entries, snippet: v.string(), }); @@ -32,7 +32,7 @@ export const ComponentManifest = v.object({ ...BaseManifest.entries, id: v.string(), summary: v.exactOptional(v.string()), - examples: v.exactOptional(v.array(Example)), + stories: v.exactOptional(v.array(Story)), props: v.exactOptional(v.any()), }); export type ComponentManifest = v.InferOutput; From 651ec55a3d554c4892b4701a631507b1dcb9699f Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 31 Oct 2025 11:26:08 +0100 Subject: [PATCH 3/4] delete unused files --- .../format-manifest.test.ts.snap | 351 ------------------ packages/mcp/types.ts | 44 --- 2 files changed, 395 deletions(-) delete mode 100644 packages/mcp/__snapshots__/format-manifest.test.ts.snap delete mode 100644 packages/mcp/types.ts diff --git a/packages/mcp/__snapshots__/format-manifest.test.ts.snap b/packages/mcp/__snapshots__/format-manifest.test.ts.snap deleted file mode 100644 index a9d8a9a7..00000000 --- a/packages/mcp/__snapshots__/format-manifest.test.ts.snap +++ /dev/null @@ -1,351 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`formatComponentManifest > formats all full fixtures 1`] = ` -" -button -Button - -A versatile button component that supports multiple variants, sizes, and states. - -The Button component is a fundamental building block for user interactions. It can be styled as primary, secondary, or tertiary actions, and supports disabled and loading states. - -## Usage - -Buttons should be used for actions that affect the current page or trigger operations. For navigation, consider using a Link component instead. - - -Primary - -The primary button variant is used for the main call-to-action on a page. It has the highest visual prominence and should be used sparingly to guide users toward the most important action. - -## Best Practices - -- Use only one primary button per section -- Keep button text concise and action-oriented -- Ensure sufficient contrast for accessibility - - -import { Button } from '@storybook/design-system'; - -const Primary = () => - - - -Secondary - -The secondary button variant is used for secondary actions that are still important but not the primary focus of the page. - -Secondary buttons have less visual weight than primary buttons and can be used multiple times on a page. - - -import { Button } from '@storybook/design-system'; - -const Secondary = () => - - - -With Sizes - -Buttons are available in three sizes: small, medium (default), and large. - -Choose the appropriate size based on the context and hierarchy of actions. Larger buttons are more prominent and easier to tap on mobile devices. - - -import { Button } from '@storybook/design-system'; - -const WithSizes = () => ( - <> - - - - -) - - - -Loading - -The loading state provides visual feedback when an async operation is in progress. - -When loading is true, the button displays a spinner and is automatically disabled to prevent multiple submissions. The button text remains visible to maintain layout stability. - - -import { Button } from '@storybook/design-system'; - -const Loading = () => - - - -Danger - -The danger variant is used for destructive actions that cannot be easily undone, such as deleting data or canceling subscriptions. - -Use this variant to draw attention to the serious nature of the action. Consider adding a confirmation dialog for critical operations. - - -import { Button } from '@storybook/design-system'; - -const Danger = () => - - -" -`; - -exports[`formatComponentManifest > formats all full fixtures 2`] = ` -" -card -Card - -A flexible container component for grouping related content with optional header, footer, and action areas. - -The Card component provides a consistent way to present information in a contained, elevated surface. It's commonly used for displaying articles, products, user profiles, or any grouped content that benefits from visual separation. - -## Design Principles - -- Cards should contain a single subject or action -- Maintain consistent padding and spacing -- Use elevation to indicate interactive vs static cards -- Keep content hierarchy clear with proper use of typography - - -Basic - -A basic card with just content. - -The default elevated variant provides subtle depth through shadow, making the card appear to float above the page. This is ideal for creating visual hierarchy and grouping related information. - - -import { Card } from '@storybook/design-system'; - -const Basic = () => ( - -

Card Title

-

This is some card content that provides information to the user.

-
-) -
-
- -With Header And Footer - -A card with distinct header and footer sections. - -Headers typically contain titles, subtitles, or avatars. Footers often contain actions like buttons or metadata like timestamps. The header and footer are visually separated from the main content area. - - -import { Card } from '@storybook/design-system'; - -const WithHeaderAndFooter = () => ( - Article Title} - footer={} - > -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

-
-) -
-
- -Clickable - -An interactive card that responds to clicks. - -Clickable cards add hover effects and cursor changes to indicate interactivity. This pattern is useful for navigation cards, product cards, or any scenario where the entire card acts as a single interactive element. - -## Accessibility - -Clickable cards are rendered as buttons with proper keyboard support and ARIA attributes. - - -import { Card } from '@storybook/design-system'; - -const Clickable = () => ( - alert('Card clicked!')}> -

Product Name

-

Click anywhere on this card to view details.

-
-) -
-
- -Variants - -Different visual variants of the card component. - -- **Elevated**: Default variant with shadow for depth -- **Outlined**: Border-only variant without shadow -- **Flat**: No border or shadow, minimal visual separation - -Choose variants based on your design system and the level of emphasis needed. - - -import { Card } from '@storybook/design-system'; - -const Variants = () => ( - <> - -

Elevated card with shadow

-
- -

Outlined card with border

-
- -

Flat card without border or shadow

-
- -) -
-
- -User Profile - -A real-world example of a user profile card. - -This example demonstrates how to compose the Card component with other design system components to create a complete, functional UI element. It includes an avatar, user information, stats, and action buttons. - - -import { Card, Avatar, Button } from '@storybook/design-system'; - -const UserProfile = () => ( - - -
-

Jane Doe

-

Senior Developer

-
- - } - footer={ -
- - -
- } - > -
-
1.2K
Followers
-
342
Following
-
89
Posts
-
-
-) -
-
-
" -`; - -exports[`formatComponentManifest > formats all full fixtures 3`] = ` -" -input -Input - -A flexible text input component that supports various input types, validation states, and accessibility features. - -The Input component is a foundational form element that wraps the native HTML input with consistent styling and behavior. It includes support for labels, error messages, helper text, and different visual states. - -## Accessibility - -The Input component automatically manages ARIA attributes for labels, descriptions, and error messages to ensure screen reader compatibility. - - -Basic - -A basic text input with a label. - -This is the most common use case for the Input component. Always include a label for accessibility, even if it's visually hidden in your design. - - -import { Input } from '@storybook/design-system'; - -const Basic = () => - - - -With Error - -An input displaying an error state with an error message. - -Error messages should be clear, concise, and provide actionable guidance to help users fix the issue. The input border and message text are styled in red to indicate the error state. - - -import { Input } from '@storybook/design-system'; - -const WithError = () => - - - -With Helper Text - -An input with helper text providing additional context or instructions. - -Helper text appears below the input and provides guidance without being an error. Use it to clarify format expectations, character limits, or provide helpful hints. - - -import { Input } from '@storybook/design-system'; - -const WithHelperText = () => - - - -Types - -Different input types for various data formats. - -Using the correct input type improves the user experience by showing appropriate mobile keyboards and enabling browser validation features. - - -import { Input } from '@storybook/design-system'; - -const Types = () => ( - <> - - - - - -) - - - -Disabled - -A disabled input that cannot be interacted with. - -Disabled inputs are useful for displaying non-editable data in forms or for inputs that become available only after certain conditions are met. - - -import { Input } from '@storybook/design-system'; - -const Disabled = () => - - -" -`; - -exports[`formatComponentManifestMapToList > formats the full manifest fixture 1`] = ` -" - -button -Button - -A versatile button component for user interactions - - - -card -Card - -A flexible container component for grouping related content - - - -input -Input - -A flexible text input component with validation support - - -" -`; diff --git a/packages/mcp/types.ts b/packages/mcp/types.ts deleted file mode 100644 index 908886d6..00000000 --- a/packages/mcp/types.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as v from 'valibot'; - -/** - * Custom context passed to MCP server and tools. - * Contains the source URL for fetching component manifests. - */ -export interface StorybookContext extends Record { - /** - * The URL of the remote manifest to fetch component data from. - */ - source?: string; -} - -const JSDocTag = v.object({ - key: v.string(), - value: v.union([v.string(), v.number(), v.boolean(), v.null()]), -}); - -const BaseManifest = v.object({ - name: v.string(), - description: v.exactOptional(v.string()), - import: v.exactOptional(v.string()), - jsDocTags: v.exactOptional(v.array(JSDocTag)), -}); - -const Story = v.object({ - ...BaseManifest.entries, - snippet: v.string(), -}); - -export const ComponentManifest = v.object({ - ...BaseManifest.entries, - id: v.string(), - summary: v.exactOptional(v.string()), - stories: v.exactOptional(v.array(Story)), - props: v.exactOptional(v.any()), -}); -export type ComponentManifest = v.InferOutput; - -export const ComponentManifestMap = v.object({ - v: v.number(), - components: v.record(v.string(), ComponentManifest), -}); -export type ComponentManifestMap = v.InferOutput; From 62e871469812126529fdffb90c2e083ac4349bad Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 31 Oct 2025 11:27:00 +0100 Subject: [PATCH 4/4] add changeset --- .changeset/ready-ends-attend.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ready-ends-attend.md diff --git a/.changeset/ready-ends-attend.md b/.changeset/ready-ends-attend.md new file mode 100644 index 00000000..667bff02 --- /dev/null +++ b/.changeset/ready-ends-attend.md @@ -0,0 +1,5 @@ +--- +'@storybook/mcp': patch +--- + +rename examples to stories in manifest