Fix documentation of view component in storybook and migrate to CSF3 format (#32604)

* chore: add a way to keep story doc in wrapper

* chore: use `withViewDocs`

* doc: update SC readme

* doc: update copyright
This commit is contained in:
Florian Duros
2026-02-23 16:03:49 +00:00
committed by GitHub
parent 77670eb369
commit b08cf5fdaa
16 changed files with 422 additions and 258 deletions
+31 -15
View File
@@ -68,7 +68,7 @@ instance should be provided as a prop.
Here's a basic example:
```jsx
```tsx
import { ViewExample } from "@element-hq/web-shared-components";
function MyApp() {
@@ -180,27 +180,32 @@ export const Disabled: Story = {
#### MVVM Component Stories
For MVVM components, create a wrapper component that uses `useMockedViewModel`:
For MVVM components, create a wrapper component that uses `useMockedViewModel` and `withViewDocs`:
```tsx
import React, { type JSX } from "react";
import { fn } from "storybook/test";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
import { MyComponentView, type MyComponentViewSnapshot, type MyComponentViewActions } from "./MyComponentView";
import { useMockedViewModel } from "../../useMockedViewModel";
import { useMockedViewModel } from "../../viewmodel";
import { withViewDocs } from "../../../.storybook/withViewDocs";
// Combine snapshot and actions for easier typing
type MyComponentProps = MyComponentViewSnapshot & MyComponentViewActions;
// Wrapper component that creates a mocked ViewModel
const MyComponentViewWrapper = ({ onAction, ...rest }: MyComponentProps): JSX.Element => {
// Wrapper component that creates a mocked ViewModel.
// Must be a named variable (not inline) for docgen to extract its props.
const MyComponentViewWrapperImpl = ({ onAction, ...rest }: MyComponentProps): JSX.Element => {
const vm = useMockedViewModel(rest, {
onAction,
});
return <MyComponentView vm={vm} />;
};
// withViewDocs copies the View's JSDoc description onto the wrapper for Storybook autodocs
const MyComponentViewWrapper = withViewDocs(MyComponentViewWrapperImpl, MyComponentView);
export default {
// Must use `satisfies` (not `as` or `: Meta`) to preserve type info for docgen
const meta = {
title: "Category/MyComponentView",
component: MyComponentViewWrapper,
tags: ["autodocs"],
@@ -211,20 +216,29 @@ export default {
// Action properties (callbacks)
onAction: fn(),
},
} as Meta<typeof MyComponentViewWrapper>;
} satisfies Meta<typeof MyComponentViewWrapper>;
const Template: StoryFn<typeof MyComponentViewWrapper> = (args) => <MyComponentViewWrapper {...args} />;
export default meta;
type Story = StoryObj<typeof MyComponentViewWrapper>;
export const Default = Template.bind({});
export const Default: Story = {};
export const Loading = Template.bind({});
Loading.args = {
isLoading: true,
export const Loading: Story = {
args: {
isLoading: true,
},
};
```
Thanks to this approach, we can directly use primitives in the story arguments instead of a view model object.
> [!IMPORTANT]
> Three requirements must be met for snapshot field documentation to appear in Storybook's ArgTypes table:
>
> 1. **Named wrapper variable** — the wrapper must be assigned to a named `const` (e.g. `MyComponentViewWrapperImpl`) before being passed to `withViewDocs`, so that `react-docgen-typescript` can extract its props.
> 2. **`withViewDocs` call** — wraps the wrapper component with the original View to copy the View's JSDoc description.
> 3. **`satisfies Meta`** — the meta object must use `satisfies Meta<...>` (not `as Meta<...>` or `: Meta<...> =`). Type assertions and annotations erase the inferred component type that docgen relies on.
#### Linking Figma Designs
This package uses [@storybook/addon-designs](https://github.com/storybookjs/addon-designs) to embed Figma designs directly in Storybook. This helps developers compare their implementation with the design specs.
@@ -239,7 +253,7 @@ This package uses [@storybook/addon-designs](https://github.com/storybookjs/addo
Example with Figma integration:
```tsx
export default {
const meta = {
title: "Room List/RoomListSearchView",
component: RoomListSearchViewWrapper,
tags: ["autodocs"],
@@ -252,7 +266,9 @@ export default {
url: "https://www.figma.com/design/vlmt46QDdE4dgXDiyBJXqp/ER-33-Left-Panel?node-id=98-1979",
},
},
} as Meta<typeof RoomListSearchViewWrapper>;
} satisfies Meta<typeof RoomListSearchViewWrapper>;
export default meta;
```
The Figma design will appear in the "Design" tab in Storybook.