webview-ui/.storybook/README.md
Storybook is a frontend workshop for building UI components and pages in isolation. It allows developers to:
In Cline's webview, Storybook helps us develop and test React components that make up the chat interface, settings panels, and other UI elements in isolation from the VSCode extension environment.
To launch the Storybook development server:
npm run storybook
This will start Storybook on http://localhost:6006 where you can browse all available stories and interact with components.
webview-ui/.storybook/
├── main.ts # Main configuration
├── preview.ts # Global decorators and parameters
├── themes.ts # VSCode theme definitions
└── README.md # This documentation
main.ts)*.stories.* files in ../src/@storybook/react-vite for React + Vite integrationIS_DEV, IS_TEST, TEMP_PROFILE)preview.ts)StorybookWebview provides VSCode-like environmentthemes.ts)Provides mock VSCode CSS variables for both dark and light themes, ensuring components render correctly outside the VSCode environment.
Create a *.stories.tsx file alongside your component:
import type { Meta, StoryObj } from "@storybook/react-vite"
import { MyComponent } from "./MyComponent"
const meta: Meta<typeof MyComponent> = {
title: "Components/MyComponent",
component: MyComponent,
parameters: {
docs: {
description: {
component: "Description of what this component does"
}
}
}
}
export default meta
type Story = StoryObj<typeof MyComponent>
export const Default: Story = {
args: {
prop1: "value1",
prop2: true
}
}
export const WithDifferentState: Story = {
args: {
prop1: "different value",
prop2: false
}
}
For complex components requiring context or state, use decorators:
import { ExtensionStateContext } from "@/context/ExtensionStateContext"
const createMockState = (overrides = {}) => ({
// Mock state properties
clineMessages: [],
taskHistory: [],
...overrides
})
export const WithMockState: Story = {
decorators: [
(Story) => {
const mockState = createMockState({
clineMessages: mockMessages
})
return (
<ExtensionStateContext.Provider value={mockState}>
<Story />
</ExtensionStateContext.Provider>
)
}
]
}
"Views/Chat" or "Components/Button"play FunctionsStorybook supports automated interaction testing using the play function:
import { expect, userEvent, within } from "storybook/test"
export const InteractiveTest: Story = {
args: {
// Component props
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
// Find elements
const button = canvas.getByText("Click me")
const input = canvas.getByPlaceholderText("Enter text")
// Perform interactions
await userEvent.type(input, "Hello world")
await userEvent.click(button)
// Assert results
await expect(canvas.getByText("Hello world")).toBeInTheDocument()
}
}
The WelcomeScreen story demonstrates comprehensive testing:
export const WelcomeScreen: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
// Test initial state
const getStartedButton = canvas.getByText("Get Started for Free")
const byokButton = canvas.getByText("Use your own API key")
await expect(getStartedButton).toBeInTheDocument()
await expect(byokButton).toBeInTheDocument()
// Test interaction
await userEvent.click(byokButton)
// Test state change
await expect(getStartedButton).toBeInTheDocument()
await expect(byokButton).not.toBeInTheDocument()
}
}
Use the theme switcher in Storybook's toolbar to test components in both VSCode Dark and Light themes.
The default "Editor Sidebar" viewport (700x800px) matches VSCode's sidebar dimensions, ensuring components render correctly in the actual extension environment.
The StorybookWebview decorator provides a VSCode-like environment with proper CSS variables and context providers, making stories behave similarly to the real extension.
StorybookWebview decorator is appliedmain.ts and preview.ts for configuration issues