storybook 推荐的编写动态故事并生成适当故事源代码的方法是什么?

pdsfdshx  于 4个月前  发布在  其他
关注(0)|答案(3)|浏览(69)

关于编写故事的示例有很多,对于新手来说很难理解推荐的方法,尤其是当我们想要使用 args 动态编写故事时。

以下是我目前的做法,我认为还不错:

import {
  Meta,
  Story,
} from '@storybook/react/types-6-0';
import React from 'react';
import Btn from '../../../components/utils/Btn';
import SpoilerLink, { Props } from '../../../components/utils/SpoilerLink';

export default {
  title: 'Next Right Now/Form/SpoilerLink',
  component: SpoilerLink,
  argTypes: {},
} as Meta;

const Template: Story<Props> = (props) => {
  return (
    <SpoilerLink
      {...props}
    />
  );
};

export const DynamicExample: Story<Props> = Template.bind({});
DynamicExample.args = {
  previewElement: (
    <span>Spoil me!</span>
  ),
  spoilerElement: (
    <span>Arya Stark's phone number is 000000000</span>
  ),
  className: '',
  href: 'tel:000000000',
};

export const DynamicExampleWithBtn: Story<Props> = Template.bind({});
DynamicExampleWithBtn.args = {
  previewElement: (
    <Btn>Spoil me!</Btn>
  ),
  spoilerElement: (
    <Btn mode={'primary-reverse'}>Arya Stark's phone number is 000000000</Btn>
  ),
  className: '',
  href: 'tel:000000000',
};

这种方式对我来说足够灵活,可以在不产生太多代码重复的情况下添加更多的故事。

问题在于 Story 面板显示无意义的源代码(与其他编写故事的方式相比):

演示: https://nrn-v2-mst-aptd-at-lcz-sty-storybook.vercel.app/?path=/story/next-right-now-form-spoilerlink--dynamic-example-with-btn
所有故事都会显示相同的源代码,这使得整个“故事”面板无法使用。

这是一个已知的问题吗?有解决方法吗?
我尝试思考了一下,而“故事”面板的目标是显示可以快速复制使用的代码。显示上述源代码或整个故事文件(*.stories.tsx)都是不可用的。它需要显示一个推断出 args 的代码示例,例如:

(props) => {
  return (
    <SpoilerLink
      previewElement={(
	      <span>Spoil me!</span>
	    )}
      spoilerElement={(
	      <span>Arya Stark's phone number is 000000000</span>
	    )}
      className={''}
      href={'tel:000000000'}
    />
  );
}

这样的展示方式会给开发者带来更好的体验。

9w11ddsr

9w11ddsr1#

我们目前在 addon-docsSource 区块中支持这个功能:#11332。一旦这个功能稳定下来,我们将尝试协调文档选项卡中出现的文档区块和Storysource等插件面板中出现的插件之间的差异。cc @phated

jtw3ybtb

jtw3ybtb2#

昨天我使用模板重构了一个 useUndo 的故事,但生成的代码并没有像实际复制整个代码那样好,所以我今天又回退了它。
查看提交:UnlyEd/reaflow@72d1ddc

提交前:(使用模板)

代码:

import {
  Meta,
  Story
} from '@storybook/react/types-6-0';
import React, { useState } from 'react';
import {
  EdgeData,
  NodeData
} from '../src';
import { Canvas } from '../src/Canvas';
import {
  UndoRedoEvent,
  useUndo
} from '../src/helpers';
import {
  Add,
  Arrow,
  Edge,
  Icon,
  Label,
  MarkerArrow,
  Node,
  Port,
  Remove
} from '../src/symbols';

export default {
  title: 'Demos/Undo Redo',
  component: Canvas,
  argTypes: {
    initialHistory: {
      control: {
        disable: true // TODO make it readonly when it'll be possible - See https://github.com/storybookjs/storybook/issues/14048
      }
    }
  },
  subcomponents: {
    Node,
    Edge,
    MarkerArrow,
    Arrow,
    Icon,
    Label,
    Port,
    Remove,
    Add
  }
} as Meta;

