typescriptstorybookreact-tsx

How to write decorator in typescript for storybook?


I am new to storybook as well as typescript, I am stuck, when creating a decorator which takes two parameters Story and context.

const CustomDecorator = (Story, context) => {
  console.log("My Decorator");
  return (
      <Story />
  );
};

const preview: Preview = {
  decorators: [CustomDecorator],
  parameters: {
    actions: { argTypesRegex: "^on[A-Z].*" },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },

  globalTypes: {
    theme: {
      description: 'Global theme for components',
      defaultValue: 'light',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'circlehollow',
        // Array of plain string values or MenuItem shape (see below)
        items: ['light', 'dark'],
        // Change title based on selected value
        dynamicTitle: true,
      },
    },
  },
};

It shows me the following error:

Failed to compile.
Syntax error: Unexpected token, expected "," (8:13)
storybook/preview.ts undefined

   6 |   console.log("My Decorator");
   7 |   return (
>  8 |       <Story />
     |              ^
   9 |   );
  10 | };
  11 |

And when hovering on <Story /> in vscode, it says 'Story' refers to a value, but is being used as a type here. Did you mean 'typeof Story'?

NOTE: I am writing a global decorator.

I have tried to search on the internet, but I have not found much clue to get resolved.


Solution

  • You can try this way: First, rename your .storybook/preview.ts file to .storybook/preview.tsx. Then, if you see the error 'React' refers to a UMD global, import React from "react" will solve the problem.

    My current preview.tsx file:

    import React from "react";
    import type { Preview } from "@storybook/react";
    import { ThemeProvider } from "styled-components";
    import theme from "../src/theme";
    
    const preview: Preview = {
      parameters: {
        actions: { argTypesRegex: "^on[A-Z].*" },
        controls: {
          matchers: {
            color: /(background|color)$/i,
            date: /Date$/,
          },
        },
      },
      decorators: [
        (Story) => (
          <ThemeProvider theme={theme}>
            <Story />
          </ThemeProvider>
        ),
      ],
    };
    
    export default preview;