From f790bc2a0cd9136b358f265b80f8cb4351f2ec24 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 10 Dec 2024 11:42:55 +0100 Subject: [PATCH] Normalise how we write stories --- src/components/Alert/Alert.stories.tsx | 19 ++-- src/components/Avatar/Avatar.stories.tsx | 92 ++++++++++--------- src/components/Avatar/AvatarStack.stories.tsx | 48 +++++----- src/components/Badge/Badge.stories.tsx | 59 ++++++------ .../Button/ActionButton.stories.tsx | 53 ++++++----- src/components/Button/Button.stories.tsx | 45 +++++---- .../Button/IconButton/IconButton.stories.tsx | 65 +++++++------ .../Button/IconButton/IconButton.tsx | 64 ++++++------- src/components/Dropdown/Dropdown.stories.tsx | 18 ++-- .../Form/Controls/Action/Action.stories.tsx | 7 +- .../Controls/Checkbox/Checkbox.stories.tsx | 5 +- .../EditInPlace/EditInPlace.stories.tsx | 5 +- .../Form/Controls/MFA/MFA.stories.tsx | 5 +- .../Controls/Password/Password.stories.tsx | 5 +- .../Form/Controls/Radio/Radio.stories.tsx | 5 +- .../Form/Controls/Text/Text.stories.tsx | 5 +- .../Form/Controls/Toggle/Toggle.stories.tsx | 5 +- src/components/Form/Form.stories.tsx | 7 +- src/components/Form/PasswordForm.stories.tsx | 12 +-- src/components/Glass/Glass.stories.tsx | 58 ++++++------ src/components/Icon/Icon.stories.tsx | 13 ++- .../IndicatorIcon/IndicatorIcon.stories.tsx | 73 ++++++++------- .../InlineSpinner/InlineSpinner.stories.tsx | 11 ++- src/components/Link/Link.stories.tsx | 21 ++--- src/components/Menu/ContextMenu.stories.tsx | 29 +++--- src/components/Menu/DrawerMenu.stories.tsx | 27 ++++-- src/components/Menu/FloatingMenu.stories.tsx | 27 ++++-- src/components/Menu/Menu.stories.tsx | 37 ++++---- src/components/Menu/MenuItem.stories.tsx | 46 +++++----- src/components/Menu/MenuItem.tsx | 8 +- .../Menu/ToggleMenuItem.stories.tsx | 35 ++++--- src/components/Nav/NavBar.stories.tsx | 12 ++- src/components/Nav/NavItem.stories.tsx | 31 ++++--- src/components/Nav/NavItem.tsx | 8 +- src/components/Progress/Progress.stories.tsx | 19 ++-- .../ReleaseAnnouncement.stories.tsx | 70 ++++++++------ src/components/Search/Search.stories.tsx | 33 ++++--- .../Separator/Separator.stories.tsx | 15 +-- src/components/Toast/Toast.stories.tsx | 19 ++-- src/components/Tooltip/Tooltip.stories.tsx | 41 ++++++--- src/components/Typography/Heading.stories.tsx | 28 +++--- src/components/Typography/Text.stories.tsx | 13 ++- .../__ComponentTemplate__.stories.tsx | 11 ++- 43 files changed, 668 insertions(+), 541 deletions(-) diff --git a/src/components/Alert/Alert.stories.tsx b/src/components/Alert/Alert.stories.tsx index 42a3d6f1..1b60b8c7 100644 --- a/src/components/Alert/Alert.stories.tsx +++ b/src/components/Alert/Alert.stories.tsx @@ -15,12 +15,12 @@ limitations under the License. */ import React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Button } from "../Button/Button"; import { Alert as AlertComponent } from "./Alert"; -export default { +const meta = { title: "Alert", component: AlertComponent, tags: ["autodocs"], @@ -43,27 +43,30 @@ export default { url: "https://www.figma.com/file/rTaQE2nIUSLav4Tg3nozq7/Compound-Web-Components?type=design&node-id=795-7802&mode=design&t=g71gv6nZdJA7QSGB-0", }, }, -} as Meta; +} satisfies Meta; +export default meta; -export const Success = { +type Story = StoryObj; + +export const Success: Story = { args: { type: "success", }, }; -export const Critical = { +export const Critical: Story = { args: { type: "critical", }, }; -export const Info = { +export const Info: Story = { args: { type: "info", }, }; -export const WithActions = { +export const WithActions: Story = { args: { type: "info", title: @@ -79,7 +82,7 @@ export const WithActions = { }, }; -export const WithoutClose = { +export const WithoutClose: Story = { ...Success, args: { ...Success.args, diff --git a/src/components/Avatar/Avatar.stories.tsx b/src/components/Avatar/Avatar.stories.tsx index a68c97de..9c41b1ff 100644 --- a/src/components/Avatar/Avatar.stories.tsx +++ b/src/components/Avatar/Avatar.stories.tsx @@ -15,11 +15,11 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Avatar as AvatarComponent } from "./Avatar"; -export default { +const meta = { title: "Avatar", component: AvatarComponent, tags: ["autodocs"], @@ -31,58 +31,62 @@ export default { src: "/images/__test__/kitten.jpg", type: "round", }, -} as Meta; +} satisfies Meta; +export default meta; -const Template: StoryFn = (args) => ( - -); +type Story = StoryObj; -export const Round = Template.bind({}); -Round.args = { - type: "round", +export const Round: Story = { + args: { + type: "round", + }, }; -export const Square = Template.bind({}); -Square.args = { - type: "square", +export const Square: Story = { + args: { + type: "square", + }, }; -export const Button = Template.bind({}); -Button.args = { - type: "round", - onClick: () => console.log("clicked!"), +export const Button: Story = { + args: { + type: "round", + onClick: () => console.log("clicked!"), + }, }; -export const NoImageFallback = Template.bind({}); -NoImageFallback.args = { - src: "", +export const NoImageFallback: Story = { + args: { + src: "", + }, }; -export const LargeNoImageFallback = Template.bind({}); -LargeNoImageFallback.args = { - src: "", - size: "128px", +export const LargeNoImageFallback: Story = { + args: { + src: "", + size: "128px", + }, }; -const ImageLessCollection: StoryFn = (args) => ( - <> - -   - -   - -   - -   - -   - -   - -); - -export const AllAvatars = ImageLessCollection.bind({}); -AllAvatars.args = { - src: "", - size: "36px", +export const AllAvatars: Story = { + args: { + src: "", + size: "36px", + }, + render: (args: React.ComponentProps) => ( + <> + +   + +   + +   + +   + +   + +   + + ), }; diff --git a/src/components/Avatar/AvatarStack.stories.tsx b/src/components/Avatar/AvatarStack.stories.tsx index 371f3c55..ddc04735 100644 --- a/src/components/Avatar/AvatarStack.stories.tsx +++ b/src/components/Avatar/AvatarStack.stories.tsx @@ -15,37 +15,37 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { AvatarStack as AvatarStackComponent } from "./AvatarStack"; import { Avatar } from "./Avatar"; -export default { +const meta = { title: "Avatar/StackedAvatar", component: AvatarStackComponent, tags: ["autodocs"], argTypes: {}, args: { - size: "64px", + children: ( + <> + + + + ), }, -} as Meta; - -const Template: StoryFn = (args) => ( - - - - -); - -export const AvatarStack = Template.bind({}); -AvatarStack.args = {}; +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const AvatarStack: Story = { args: {} }; diff --git a/src/components/Badge/Badge.stories.tsx b/src/components/Badge/Badge.stories.tsx index 67de8c24..1851de5a 100644 --- a/src/components/Badge/Badge.stories.tsx +++ b/src/components/Badge/Badge.stories.tsx @@ -15,42 +15,43 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Badge as BadgeComponent } from "./Badge"; -export default { +const meta = { title: "Badge", component: BadgeComponent, argTypes: {}, args: {}, -} as Meta; - -const Template: StoryFn = () => ( -
-
- Trusted -   - Not trusted -   - Public room -
-
+ render: () => (
- Default -   - Grey -   - On Solid -   - Blue -   - Green -   - Red +
+ Trusted +   + Not trusted +   + Public room +
+
+
+ Default +   + Grey +   + On Solid +   + Blue +   + Green +   + Red +
-
-); + ), +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Badge = Template.bind({}); -Badge.args = {}; +export const Badge: Story = { args: {} }; diff --git a/src/components/Button/ActionButton.stories.tsx b/src/components/Button/ActionButton.stories.tsx index 017c8b92..659682c0 100644 --- a/src/components/Button/ActionButton.stories.tsx +++ b/src/components/Button/ActionButton.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; import * as icons from "@vector-im/compound-design-tokens/assets/web/icons"; @@ -25,7 +25,9 @@ import { Tooltip } from "../Tooltip/Tooltip"; import { TooltipProvider } from "../Tooltip/TooltipProvider"; const Template: React.FC< - { label: string } & React.ComponentProps + { label: string; as: "button" | "a" } & React.ComponentProps< + typeof ButtonComponent + > > = ({ label, ...args }) => ( @@ -34,7 +36,7 @@ const Template: React.FC< ); -export default { +const meta = { title: "Button/Actions", component: Template, tags: ["autodocs"], @@ -73,12 +75,17 @@ export default { disabled: false, onClick: fn(), }, - controls: { - exclude: ["children"], + parameters: { + controls: { + exclude: ["children"], + }, }, -} as Meta; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Settings = { +export const Settings: Story = { args: { label: "Settings", kind: "secondary", @@ -86,7 +93,7 @@ export const Settings = { }, }; -export const ShareLink = { +export const ShareLink: Story = { args: { label: "Copy link", kind: "secondary", @@ -94,7 +101,7 @@ export const ShareLink = { }, }; -export const VideoOn = { +export const VideoOn: Story = { args: { label: "Turn video off", kind: "secondary", @@ -102,7 +109,7 @@ export const VideoOn = { }, }; -export const VideoOff = { +export const VideoOff: Story = { args: { label: "Turn video on", kind: "primary", @@ -110,7 +117,7 @@ export const VideoOff = { }, }; -export const MicOn = { +export const MicOn: Story = { args: { label: "Turn mic off", kind: "secondary", @@ -118,7 +125,7 @@ export const MicOn = { }, }; -export const MicOff = { +export const MicOff: Story = { args: { label: "Turn mic on", kind: "primary", @@ -126,7 +133,7 @@ export const MicOff = { }, }; -export const ShareScreen = { +export const ShareScreen: Story = { args: { label: "Share screen", kind: "secondary", @@ -134,7 +141,7 @@ export const ShareScreen = { }, }; -export const SharingScreen = { +export const SharingScreen: Story = { args: { label: "Stop sharing screen", kind: "primary", @@ -142,7 +149,7 @@ export const SharingScreen = { }, }; -export const Fullscreen = { +export const Fullscreen: Story = { args: { label: "Full screen", kind: "secondary", @@ -150,7 +157,7 @@ export const Fullscreen = { }, }; -export const EndCall = { +export const EndCall: Story = { args: { label: "End call", kind: "primary", @@ -159,7 +166,7 @@ export const EndCall = { }, }; -export const Invite = { +export const Invite: Story = { args: { label: "Invite", kind: "primary", @@ -168,7 +175,7 @@ export const Invite = { }, }; -export const Edit = { +export const Edit: Story = { args: { label: "Edit", kind: "primary", @@ -177,7 +184,7 @@ export const Edit = { }, }; -export const Search = { +export const Search: Story = { args: { label: "Search", kind: "secondary", @@ -186,7 +193,7 @@ export const Search = { }, }; -export const Save = { +export const Save: Story = { args: { label: "Save", kind: "primary", @@ -195,7 +202,7 @@ export const Save = { }, }; -export const SaveDisabled = { +export const SaveDisabled: Story = { args: { label: "Save", kind: "primary", @@ -205,7 +212,7 @@ export const SaveDisabled = { }, }; -export const Cancel = { +export const Cancel: Story = { args: { label: "Cancel", kind: "secondary", @@ -214,7 +221,7 @@ export const Cancel = { }, }; -export const Close = { +export const Close: Story = { args: { label: "Close", kind: "secondary", diff --git a/src/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx index e424fb8a..10289bac 100644 --- a/src/components/Button/Button.stories.tsx +++ b/src/components/Button/Button.stories.tsx @@ -14,16 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; import { Button as ButtonComponent } from "./Button"; import * as icons from "@vector-im/compound-design-tokens/assets/web/icons"; -export default { +// The type of ButtonComponent is a little hard to work with, so we'll just redefined the props we need +type Props = React.ComponentProps & { + as: "a" | "button"; + href?: string; +}; + +const meta = { title: "Button", - component: ButtonComponent, + component: ButtonComponent as React.FC, tags: ["autodocs"], argTypes: { size: { @@ -52,15 +58,18 @@ export default { }, args: { size: "lg", - as: undefined, + as: "button", destructive: false, disabled: false, children: "Click me!", onClick: fn(), }, -} as Meta; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Default = { +export const Default: Story = { args: { // test component defaults kind: undefined, @@ -68,7 +77,7 @@ export const Default = { }, }; -export const Small = { +export const Small: Story = { args: { // test component defaults kind: undefined, @@ -76,53 +85,53 @@ export const Small = { }, }; -export const Primary = { +export const Primary: Story = { args: { kind: "primary", }, }; -export const PrimaryDestructive = { +export const PrimaryDestructive: Story = { args: { kind: "primary", destructive: true, }, }; -export const Secondary = { +export const Secondary: Story = { args: { kind: "secondary", }, }; -export const SecondaryDestructive = { +export const SecondaryDestructive: Story = { args: { kind: "secondary", destructive: true, }, }; -export const Tertiary = { +export const Tertiary: Story = { args: { kind: "tertiary", }, }; -export const TertiaryDestructive = { +export const TertiaryDestructive: Story = { args: { kind: "tertiary", destructive: true, }, }; -export const WithIcon = { +export const WithIcon: Story = { args: { ...Primary.args, Icon: icons.VisibilityOnIcon, }, }; -export const SmallWithIcon = { +export const SmallWithIcon: Story = { args: { ...Primary.args, size: "sm", @@ -130,14 +139,14 @@ export const SmallWithIcon = { }, }; -export const Disabled = { +export const Disabled: Story = { args: { ...Primary.args, disabled: true, }, }; -export const Link = { +export const Link: Story = { args: { ...Primary.args, as: "a", @@ -145,7 +154,7 @@ export const Link = { }, }; -export const LinkDisabled = { +export const LinkDisabled: Story = { args: { ...Link.args, disabled: true, diff --git a/src/components/Button/IconButton/IconButton.stories.tsx b/src/components/Button/IconButton/IconButton.stories.tsx index 94f9f52d..a3c63b3a 100644 --- a/src/components/Button/IconButton/IconButton.stories.tsx +++ b/src/components/Button/IconButton/IconButton.stories.tsx @@ -15,19 +15,19 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; import { IconButton as IconButtonComponent } from "./IconButton"; import UserIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; -export default { +const meta = { title: "Button/IconButton", component: IconButtonComponent, tags: ["autodocs"], argTypes: { - control: { type: "boolean" }, + disabled: { type: "boolean" }, onClick: { action: "onClick" }, }, args: { @@ -36,67 +36,76 @@ export default { children: , onClick: fn(), }, -} as Meta; +} satisfies Meta; +export default meta; -const Template: StoryFn = (args) => ( - <> - - - +type Story = StoryObj; - - - +export const Demo: Story = { + render: (args: React.ComponentProps) => ( + <> + + + - - - - -); + + + -export const Demo = Template.bind({}); + + + + + ), +}; + +export const Default: Story = { args: {} }; -export const Default = { args: {} }; -export const DefaultDisabled = { +export const DefaultDisabled: Story = { args: { disabled: true, }, }; -export const WithIndicator = { + +export const WithIndicator: Story = { args: { indicator: "default", }, }; -export const WithIndicatorDisabled = { + +export const WithIndicatorDisabled: Story = { args: { indicator: "default", disabled: true, }, }; -export const WithSuccessIndicator = { + +export const WithSuccessIndicator: Story = { args: { indicator: "success", }, }; -export const WithCriticalIndicator = { + +export const WithCriticalIndicator: Story = { args: { indicator: "critical", }, }; -export const WithSubtleBackground = { + +export const WithSubtleBackground: Story = { args: { subtleBackground: true, }, }; -export const WithLabel = { +export const WithLabel: Story = { args: { label: "label", }, }; -export const Destructive = { +export const Destructive: Story = { args: { - destructive: "true", + destructive: true, }, }; diff --git a/src/components/Button/IconButton/IconButton.tsx b/src/components/Button/IconButton/IconButton.tsx index 4c8f7840..49e71298 100644 --- a/src/components/Button/IconButton/IconButton.tsx +++ b/src/components/Button/IconButton/IconButton.tsx @@ -23,38 +23,38 @@ import { UnstyledButtonPropsFor } from "../UnstyledButton"; import { IndicatorIcon } from "../../Icon/IndicatorIcon/IndicatorIcon"; import { Tooltip } from "../../Tooltip/Tooltip"; -type IconButtonProps = UnstyledButtonPropsFor<"button"> & - JSX.IntrinsicElements["button"] & { - /** - * The CSS class name. - */ - className?: string; - /** - * The size of the button in CSS units, e.g. `"24px"`. - * Note that this is the size of the *button* itself: the icon will be 0.75 * this size - * @default 32px - */ - size?: CSSStyleDeclaration["height"]; - /** - * The icon button indicator dot displayed on the top right - * As in IndicatorIcon - */ - indicator?: "default" | "success" | "critical"; - /** - * Whether the button is interactable - */ - disabled?: boolean; - /** - * Whether this button triggers a destructive action. - * @default false - */ - destructive?: boolean; - /** - * Optional tooltip for the button - */ - tooltip?: string; - subtleBackground?: boolean; - }; +type IconButtonProps = UnstyledButtonPropsFor<"button"> & { + /** + * The CSS class name. + */ + className?: string; + /** + * The size of the button in CSS units, e.g. `"24px"`. + * Note that this is the size of the *button* itself: the icon will be 0.75 * this size + * @default 32px + */ + size?: CSSStyleDeclaration["height"]; + /** + * The icon button indicator dot displayed on the top right + * As in IndicatorIcon + */ + indicator?: "default" | "success" | "critical"; + /** + * Whether the button is interactable + */ + disabled?: boolean; + /** + * Whether this button triggers a destructive action. + * @default false + */ + destructive?: boolean; + /** + * Optional tooltip for the button + */ + tooltip?: string; + subtleBackground?: boolean; + label?: string; +}; /** * Display an icon as a button. Can render an indicator diff --git a/src/components/Dropdown/Dropdown.stories.tsx b/src/components/Dropdown/Dropdown.stories.tsx index 8b0ca71e..f6231b39 100644 --- a/src/components/Dropdown/Dropdown.stories.tsx +++ b/src/components/Dropdown/Dropdown.stories.tsx @@ -15,10 +15,10 @@ limitations under the License. */ import { Dropdown } from "./Dropdown"; import { fn } from "@storybook/test"; -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { ComponentProps } from "react"; -export default { +const meta = { title: "Dropdown", component: Dropdown, tags: ["autodocs"], @@ -52,8 +52,11 @@ export default { ], }, } satisfies Meta>; +export default meta; -export const Default = { +type Story = StoryObj; + +export const Default: Story = { parameters: { design: { type: "figma", @@ -61,7 +64,8 @@ export const Default = { }, }, }; -export const WithHelpLabel = { + +export const WithHelpLabel: Story = { args: { helpLabel: "Optional help text.", }, @@ -72,7 +76,8 @@ export const WithHelpLabel = { }, }, }; -export const WithError = { + +export const WithError: Story = { args: { error: "Select an option", }, @@ -83,7 +88,8 @@ export const WithError = { }, }, }; -export const WithDefaultValue = { + +export const WithDefaultValue: Story = { args: { defaultValue: "Option2", }, diff --git a/src/components/Form/Controls/Action/Action.stories.tsx b/src/components/Form/Controls/Action/Action.stories.tsx index f786e856..1ea51712 100644 --- a/src/components/Form/Controls/Action/Action.stories.tsx +++ b/src/components/Form/Controls/Action/Action.stories.tsx @@ -18,6 +18,7 @@ limitations under the License. import React from "react"; import { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; import * as icons from "@vector-im/compound-design-tokens/assets/web/icons"; @@ -26,7 +27,7 @@ import { TooltipProvider } from "../../../Tooltip/TooltipProvider"; type Props = { invalid?: boolean } & React.ComponentProps; -export default { +const meta = { title: "Form/Controls/Action", component: ActionInput, tags: ["autodocs"], @@ -91,11 +92,13 @@ export default { readOnly: false, invalid: false, actionLabel: "Action", + onActionClick: fn(), Icon: icons.CheckIcon, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Empty: Story = { parameters: { diff --git a/src/components/Form/Controls/Checkbox/Checkbox.stories.tsx b/src/components/Form/Controls/Checkbox/Checkbox.stories.tsx index 59722c79..b3ce8383 100644 --- a/src/components/Form/Controls/Checkbox/Checkbox.stories.tsx +++ b/src/components/Form/Controls/Checkbox/Checkbox.stories.tsx @@ -24,7 +24,7 @@ type Props = React.ComponentProps & { invalid?: boolean; }; -export default { +const meta = { title: "Form/Controls/Checkbox", component: CheckboxInput, render: ({ invalid, ...props }) => ( @@ -53,8 +53,9 @@ export default { invalid: false, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Unchecked: Story = { parameters: { diff --git a/src/components/Form/Controls/EditInPlace/EditInPlace.stories.tsx b/src/components/Form/Controls/EditInPlace/EditInPlace.stories.tsx index 4c9a9c6f..973eb063 100644 --- a/src/components/Form/Controls/EditInPlace/EditInPlace.stories.tsx +++ b/src/components/Form/Controls/EditInPlace/EditInPlace.stories.tsx @@ -24,7 +24,7 @@ import { TooltipProvider } from "../../../Tooltip/TooltipProvider"; type Props = { invalid?: boolean } & React.ComponentProps; -export default { +const meta = { title: "Form/Controls/EditInPlace", component: EditInPlace, tags: ["autodocs"], @@ -102,8 +102,9 @@ export default { savingLabel: "Saving…", }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Empty: Story = {}; diff --git a/src/components/Form/Controls/MFA/MFA.stories.tsx b/src/components/Form/Controls/MFA/MFA.stories.tsx index e0a7011c..379ce7a7 100644 --- a/src/components/Form/Controls/MFA/MFA.stories.tsx +++ b/src/components/Form/Controls/MFA/MFA.stories.tsx @@ -25,7 +25,7 @@ type Props = React.ComponentProps & { invalid?: boolean; }; -export default { +const meta = { title: "Form/Controls/MFA", component: MFAInput, render: ({ invalid, ...props }) => ( @@ -59,8 +59,9 @@ export default { invalid: false, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Empty: Story = { parameters: { diff --git a/src/components/Form/Controls/Password/Password.stories.tsx b/src/components/Form/Controls/Password/Password.stories.tsx index f772297e..ce7d3216 100644 --- a/src/components/Form/Controls/Password/Password.stories.tsx +++ b/src/components/Form/Controls/Password/Password.stories.tsx @@ -26,7 +26,7 @@ import { userEvent } from "@storybook/test"; type Props = { invalid?: boolean } & React.ComponentProps; -export default { +const meta = { title: "Form/Controls/Password", component: PasswordInput, tags: ["autodocs"], @@ -75,8 +75,9 @@ export default { invalid: false, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Empty: Story = { parameters: { diff --git a/src/components/Form/Controls/Radio/Radio.stories.tsx b/src/components/Form/Controls/Radio/Radio.stories.tsx index 50de2156..6f5b1b8f 100644 --- a/src/components/Form/Controls/Radio/Radio.stories.tsx +++ b/src/components/Form/Controls/Radio/Radio.stories.tsx @@ -24,7 +24,7 @@ type Props = React.ComponentProps & { invalid?: boolean; }; -export default { +const meta = { title: "Form/Controls/Radio", component: RadioInput, render: ({ invalid, ...props }) => ( @@ -53,8 +53,9 @@ export default { invalid: false, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Unchecked: Story = { parameters: { diff --git a/src/components/Form/Controls/Text/Text.stories.tsx b/src/components/Form/Controls/Text/Text.stories.tsx index 06b9e2f4..4036004b 100644 --- a/src/components/Form/Controls/Text/Text.stories.tsx +++ b/src/components/Form/Controls/Text/Text.stories.tsx @@ -23,7 +23,7 @@ import { TextInput } from "./"; type Props = { invalid?: boolean } & React.ComponentProps; -export default { +const meta = { title: "Form/Controls/Text", component: TextInput, tags: ["autodocs"], @@ -75,8 +75,9 @@ export default { enableLigatures: undefined, }, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Empty: Story = { parameters: { diff --git a/src/components/Form/Controls/Toggle/Toggle.stories.tsx b/src/components/Form/Controls/Toggle/Toggle.stories.tsx index 00091f26..52f89ac0 100644 --- a/src/components/Form/Controls/Toggle/Toggle.stories.tsx +++ b/src/components/Form/Controls/Toggle/Toggle.stories.tsx @@ -19,15 +19,16 @@ import { Meta, StoryObj } from "@storybook/react"; import { ToggleInput } from "./Toggle"; -export default { +const meta = { title: "Form/Controls/Toggle", component: ToggleInput, tags: ["autodocs"], argTypes: {}, args: {}, } satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Unchecked: Story = { args: { diff --git a/src/components/Form/Form.stories.tsx b/src/components/Form/Form.stories.tsx index f4972304..d9f895df 100644 --- a/src/components/Form/Form.stories.tsx +++ b/src/components/Form/Form.stories.tsx @@ -153,7 +153,7 @@ const KitchenSink = ({ disabled, invalid, readOnly }: Props) => ( ); -export default { +const meta = { title: "Form/Kitchen Sink", component: KitchenSink, argTypes: { @@ -172,9 +172,10 @@ export default { readOnly: false, invalid: false, }, -} as Meta; +} satisfies Meta; +export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Normal: Story = {}; export const Disabled: Story = { args: { disabled: true } }; diff --git a/src/components/Form/PasswordForm.stories.tsx b/src/components/Form/PasswordForm.stories.tsx index 98d43ddd..f21ab130 100644 --- a/src/components/Form/PasswordForm.stories.tsx +++ b/src/components/Form/PasswordForm.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta } from "@storybook/react"; import WarningIcon from "@vector-im/compound-design-tokens/assets/web/icons/warning"; import { @@ -29,13 +29,12 @@ import { import { Progress } from "../Progress/Progress"; import { TooltipProvider } from "../Tooltip/TooltipProvider"; -export default { +const meta = { title: "Form/Password form", component: Root, tags: ["autodocs"], - subcomponents: { Progress, PasswordControl, Label, Field }, decorators: [ - (Story: StoryFn) => ( + (Story) => (
@@ -43,7 +42,8 @@ export default { ), ], -} as Meta; +} satisfies Meta; +export default meta; const getValueLabel = (value: number) => { switch (value) { @@ -60,7 +60,7 @@ const getValueLabel = (value: number) => { } }; -export const Empty: React.FC = () => { +export const Empty = () => { return ( diff --git a/src/components/Glass/Glass.stories.tsx b/src/components/Glass/Glass.stories.tsx index 58cede00..9e6eed4f 100644 --- a/src/components/Glass/Glass.stories.tsx +++ b/src/components/Glass/Glass.stories.tsx @@ -15,37 +15,23 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Glass as GlassComponent } from "./Glass"; import { Text } from "../Typography/Text"; -export default { +const meta = { title: "Glass", component: GlassComponent, tags: ["autodocs"], argTypes: {}, - args: {}, -} as Meta; + args: { + style: { + inlineSize: 250, + blockSize: 150, + }, -const Template: StoryFn = (args) => ( - // Use an image as the background to really show off the glass effect -
- + children: (
= (args) => ( > Your content here
-
-
-); + ), + }, -export const Glass = Template.bind({}); -Glass.args = {}; + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Glass: Story = { args: {} }; diff --git a/src/components/Icon/Icon.stories.tsx b/src/components/Icon/Icon.stories.tsx index a965ae47..4194d540 100644 --- a/src/components/Icon/Icon.stories.tsx +++ b/src/components/Icon/Icon.stories.tsx @@ -14,18 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import ThreadIcon from "@vector-im/compound-design-tokens/assets/web/icons/threads"; -export default { +const meta = { title: "Icon", component: ThreadIcon, argTypes: {}, -} as Meta; +} satisfies Meta; +export default meta; -const Template: StoryFn = () => ; +type Story = StoryObj; -export const Icon = Template.bind({}); -Icon.args = {}; +export const Icon: Story = { args: {} }; diff --git a/src/components/Icon/IndicatorIcon/IndicatorIcon.stories.tsx b/src/components/Icon/IndicatorIcon/IndicatorIcon.stories.tsx index bab0050d..28f38f62 100644 --- a/src/components/Icon/IndicatorIcon/IndicatorIcon.stories.tsx +++ b/src/components/Icon/IndicatorIcon/IndicatorIcon.stories.tsx @@ -15,71 +15,70 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; -import { fn } from "@storybook/test"; +import { Meta, StoryObj } from "@storybook/react"; import { IndicatorIcon as IndicatorIconComponent } from "./IndicatorIcon"; import ThreadIcon from "@vector-im/compound-design-tokens/assets/web/icons/threads"; -export default { +const meta = { title: "Icon/IndicatorIcon", component: IndicatorIconComponent, tags: ["autodocs"], - argTypes: { - control: { type: "boolean" }, - onClick: { action: "onClick" }, - }, args: { size: "32px", - disabled: false, children: , - onClick: fn(), }, -} as Meta; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -const Template: StoryFn = (args) => ( - <> - - - +export const Demo: Story = { + render: (args) => ( + <> + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - -); + + + + + ), +}; -export const Demo = Template.bind({}); +export const Default: Story = { args: {} }; -export const Default = { args: {} }; -export const WithIndicator = { +export const WithIndicator: Story = { args: { indicator: "default", }, }; -export const WithSuccessIndicator = { + +export const WithSuccessIndicator: Story = { args: { indicator: "success", }, }; -export const WithCriticalIndicator = { + +export const WithCriticalIndicator: Story = { args: { indicator: "critical", }, diff --git a/src/components/InlineSpinner/InlineSpinner.stories.tsx b/src/components/InlineSpinner/InlineSpinner.stories.tsx index a98849c3..bbe2b497 100644 --- a/src/components/InlineSpinner/InlineSpinner.stories.tsx +++ b/src/components/InlineSpinner/InlineSpinner.stories.tsx @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { InlineSpinner as InlineSpinnerComponent } from "./InlineSpinner"; -export default { +const meta = { title: "InlineSpinner", component: InlineSpinnerComponent, tags: ["autodocs"], @@ -28,9 +28,12 @@ export default { }, }, args: {}, -} as Meta; +} satisfies Meta; +export default meta; -export const Default = { +type Story = StoryObj; + +export const Default: Story = { args: {}, parameters: {}, }; diff --git a/src/components/Link/Link.stories.tsx b/src/components/Link/Link.stories.tsx index c32c62d0..b0619119 100644 --- a/src/components/Link/Link.stories.tsx +++ b/src/components/Link/Link.stories.tsx @@ -14,29 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Link as LinkComponent } from "./Link"; -export default { +const meta = { title: "Link", component: LinkComponent, tags: ["autodocs"], argTypes: {}, args: { size: "medium", + children: "Text link", }, -} as Meta; +} satisfies Meta; +export default meta; -const Template: StoryFn = (args) => ( - Text link -); +type Story = StoryObj; -export const Round = Template.bind({}); -Round.args = {}; +export const Round: Story = { args: {} }; -export const Small = Template.bind({}); -Small.args = { - size: "small", -}; +export const Small: Story = { args: { size: "small" } }; diff --git a/src/components/Menu/ContextMenu.stories.tsx b/src/components/Menu/ContextMenu.stories.tsx index a9bf308f..2cee9a36 100644 --- a/src/components/Menu/ContextMenu.stories.tsx +++ b/src/components/Menu/ContextMenu.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import UserProfileIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; import NotificationsIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications"; import ChatProblemIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat-problem"; @@ -25,15 +25,12 @@ import { ContextMenu as ContextMenuComponent } from "./ContextMenu"; import { MenuItem } from "./MenuItem"; import { Separator } from "../Separator/Separator"; -export default { - title: "Menu/ContextMenu", - component: ContextMenuComponent, - tags: ["autodocs"], - argTypes: {}, - args: {}, -} as Meta; +type Props = Omit< + React.ComponentProps, + "trigger" | "title" | "hasAccessibleAlternative" | "children" +>; -const Template: StoryFn = (args) => { +const Template: React.FC = (args) => { return ( = (args) => { ); }; -export const ContextMenu = Template.bind({}); -ContextMenu.args = {}; +const meta = { + title: "Menu/ContextMenu", + component: Template, + tags: ["autodocs"], + argTypes: {}, + args: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const ContextMenu: Story = { args: {} }; diff --git a/src/components/Menu/DrawerMenu.stories.tsx b/src/components/Menu/DrawerMenu.stories.tsx index 045f1913..ee7872d2 100644 --- a/src/components/Menu/DrawerMenu.stories.tsx +++ b/src/components/Menu/DrawerMenu.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import UserProfileIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; import NotificationsIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications"; import ChatProblemIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat-problem"; @@ -26,14 +26,12 @@ import drawerStyles from "./DrawerMenu.module.css"; import { MenuItem } from "./MenuItem"; import { Separator } from "../Separator/Separator"; -export default { - title: "Menu/DrawerMenu", - component: DrawerMenuComponent, - argTypes: {}, - args: {}, -} as Meta; +type Props = Omit< + React.ComponentProps, + "title" | "children" +>; -const Template: StoryFn = (args) => ( +const Template: React.FC = (args) => ( <>
@@ -55,5 +53,14 @@ const Template: StoryFn = (args) => ( ); -export const DrawerMenu = Template.bind({}); -DrawerMenu.args = {}; +const meta = { + title: "Menu/DrawerMenu", + component: Template, + argTypes: {}, + args: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const DrawerMenu: Story = { args: {} }; diff --git a/src/components/Menu/FloatingMenu.stories.tsx b/src/components/Menu/FloatingMenu.stories.tsx index 3ca674b9..71d31192 100644 --- a/src/components/Menu/FloatingMenu.stories.tsx +++ b/src/components/Menu/FloatingMenu.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import UserProfileIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; import NotificationsIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications"; import ChatProblemIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat-problem"; @@ -25,14 +25,12 @@ import { FloatingMenu as FloatingMenuComponent } from "./FloatingMenu"; import { MenuItem } from "./MenuItem"; import { Separator } from "../Separator/Separator"; -export default { - title: "Menu/FloatingMenu", - component: FloatingMenuComponent, - argTypes: {}, - args: {}, -} as Meta; +type Props = Omit< + React.ComponentProps, + "title" | "children" +>; -const Template: StoryFn = (args) => ( +const Template: React.FC = (args) => ( {}} /> {/* Extra long label to demonstrate word breaking */} @@ -52,5 +50,14 @@ const Template: StoryFn = (args) => ( ); -export const FloatingMenu = Template.bind({}); -FloatingMenu.args = {}; +const meta = { + title: "Menu/FloatingMenu", + component: Template, + argTypes: {}, + args: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const FloatingMenu: Story = { args: {} }; diff --git a/src/components/Menu/Menu.stories.tsx b/src/components/Menu/Menu.stories.tsx index 5db67ebc..15f53ae2 100644 --- a/src/components/Menu/Menu.stories.tsx +++ b/src/components/Menu/Menu.stories.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React, { useState } from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import UserProfileIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; import NotificationsIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications"; import ChatProblemIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat-problem"; @@ -26,15 +26,12 @@ import { MenuItem } from "./MenuItem"; import { Separator } from "../Separator/Separator"; import { Button } from "../Button/Button"; -export default { - title: "Menu", - component: MenuComponent, - tags: ["autodocs"], - argTypes: {}, - args: {}, -} as Meta; +type Props = Omit< + React.ComponentProps, + "open" | "onOpenChange" | "trigger" | "align" | "children" +>; -const Template: StoryFn = (args) => { +const Template: React.FC = (args) => { const [open, setOpen] = useState(true); return ( @@ -63,13 +60,19 @@ const Template: StoryFn = (args) => { ); }; -export const Menu = Template.bind({}); -Menu.args = { - title: "Today's Menu", -}; +const meta = { + title: "Menu", + component: Template, + tags: ["autodocs"], + argTypes: {}, + args: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Menu: Story = { args: { title: "Today's Menu" } }; -export const WithoutTitle = Template.bind({}); -WithoutTitle.args = { - title: "Untitled Menu", - showTitle: false, +export const WithoutTitle = { + args: { title: "Untitled Menu", showTitle: false }, }; diff --git a/src/components/Menu/MenuItem.stories.tsx b/src/components/Menu/MenuItem.stories.tsx index e9fc915f..64ed4427 100644 --- a/src/components/Menu/MenuItem.stories.tsx +++ b/src/components/Menu/MenuItem.stories.tsx @@ -15,7 +15,8 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; import ExtensionsIcon from "@vector-im/compound-design-tokens/assets/web/icons/extensions"; import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat"; import SettingsLabel from "@vector-im/compound-design-tokens/assets/web/icons/settings"; @@ -23,13 +24,10 @@ import SettingsLabel from "@vector-im/compound-design-tokens/assets/web/icons/se import { MenuItem as MenuItemComponent } from "./MenuItem"; import { Text } from "../Typography/Text"; -export default { +const meta = { title: "Menu/MenuItem", component: MenuItemComponent, tags: ["autodocs"], - argTypes: { - onClick: { action: "clicked!" }, - }, args: { label: "Menu item", children: ( @@ -38,17 +36,21 @@ export default { ), Icon: ChatIcon, + onSelect: fn(), }, decorators: [ - (Story: StoryFn) => ( + (Story) => (
), ], -} as Meta; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Example = { +export const Example: Story = { render: () => (
{}}> @@ -70,56 +72,52 @@ export const Example = { ), }; -export const Primary = { +export const Primary: Story = { args: { kind: "primary", }, }; -export const Critical = { +export const Critical: Story = { args: { kind: "critical", }, }; -export const PrimaryDisabled = { +export const PrimaryDisabled: Story = { args: { ...Primary.args, disabled: true, }, }; -export const CriticalDisabled = { +export const CriticalDisabled: Story = { args: { ...Critical.args, disabled: true, }, }; -function SimpleComponent(props: object) { - return ( -
- ); -} +const SimpleComponent: React.FC> = (props) => ( +
+); -export const IconIsComponent = { +export const IconIsComponent: Story = { args: { ...Primary.args, + // @ts-expect-error: For some reason, this isn't liking the type here Icon: , }, }; -export const WithoutLabel = { +export const WithoutLabel: Story = { args: { ...Primary.args, label: undefined, }, }; -export const WithALongLabel = { +export const WithALongLabel: Story = { args: { ...Primary.args, label: @@ -127,7 +125,7 @@ export const WithALongLabel = { }, }; -export const WithALongLabelAndChildren = { +export const WithALongLabelAndChildren: Story = { args: { ...Primary.args, label: diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 969e8875..132075e0 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -20,7 +20,7 @@ import React, { ComponentType, ElementType, isValidElement, - ReactNode, + ReactElement, SVGAttributes, useCallback, useContext, @@ -45,9 +45,9 @@ type Props = { className?: string; /** * The icon to show on this menu item. - * When `Icon` is a ReactNode, it should spread the props + * When `Icon` is a ReactElement, it should spread the props */ - Icon: ComponentType> | ReactNode; + Icon: ComponentType> | ReactElement; /** * The label to show on this menu item. */ @@ -111,7 +111,7 @@ export const MenuItem = ({ ); const iconIsReactElement = isValidElement(Icon); - const componentIcon = Icon as ReactNode; + const componentIcon = Icon as ReactElement; const SvgIcon = Icon as ComponentType>; const content = ( diff --git a/src/components/Menu/ToggleMenuItem.stories.tsx b/src/components/Menu/ToggleMenuItem.stories.tsx index c9425607..c6022a35 100644 --- a/src/components/Menu/ToggleMenuItem.stories.tsx +++ b/src/components/Menu/ToggleMenuItem.stories.tsx @@ -15,27 +15,23 @@ limitations under the License. */ import React, { useState } from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import ExtensionsIcon from "@vector-im/compound-design-tokens/assets/web/icons/extensions"; import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat"; import { ToggleMenuItem as ToggleMenuItemComponent } from "./ToggleMenuItem"; -export default { - title: "Menu/ToggleMenuItem", - component: ToggleMenuItemComponent, - tags: ["autodocs"], - argTypes: {}, - args: {}, -} as Meta; +type Props = Omit< + React.ComponentProps, + "Icon" | "label" | "checked" | "onSelect" +>; -const Template: StoryFn = (args) => { +const Template: React.FC = (props: Props) => { const [firstChecked, setFirstChecked] = useState(false); - return (
= (args) => { }} /> {}} />
); }; -export const Primary = Template.bind({}); -Primary.args = {}; +const meta = { + title: "Menu/ToggleMenuItem", + component: Template, + tags: ["autodocs"], + argTypes: {}, + args: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Primary: Story = { args: {} }; diff --git a/src/components/Nav/NavBar.stories.tsx b/src/components/Nav/NavBar.stories.tsx index 94fedd04..f3a3b0c8 100644 --- a/src/components/Nav/NavBar.stories.tsx +++ b/src/components/Nav/NavBar.stories.tsx @@ -13,9 +13,10 @@ // limitations under the License. import React, { useEffect, useState } from "react"; +import { Meta, StoryObj } from "@storybook/react"; import { NavBar, NavItem } from "."; -export default { +const meta = { title: "Nav", component: NavBar, tags: ["autodocs"], @@ -31,9 +32,12 @@ export default { args: { "aria-label": "Main", }, -}; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Default = { +export const Default: Story = { args: { children: ( <> @@ -50,7 +54,7 @@ export const Default = { }, }; -export const TabRole = { +export const TabRole: Story = { render: function Component() { // An example tab implementation const [activePanelId, setActivePanelId] = useState("panel-2"); diff --git a/src/components/Nav/NavItem.stories.tsx b/src/components/Nav/NavItem.stories.tsx index 829e8799..af889b0e 100644 --- a/src/components/Nav/NavItem.stories.tsx +++ b/src/components/Nav/NavItem.stories.tsx @@ -16,22 +16,22 @@ limitations under the License. */ import React from "react"; +import { StoryObj, Meta } from "@storybook/react"; +import { fn } from "@storybook/test"; import { NavItem } from "./NavItem"; import { NavBar } from "."; -import { StoryFn } from "@storybook/react"; -export default { +const meta = { title: "Nav/Nav Item", component: NavItem, tags: ["autodocs"], - argTypes: { - onClick: { - action: "clicked", - }, + args: { + onClick: fn(), + href: undefined, }, decorators: [ - (Story: StoryFn) => ( + (Story) => ( @@ -43,43 +43,46 @@ export default { url: "https://www.figma.com/file/rTaQE2nIUSLav4Tg3nozq7/Compound-Web-Components?type=design&node-id=669-2723&mode=design&t=9Hy0h7BBDH0kJ2Ow-0", }, }, -}; +} satisfies Meta; +export default meta; + +type Story = StoryObj; -export const Default = { +export const Default: Story = { args: { children: "Sessions", }, }; -export const Disabled = { +export const Disabled: Story = { args: { children: "Sessions", disabled: true, }, }; -export const Link = { +export const Link: Story = { args: { children: "Sessions", href: "https://example.org", }, }; -export const Active = { +export const Active: Story = { args: { children: "Sessions", active: true, }, }; -export const ActiveLink = { +export const ActiveLink: Story = { args: { ...Link.args, active: true, }, }; -export const ActiveDisabled = { +export const ActiveDisabled: Story = { args: { children: "Sessions", active: true, diff --git a/src/components/Nav/NavItem.tsx b/src/components/Nav/NavItem.tsx index e222104c..453cfb43 100644 --- a/src/components/Nav/NavItem.tsx +++ b/src/components/Nav/NavItem.tsx @@ -22,7 +22,6 @@ import React, { MouseEventHandler, forwardRef, } from "react"; -import type { XOR } from "ts-xor"; import styles from "./Nav.module.css"; @@ -90,15 +89,16 @@ const NavItemButton = forwardRef(function NavItemButton( }); const renderAsLink = ( - props: React.PropsWithChildren>, -): props is React.PropsWithChildren => !!props.href; + props: React.PropsWithChildren, +): props is React.PropsWithChildren => + "href" in props && !!props.href; /** * A navigation item component to be used with a navigation bar. * Will render an anchor when href is provided, otherwise a button element. */ export const NavItem = forwardRef(function NavItem( - props: React.PropsWithChildren>, + props: React.PropsWithChildren, ref: | ForwardedRef | ForwardedRef, diff --git a/src/components/Progress/Progress.stories.tsx b/src/components/Progress/Progress.stories.tsx index 2654f983..e9d3bc24 100644 --- a/src/components/Progress/Progress.stories.tsx +++ b/src/components/Progress/Progress.stories.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Progress as ProgressComponent } from "./Progress"; @@ -32,7 +32,7 @@ function getValueLabel(value: number) { } } -export default { +const meta = { title: "Progress", component: ProgressComponent, tags: ["autodocs"], @@ -50,9 +50,12 @@ export default { max: 100, value: 50, }, -} as Meta; +} satisfies Meta; +export default meta; -export const LargeHalf = { +type Story = StoryObj; + +export const LargeHalf: Story = { args: { tint: "green", size: "lg", @@ -60,7 +63,7 @@ export const LargeHalf = { }, }; -export const SmallHalf = { +export const SmallHalf: Story = { args: { tint: "green", size: "sm", @@ -68,7 +71,7 @@ export const SmallHalf = { }, }; -export const LargeFull = { +export const LargeFull: Story = { args: { tint: "green", size: "lg", @@ -76,7 +79,7 @@ export const LargeFull = { }, }; -export const SmallFull = { +export const SmallFull: Story = { args: { tint: "green", size: "sm", @@ -84,7 +87,7 @@ export const SmallFull = { }, }; -export const Empty = { +export const Empty: Story = { args: { value: 0, }, diff --git a/src/components/ReleaseAnnouncement/ReleaseAnnouncement.stories.tsx b/src/components/ReleaseAnnouncement/ReleaseAnnouncement.stories.tsx index d46caed1..020c5caa 100644 --- a/src/components/ReleaseAnnouncement/ReleaseAnnouncement.stories.tsx +++ b/src/components/ReleaseAnnouncement/ReleaseAnnouncement.stories.tsx @@ -14,14 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta, StoryFn } from "@storybook/react"; import React, { useState } from "react"; +import { Meta, StoryObj } from "@storybook/react"; import { Button } from "../Button"; import { ReleaseAnnouncement as ReleaseAnnouncementComponent } from "./ReleaseAnnouncement"; -export default { +type Props = Omit< + React.ComponentProps, + "open" | "children" | "onClick" +>; + +const Template: React.FC = (args) => { + const [open, setOpen] = useState(false); + return ( + <> + + setOpen(false)} + /> + + ); +}; + +const meta = { title: "Release Announcement", - component: ReleaseAnnouncementComponent, + component: Template, tags: ["autodocs"], argTypes: {}, args: { @@ -30,38 +49,29 @@ export default { placement: "right", closeLabel: "Ok", }, -} as Meta; +} satisfies Meta; +export default meta; -const Template: StoryFn = (args) => { - const [open, setOpen] = useState(true); +type Story = StoryObj; - return ( - setOpen(false)} - > - - - ); -}; +export const Default: Story = { args: {} }; -export const Default = Template.bind({}); -Default.args = {}; - -export const MultiLinesContent = Template.bind({}); -MultiLinesContent.args = { - header: "A multi line header which is taking multiple lines", - description: - "A multi line description which is taking multiple lines. The OK button should be vertically centred.", +export const MultiLinesContent: Story = { + args: { + header: "A multi line header which is taking multiple lines", + description: + "A multi line description which is taking multiple lines. The OK button should be vertically centred.", + }, }; -export const BottomPlacement = Template.bind({}); -BottomPlacement.args = { - placement: "bottom", +export const BottomPlacement: Story = { + args: { + placement: "bottom", + }, }; -export const NoArrow = Template.bind({}); -NoArrow.args = { - displayArrow: false, +export const NoArrow: Story = { + args: { + displayArrow: false, + }, }; diff --git a/src/components/Search/Search.stories.tsx b/src/components/Search/Search.stories.tsx index 5bd1cb7d..d39672a3 100644 --- a/src/components/Search/Search.stories.tsx +++ b/src/components/Search/Search.stories.tsx @@ -15,24 +15,29 @@ limitations under the License. */ import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; +import { Form } from "@radix-ui/react-form"; import { Search as SearchComponent } from "./Search"; -import { Form } from "@radix-ui/react-form"; -export default { +const meta = { title: "Search", component: SearchComponent, tags: ["autodocs"], argTypes: {}, - args: {}, -} as Meta; - -const Template: StoryFn = (args) => ( -
- - -); - -export const Search = Template.bind({}); -Search.args = {}; + args: { + name: "search", + }, + decorators: [ + (Story) => ( +
+ + + ), + ], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Search: Story = { args: {} }; diff --git a/src/components/Separator/Separator.stories.tsx b/src/components/Separator/Separator.stories.tsx index 28e99c2b..5353b7d6 100644 --- a/src/components/Separator/Separator.stories.tsx +++ b/src/components/Separator/Separator.stories.tsx @@ -14,20 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Separator as SeparatorComponent } from "./Separator"; -export default { +const meta = { title: "Separator", component: SeparatorComponent, tags: ["autodocs"], argTypes: {}, args: {}, -} as Meta; +} satisfies Meta; +export default meta; -export const Primary = { args: { kind: "primary" } }; +type Story = StoryObj; -export const Secondary = { args: { kind: "secondary" } }; +export const Primary: Story = { args: { kind: "primary" } }; -export const Section = { args: { kind: "section" } }; +export const Secondary: Story = { args: { kind: "secondary" } }; + +export const Section: Story = { args: { kind: "section" } }; diff --git a/src/components/Toast/Toast.stories.tsx b/src/components/Toast/Toast.stories.tsx index 2754829e..21408a22 100644 --- a/src/components/Toast/Toast.stories.tsx +++ b/src/components/Toast/Toast.stories.tsx @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Toast as ToastComponent } from "./Toast"; -export default { +const meta = { title: "Toast", component: ToastComponent, tags: ["autodocs"], @@ -26,13 +26,18 @@ export default { args: { children: "Would you like some toast?", }, - design: { - type: "figma", - url: "https://www.figma.com/design/rTaQE2nIUSLav4Tg3nozq7/Compound-Web-Components?node-id=3627-42633&t=m0RMwUTXkukgU29g-0", + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/design/rTaQE2nIUSLav4Tg3nozq7/Compound-Web-Components?node-id=3627-42633&t=m0RMwUTXkukgU29g-0", + }, }, -} as Meta; +} satisfies Meta; +export default meta; -export const Default = { +type Story = StoryObj; + +export const Default: Story = { args: {}, parameters: {}, }; diff --git a/src/components/Tooltip/Tooltip.stories.tsx b/src/components/Tooltip/Tooltip.stories.tsx index a90bff88..f086c6b6 100644 --- a/src/components/Tooltip/Tooltip.stories.tsx +++ b/src/components/Tooltip/Tooltip.stories.tsx @@ -18,16 +18,24 @@ import { Placement as PlacementType } from "@floating-ui/react"; import { Tooltip as TooltipComponent } from "./Tooltip"; import { IconButton } from "../Button"; import UserIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryFn, StoryObj } from "@storybook/react"; import React, { FC, ReactNode } from "react"; import { TooltipProvider } from "./TooltipProvider"; -export default { +const meta = { title: "Tooltip", component: TooltipComponent, tags: ["autodocs"], - controls: { - include: ["placement", "open", "label", "caption", "isTriggerInteractive"], + parameters: { + controls: { + include: [ + "placement", + "open", + "label", + "caption", + "isTriggerInteractive", + ], + }, }, argTypes: { placement: { @@ -68,7 +76,10 @@ export default {
), ], -} as Meta; +} satisfies Meta; +export default meta; + +type Story = StoryObj; interface LayoutProps { children: ReactNode; @@ -87,7 +98,7 @@ const Layout: FC = ({ children }) => (
); -const TemplatePlacement: StoryFn = () => ( +const TemplatePlacement: StoryFn = () => ( {( [ @@ -118,20 +129,20 @@ const TemplatePlacement: StoryFn = () => ( export const Placement = TemplatePlacement.bind({}); Placement.args = {}; -export const Default = { +export const Default: Story = { args: { label: "@bob:example.org", }, }; -export const WithStringCaption = { +export const WithStringCaption: Story = { args: { label: "I can have a caption", caption: "My beautiful caption", }, }; -export const WithComponentCaption = { +export const WithComponentCaption: Story = { args: { label: "Copy", caption: ( @@ -142,14 +153,14 @@ export const WithComponentCaption = { }, }; -export const ForcedOpen = { +export const ForcedOpen: Story = { args: { open: true, label: "I'm always open", }, }; -export const ForcedClose = { +export const ForcedClose: Story = { args: { open: false, description: "You can't see me", @@ -157,7 +168,7 @@ export const ForcedClose = { }, }; -export const ForcedDisabled = { +export const ForcedDisabled: Story = { args: { disabled: true, description: "You can't see me", @@ -165,7 +176,7 @@ export const ForcedDisabled = { }, }; -export const InteractiveTrigger = { +export const InteractiveTrigger: Story = { args: { isTriggerInteractive: true, description: "Shown with delay", @@ -173,7 +184,7 @@ export const InteractiveTrigger = { }, }; -export const NonInteractiveTrigger = { +export const NonInteractiveTrigger: Story = { args: { isTriggerInteractive: false, description: "Shown without delay", @@ -181,7 +192,7 @@ export const NonInteractiveTrigger = { }, }; -export const Descriptive = { +export const Descriptive: Story = { args: { open: true, description: "Employer Identification Number", diff --git a/src/components/Typography/Heading.stories.tsx b/src/components/Typography/Heading.stories.tsx index 4f8dbf68..80945527 100644 --- a/src/components/Typography/Heading.stories.tsx +++ b/src/components/Typography/Heading.stories.tsx @@ -15,12 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from "react"; -import { Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Heading as HeadingComponent } from "./Heading"; -export default { +const meta = { title: "Typography", component: HeadingComponent, argTypes: { @@ -33,16 +32,15 @@ export default { control: { type: "inline-radio" }, }, }, -} as Meta; - -const Template: StoryFn = (args) => ( - - The quick brown fox jumps over the lazy dog - -); - -export const Heading = Template.bind({}); -Heading.args = { - size: "md", - weight: "regular", +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Heading: Story = { + args: { + children: "The quick brown fox jumps over the lazy dog", + size: "md", + weight: "regular", + }, }; diff --git a/src/components/Typography/Text.stories.tsx b/src/components/Typography/Text.stories.tsx index 2e37d3cb..8707aee2 100644 --- a/src/components/Typography/Text.stories.tsx +++ b/src/components/Typography/Text.stories.tsx @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { Text as TextComponent } from "./Text"; -export default { +const meta = { title: "Typography", component: TextComponent, argTypes: { @@ -39,10 +39,13 @@ export default { size: "md", weight: "regular", }, -} as Meta; +} satisfies Meta; +export default meta; -export const Text = {}; -export const Ligatures = { +type Story = StoryObj; + +export const Text: Story = {}; +export const Ligatures: Story = { args: { children: "-> 1x2x3", }, diff --git a/src/utils/__ComponentTemplate__/__ComponentTemplate__.stories.tsx b/src/utils/__ComponentTemplate__/__ComponentTemplate__.stories.tsx index 94f86b0d..82163c8f 100644 --- a/src/utils/__ComponentTemplate__/__ComponentTemplate__.stories.tsx +++ b/src/utils/__ComponentTemplate__/__ComponentTemplate__.stories.tsx @@ -14,19 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Meta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { __ComponentTemplate__ as __ComponentTemplate__Component } from "./__ComponentTemplate__"; -export default { +const meta = { title: "__ComponentTemplate__", component: __ComponentTemplate__Component, tags: ["autodocs"], argTypes: {}, args: {}, -} as Meta; +} satisfies Meta; +export default meta; -export const Default = { +type Story = StoryObj; + +export const Default: Story = { args: {}, parameters: {}, };