nx icon indicating copy to clipboard operation
nx copied to clipboard

@nx/react:stories generates index.stories.stories.tsx for some files

Open LouisLecouturier opened this issue 2 years ago • 1 comments

Current Behavior

When I execute @nx/react:stories, it generates stories for files that already have stories...

/Users/louislecouturier/Documents/Resply/code/resply/node_modules/.bin/nx g @nx/react:stories --project=ui-shared --no-interactive --dry-run

>  NX  Generating @nx/react:stories


NOTE: The "dryRun" flag means no changes were made.
CREATE libs/ui/shared/src/lib/components/Layout/Feedback/ProgressBar/index.stories.stories.tsx
CREATE libs/ui/shared/src/lib/components/Layout/Interactions/Forms/Inputs/FileInput/Dropzone/index.stories.tsx
CREATE libs/ui/shared/src/lib/components/Layout/Interactions/Forms/Inputs/FileInput/FileCard/index.stories.stories.tsx
CREATE libs/ui/shared/src/lib/components/Layout/Interactions/Forms/Inputs/FileInput/index.stories.stories.tsx
CREATE libs/ui/shared/src/lib/components/Layout/Menus/DropDown/index.stories.stories.tsx
CREATE libs/ui/shared/src/lib/components/Layout/Texts/List/index.stories.stories.tsx

Expected Behavior

Generate stories only for component that do not have one

GitHub Repo

No response

Steps to Reproduce

  1. Generate a component library
  2. Create a component and a story
  3. Run @nx/react:stories

Nx Report

Node   : 18.16.0
   OS     : darwin-arm64
   pnpm   : 8.6.5
   
   nx             : 16.4.3
   @nx/js         : 16.4.3
   @nx/jest       : 16.4.3
   @nx/linter     : 16.4.3
   @nx/workspace  : 16.4.3
   @nx/cypress    : 16.4.3
   @nx/devkit     : 16.4.3
   @nx/nest       : 16.4.3
   @nx/next       : 16.4.3
   @nx/node       : 16.4.3
   @nx/react      : 16.4.3
   @nx/storybook  : 16.4.3
   @nrwl/tao      : 16.4.3
   @nx/vite       : 16.4.3
   @nx/web        : 16.4.3
   @nx/webpack    : 16.4.3
   nx-cloud       : 16.0.5
   typescript     : 5.1.6
   ---------------------------------------
   Local workspace plugins:
         @resply/shared/hooks
         @resply/shared/utils

Failure Logs

No response

Operating System

  • [X] macOS
  • [ ] Linux
  • [ ] Windows
  • [ ] Other (Please specify)

Additional Information

Here's an example of component + story that makes the script generate the story twice

Component (index.tsx)

"use client";

import { ComponentPropsWithoutRef, ReactNode } from "react";
import clsx from "clsx";

type ListProps = {
  ordered?: boolean;
  orientation?: 'horizontal' | 'vertical';
  items: ReactNode[];
  bullet?: ReactNode;
} & ComponentPropsWithoutRef<'ul'>;

const itemClassNames = clsx('flex gap-2', 'text-dark-500');

export function List(props: ListProps) {
  const containerClassNames = clsx(
    'flex  gap-x-4 gap-y-2',
    props.orientation === 'horizontal' ? "" : 'flex-col'
  );

  if (props.ordered) {
    return (
      <ol className={containerClassNames}>
        {props.items.map((item, index) => (
          <li className={itemClassNames} key={item!.toString()}>
            <span className={clsx('flex items-center')}>{index + 1}.</span>
            {item}
          </li>
        ))}
      </ol>
    );
  }

  return (
    <ul className={containerClassNames}>
      {props.items.map((item) => (
        <li className={itemClassNames} key={item!.toString()}>
          {props.bullet && (
            <span className={clsx('flex h-6 w-6 items-center justify-center')} style={{aspectRatio : 1}}>{props.bullet}</span>
          )}
          {item}
        </li>
      ))}
    </ul>
  );
}

export default List;

Story (index.stories.tsx)

import type { Meta } from '@storybook/react';
import { List } from './index';

