Learn how to import from a .storybook.ts file in Vue with TypeScript and Storybook, including how to manage Webpack configurations

I'm currently utilizing Vue with TypeScript in Storybook. Unfortunately, there are no official TypeScript configurations available for using Vue with Storybook.

How can I set up Webpack so that I am able to import from another .storybook.ts file within a .storybook.ts?

Encountering an error message:

ERROR in ./src/components/Button/Button.stories.ts
Module not found: Error: Can't resolve '../Icon/Icon.stories'
in '/Users/dude/monorepo/frontend/storybook/src/components/Button'

The import causing the issue is:

import AppButton from './Button.vue';
import { iconPackOptions, iconPackDefaultValue } from '../Icon/Icon.stories';

The content of the file src/components/Icon/Icon.stories.ts looks like this:

import { storiesOf } from '@storybook/vue';
import { withKnobs, text, select } from '@storybook/addon-knobs';

import AppIcon from './Icon.vue';

// Knobs grouping
const groupId01 = 'icon';

// Icon Pack
export const iconPackOptions = {
  None: false,
  FontAwesomeProRegular: 'far',
  FontAwesomeFreeBrands: 'fab'
};
export const iconPackDefaultValue = iconPackOptions.FontAwesomeProRegular;

The contents of ./.storybook/webpack.config.js file are as follows:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const path = require('path');

module.exports = async ({ config }) => {

  config.module.rules.push({
    test: /\.css$/,
    loaders: ['style-loader', 'css-loader', 'postcss-loader'],
    include: path.resolve(__dirname, '../'),
  });

  config.module.rules.push({
    test: /\.scss$/,
    use: ['style-loader', 'css-loader', 'sass-loader'],
    include: path.resolve(__dirname, '../assets/styles')
  });

  config.resolve = {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      'assets': path.resolve('../src/assets'),
      '@': path.join(__dirname, '../src'),
    }
  };

  config.module.rules.push({
    test: /\.ts$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true
        },
      }
    ]
  });

  config.plugins.push(new ForkTsCheckerWebpackPlugin());

  return config;
};

The content of ./.storybook/config.js file includes:

import { configure } from '@storybook/vue';

import '../src/plugins';
import '../src/assets/styles/main.scss';

const req = require.context('../src/components', true, /.stories.ts$/);
function loadStories() {
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);

Answer №1

This configuration for the .storybook/webpack.config.js file is currently effective for me, especially when combined with the storysource addon. In case you do not require the storysource feature, simply eliminate the loader object by removing

@storybook/addon-storysource/loader
:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const path = require('path');

module.exports = async ({ config }) => {

  config.module.rules.push({
    test: /\.css$/,
    loaders: ['style-loader', 'css-loader', 'postcss-loader'],
    include: path.resolve(__dirname, '../'),
  });

  config.module.rules.push({
    test: /\.scss$/,
    use: ['style-loader', 'css-loader', 'sass-loader'],
    include: path.resolve(__dirname, '../assets/styles')
  });

  config.resolve = {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      'assets': path.resolve('../src/assets'),
      '@': path.join(__dirname, '../src'),
    }
  };

  config.module.rules.push({
    test: /\.stories\.ts?$/,
    exclude: /node_modules/,
    use: [
      {
        loader: require.resolve('babel-loader')
      },
      {
        loader: require.resolve('@storybook/addon-storysource/loader')
      }
    ]
  });

  config.module.rules.push({
    test: /\.ts$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true
        },
      }
    ]
  });

  config.plugins.push(new ForkTsCheckerWebpackPlugin());

  return config;
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The alignment of two elements is off in mobile display

Why aren't my two divs centered in mobile view? I am using Vuetify CSS flex helper justify-center to try and achieve it, but it doesn't seem to be working. Even when I use justify-sm-center, it still doesn't work. What am I missing? <v-co ...

Converting Epoch timestamp to AM/PM format in a React render function

I am currently working on a personal project using React.js. I have successfully fetched an API, and one of the values returned is an Epoch timestamp. My goal is to display this timestamp in a human-readable format such as am/pm. The Epoch timestamp is dis ...

Display or conceal toggle in ruby utilizing jQuery

I'm facing an issue with the functionality of a button that is meant to hide and show a form using jQuery. Initially, I added a path to signup in the button so that it would display and function properly. Now, when I click the button, the form shows u ...

Using a Component as a Property in Angular