type PropsWithChildrenMock = {
  initialHistory?: { nodes: NodeData[]; edges: EdgeData[] }[];
};

const Template: Story<PropsWithChildrenMock> = (props) => {
  const { initialHistory } = props;
  const [nodes, setNodes] = useState<any[]>([
    {
      id: '1',
      text: 'Node 1'
    },
    {
      id: '2',
      text: 'Node 2'
    },
    {
      id: '3',
      text: 'Node 3'
    }
  ]);

  const [edges, setEdges] = useState<any[]>([
    {
      id: '1-2',
      from: '1',
      to: '2'
    },
    {
      id: '1-3',
      from: '1',
      to: '3'
    }
  ]);

  const { undo, redo, canUndo, canRedo } = useUndo({
    nodes,
    edges,
    initialHistory,
    onUndoRedo: (state: UndoRedoEvent) => {
      console.log('Undo / Redo', state);
      setEdges(state.edges);
      setNodes(state.nodes);
    }
  });

  const addNode = () => {
    setNodes([
      ...nodes,
      {
        id: `a${Math.random()}`,
        text: `Node ${Math.random()}`
      }
    ]);
  };

  return (
    <div style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0 }}>
      <button
        style={{ position: 'absolute', top: 10, left: 10, zIndex: 999 }}
        onClick={addNode}
      >
        Add Nodes
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 100, zIndex: 999 }}
        onClick={undo}
        disabled={!canUndo}
      >
        Undo
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 160, zIndex: 999 }}
        onClick={redo}
        disabled={!canRedo}
      >
        Redo
      </button>
      <Canvas
        nodes={nodes}
        edges={edges}
        onLayoutChange={layout => console.log('Layout', layout)}
      />
    </div>
  );
};

export const Simple: Story<PropsWithChildrenMock> = Template.bind({});
Simple.args = {};

export const WithInitialHistory: Story<PropsWithChildrenMock> = Template.bind({});
WithInitialHistory.args = {
  initialHistory: [
    {
      nodes: [],
      edges: []
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        }
      ],
      edges: []
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        },
        {
          id: '2',
          text: 'Node 2'
        }
      ],
      edges: [
        {
          id: '1-2',
          from: '1',
          to: '2'
        }
      ]
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        },
        {
          id: '2',
          text: 'Node 2'
        },
        {
          id: '3',
          text: 'Node 3'
        }
      ],
      edges: [
        {
          id: '1-2',
          from: '1',
          to: '2'
        },
        {
          id: '1-3',
          from: '1',
          to: '3'
        }
      ]
    }
  ]
};

提交后:(使用代码复制,没有模板)

代码:

import {
  Meta,
  Story
} from '@storybook/react/types-6-0';
import React, { useState } from 'react';
import {
  EdgeData,
  NodeData
} from '../src';
import { Canvas } from '../src/Canvas';
import {
  UndoRedoEvent,
  useUndo
} from '../src/helpers';
import {
  Add,
  Arrow,
  Edge,
  Icon,
  Label,
  MarkerArrow,
  Node,
  Port,
  Remove
} from '../src/symbols';

export default {
  title: 'Demos/Undo Redo',
  component: Canvas,
  argTypes: {
    initialHistory: {
      control: {
        disable: true // TODO make it readonly when it'll be possible - See https://github.com/storybookjs/storybook/issues/14048
      }
    }
  },
  subcomponents: {
    Node,
    Edge,
    MarkerArrow,
    Arrow,
    Icon,
    Label,
    Port,
    Remove,
    Add
  }
} as Meta;

type Props = {}

export const Simple: Story<Props> = () => {
  const [nodes, setNodes] = useState<any[]>([
    {
      id: '1',
      text: 'Node 1'
    },
    {
      id: '2',
      text: 'Node 2'
    },
    {
      id: '3',
      text: 'Node 3'
    }
  ]);

  const [edges, setEdges] = useState<any[]>([
    {
      id: '1-2',
      from: '1',
      to: '2'
    },
    {
      id: '1-3',
      from: '1',
      to: '3'
    }
  ]);

  const { undo, redo, canUndo, canRedo } = useUndo({
    nodes,
    edges,
    onUndoRedo: (state: UndoRedoEvent) => {
      console.log('Undo / Redo', state);
      setEdges(state.edges);
      setNodes(state.nodes);
    }
  });

  const addNode = () => {
    setNodes([
      ...nodes,
      {
        id: `a${Math.random()}`,
        text: `Node ${Math.random()}`
      }
    ]);
  };

  return (
    <div style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0 }}>
      <button
        style={{ position: 'absolute', top: 10, left: 10, zIndex: 999 }}
        onClick={addNode}
      >
        Add Nodes
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 100, zIndex: 999 }}
        onClick={undo}
        disabled={!canUndo}
      >
        Undo
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 160, zIndex: 999 }}
        onClick={redo}
        disabled={!canRedo}
      >
        Redo
      </button>
      <Canvas
        nodes={nodes}
        edges={edges}
        onLayoutChange={layout => console.log('Layout', layout)}
      />
    </div>
  );
};

export const WithInitialHistory: Story<Props> = () => {
  const initialHistory: { nodes: NodeData[]; edges: EdgeData[] }[] = [
    {
      nodes: [],
      edges: []
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        }
      ],
      edges: []
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        },
        {
          id: '2',
          text: 'Node 2'
        }
      ],
      edges: [
        {
          id: '1-2',
          from: '1',
          to: '2'
        }
      ]
    },
    {
      nodes: [
        {
          id: '1',
          text: 'Node 1'
        },
        {
          id: '2',
          text: 'Node 2'
        },
        {
          id: '3',
          text: 'Node 3'
        }
      ],
      edges: [
        {
          id: '1-2',
          from: '1',
          to: '2'
        },
        {
          id: '1-3',
          from: '1',
          to: '3'
        }
      ]
    }
  ];
  const [nodes, setNodes] = useState<any[]>([
    {
      id: '1',
      text: 'Node 1'
    },
    {
      id: '2',
      text: 'Node 2'
    },
    {
      id: '3',
      text: 'Node 3'
    }
  ]);

  const [edges, setEdges] = useState<any[]>([
    {
      id: '1-2',
      from: '1',
      to: '2'
    },
    {
      id: '1-3',
      from: '1',
      to: '3'
    }
  ]);

  const { undo, redo, canUndo, canRedo } = useUndo({
    nodes,
    edges,
    initialHistory,
    onUndoRedo: (state: UndoRedoEvent) => {
      console.log('Undo / Redo', state);
      setEdges(state.edges);
      setNodes(state.nodes);
    }
  });

  const addNode = () => {
    setNodes([
      ...nodes,
      {
        id: `a${Math.random()}`,
        text: `Node ${Math.random()}`
      }
    ]);
  };

  return (
    <div style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0 }}>
      <button
        style={{ position: 'absolute', top: 10, left: 10, zIndex: 999 }}
        onClick={addNode}
      >
        Add Nodes
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 100, zIndex: 999 }}
        onClick={undo}
        disabled={!canUndo}
      >
        Undo
      </button>
      <button
        style={{ position: 'absolute', top: 10, left: 160, zIndex: 999 }}
        onClick={redo}
        disabled={!canRedo}
      >
        Redo
      </button>
      <Canvas
        nodes={nodes}
        edges={edges}
        onLayoutChange={layout => console.log('Layout', layout)}
      />
    </div>
  );
};

我不确定在提供阅读故事文档时的最佳用户体验的同时,保持尽可能可重用代码的正确方法是什么。
我觉得自从上次以来事情发生了变化(是吗?),但仍然不够有帮助😞

omqzjyyz

omqzjyyz3#

是否有关于这个的更新?遗憾的是,当前的情况使得storysource插件无法发挥其应有的作用。

相关问题