const Story: Meta<typeof List> = {
  component: List,
  title: 'Layout/Texts/List',
};
export default Story;

const fakeListItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];


export const Primary = {
  args: {
    items: fakeListItems,
    ordered: false,
    bullet: <div className={"bg-primary-500 w-1 h-1 rounded-sm"}></div>,
  },
};

LouisLecouturier avatar Jul 05 '23 14:07 LouisLecouturier

Hi there @LouisLecouturier ! Can you please share a full reproduction repository with me? We have a pretty detailed isThisFileAStory function that identifies stories, so it makes me wonder what may be going on here. A reproduction repository would really help me out here, to understand what is going on! Thanks for filing an issue!

mandarini avatar Jul 06 '23 11:07 mandarini

Hello @mandarini ! Sure, I was simply afraid it was only occurring on my current repo but I apparently could reproduce the issue so good news ! (at least for me hahaha)

Here's my repo : https://github.com/LouisLecouturier/nx-issue

You just have to run the @nx/react:stories nx script on 'my-library' and you should see the issue

Maybe it's just the way I'm writing my components that is causing it, I'm curious so let me know ;)

LouisLecouturier avatar Jul 06 '23 21:07 LouisLecouturier

Okay I just tried some things quickly and I know understand what's happening !!!

in libs/my-library/src/lib/Text/List/index.stories.tsx, I've written this line :

const fakeListItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

When I remove it everything works as expected... Is this way of coding bad or you just didn't handle this type of situation in your isThisFileAStory function ? Let me know ! :)

LouisLecouturier avatar Jul 06 '23 21:07 LouisLecouturier

When trying to fix my stories file, I found that it was also occurring for stories having decorators like so :

import type { Meta } from '@storybook/react';
import { FileCard } from './index';

const Story: Meta<typeof FileCard> = {
  component: FileCard,
  title: 'FileCard',
  decorators: [
    (Story) => (
      <div className="w-96">
        <Story />
      </div>
    ),
  ],
};
export default Story;

export const Primary = {
  args: {
    name: 'myFile',
    size: 1000000,
    progress: 50,
    preview: 'https://www.base64-image.de/build/img/mr-base64-482fa1f767.png',
    message: 'Fichier trop lourd',
    valid: true,
  },
};

And for this story too :

import type { Meta } from '@storybook/react';
import { DropDown } from './index';

const Story: Meta<typeof DropDown> = {
  component: DropDown,
  title: 'DropDown',
};
export default Story;

export const Primary = {
  args: {
    children: <span>DropDown</span>,
    sections: [
      {
        items: [
          {
            label: 'Item 1',
            icon: <span>Icon</span>,
          },
          {
            label: 'Item 2',
            icon: <span>Icon</span>,
          },
        ],
      },
      {
        items: [
          {
            label: 'Item 3',
            icon: <span>Icon</span>,
          },
        ],
      },
    ],
  },
};

LouisLecouturier avatar Jul 06 '23 21:07 LouisLecouturier

Interesting! Thanks, I'll take a look! I am not sure how much more use-cases we can look out for on the isThisFileAStory function, since we don't want to be making too many assumptions, you know. We don't want false positives. So we do have ignorePaths flag, that you can use, to exclude a pattern of paths for your use-case. We have some examples on how you can use.

In any case, I will look into your issue, but I also want to make a note of that as well, that we don't want to be making far too many assumptions, because we could end up skipping files that should be taken into account. I hope that makes sense?

Thank you for looking into it so much @LouisLecouturier !

mandarini avatar Jul 07 '23 07:07 mandarini

OK, found the issue!!! It was totally my bad! :D Should be fixed with the linked PR!

mandarini avatar Jul 07 '23 08:07 mandarini

Wonderful ! I'm glad I could help :) Will this be fixed in the next Nx update ?

Thanks for your help !

LouisLecouturier avatar Jul 07 '23 08:07 LouisLecouturier

@LouisLecouturier I think yes! PR is merged, so this should be part of our next patch release !

mandarini avatar Jul 07 '23 08:07 mandarini

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

github-actions[bot] avatar Aug 07 '23 00:08 github-actions[bot]