There is a small gridComponent: @Component({ selector: 'moving-grid', templateUrl: './grid.component.html', styleUrls: ['./grid.component.css'] }) export class GridComponent { @Input('widgets') ext ...

Implementing route navigation in two components using a click button

To display the content of the Quiz component with the path "/quiz" after clicking a button and fetching the component with the path "/" is my goal. Here is the code snippet from the App.jsx file: <Router> <Routes> <Route ...

Troubleshooting Angular JS loading problems

I'm attempting to implement the Angular-Spinner in my project: Specifically, I want to use it with http.get calls. This is what I have so far: Within controllers: $scope.loading = true; $http.get('js/data/test.json').success(function(resu ...

What is the best way to utilize the GET Method with a hashtag incorporated into the URL?

For instance: www.sample.com#?id=10 Currently, I am not able to retrieve any value from $_GET['id']. Despite my attempt to eliminate the hashtag from the URL using JavaScript, no change occurs: $(document).ready(function(){ $(window.location ...

How can Swipe support help you slide a menu back in?

For implementing swipe support on my landing page carousel, I included jquery.mobile.custom.min.js. However, I am facing a challenge with adding swipe support to "close" the menu. Essentially, swiping left should have the same effect as clicking the butto ...

Using CSS to position elements absolutely while also adjusting the width of the div

In one section of my website, I have a specific div structure. This structure consists of two divs stacked on top of each other. The first div is divided into two parts: one part with a width of 63% and another part with a button. Beneath the first div, t ...

Dealing with Scoping Problems in a Typescript d3 Update Tutorial

I'm facing challenges trying to implement the provided bl.ocks example in Typescript (using Angular). This is my implementation in TypeScript: StackBlitz Could anyone offer insights on what might be causing the issues I'm encountering? My initi ...

What steps can be taken to enhance cleanliness and efficiency, and what are some recommended practices to adhere to?

Currently, I am in the process of developing a user authentication system on the backend. Specifically, I have implemented a POST method for registering new users. userRouter.post("/", expressAsyncHandler(async (req, res) => { try { const { na ...

Creating a sleek navigation bar and sliding feature within the header of your Ionic 2

I am looking to create a sliding header for my website where the gallery hides and the navbar moves to the top as I scroll down, similar to the gif provided. Any help or ideas on how to achieve this would be greatly appreciated. Thank you. https://i.sstat ...

What is the best way to transfer static assets from an npm package to a nuxt project?

Has anyone successfully sent assets from an npm package to a nuxt application before? I have a vue component within an npm package with the following structure: -src/ -assets/ -noun-filter.svg In this npm package, the vector image is included in the v ...

How can we eliminate the need for specifying the order of generic arguments in TypeScript?

In the development of my middleware engine, I have incorporated various generic arguments that are specific to the particular implementation in use. export type Middleware< Store = never, Args = unknown, Response = unknown > = ( context: { ...

How to fetch a single document from a nested array using Mongoose

Currently, I am working on a MongoDB database using Mongoose in Node.js. The collection structure resembles the following: { cinema: 'xxx', account: 'yyy', media: { data: [{ id: 1, name: 'zzz& ...

Analyzing Compatibility and Ensuring Security

I recently started using Parse and have been exploring the documentation and answered questions. However, I still have a couple of inquiries on my mind. Firstly, I discovered that the Javascript SDK does not function on IE9 and IE8 without an SSL certific ...

Issue with Nuxt: Data inaccessible within a method

Incorporating CKEditor 5 + CKFinder (Modal Mode) to initiate image selection through the @click event presents a challenge in accessing data within the onInit function block. Below is the function in question: data() { return { post: { ...

The teleport-controls feature is currently not functioning properly in VR mode with Aframe version 0.8.2

Having an issue with the teleport-controls under aframe 0.8.2. When in VR mode using Vive, only the curve appears after touching the trackpad of the controller, but the camera position does not change. However, in flat mode, both the curve and camera posit ...

The autofocus feature on the textarea in Angular Material Dialog seems to be malfunctioning

Within a web app, I am utilizing the Dialog component from Angular Material. The Dialog consists of only a textarea that is initially empty. I aim to automatically focus on the textarea when the user opens the modal dialog. How can I achieve this? Despite ...

Guide to adding a line break following each set of 200 characters utilizing jQuery

I have a text input field where I need to enter some data. My requirement is to automatically add a line break after every 200 characters using JavaScript or jQuery. For example: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ...