Enforce usage of CSF3 story in storybook (#32610)

* chore: enforce usage of CSF3 story by eslint

* chore: migrate remaining stories to CSF3
This commit is contained in:
Florian Duros
2026-02-23 18:14:25 +01:00
committed by GitHub
parent 39317123c7
commit 9c050c58b7
9 changed files with 126 additions and 108 deletions
+1
View File
@@ -65,6 +65,7 @@ module.exports = {
allowInterfaces: "with-single-extends",
},
],
"storybook/meta-satisfies-type": "error",
},
overrides: [
{
@@ -5,25 +5,25 @@
* Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
import { Clock } from "./Clock";
export default {
const meta = {
title: "Audio/Clock",
component: Clock,
tags: ["autodocs"],
args: {
seconds: 20,
},
} as Meta<typeof Clock>;
} satisfies Meta<typeof Clock>;
const Template: StoryFn<typeof Clock> = (args) => <Clock {...args} />;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
export const LotOfSeconds = Template.bind({});
LotOfSeconds.args = {
seconds: 99999999999999,
export const LotOfSeconds: Story = {
args: {
seconds: 99999999999999,
},
};
@@ -9,9 +9,9 @@ import React from "react";
import { useArgs } from "storybook/preview-api";
import { SeekBar } from "./SeekBar";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
export default {
const meta = {
title: "Audio/SeekBar",
component: SeekBar,
tags: ["autodocs"],
@@ -23,16 +23,19 @@ export default {
args: {
value: 50,
},
} as Meta<typeof SeekBar>;
render: function Render(args) {
const [, updateArgs] = useArgs();
return <SeekBar onChange={(evt) => updateArgs({ value: parseInt(evt.target.value, 10) })} {...args} />;
},
} satisfies Meta<typeof SeekBar>;
const Template: StoryFn<typeof SeekBar> = (args) => {
const [, updateArgs] = useArgs();
return <SeekBar onChange={(evt) => updateArgs({ value: parseInt(evt.target.value, 10) })} {...args} />;
};
export const Default = Template.bind({});
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const Disabled: Story = {
args: {
disabled: true,
},
};
@@ -8,10 +8,10 @@
import React from "react";
import { LockSolidIcon, ErrorSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
import { EventTileBubble } from "./EventTileBubble";
export default {
const meta = {
title: "Event/EventTileBubble",
component: EventTileBubble,
tags: ["autodocs"],
@@ -21,29 +21,33 @@ export default {
subtitle: "Subtitle goes here",
className: "custom-class",
},
} as Meta<typeof EventTileBubble>;
} satisfies Meta<typeof EventTileBubble>;
const Template: StoryFn<typeof EventTileBubble> = (args) => <EventTileBubble {...args} />;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
export const HasLockSolidIcon = Template.bind({});
HasLockSolidIcon.args = {
className: undefined,
icon: <LockSolidIcon />,
children: undefined,
export const HasLockSolidIcon: Story = {
args: {
className: undefined,
icon: <LockSolidIcon />,
children: undefined,
},
};
export const HasChildren = Template.bind({});
HasChildren.args = {
className: undefined,
children: <div>children</div>,
export const HasChildren: Story = {
args: {
className: undefined,
children: <div>children</div>,
},
};
export const IsCryptoEventBubble = Template.bind({});
IsCryptoEventBubble.args = {
className: undefined,
icon: <LockSolidIcon />,
title: "Encryption enabled",
subtitle: "Messages here are end-to-end encrypted. Verify XYZ in their profile - tap on their profile picture.",
export const IsCryptoEventBubble: Story = {
args: {
className: undefined,
icon: <LockSolidIcon />,
title: "Encryption enabled",
subtitle: "Messages here are end-to-end encrypted. Verify XYZ in their profile - tap on their profile picture.",
},
};
@@ -5,21 +5,21 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { type Meta, type StoryFn } from "@storybook/react-vite";
import { type Meta, type StoryObj } from "@storybook/react-vite";
import { TextualEventView as TextualEventComponent } from "./TextualEventView";
import { MockViewModel } from "../../viewmodel/MockViewModel";
export default {
const meta = {
title: "Event/TextualEvent",
component: TextualEventComponent,
tags: ["autodocs"],
args: {
vm: new MockViewModel({ content: "Dummy textual event text" }),
},
} as Meta<typeof TextualEventComponent>;
} satisfies Meta<typeof TextualEventComponent>;
const Template: StoryFn<typeof TextualEventComponent> = (args) => <TextualEventComponent {...args} />;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
@@ -5,20 +5,19 @@
* Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { MediaBody } from "./MediaBody";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
export default {
const meta = {
title: "MessageBody/MediaBody",
component: MediaBody,
tags: ["autodocs"],
args: {
children: "Media content goes here",
},
} as Meta<typeof MediaBody>;
} satisfies Meta<typeof MediaBody>;
const Template: StoryFn<typeof MediaBody> = (args) => <MediaBody {...args} />;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
@@ -7,11 +7,11 @@
import React from "react";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
import TimelineSeparator from "./TimelineSeparator";
import styles from "./TimelineSeparator.module.css";
export default {
const meta = {
title: "MessageBody/TimelineSeparator",
component: TimelineSeparator,
tags: ["autodocs"],
@@ -19,36 +19,41 @@ export default {
label: "Label Separator",
children: "Timeline Separator",
},
} as Meta<typeof TimelineSeparator>;
} satisfies Meta<typeof TimelineSeparator>;
const Template: StoryFn<typeof TimelineSeparator> = (args) => <TimelineSeparator {...args} />;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
export const WithHtmlChild = Template.bind({});
WithHtmlChild.args = {
label: "Custom Label",
children: (
<h2 className={styles.timelineSeparator} aria-hidden="true">
Thursday
</h2>
),
export const WithHtmlChild: Story = {
args: {
label: "Custom Label",
children: (
<h2 className={styles.timelineSeparator} aria-hidden="true">
Thursday
</h2>
),
},
};
export const WithDateEvent = Template.bind({});
WithDateEvent.args = {
label: "Date Event Separator",
children: "Wednesday",
export const WithDateEvent: Story = {
args: {
label: "Date Event Separator",
children: "Wednesday",
},
};
export const WithLateEvent = Template.bind({});
WithLateEvent.args = {
label: "Late Event Separator",
children: "Fri, Jan 9, 2026",
export const WithLateEvent: Story = {
args: {
label: "Late Event Separator",
children: "Fri, Jan 9, 2026",
},
};
export const WithoutChildren = Template.bind({});
WithoutChildren.args = {
children: undefined,
label: "Separator without children",
export const WithoutChildren: Story = {
args: {
children: undefined,
label: "Separator without children",
},
};
@@ -8,12 +8,12 @@
import React from "react";
import { fn } from "storybook/test";
import type { Meta, StoryFn } from "@storybook/react-vite";
import type { Meta, StoryObj } from "@storybook/react-vite";
import { RichItem } from "./RichItem";
const currentTimestamp = new Date("2025-03-09T12:00:00Z").getTime();
export default {
const meta = {
title: "RichList/RichItem",
component: RichItem,
tags: ["autodocs"],
@@ -32,33 +32,39 @@ export default {
context: "button",
},
},
} as Meta<typeof RichItem>;
render: (args) => (
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<RichItem {...args} />
</ul>
),
} satisfies Meta<typeof RichItem>;
const Template: StoryFn<typeof RichItem> = (args) => (
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<RichItem {...args} />
</ul>
);
export default meta;
type Story = StoryObj<typeof meta>;
export const Default = Template.bind({});
export const Default: Story = {};
export const Selected = Template.bind({});
Selected.args = {
selected: true,
export const Selected: Story = {
args: {
selected: true,
},
};
export const WithoutTimestamp = Template.bind({});
WithoutTimestamp.args = {
timestamp: undefined,
export const WithoutTimestamp: Story = {
args: {
timestamp: undefined,
},
};
export const Hover = Template.bind({});
Hover.parameters = { pseudo: { hover: true } };
export const Hover: Story = {
parameters: { pseudo: { hover: true } },
};
const TemplateSeparator: StoryFn<typeof RichItem> = (args) => (
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<RichItem {...args} />
<RichItem {...args} />
</ul>
);
export const Separator = TemplateSeparator.bind({});
export const Separator: Story = {
render: (args) => (
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<RichItem {...args} />
<RichItem {...args} />
</ul>
),
};
@@ -12,7 +12,7 @@ import type { Meta, StoryObj } from "@storybook/react-vite";
import { RoomListPrimaryFilters } from "./RoomListPrimaryFilters";
import type { FilterId } from "./useVisibleFilters";
const meta: Meta<typeof RoomListPrimaryFilters> = {
const meta = {
title: "Room List/RoomListPrimaryFilters",
component: RoomListPrimaryFilters,
tags: ["autodocs"],
@@ -25,10 +25,10 @@ const meta: Meta<typeof RoomListPrimaryFilters> = {
url: "https://www.figma.com/design/vlmt46QDdE4dgXDiyBJXqp/ER-33-Left-Panel-2025?node-id=98-1979&t=vafb4zoYMNLRuAbh-4",
},
},
};
} satisfies Meta<typeof RoomListPrimaryFilters>;
export default meta;
type Story = StoryObj<typeof RoomListPrimaryFilters>;
type Story = StoryObj<typeof meta>;
// All available filter IDs
const allFilterIds: FilterId[] = ["unread", "people", "rooms", "favourite", "mentions", "invites", "low_priority"];